r13951 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r13950‎ | r13951 | r13952 >
Date:23:56, 29 April 2006
Author:yurik
Status:old
Tags:
Comment:
* "image used by" pages
* user lists
* generalized parameter reading and validation
Modified paths:
  • /trunk/extensions/BotQuery/query.php (modified) (history)

Diff [purge]

Index: trunk/extensions/BotQuery/query.php
@@ -1,25 +1,25 @@
22 <?php
33 /**
4 - * Bot Query extension for MediaWiki 1.7+
5 - *
6 - * Copyright (C) 2006 Yuri Astrakhan <FirstnameLastname@gmail.com>
7 - * Uses bits from the original query.php code written by Tim Starling.
8 - *
9 - * This program is free software; you can redistribute it and/or modify
10 - * it under the terms of the GNU General Public License as published by
11 - * the Free Software Foundation; either version 2 of the License, or
12 - * (at your option) any later version.
13 - *
14 - * This program is distributed in the hope that it will be useful,
15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 - * GNU General Public License for more details.
18 - *
19 - * You should have received a copy of the GNU General Public License along
20 - * with this program; if not, write to the Free Software Foundation, Inc.,
21 - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 - * http://www.gnu.org/copyleft/gpl.html
23 - */
 4+* Bot Query extension for MediaWiki 1.7+
 5+*
 6+* Copyright (C) 2006 Yuri Astrakhan <FirstnameLastname@gmail.com>
 7+* Uses bits from the original query.php code written by Tim Starling.
 8+*
 9+* This program is free software; you can redistribute it and/or modify
 10+* it under the terms of the GNU General Public License as published by
 11+* the Free Software Foundation; either version 2 of the License, or
 12+* (at your option) any later version.
 13+*
 14+* This program is distributed in the hope that it will be useful,
 15+* but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 17+* GNU General Public License for more details.
 18+*
 19+* You should have received a copy of the GNU General Public License along
 20+* with this program; if not, write to the Free Software Foundation, Inc.,
 21+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 22+* http://www.gnu.org/copyleft/gpl.html
 23+*/
2424
2525
2626 define( 'MEDIAWIKI', true );
@@ -42,7 +42,8 @@
4343 define( 'GEN_MIME', 1 );
4444 define( 'GEN_ISMETA', 1 );
4545 define( 'GEN_PARAMS', 2 );
46 -define( 'GEN_DESC', 3 );
 46+define( 'GEN_DEFAULTS', 3 );
 47+define( 'GEN_DESC', 4 );
4748
4849 $db =& wfGetDB( DB_SLAVE );
4950 $bqp = new BotQueryProcessor( $db );
@@ -59,10 +60,14 @@
6061 * 0) Function to call
6162 * 1) mime type
6263 * 2) array of accepted parameters
63 - * 3) Format description
 64+ * 3) array of default parameter values
 65+ * 4) Format description
6466 */
6567 var $outputGenerators = array(
66 - 'xml' => array( 'printXML', 'text/xml', array('xmlindent','nousage'), array(
 68+ 'xml' => array( 'printXML', 'text/xml',
 69+ array('xmlindent', 'nousage'),
 70+ array(null, null),
 71+ array(
6772 "XML format",
6873 "Optional indentation can be enabled by supplying 'xmlindent' parameter.",
6974 "Errors will return this usage screen, unless 'nousage' parameter is given.",
@@ -70,29 +75,32 @@
7176 "Please use other browsers or switch to html format while debuging.",
7277 "Example: query.php?what=info&format=xml",
7378 )),
74 - 'html'=> array( 'printHTML', 'text/html', array('nousage'), array(
 79+ 'html'=> array( 'printHTML', 'text/html',
 80+ array('nousage'),
 81+ array(null),
 82+ array(
7583 "HTML format",
7684 "The data is presented as an indented syntax-highlighted XML format.",
7785 "Errors will return this usage screen, unless 'nousage' parameter is given.",
7886 "Example: query.php?what=info&format=html",
7987 )),
80 - 'txt' => array( 'printHumanReadable', 'application/x-wiki-botquery-print_r', null, array(
 88+ 'txt' => array( 'printHumanReadable', 'application/x-wiki-botquery-print_r', null, null, array(
8189 "Human-readable format using print_r() (http://www.php.net/print_r)",
8290 "Example: query.php?what=info&format=txt",
8391 )),
84 - 'json'=> array( 'printJSON', 'application/json', null, array(
 92+ 'json'=> array( 'printJSON', 'application/json', null, null, array(
8593 "JSON format (http://en.wikipedia.org/wiki/JSON)",
8694 "Example: query.php?what=info&format=json",
8795 )),
88 - 'php' => array( 'printPHP', 'application/vnd.php.serialized', null, array(
 96+ 'php' => array( 'printPHP', 'application/vnd.php.serialized', null, null, array(
8997 "PHP serialized format using serialize() (http://www.php.net/serialize)",
9098 "Example: query.php?what=info&format=php",
9199 )),
92 - 'dbg' => array( 'printParsableCode', 'application/x-wiki-botquery-var_export', null, array(
 100+ 'dbg' => array( 'printParsableCode', 'application/x-wiki-botquery-var_export', null, null, array(
93101 "PHP source code format using var_export() (http://www.php.net/var_export)",
94102 "Example: query.php?what=info&format=dbg",
95103 )),
96 -// 'tsv' => array( 'print', 'text/tab-separated-values', null, '' ),
 104+// 'tsv' => array( 'print', 'text/tab-separated-values', null, null, '' ),
97105 );
98106
99107 /**
@@ -100,53 +108,73 @@
101109 * 0) Function to call
102110 * 1) true/false - does this property work on individual pages? (false for site's metadata)
103111 * 2) array of accepted parameters
104 - * 3) Format description
 112+ * 3) array of default parameter values
 113+ * 4) Format description
105114 */
106115 var $propGenerators = array(
107116
108117 // Site-wide Generators
109 - 'info' => array( "genMetaSiteInfo", true, null, array(
 118+ 'info' => array( "genMetaSiteInfo", true, null, null, array(
110119 "General site information",
111120 "Example: query.php?what=info",
112121 )),
113 - 'namespaces' => array( "genMetaNamespaceInfo", true, null, array(
 122+ 'namespaces' => array( "genMetaNamespaceInfo", true, null, null, array(
114123 "List of localized namespace names",
115124 "Example: query.php?what=namespaces",
116125 )),
117 - 'userinfo' => array( "genMetaUserInfo", true, null, array(
 126+ 'userinfo' => array( "genMetaUserInfo", true, null, null, array(
118127 "Information about current user",
119128 "Example: query.php?what=userinfo",
120129 )),
121 - 'recentchanges' => array( "genMetaRecentChanges", true, array( 'rcfrom','rclimit','rchide' ), array(
 130+ 'recentchanges' => array( "genMetaRecentChanges", true,
 131+ array( 'rcfrom', 'rclimit', 'rchide' ),
 132+ array( null, 50, array(null, 'minor', 'bots', 'anons', 'liu') ),
 133+ array(
122134 "Adds recently changed articles to the output list.",
123135 "Parameters supported:",
124136 "rcfrom - Timestamp of the first entry to start from. The list order reverses.",
125137 "rclimit - how many total links to return.",
126138 " Smaller size is possible if pages changes multiple times.",
127 - "rchide - Which entries to ignore 'minor','bots','anons','liu' (loged-in users).",
 139+ "rchide - Which entries to ignore 'minor', 'bots', 'anons', 'liu' (loged-in users).",
128140 " Cannot specify both anons and liu.",
129141 "Example: query.php?what=recentchanges&rchide=liu|bots",
130142 )),
131 - 'dblredirects' => array( "genMetaDoubleRedirects", true, null, array(
 143+ 'users' => array( "genUserPages", true,
 144+ array( 'usfrom', 'uslimit' ),
 145+ array( null, 50 ),
 146+ array(
 147+ "Adds user pages to the output list.",
 148+ "Parameters supported:",
 149+ "usfrom - Start user listing from...",
 150+ "uslimit - how many total links to return.",
 151+ "Example: query.php?what=users&usfrom=Y",
 152+ )),
 153+ 'dblredirects' => array( "genMetaDoubleRedirects", true,
 154+ array('dfoffset', 'drlimit'),
 155+ array(null, 50),
 156+ array(
132157 "List of double-redirect pages",
133158 "THIS QUERY IS CURRENTLY DISABLED DUE TO PERFORMANCE REASONS",
134159 "Example: query.php?what=dblredirects",
135160 )),
136161
137162 // Page-specific Generators
138 - 'links' => array( "genPageLinks", false, null, array(
 163+ 'links' => array( "genPageLinks", false, null, null, array(
139164 "List of regular page links",
140165 "Example: query.php?what=links&titles=MediaWiki|Wikipedia",
141166 )),
142 - 'langlinks' => array( "genPageLangLinks", false, null, array(
 167+ 'langlinks' => array( "genPageLangLinks", false, null, null, array(
143168 "Inter-language links",
144169 "Example: query.php?what=langlinks&titles=MediaWiki|Wikipedia",
145170 )),
146 - 'templates' => array( "genPageTemplates", false, null, array(
 171+ 'templates' => array( "genPageTemplates", false, null, null, array(
147172 "List of used templates",
148173 "Example: query.php?what=templates&titles=Main%20Page",
149174 )),
150 - 'backlinks' => array( "genPageBackLinks", false, array('blfilter','bllimit','bloffset'), array(
 175+ 'backlinks' => array( "genPageBackLinksHelper", false,
 176+ array('blfilter', 'bllimit', 'bloffset'),
 177+ array(array('existing', 'nonredirects', 'all'), 50, null),
 178+ array(
151179 "What pages link to this page(s)",
152180 "Parameters supported:",
153181 "blfilter - Of all given pages, which should be queried:",
@@ -155,7 +183,10 @@
156184 "bloffset - when too many results are found, use this to page",
157185 "Example: query.php?what=backlinks&titles=Main%20Page&bllimit=10",
158186 )),
159 - 'embeddedin' => array( "genPageEmbeddedIn", false, array('eifilter','eilimit','eioffset'), array(
 187+ 'embeddedin' => array( "genPageBackLinksHelper", false,
 188+ array('eifilter', 'eilimit', 'eioffset'),
 189+ array(array('existing', 'nonredirects', 'all'), 50, null),
 190+ array(
160191 "What pages include this page(s) as template(s)",
161192 "Parameters supported:",
162193 "eifilter - Of all given pages, which should be queried:",
@@ -166,12 +197,28 @@
167198 " Page 1: query.php?what=embeddedin&titles=Template:Stub&eilimit=10",
168199 " Page 2: query.php?what=embeddedin&titles=Template:Stub&eilimit=10&eioffset=10",
169200 )),
170 - 'revisions' => array( "genPageHistory", false, array('rvcomments','rvlimit','rvoffset'), array(
 201+ 'imagelinks' => array( "genPageBackLinksHelper", false,
 202+ array('ilfilter', 'illimit', 'iloffset'),
 203+ array(array('existing', 'nonredirects', 'all'), 50, null),
 204+ array(
 205+ "What pages use this image(s)",
 206+ "ilfilter - Of all given images, which should be queried:",
 207+ " 'nonredirects', 'existing' (default), or 'all' (including non-existant)",
 208+ "illimit - how many total links to return",
 209+ "iloffset - when too many results are found, use this to page",
 210+ "Example: query.php?what=imagelinks&titles=image:test.jpg&illimit=10",
 211+ )),
 212+ 'revisions' => array( "genPageHistory", false,
 213+ array('rvcomments', 'rvlimit', 'rvoffset', 'rvstart', 'rvend'),
 214+ array(null, 50, null, null, null),
 215+ array(
171216 "Revision history - Lists edits performed to the given pages",
172217 "Parameters supported:",
173218 "rvcomments - if specified, the result will include summary strings",
174219 "rvlimit - how many links to return *for each title*",
175220 "rvoffset - when too many results are found, use this to page",
 221+ "rvstart - timestamp of the earliest entry",
 222+ "rvend - timestamp of the latest entry",
176223 "Example: query.php?what=revisions&titles=Main%20Page&rvlimit=10&rvcomments",
177224 )),
178225 );
@@ -182,10 +229,13 @@
183230 $this->data = array();
184231 $this->requestsize = 0;
185232 $this->db = $db;
186 - $this->format = 'html'; // set it here because if parseFormat fails, it should still output something
 233+
 234+ $this->format = 'html'; // set it here because if parseFormat fails, the usage output rilies on this variable
187235 $this->format = $this->parseFormat( $wgRequest->getVal('format', 'html') );
188 - $this->properties = $this->parseMultiValue( 'what', null, array_keys( $this->propGenerators ) );
189236
 237+ $allProperties = array_merge(array(null), array_keys( $this->propGenerators ));
 238+ $this->properties = $this->parseMultiValue( 'what', $allProperties );
 239+
190240 // Neither one of these variables is referenced directly!
191241 // Meta generators may append titles or pageids to these varibales.
192242 // Do not modify this values directly - use the AddRaw() method
@@ -213,7 +263,7 @@
214264 function callGenerators( $callMetaGenerators ) {
215265 foreach( $this->propGenerators as $property => &$generator ) {
216266 if( $generator[GEN_ISMETA] === $callMetaGenerators && in_array( $property, $this->properties )) {
217 - $this->{$generator[GEN_FUNCTION]}();
 267+ $this->{$generator[GEN_FUNCTION]}($property, $generator);
218268 }
219269 }
220270 }
@@ -263,10 +313,10 @@
264314 }
265315 }
266316
267 - function parseMultiValue( $valueName, $defaultValue, $allowedValues ) {
 317+ function parseMultiValue( $valueName, $allowedValues ) {
268318 global $wgRequest;
269319
270 - $values = $wgRequest->getVal($valueName, $defaultValue);
 320+ $values = $wgRequest->getVal($valueName, $allowedValues[0]);
271321 $valuesList = explode( '|', $values );
272322 $unknownValues = array_diff( $valuesList, $allowedValues);
273323 if( $unknownValues ) {
@@ -339,15 +389,7 @@
340390 //
341391 // User restrictions
342392 //
343 - if( $wgUser->isBot() ) {
344 - if ( $this->requestsize > 1000 ) {
345 - $this->dieUsage( 'Bots may not request over 1000 pages', 'pi_botquerytoobig' );
346 - }
347 - } else {
348 - if( $this->requestsize > 20 ) {
349 - $this->dieUsage( 'Users may not request over 20 pages', 'pi_userquerytoobig' );
350 - }
351 - }
 393+ $this->validateLimit( 'pi_botquerytoobig', $this->requestsize, 50, 1000 );
352394
353395 //
354396 // Make sure that this->data['pages'] is empty
@@ -440,7 +482,7 @@
441483 return true; // success
442484 }
443485
444 - function genMetaSiteInfo() {
 486+ function genMetaSiteInfo(&$prop, &$genInfo) {
445487 global $wgSitename, $wgVersion, $wgCapitalLinks;
446488 $meta = array();
447489 $mainPage = Title::newFromText( wfMsgForContent( 'mainpage' ) );
@@ -454,7 +496,7 @@
455497 $this->data['meta']['site'] = $meta;
456498 }
457499
458 - function genMetaNamespaceInfo() {
 500+ function genMetaNamespaceInfo(&$prop, &$genInfo) {
459501 global $wgContLang;
460502 $meta = array();
461503 $meta['_element'] = 'ns';
@@ -464,7 +506,7 @@
465507 $this->data['meta']['namespaces'] = $meta;
466508 }
467509
468 - function genMetaUserInfo() {
 510+ function genMetaUserInfo(&$prop, &$genInfo) {
469511 global $wgUser;
470512
471513 $meta = array();
@@ -479,31 +521,21 @@
480522 $this->data['meta']['user'] = $meta;
481523 }
482524
483 - function genMetaRecentChanges() {
484 - global $wgRequest;
 525+ function genMetaRecentChanges(&$prop, &$genInfo) {
485526
486 - # Get last modified date, for client caching
487 - $from = $wgRequest->getVal( 'rcfrom' );
488 - $limit = $wgRequest->getInt( 'rclimit', 20 );
489 - $hide = $this->parseMultiValue( 'rchide', '', array('','minor','bots','anons','liu') );
490 -
 527+ extract( $this->getParams( $prop, $genInfo ));
491528 # It makes no sense to hide both anons and logged-in users
492 - # Where this occurs, force anons to be shown
493 - if( in_array('anons', $hide) && in_array('liu', $hide) ) {
 529+ if( in_array('anons', $rchide) && in_array('liu', $rchide) ) {
494530 $this->dieUsage( "Both 'anons' and 'liu' cannot be given for 'rchide' parameter", 'rc_badrchide' );
495531 }
 532+ $this->validateLimit( 'rc_badrclimit', $rclimit, 100, 5000 );
496533
497 - $conds = array();
498 -
499 - if ( $from != '' ) {
500 - $conds[] = 'rev_timestamp >= ' . $this->prepareTimestamp($from);
 534+ $conds = array();
 535+ if ( $rcfrom != '' ) {
 536+ $conds[] = 'rev_timestamp >= ' . $this->prepareTimestamp($rcfrom);
501537 }
502538
503 - if ( $limit < 1 || $limit > 5000 ) {
504 - $this->dieUsage( "Invalid rclimit value '$limit' - must be between 1 and 5000", 'rc_badrclimit' );
505 - }
506 -
507 - foreach( $hide as &$elem ) {
 539+ foreach( $rchide as &$elem ) {
508540 switch( $elem ) {
509541 case '': // nothing
510542 break;
@@ -524,8 +556,8 @@
525557 }
526558 }
527559
528 - $options = array( 'USE INDEX' => 'rc_timestamp', 'LIMIT' => $limit );
529 - $options['ORDER BY'] = 'rc_timestamp' . ( $from != '' ? '' : ' DESC' );
 560+ $options = array( 'USE INDEX' => 'rc_timestamp', 'LIMIT' => $rclimit );
 561+ $options['ORDER BY'] = 'rc_timestamp' . ( $rcfrom != '' ? '' : ' DESC' );
530562
531563 $res = $this->db->select(
532564 'recentchanges',
@@ -542,34 +574,56 @@
543575 $this->db->freeResult( $res );
544576 }
545577
546 - function genMetaDoubleRedirects() {
547 - global $wgRequest, $wgUser;
 578+ function genUserPages(&$prop, &$genInfo) {
 579+ global $wgContLang;
 580+
 581+ extract( $this->getParams( $prop, $genInfo ));
548582
 583+ $res = $this->db->select(
 584+ 'user',
 585+ 'user_name',
 586+ "user_name >= '$usfrom'",
 587+ $this->classname . '::genUserPages',
 588+ array( 'ORDER BY' => 'user_name', 'LIMIT' => $uslimit )
 589+ );
 590+
 591+ $userNS = $wgContLang->getNsText(NS_USER);
 592+ if( !$userNS ) $userNS = 'User';
 593+ $userNS .= ':';
 594+
 595+ while ( $row = $this->db->fetchObject( $res ) ) {
 596+ $this->addRaw( 'titles', $userNS . $row->user_name );
 597+ }
 598+ $this->db->freeResult( $res );
 599+ }
 600+
 601+ function genMetaDoubleRedirects(&$prop, &$genInfo) {
 602+ global $wgUser;
 603+
549604 $this->dieUsage( "DoubleRedirect generator is disabled until caching is implemented", 'dr_disabled' );
550605
551606 if( !$wgUser->isBot() ) {
552607 $this->dieUsage( "Only bots are allowed to query for double-redirects", 'dr_notbot' );
553608 }
554609
 610+ extract( $this->getParams( $prop, $genInfo ));
555611 extract( $this->db->tableNames( 'page', 'pagelinks' ) );
556612
557 - $offset = $wgRequest->getInt( 'droffset', 0 );
558 - $limit = $wgRequest->getInt( 'drlimit', 50 );
559613 $sql = "SELECT " .
560 - " pa.page_id id_a," .
561 - " pb.page_id id_b," .
562 - " pc.page_id id_c" .
 614+ " pa.page_id id_a," .
 615+ " pb.page_id id_b," .
 616+ " pc.page_id id_c" .
563617 " FROM $pagelinks AS la, $pagelinks AS lb, $page AS pa, $page AS pb, $page AS pc" .
564618 " WHERE pa.page_is_redirect=1 AND pb.page_is_redirect=1" .
565 - " AND la.pl_from=pa.page_id" .
566 - " AND la.pl_namespace=pb.page_namespace" .
567 - " AND la.pl_title=pb.page_title" .
568 - " AND lb.pl_from=pb.page_id" .
569 - " AND lb.pl_namespace=pc.page_namespace" .
570 - " AND lb.pl_title=pc.page_title" .
571 - " LIMIT $limit";
572 - if( $offset > 0 ) {
573 - $sql .= " OFFSET $offset";
 619+ " AND la.pl_from=pa.page_id" .
 620+ " AND la.pl_namespace=pb.page_namespace" .
 621+ " AND la.pl_title=pb.page_title" .
 622+ " AND lb.pl_from=pb.page_id" .
 623+ " AND lb.pl_namespace=pc.page_namespace" .
 624+ " AND lb.pl_title=pc.page_title" .
 625+ " LIMIT $drlimit";
 626+ if( isset($droffset) ) {
 627+ $sql .= " OFFSET $droffset";
574628 }
575629
576630 // Add found page ids to the list of requested ids - they will be auto-populated later
@@ -581,7 +635,7 @@
582636 $this->db->freeResult( $res );
583637 }
584638
585 - function genPageLangLinks() {
 639+ function genPageLangLinks(&$prop, &$genInfo) {
586640 if( !$this->nonRedirPageIds ) {
587641 return;
588642 }
@@ -596,7 +650,7 @@
597651 $this->db->freeResult( $res );
598652 }
599653
600 - function genPageTemplates() {
 654+ function genPageTemplates(&$prop, &$genInfo) {
601655 if( !$this->nonRedirPageIds ) {
602656 return;
603657 }
@@ -630,24 +684,15 @@
631685 $this->addPageSubElement( $row->pl_from, 'links', 'l', $this->getLinkInfo( $row->pl_namespace, $row->pl_title ));
632686 }
633687 $this->db->freeResult( $res );
634 - }
635 -
636 - function genPageBackLinks() {
637 - $this->genPageBackLinksHelper( 'backlinks' );
638 - }
 688+ }
639689
640 - function genPageEmbeddedIn() {
641 - $this->genPageBackLinksHelper( 'embeddedin' );
642 - }
643 -
644690 /**
645691 * Generate backlinks for either links, templates, or both
646692 * $type - either 'template' or 'page'
647693 */
648 - function genPageBackLinksHelper( $type ) {
649 - global $wgRequest;
650 -
651 - switch( $type ) {
 694+ function genPageBackLinksHelper(&$prop, &$genInfo) {
 695+ $isImage = false;
 696+ switch( $prop ) {
652697 case 'embeddedin' :
653698 $columnPrefix = 'tl'; // database column name prefix
654699 $code = 'ei'; //
@@ -658,15 +703,27 @@
659704 $code = 'bl';
660705 $linktbl = $this->db->tableName( 'pagelinks' );
661706 break;
 707+ case 'imagelinks' :
 708+ $columnPrefix = 'il';
 709+ $code = 'il';
 710+ $linktbl = $this->db->tableName( 'imagelinks' );
 711+ $isImage = true;
 712+ break;
662713 default :
663714 die("unknown type");
664715 }
665716 $pagetbl = $this->db->tableName( 'page' );
666 -
667 - $offset = $wgRequest->getInt( "{$code}offset", 0 );
668 - $limit = $wgRequest->getInt( "{$code}limit", 50 ) + 1;
669 - $filter = $wgRequest->getVal( "{$code}filter", 'existing' );
670717
 718+ $parameters = $this->getParams( $prop, $genInfo );
 719+ $offset = $parameters["{$code}offset"];
 720+ $limit = $parameters["{$code}limit"] + 1;
 721+ $filter = $parameters["{$code}filter"];
 722+ if( count($filter) != 1 ) {
 723+ $this->dieUsage( "{$code}filter must either be 'all', 'existing', or 'nonredirects'", "{$code}_badmultifilter" );
 724+ } else {
 725+ $filter = $filter[0];
 726+ }
 727+
671728 $nonredir = $existing = $all = false;
672729 switch( $filter ) {
673730 case 'all' :
@@ -684,32 +741,59 @@
685742
686743 $linkBatch = new LinkBatch;
687744 foreach( $this->data['pages'] as $key => &$page ) {
688 - if(( $key < 0 && $all && array_key_exists('_obj', $page) ) ||
689 - ( $key > 0 && ($existing || ($nonredir && !array_key_exists('redirect', $page))) )) {
690 -
 745+ if( (
 746+ ( $key < 0 && $all && array_key_exists('_obj', $page) ) ||
 747+ ( $key > 0 && ($existing || ($nonredir && !array_key_exists('redirect', $page))) )
 748+ )
 749+ &&
 750+ ( !$isImage || $page['ns'] == NS_IMAGE ) // when doing image links search, only allow NS_IMAGE
 751+ ) {
691752 $linkBatch->addObj( $page['_obj'] );
692753 }
693754 }
694755
695756 if( $linkBatch->isEmpty() ) {
696 - $this->addStatusMessage( $type, 'emptyrequest' );
 757+ $this->addStatusMessage( $prop, 'emptyrequest' );
697758 return; // Nothing to do
698759 }
 760+
 761+ if( $isImage ) {
 762+ $where = "{$columnPrefix}_to IN (";
 763+ $firstTitle = true;
 764+ foreach( $linkBatch->data[NS_IMAGE] as $dbkey => $nothing ) {
 765+ if ( $firstTitle ) {
 766+ $firstTitle = false;
 767+ } else {
 768+ $where .= ',';
 769+ }
 770+ $where .= $this->db->addQuotes( $dbkey );
 771+ }
 772+ $where .= ')';
 773+ } else {
 774+ $where = $linkBatch->constructSet( $columnPrefix, $this->db );
 775+ }
699776
700777 $sql = "SELECT"
701 - ." pfrom.page_id from_id, pfrom.page_namespace from_namespace, pfrom.page_title from_title,"
702 - ." pto.page_id to_id, {$columnPrefix}_namespace to_namespace, {$columnPrefix}_title to_title"
 778+ ." pfrom.page_id from_id, pfrom.page_namespace from_namespace,"
 779+ ." pfrom.page_title from_title, pto.page_id to_id,"
 780+ .($isImage ?
 781+ " {$columnPrefix}_to to_title" :
 782+ " {$columnPrefix}_namespace to_namespace, {$columnPrefix}_title to_title" )
703783 ." FROM"
704784 ." ("
705 - ." $linktbl INNER JOIN $pagetbl pfrom ON {$columnPrefix}_from = pfrom.page_id"
 785+ ." $linktbl INNER JOIN $pagetbl pfrom ON {$columnPrefix}_from = pfrom.page_id"
706786 ." )"
707 - ." LEFT JOIN $pagetbl pto ON {$columnPrefix}_namespace = pto.page_namespace AND {$columnPrefix}_title = pto.page_title"
708 - ." WHERE"
709 - ." " . $linkBatch->constructSet( $columnPrefix, $this->db )
 787+ ." LEFT JOIN $pagetbl pto ON"
 788+ .($isImage ?
 789+ " {$columnPrefix}_to = pto.page_title" :
 790+ " {$columnPrefix}_title = pto.page_title AND {$columnPrefix}_namespace = pto.page_namespace")
 791+ ." WHERE $where"
710792 ." ORDER BY"
711 - ." {$columnPrefix}_namespace, {$columnPrefix}_title"
 793+ .($isImage ?
 794+ " {$columnPrefix}_to" :
 795+ " {$columnPrefix}_namespace, {$columnPrefix}_title")
712796 ." LIMIT $limit"
713 - . ( $offset > 0 ? " OFFSET $offset" : "" );
 797+ . ( isset($offset) ? " OFFSET $offset" : "" );
714798
715799 $count = 0;
716800 $res = $this->db->query( $sql, $this->classname . "::genPageBackLinks_{$code}" );
@@ -721,56 +805,48 @@
722806 }
723807 $pageId = $row->to_id;
724808 if( $pageId === null ) {
725 - $pageId = $this->lookupInvalidPageId( $row->to_namespace, $row->to_title );
 809+ $pageId = $this->lookupInvalidPageId(
 810+ $isImage ? NS_IMAGE : $row->to_namespace,
 811+ $row->to_title );
726812 }
727813 $values = $this->getLinkInfo( $row->from_namespace, $row->from_title, $row->from_id );
728 - $this->addPageSubElement( $pageId, $type, $code, $values );
 814+ $this->addPageSubElement( $pageId, $prop, $code, $values );
729815 }
730816 $this->db->freeResult( $res );
731817
732818 if( $count < $limit ) {
733 - $this->addStatusMessage( $type, 'done' );
 819+ $this->addStatusMessage( $prop, 'done' );
734820 } else {
735 - $this->addStatusMessage( $type, 'havemore' );
 821+ $this->addStatusMessage( $prop, 'havemore' );
736822 }
737823 }
738824
739 - function genPageHistory() {
740 - global $wgRequest;
741 -
 825+ function genPageHistory(&$prop, &$genInfo) {
742826 if( !$this->existingPageIds ) {
743827 return;
744828 }
 829+ extract( $this->getParams( $prop, $genInfo ));
745830
746 - $includeComments = $wgRequest->getCheck('rvcomments');
747 -
748831 // select *: rev_page, rev_text_id, rev_comment, rev_user, rev_user_text, rev_timestamp, rev_minor_edit, rev_deleted
749 - $fields = array('rev_id','rev_timestamp','rev_user','rev_user_text','rev_minor_edit');
750 - if( $includeComments ) {
 832+ $fields = array('rev_id', 'rev_timestamp', 'rev_user', 'rev_user_text', 'rev_minor_edit');
 833+ if( isset($rvcomments) ) {
751834 $fields[] = 'rev_comment';
752835 }
753 -
754 - $conds = array(
755 - 'rev_deleted' => 0,
756 - );
757 -
758 - $start = $wgRequest->getVal( 'rvstart' );
759 - if ( $start != '' ) {
760 - $conds[] = 'rev_timestamp >= ' . $this->prepareTimestamp($start);
 836+ $conds = array( 'rev_deleted' => 0 );
 837+ if ( isset($rvstart) ) {
 838+ $conds[] = 'rev_timestamp >= ' . $this->prepareTimestamp($rvstart);
761839 }
762 -
763 - $end = $wgRequest->getVal( 'rvend' );
764 - if ( $end != '' ) {
765 - $conds[] = 'rev_timestamp <= ' . $this->prepareTimestamp($end);
 840+ if ( isset($rvend) ) {
 841+ $conds[] = 'rev_timestamp <= ' . $this->prepareTimestamp($rvend);
766842 }
767 -
768 - $limit = $wgRequest->getInt( 'rvlimit', 50 );
769843 $options = array(
770 - 'LIMIT' => $limit,
 844+ 'LIMIT' => $rvlimit,
771845 'ORDER BY' => 'rev_timestamp DESC'
772846 );
773 -
774 - if( $limit * count($this->existingPageIds) > 20000 ) {
 847+ if( isset($rvoffset) ) {
 848+ $options['OFFSET'] = $rvoffset;
 849+ }
 850+ if( $rvlimit * count($this->existingPageIds) > 20000 ) {
775851 $this->dieUsage( "rvlimit multiplied by number of requested titles must be less than 20000", 'rv_querytoobig' );
776852 }
777853
@@ -789,7 +865,7 @@
790866 if( $row->rev_minor_edit ) {
791867 $vals['minor'] = '';
792868 }
793 - $vals['*'] = $includeComments ? $row->rev_comment : '';
 869+ $vals['*'] = $rvcomments ? $row->rev_comment : '';
794870 $this->addPageSubElement( $pageId, 'revisions', 'rv', $vals);
795871 }
796872 $this->db->freeResult( $res );
@@ -800,6 +876,39 @@
801877 // ************************************* UTILITIES *************************************
802878 //
803879
 880+ /**
 881+ * From two parameter arrays, makes an array of the values provided by the user.
 882+ */
 883+ function getParams( &$property, &$generator ) {
 884+ global $wgRequest;
 885+
 886+ $paramNames = &$generator[GEN_PARAMS];
 887+ $paramDefaults = &$generator[GEN_DEFAULTS];
 888+ if( count($paramNames) !== count($paramDefaults) ) {
 889+ die("Internal error: '$property' param count mismatch");
 890+ }
 891+ $results = array();
 892+ for( $i = 0; $i < count($paramNames); $i++ ) {
 893+ $param = &$paramNames[$i];
 894+ $dflt = &$paramDefaults[$i];
 895+ switch( gettype($dflt) ) {
 896+ case 'NULL':
 897+ case 'string':
 898+ $result = $wgRequest->getVal( $param, $dflt );
 899+ break;
 900+ case 'integer':
 901+ $result = $wgRequest->getInt( $param, $dflt );
 902+ break;
 903+ case 'array':
 904+ $result = $this->parseMultiValue( $param, $dflt );
 905+ break;
 906+ default:
 907+ die('Internal error: unprocessed type ' . gettype($dflt));
 908+ }
 909+ $results[$param] = $result;
 910+ }
 911+ return $results;
 912+ }
804913
805914 /**
806915 * Lookup of the page id by ns:title in the data array. Very slow - lookup by id if possible.
@@ -986,6 +1095,24 @@
9871096 }
9881097 }
9891098 }
 1099+
 1100+ function validateLimit( $varname, &$value, $max, $botMax = false, $min = 1 ) {
 1101+ global $wgUser;
 1102+ if( !$botMax ) $botMax = $max;
 1103+
 1104+ if ( $value < $min ) {
 1105+ $this->dieUsage( "Minimum cannot be less than $min", $varname );
 1106+ }
 1107+ if( $wgUser->isBot() ) {
 1108+ if ( $value > $botMax ) {
 1109+ $this->dieUsage( "Bots may not request over $botMax pages", $varname );
 1110+ }
 1111+ } else {
 1112+ if( $this->requestsize > $max ) {
 1113+ $this->dieUsage( "Users may not request over $max pages", $varname );
 1114+ }
 1115+ }
 1116+ }
9901117 }
9911118
9921119 //
@@ -1036,7 +1163,6 @@
10371164 function echoprinter( $text ) {
10381165 echo $text;
10391166 }
1040 -
10411167 function printHumanReadable( &$data ) {
10421168 sanitizeOutputData($data);
10431169 print_r($data);
@@ -1154,4 +1280,5 @@
11551281 }
11561282 return $params;
11571283 }
 1284+
11581285 ?>

Status & tagging log