API * backlinks (forgot to add)
[lhc/web/wiklou.git] / includes / api / ApiQueryBacklinks.php
1 <?php
2
3
4 /*
5 * Created on Oct 16, 2006
6 *
7 * API for MediaWiki 1.8+
8 *
9 * Copyright (C) 2006 Yuri Astrakhan <FirstnameLastname@gmail.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 * http://www.gnu.org/copyleft/gpl.html
25 */
26
27 if (!defined('MEDIAWIKI')) {
28 // Eclipse helper - will be ignored in production
29 require_once ("ApiQueryBase.php");
30 }
31
32 class ApiQueryBacklinks extends ApiQueryGeneratorBase {
33
34 private $rootTitle;
35
36 public function __construct($query, $moduleName) {
37 parent :: __construct($query, $moduleName, 'bl');
38 }
39
40 public function execute() {
41 $this->run();
42 }
43
44 public function executeGenerator($resultPageSet) {
45 $this->run($resultPageSet);
46 }
47
48 private function run($resultPageSet = null) {
49 $continue = $namespace = $redirect = $limit = null;
50 extract($this->extractRequestParams());
51
52 if ($redirect)
53 $this->dieDebug('Redirect is not yet been implemented', 'notimplemented');
54
55 $this->processContinue($continue, $redirect);
56
57 if (is_null($resultPageSet)) {
58 $this->addFields( array (
59 'page_id',
60 'page_namespace',
61 'page_title'
62 ));
63 } else {
64 $this->addFields( $resultPageSet->getPageTableFields());
65 }
66
67 $this->addTables(array (
68 'pagelinks',
69 'page'
70 ));
71 $this->addWhere('pl_from=page_id');
72
73 $this->addWhereFld('pl_namespace', $this->rootTitle->getNamespace());
74 $this->addWhereFld('pl_title', $this->rootTitle->getDBkey());
75 $this->addWhereFld('page_namespace', $namespace);
76 $this->addOption('LIMIT', $limit +1);
77 $this->addOption('ORDER BY', 'page_namespace, page_title');
78
79 if ($redirect)
80 $this->addWhereFld('page_is_redirect', 0);
81
82 $db = & $this->getDB();
83 if(!is_null($this->fromTitle)) {
84 $ns = $this->fromTitle->getNamespace();
85 $t = $db->addQuotes($this->fromTitle->getDBkey());
86 $this->addWhere("(page_namespace>$ns OR (page_namespace=$ns AND page_title>=$t))");
87 }
88
89 $res = $this->select(__METHOD__);
90
91 $count = 0;
92 $data = array ();
93 while ($row = $db->fetchObject($res)) {
94 if (++ $count > $limit) {
95 // We've reached the one extra which shows that there are additional pages to be had. Stop here...
96 $continue = $this->rootTitle->getNamespace() . '|' . $this->rootTitle->getDBkey() . '|1|0|' . $row->page_namespace . '|' . $row->page_title;
97 $this->setContinueEnumParameter('continue', $continue);
98 break;
99 }
100
101 if (is_null($resultPageSet)) {
102 $vals = $this->addRowInfo('page', $row);
103 if ($vals)
104 $data[intval($row->page_id)] = $vals;
105 } else {
106 $resultPageSet->processDbRow($row);
107 }
108 }
109 $db->freeResult($res);
110
111 if (is_null($resultPageSet)) {
112 $result = $this->getResult();
113 $result->setIndexedTagName($data, 'bl');
114 $result->addValue('query', $this->getModuleName(), $data);
115 }
116 }
117
118 protected function processContinue($continue, $redirect) {
119 $pageSet = $this->getPageSet();
120 $count = $pageSet->getGoodTitleCount();
121 if (!is_null($continue)) {
122 if ($count !== 0)
123 $this->dieUsage('When continuing the backlink query, no other titles may be provided', 'titles_on_continue');
124 $this->parseContinueParam($continue, $redirect);
125
126 // Skip all completed links
127 $db = & $this->getDB();
128
129 } else {
130 if ($count !== 1)
131 $this->dieUsage('Backlinks requires one title to start the query', 'bad_title_count');
132 $this->rootTitle = array_pop($pageSet->getGoodTitles()); // only one title there
133 $this->contFromRedirs = false;
134 $this->contFromLevel = 0;
135 // $this->contFromPageId = 0;
136 $this->fromTitle = null;
137 }
138 }
139
140 protected function parseContinueParam($continue, $redirect) {
141 //
142 // the parameter will be in the format:
143 // ns|db_key|step|level|ns|db_key
144 // ns+db_key -- the root title
145 // step = 1 or 2 - which step to continue from - 1-titles, 2-redirects
146 // level -- how many levels to follow before starting enumerating.
147 // ns+title to continue from
148 //
149 $continueList = explode('|', $continue);
150 if (count($continueList) === 6) {
151 $rootNs = intval($continueList[0]);
152 if (($rootNs !== 0 || $continueList[0] === '0') && !empty ($continueList[1])) {
153 $this->rootTitle = Title :: makeTitleSafe($rootNs, $continueList[1]);
154 if ($this->rootTitle && $this->rootTitle->userCanRead()) {
155
156 $step = intval($continueList[2]);
157 if ($step === 1 || $step === 2) {
158 $this->continueRedirs = ($step === 2);
159
160 $level = intval($continueList[3]);
161 if ($level !== 0 || $continueList[3] === '0') {
162 $this->continueLevel = $level;
163
164 // $pageid = intval($continueList[4]);
165 // if ($pageid !== 0 || $continueList[4] === '0') {
166 // $this->continuePageId = $pageid;
167
168 $fromNs = intval($continueList[4]);
169 if (($fromNs !== 0 || $continueList[4] === '0') && !empty ($continueList[5])) {
170 $this->fromTitle = Title :: makeTitleSafe($fromNs, $continueList[5]);
171
172 // When not processing redirects, only page through the non-redirects
173 // if ($redirect || ($step === 1 && $level === 0 && $pageid > 0)) {
174
175 if ($redirect || ($step === 1 && $level === 0 && $this->fromTitle && $this->fromTitle->userCanRead())) {
176 return; // done
177 }
178 }
179 }
180 }
181 }
182 }
183 }
184
185 $this->dieUsage("Invalid continue param. You should pass the original value returned by the previous query", "_badcontinue");
186 }
187
188 protected function getAllowedParams() {
189
190 $namespaces = $this->getQuery()->getValidNamespaces();
191 return array (
192 'continue' => null,
193 'namespace' => array (
194 ApiBase :: PARAM_ISMULTI => true,
195 ApiBase :: PARAM_TYPE => $namespaces
196 ),
197 'redirect' => false,
198 'limit' => array (
199 ApiBase :: PARAM_DFLT => 10,
200 ApiBase :: PARAM_TYPE => 'limit',
201 ApiBase :: PARAM_MIN => 1,
202 ApiBase :: PARAM_MAX1 => ApiBase :: LIMIT_BIG1,
203 ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2
204 )
205 );
206 }
207
208 protected function getParamDescription() {
209 return array (
210 'continue' => 'When more results are available, use this to continue.',
211 'namespace' => 'The namespace to enumerate.',
212 'redirect' => 'If linking page is a redirect, find all pages that link to that redirect (not implemented)',
213 'limit' => 'How many total pages to return.'
214 );
215 }
216
217 protected function getDescription() {
218 return 'Find all pages that link to the given page';
219 }
220
221 protected function getExamples() {
222 return array (
223 'api.php?action=query&list=backlinks&titles=Main%20Page',
224 'api.php?action=query&generator=backlinks&titles=Main%20Page&prop=info',
225
226 );
227 }
228
229 public function getVersion() {
230 return __CLASS__ . ': $Id$';
231 }
232 }
233 ?>