r17295 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r17294‎ | r17295 | r17296 >
Date:00:18, 30 October 2006
Author:yurik
Status:old
Tags:
Comment:
API * Implemented backlinks / imagelinks / embeddedin modules
* Revised help screen
Modified paths:
  • /trunk/phase3/includes/api/ApiBase.php (modified) (history)
  • /trunk/phase3/includes/api/ApiMain.php (modified) (history)
  • /trunk/phase3/includes/api/ApiPageSet.php (modified) (history)
  • /trunk/phase3/includes/api/ApiQuery.php (modified) (history)
  • /trunk/phase3/includes/api/ApiQueryBacklinks.php (modified) (history)
  • /trunk/phase3/includes/api/ApiQueryBase.php (modified) (history)
  • /trunk/phase3/includes/api/ApiQueryRevisions.php (modified) (history)

Diff [purge]

Index: trunk/phase3/includes/api/ApiQueryBase.php
@@ -36,7 +36,10 @@
3737 public function __construct($query, $moduleName, $paramPrefix = '') {
3838 parent :: __construct($query->getMain(), $moduleName, $paramPrefix);
3939 $this->mQueryModule = $query;
40 -
 40+ $this->resetQueryParams();
 41+ }
 42+
 43+ protected function resetQueryParams() {
4144 $this->tables = array ();
4245 $this->where = array ();
4346 $this->fields = array();
Index: trunk/phase3/includes/api/ApiQuery.php
@@ -50,7 +50,9 @@
5151 'logevents' => 'ApiQueryLogEvents',
5252 'watchlist' => 'ApiQueryWatchlist',
5353 'recentchanges' => 'ApiQueryRecentChanges',
54 - 'backlinks' => 'ApiQueryBacklinks'
 54+ 'backlinks' => 'ApiQueryBacklinks',
 55+ 'embeddedin' => 'ApiQueryBacklinks',
 56+ 'imagelinks' => 'ApiQueryBacklinks'
5557 );
5658 // 'categorymembers' => 'ApiQueryCategorymembers',
5759 // 'embeddedin' => 'ApiQueryEmbeddedin',
Index: trunk/phase3/includes/api/ApiQueryRevisions.php
@@ -118,7 +118,7 @@
119119 $this->validateLimit($this->encodeParamName('limit'), $limit, 1, $userMax, $botMax);
120120
121121 // There is only one ID, use it
122 - $this->addWhereFld('rev_page', array_pop(array_keys($pageSet->getGoodTitles())));
 122+ $this->addWhereFld('rev_page', current(array_keys($pageSet->getGoodTitles())));
123123 }
124124 elseif ($pageCount > 0) {
125125 // When working in multi-page non-enumeration mode,
Index: trunk/phase3/includes/api/ApiBase.php
@@ -170,14 +170,17 @@
171171 $desc = isset ($paramsDescription[$paramName]) ? $paramsDescription[$paramName] : '';
172172 if (is_array($desc))
173173 $desc = implode($paramPrefix, $desc);
 174+
174175 if (isset ($paramSettings[self :: PARAM_TYPE])) {
 176+ if (isset ($paramSettings[self :: PARAM_ISMULTI]))
 177+ $prompt = 'Multiple "|"-separated values: ';
 178+ else
 179+ $prompt = 'Any one of these values: ';
175180 $type = $paramSettings[self :: PARAM_TYPE];
176181 if (is_array($type))
177 - $desc .= $paramPrefix . 'Allowed values: ' . implode(', ', $type);
 182+ $desc .= $paramPrefix . $prompt . implode(', ', $type);
178183 }
179 - if (isset ($paramSettings[self :: PARAM_ISMULTI]))
180 - $desc .= $paramPrefix . 'Allows multiple values separated with "|"';
181 -
 184+
182185 $default = is_array($paramSettings) ? (isset ($paramSettings[self :: PARAM_DFLT]) ? $paramSettings[self :: PARAM_DFLT] : null) : $paramSettings;
183186 if (!is_null($default) && $default !== false)
184187 $desc .= $paramPrefix . "Default: $default";
@@ -327,7 +330,6 @@
328331 break;
329332 default :
330333 ApiBase :: dieDebug(__METHOD__, "Param $paramName's type is unknown - $type");
331 -
332334 }
333335 }
334336
@@ -437,7 +439,7 @@
438440 $this->profileOut();
439441 }
440442 }
441 -
 443+
442444 /**
443445 * Total time the module was executed
444446 */
Index: trunk/phase3/includes/api/ApiMain.php
@@ -271,9 +271,21 @@
272272 '',
273273 'This API allows programs to access various functions of MediaWiki software.',
274274 'For more details see API Home Page @ http://meta.wikimedia.org/wiki/API',
 275+ '',
 276+ 'Status: ALPHA -- all features shown on this page should be working,',
 277+ ' but the API is still in active development, and may change at any time.',
 278+ ' Make sure you monitor changes to this page, wikitech-l mailing list,',
 279+ ' or the source code in the includes/api directory for any changes.',
275280 ''
276281 );
277282 }
 283+
 284+ protected function getCredits() {
 285+ return array(
 286+ 'This API is being implemented by Yuri Astrakhan [[User:Yurik]] / FirstnameLastname@gmail.com',
 287+ 'Please leave your comments and suggestions at http://meta.wikimedia.org/wiki/API'
 288+ );
 289+ }
278290
279291 /**
280292 * Override the parent to generate help messages for all available modules.
@@ -303,6 +315,9 @@
304316 $msg .= $msg2;
305317 $msg .= "\n";
306318 }
 319+
 320+ $msg .= "\n*** Credits: ***\n " . implode("\n ", $this->getCredits()) . "\n";
 321+
307322
308323 return $msg;
309324 }
Index: trunk/phase3/includes/api/ApiQueryBacklinks.php
@@ -33,8 +33,53 @@
3434
3535 private $rootTitle, $contRedirs, $contLevel, $contTitle, $contID;
3636
 37+ // output element name, database column field prefix, database table
 38+ private $backlinksSettings = array (
 39+ 'backlinks' => array (
 40+ 'code' => 'bl',
 41+ 'prefix' => 'pl',
 42+ 'linktbl' => 'pagelinks'
 43+ ),
 44+ 'embeddedin' => array (
 45+ 'code' => 'ei',
 46+ 'prefix' => 'tl',
 47+ 'linktbl' => 'templatelinks'
 48+ ),
 49+ 'imagelinks' => array (
 50+ 'code' => 'il',
 51+ 'prefix' => 'il',
 52+ 'linktbl' => 'imagelinks'
 53+ )
 54+ );
 55+
3756 public function __construct($query, $moduleName) {
38 - parent :: __construct($query, $moduleName, 'bl');
 57+ $code = $prefix = $linktbl = null;
 58+ extract($this->backlinksSettings[$moduleName]);
 59+
 60+ parent :: __construct($query, $moduleName, $code);
 61+ $this->bl_ns = $prefix . '_namespace';
 62+ $this->bl_from = $prefix . '_from';
 63+ $this->bl_tables = array (
 64+ $linktbl,
 65+ 'page'
 66+ );
 67+ $this->bl_code = $code;
 68+
 69+ $this->hasNS = $moduleName !== 'imagelinks';
 70+ if ($this->hasNS) {
 71+ $this->bl_title = $prefix . '_title';
 72+ $this->bl_sort = "{$this->bl_ns}, {$this->bl_title}, {$this->bl_from}";
 73+ $this->bl_fields = array (
 74+ $this->bl_ns,
 75+ $this->bl_title
 76+ );
 77+ } else {
 78+ $this->bl_title = $prefix . '_to';
 79+ $this->bl_sort = "{$this->bl_title}, {$this->bl_from}";
 80+ $this->bl_fields = array (
 81+ $this->bl_title
 82+ );
 83+ }
3984 }
4085
4186 public function execute() {
@@ -54,34 +99,25 @@
55100
56101 $this->processContinue($continue, $redirect);
57102
58 - if (is_null($resultPageSet)) {
 103+ $this->addFields($this->bl_fields);
 104+ if (is_null($resultPageSet))
59105 $this->addFields(array (
60 - 'pl_from as page_id', // is this more efficient than getting page_id?
61 - 'pl_namespace',
62 - 'pl_title',
 106+ 'page_id',
63107 'page_namespace',
64108 'page_title'
65109 ));
66 - } else {
67 - $this->addFields($resultPageSet->getPageTableFields());
68 - $this->addFields(array (
69 - 'pl_namespace',
70 - 'pl_title',
71 -
72 - ));
73 - }
 110+ else
 111+ $this->addFields($resultPageSet->getPageTableFields()); // will include page_id
74112
75 - $this->addTables(array (
76 - 'pagelinks',
77 - 'page'
78 - ));
79 - $this->addWhere('pl_from=page_id');
 113+ $this->addTables($this->bl_tables);
 114+ $this->addWhere($this->bl_from . '=page_id');
80115
81 - $this->addWhereFld('pl_namespace', $this->rootTitle->getNamespace());
82 - $this->addWhereFld('pl_title', $this->rootTitle->getDBkey());
 116+ if ($this->hasNS)
 117+ $this->addWhereFld($this->bl_ns, $this->rootTitle->getNamespace());
 118+ $this->addWhereFld($this->bl_title, $this->rootTitle->getDBkey());
83119 $this->addWhereFld('page_namespace', $namespace);
84120 $this->addOption('LIMIT', $limit +1);
85 - $this->addOption('ORDER BY', 'pl_namespace, pl_title, pl_from');
 121+ $this->addOption('ORDER BY', $this->bl_sort);
86122
87123 if ($redirect)
88124 $this->addWhereFld('page_is_redirect', 0);
@@ -91,11 +127,16 @@
92128 $plfrm = intval($this->contID);
93129 if ($this->contLevel == 0) {
94130 // For the first level, there is only one target title, so no need for complex filtering
95 - $this->addWhere("pl_from>=$plfrm");
 131+ $this->addWhere($this->bl_from . '>=' . $plfrm);
96132 } else {
97133 $ns = $this->contTitle->getNamespace();
98134 $t = $db->addQuotes($this->contTitle->getDBkey());
99 - $this->addWhere("(pl_namespace>$ns OR (pl_namespace=$ns AND (pl_title>$t OR (pl_title=$t AND pl_from>=$plfrm))))");
 135+ $whereWithoutNS = "{$this->bl_title}>$t OR ({$this->bl_title}=$t AND {$this->bl_from}>=$plfrm))";
 136+
 137+ if ($this->hasNS)
 138+ $this->addWhere("{$this->bl_ns}>$ns OR ({$this->bl_ns}=$ns AND ($whereWithoutNS)");
 139+ else
 140+ $this->addWhere($whereWithoutNS);
100141 }
101142 }
102143
@@ -106,7 +147,14 @@
107148 while ($row = $db->fetchObject($res)) {
108149 if (++ $count > $limit) {
109150 // We've reached the one extra which shows that there are additional pages to be had. Stop here...
110 - $continue = $this->rootTitle->getNamespace() . '|' . $this->rootTitle->getDBkey() . '|1|0|' . $row->pl_namespace . '|' . $row->pl_title . '|' . $row->page_id;
 151+ if ($redirect) {
 152+ $ns = $row-> {
 153+ $this->bl_ns };
 154+ $t = $row-> {
 155+ $this->bl_title };
 156+ $continue = $this->getContinueRedirStr(false, 0, $ns, $t, $row->page_id);
 157+ } else
 158+ $continue = $this->getContinueStr($row->page_id);
111159 $this->setContinueEnumParameter('continue', $continue);
112160 break;
113161 }
@@ -123,17 +171,17 @@
124172
125173 if (is_null($resultPageSet)) {
126174 $result = $this->getResult();
127 - $result->setIndexedTagName($data, 'bl');
 175+ $result->setIndexedTagName($data, $this->bl_code);
128176 $result->addValue('query', $this->getModuleName(), $data);
129177 }
130178 }
131179
132180 protected function processContinue($continue, $redirect) {
133181 $pageSet = $this->getPageSet();
134 - $count = $pageSet->getGoodTitleCount();
 182+ $count = $pageSet->getTitleCount();
135183 if (!is_null($continue)) {
136184 if ($count !== 0)
137 - $this->dieUsage('When continuing the backlink query, no other titles may be provided', 'titles_on_continue');
 185+ $this->dieUsage("When continuing the {$this->getModuleName()} query, no other titles may be provided", 'titles_on_continue');
138186 $this->parseContinueParam($continue, $redirect);
139187
140188 // Skip all completed links
@@ -141,46 +189,61 @@
142190
143191 } else {
144192 if ($count !== 1)
145 - $this->dieUsage('Backlinks requires one title to start the query', 'bad_title_count');
146 - $this->rootTitle = array_pop($pageSet->getGoodTitles()); // only one title there
 193+ $this->dieUsage("The {$this->getModuleName()} query requires one title to start", 'bad_title_count');
 194+ $this->rootTitle = current($pageSet->getTitles()); // only one title there
147195 }
 196+
 197+ // only image titles are allowed for the root
 198+ if (!$this->hasNS && $this->rootTitle->getNamespace() !== NS_IMAGE)
 199+ $this->dieUsage("The title for {$this->getModuleName()} query must be an image", 'bad_image_title');
148200 }
149201
150202 protected function parseContinueParam($continue, $redirect) {
151 - //
152 - // the parameter will be in the format:
153 - // ns|db_key|step|level|ns|db_key
154 - // ns+db_key -- the root title
155 - // step = 1 or 2 - which step to continue from - 1-titles, 2-redirects
156 - // level -- how many levels to follow before starting enumerating.
157 - // ns+title to continue from
158 - //
159203 $continueList = explode('|', $continue);
160 - if (count($continueList) === 7) {
161 - $rootNs = intval($continueList[0]);
162 - if (($rootNs !== 0 || $continueList[0] === '0') && !empty ($continueList[1])) {
163 - $this->rootTitle = Title :: makeTitleSafe($rootNs, $continueList[1]);
164 - if ($this->rootTitle && $this->rootTitle->userCanRead()) {
 204+ if ($redirect) {
 205+ //
 206+ // expected redirect-mode parameter:
 207+ // ns|db_key|step|level|ns|db_key|id
 208+ // ns+db_key -- the root title
 209+ // step = 1 or 2 - which step to continue from - 1-titles, 2-redirects
 210+ // level -- how many levels to follow before starting enumerating.
 211+ // if level > 0 -- ns+title to continue from, otherwise skip these
 212+ // id = last page_id to continue from
 213+ //
 214+ if (count($continueList) > 4) {
 215+ $rootNs = intval($continueList[0]);
 216+ if (($rootNs !== 0 || $continueList[0] === '0') && !empty ($continueList[1])) {
 217+ $this->rootTitle = Title :: makeTitleSafe($rootNs, $continueList[1]);
 218+ if ($this->rootTitle && $this->rootTitle->userCanRead()) {
165219
166 - $step = intval($continueList[2]);
167 - if ($step === 1 || $step === 2) {
168 - $this->contRedirs = ($step === 2);
 220+ $step = intval($continueList[2]);
 221+ if ($step === 1 || $step === 2) {
 222+ $this->contRedirs = ($step === 2);
169223
170 - $level = intval($continueList[3]);
171 - if ($level !== 0 || $continueList[3] === '0') {
172 - $this->contLevel = $level;
 224+ $level = intval($continueList[3]);
 225+ if ($level !== 0 || $continueList[3] === '0') {
 226+ $this->contLevel = $level;
173227
174 - $contNs = intval($continueList[4]);
175 - if (($contNs !== 0 || $continueList[4] === '0') && !empty ($continueList[5])) {
176 - $this->contTitle = Title :: makeTitleSafe($contNs, $continueList[5]);
 228+ if ($level === 0) {
 229+ if (count($continueList) === 5) {
 230+ $contID = intval($continueList[4]);
 231+ if ($contID !== 0 || $continueList[4] === '0') {
 232+ $this->contID = $contID;
 233+ return; // done
 234+ }
 235+ }
 236+ } else {
 237+ if (count($continueList) === 7) {
 238+ $contNs = intval($continueList[4]);
 239+ if (($contNs !== 0 || $continueList[4] === '0') && !empty ($continueList[5])) {
 240+ $this->contTitle = Title :: makeTitleSafe($contNs, $continueList[5]);
177241
178 - $contID = intval($continueList[6]);
179 - if ($contID !== 0 || $continueList[6] === '0') {
180 - $this->contID = $contID;
181 -
182 - // When not processing redirects, only page through the non-redirects
183 - if ($redirect || ($step === 1 && $level === 0 && $this->contTitle && $this->contTitle->userCanRead() && $this->contID > 0)) {
184 - return; // done
 242+ $contID = intval($continueList[6]);
 243+ if ($contID !== 0 || $continueList[6] === '0') {
 244+ $this->contID = $contID;
 245+ return; // done
 246+ }
 247+ }
185248 }
186249 }
187250 }
@@ -188,11 +251,47 @@
189252 }
190253 }
191254 }
 255+ } else {
 256+ //
 257+ // expected non-redirect-mode parameter:
 258+ // ns|db_key|id
 259+ // ns+db_key -- the root title
 260+ // id = last page_id to continue from
 261+ //
 262+ if (count($continueList) === 3) {
 263+ $rootNs = intval($continueList[0]);
 264+ if (($rootNs !== 0 || $continueList[0] === '0') && !empty ($continueList[1])) {
 265+ $this->rootTitle = Title :: makeTitleSafe($rootNs, $continueList[1]);
 266+ if ($this->rootTitle && $this->rootTitle->userCanRead()) {
 267+
 268+ $contID = intval($continueList[2]);
 269+ if ($contID !== 0) {
 270+ $this->contID = $contID;
 271+ return; // done
 272+ }
 273+ }
 274+ }
 275+ }
192276 }
193277
194278 $this->dieUsage("Invalid continue param. You should pass the original value returned by the previous query", "_badcontinue");
195279 }
196280
 281+ protected function getContinueStr($lastPageID) {
 282+ return $this->rootTitle->getNamespace() .
 283+ '|' . $this->rootTitle->getDBkey() .
 284+ '|' . $lastPageID;
 285+ }
 286+
 287+ protected function getContinueRedirStr($isRedirPhase, $level, $ns, $title, $lastPageID) {
 288+ return $this->rootTitle->getNamespace() .
 289+ '|' . $this->rootTitle->getDBkey() .
 290+ '|' . ($isRedirPhase ? 1 : 2) .
 291+ '|' . $level .
 292+ ($level > 0 ? ('|' . $ns . '|' . $title) : '') .
 293+ '|' . $lastPageID;
 294+ }
 295+
197296 protected function getAllowedParams() {
198297
199298 $namespaces = $this->getQuery()->getValidNamespaces();
@@ -227,12 +326,22 @@
228327 }
229328
230329 protected function getExamples() {
231 - return array (
232 - 'api.php?action=query&list=backlinks&titles=Main%20Page',
233 - 'api.php?action=query&generator=backlinks&titles=Main%20Page&prop=info',
 330+ static $examples = array (
 331+ 'backlinks' => array (
 332+ "api.php?action=query&list=backlinks&titles=Main%20Page",
 333+ "api.php?action=query&generator=backlinks&titles=Main%20Page&prop=info"
 334+ ),
 335+ 'embeddedin' => array (
 336+ "api.php?action=query&list=embeddedin&titles=Template:Stub",
 337+ "api.php?action=query&generator=embeddedin&titles=Template:Stub&prop=info"
 338+ ),
 339+ 'imagelinks' => array (
 340+ "api.php?action=query&list=imagelinks&titles=Image:Albert%20Einstein%20Head.jpg",
 341+ "api.php?action=query&generator=imagelinks&titles=Image:Albert%20Einstein%20Head.jpg&prop=info"
 342+ )
 343+ );
234344
235 -
236 - );
 345+ return $examples[$this->getModuleName()];
237346 }
238347
239348 public function getVersion() {
Index: trunk/phase3/includes/api/ApiPageSet.php
@@ -32,7 +32,7 @@
3333 class ApiPageSet extends ApiQueryBase {
3434
3535 private $mAllPages; // [ns][dbkey] => page_id or 0 when missing
36 - private $mGoodTitles, $mMissingTitles, $mMissingPageIDs, $mRedirectTitles, $mNormalizedTitles;
 36+ private $mTitles, $mGoodTitles, $mMissingTitles, $mMissingPageIDs, $mRedirectTitles, $mNormalizedTitles;
3737 private $mResolveRedirects, $mPendingRedirectIDs;
3838 private $mGoodRevIDs, $mMissingRevIDs;
3939
@@ -42,6 +42,7 @@
4343 parent :: __construct($query, __CLASS__);
4444
4545 $this->mAllPages = array ();
 46+ $this->mTitles = array();
4647 $this->mGoodTitles = array ();
4748 $this->mMissingTitles = array ();
4849 $this->mMissingPageIDs = array ();
@@ -89,6 +90,21 @@
9091 }
9192
9293 /**
 94+ * All Title objects provided.
 95+ * @return array of Title objects
 96+ */
 97+ public function getTitles() {
 98+ return $this->mTitles;
 99+ }
 100+
 101+ /**
 102+ * Returns the number of unique pages (not revisions) in the set.
 103+ */
 104+ public function getTitleCount() {
 105+ return count($this->mTitles);
 106+ }
 107+
 108+ /**
93109 * Title objects that were found in the database.
94110 * @return array page_id (int) => Title (obj)
95111 */
@@ -97,10 +113,10 @@
98114 }
99115
100116 /**
101 - * Returns the number of unique pages (not revisions) in the set.
 117+ * Returns the number of found unique pages (not revisions) in the set.
102118 */
103119 public function getGoodTitleCount() {
104 - return count($this->getGoodTitles());
 120+ return count($this->mGoodTitles);
105121 }
106122
107123 /**
@@ -252,6 +268,7 @@
253269
254270 $pageId = intval($row->page_id);
255271 $this->mAllPages[$row->page_namespace][$row->page_title] = $pageId;
 272+ $this->mTitles[] = $title;
256273
257274 if ($this->mResolveRedirects && $row->page_is_redirect == '1') {
258275 $this->mPendingRedirectIDs[$pageId] = $title;
@@ -366,8 +383,10 @@
367384 // The remaining titles in $remaining are non-existant pages
368385 foreach ($remaining as $ns => $dbkeys) {
369386 foreach ($dbkeys as $dbkey => $nothing) {
370 - $this->mMissingTitles[] = Title :: makeTitle($ns, $dbkey);
 387+ $title = Title :: makeTitle($ns, $dbkey);
 388+ $this->mMissingTitles[] = $title;
371389 $this->mAllPages[$ns][$dbkey] = 0;
 390+ $this->mTitles[] = $title;
372391 }
373392 }
374393 }