r14675 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r14674‎ | r14675 | r14676 >
Date:06:16, 9 June 2006
Author:yurik
Status:old
Tags:
Comment:
* Breaking change: category is now a property to fit better with the other properties, new parameter format is used.
* Major change: any generator can now modify $this->data['pages'] object at any moment during execution, so a more modular aproach is possible
* PageInfo was split into smaller functions
* Performance optimization for genMetaAllPages and genMetaNoLangLinksPages
Modified paths:
  • /trunk/extensions/BotQuery/query.php (modified) (history)

Diff [purge]

Index: trunk/extensions/BotQuery/query.php
@@ -172,6 +172,17 @@
173173 "nlnamespaces - limits which namespace to enumerate. Default 0 (Main)",
174174 "Example: query.php?what=nolanglinks&nllimit=50",
175175 )),
 176+ 'category' => array( 'genPagesInCategory', true,
 177+ array( 'cptitle', 'cplimit', 'cpfrom' ),
 178+ array( null, 200, '' ),
 179+ array(
 180+ "Adds pages in a given category to the output list.",
 181+ "Parameters supported:",
 182+ "cptitle - A category name, either with or without the 'Category:' prefix.",
 183+ "cplimit - How many total pages (in category) to return.",
 184+ "cpfrom - The category sort key to continue paging. Starts at the begining by default.",
 185+ "Example: query.php?what=category&cptitle=Days",
 186+ )),
176187 'users' => array( 'genUserPages', true,
177188 array( 'usfrom', 'uslimit' ),
178189 array( null, 50 ),
@@ -271,6 +282,7 @@
272283 $this->totalStartTime = wfTime();
273284
274285 $this->data = array();
 286+
275287 $this->pageIdByText = array(); // reverse page ID lookup
276288 $this->requestsize = 0;
277289 $this->db = $db;
@@ -289,26 +301,33 @@
290302 $this->titles = null;
291303 $this->pageids = null;
292304 $this->normalizedTitles = array();
 305+
 306+ // These fields contain ids useful for other generators (redirectPageIds + nonRedirPageIds == existingPageIds)
 307+ $this->existingPageIds = array(); // all existsing pages
 308+ $this->redirectPageIds = array(); // all redirect pages
 309+ $this->nonRedirPageIds = array(); // all regular, non-redirect pages
293310 }
294311
295312 /**
296313 * The core function - executes meta generators, populates basic page info, and then fills in the required additional data for all pages
297314 */
298315 function execute() {
299 -
300316 // Process metadata generators
301317 $this->callGenerators( true );
302 -
303 - // Query page table and initialize page ids.
304 - if( $this->genPageInfo() ) {
305 - // Process page-related generators
306 - $this->callGenerators( false );
307 - }
 318+ // Process 'titles' and 'pageids' parameters, and any other pages assembled by meta generators
 319+ $this->genPageInfo();
 320+ // Process page-related generators
 321+ $this->callGenerators( false );
308322
309 - // Report empty query
310 - if( !$this->data ) {
 323+ // Report empty query - if pages and meta elements have no subelements
 324+ if( ( !array_key_exists('pages', $this->data) || count($this->data['pages']) === 0 ) &&
 325+ ( !array_key_exists('meta', $this->data) || count($this->data['meta']) === 0 ) ) {
311326 $this->dieUsage( 'Nothing to do', 'emptyresult' );
312327 }
 328+ // All items under 'pages' will be presented as 'page' xml elements
 329+ if( array_key_exists('pages', $this->data) && count($this->data['pages']) > 0 ) {
 330+ $this->data['pages']['_element'] = 'page';
 331+ }
313332 }
314333
315334 /**
@@ -409,213 +428,75 @@
410429 * As the result of this method, $this->redirectPageIds and existingPageIds (arrays) will be available for other generators.
411430 */
412431 function genPageInfo() {
413 - global $wgUser, $wgRequest;
414432 $this->startProfiling();
415433 $where = array();
416 -
417 - //
418 - // Pages in a category
419 - //
420 - $categoryName = $wgRequest->getVal('category');
421 - if( $categoryName !== null ) {
422 - $categoryObj = &Title::newFromText( $categoryName );
423 - if( !$categoryObj ||
424 - ($categoryObj->getNamespace() !== NS_MAIN && $categoryObj->getNamespace() !== NS_CATEGORY) ||
425 - $categoryObj->isExternal() ) {
426 - $this->dieUsage( "bad category name $categoryName", 'pi_invalidcategory' );
427 - }
428 - // TODO: Should we check if the user has the rights to view this category?
 434+
 435+ // Assemble a list of titles to process. This method will modify $where and $this->requestsize
 436+ $nonexistentPages = &$this->parseTitles( $where );
 437+
 438+ // Assemble a list of pageids to process. This method will modify $where and $this->requestsize
 439+ $pageids = &$this->parsePageIds( $where );
 440+
 441+ // Have anything to do?
 442+ if( $this->requestsize > 0 ) {
 443+ // Validate limits
 444+ $this->validateLimit( 'pi_botquerytoobig', $this->requestsize, 500, 20000 );
429445
430 - $conds = array( 'cl_to' => $categoryObj->getDBkey() );
431 - $cpfrom = $wgRequest->getVal('cpfrom');
432 - if ( $cpfrom != '' ) {
433 - $conds[] = 'cl_sortkey >= ' . $this->db->addQuotes($cpfrom);
434 - }
435 - $cplimit = $wgRequest->getInt( 'cplimit', 200 );
436 - $this->validateLimit( 'pi_badcplimit', $cplimit, 500, 5000 );
437 -
 446+ // Query page information with the given lists of titles & pageIDs
438447 $this->startDbProfiling();
439 - $res = $this->db->select( 'categorylinks',
440 - array( 'cl_from', 'cl_sortkey' ),
441 - $conds,
442 - $this->classname . '::genPageInfoCategories',
443 - array( 'ORDER BY' => 'cl_sortkey', 'LIMIT' => $cplimit+1 ));
444 - $this->endDbProfiling('pageInfoCat');
445 - $count = 0;
446 - while ( $row = $this->db->fetchObject( $res ) ) {
447 - if( ++$count > $cplimit ) {
448 - // We've reached the one extra which shows that there are additional pages to be had. Stop here...
449 - $this->addStatusMessage( 'category', array('next' => $row->cl_sortkey) );
450 - break;
 448+ $res = $this->db->select(
 449+ 'page',
 450+ array( 'page_id', 'page_namespace', 'page_title', 'page_is_redirect', 'page_touched', 'page_latest' ),
 451+ $this->db->makeList( $where, LIST_OR ),
 452+ $this->classname . '::genPageInfo' );
 453+ $this->endDbProfiling('pageInfo');
 454+
 455+ while( $row = $this->db->fetchObject( $res ) ) {
 456+ $this->storePageInfo( $row );
 457+ if( $nonexistentPages !== null ) {
 458+ unset( $nonexistentPages[$row->page_namespace][$row->page_title] ); // Strike out link
451459 }
452 - $this->addRaw( 'pageids', $row->cl_from );
453460 }
454461 $this->db->freeResult( $res );
455 - }
456 -
457 - //
458 - // List of titles
459 - //
460 - $titles = $this->addRaw( 'titles', $wgRequest->getVal('titles') );
461 - if( $titles !== null ) {
462 - $titles = explode( '|', $titles );
463 - $linkBatch = new LinkBatch;
464 - foreach ( $titles as &$titleString ) {
465 - $titleObj = &Title::newFromText( $titleString );
466 - if ( !$titleObj ) {
467 - $this->dieUsage( "bad title $titleString", 'pi_invalidtitle' );
 462+
 463+ // Create records for non-existent page IDs
 464+ if( $pageids !== null ) {
 465+ foreach( array_diff_key($pageids, $this->existingPageIds) as $pageid ) {
 466+ $data = &$this->data['pages'][$pageid];
 467+ $data['id'] = 0;
 468+ $data['badId'] = $pageid;
468469 }
469 - if ( !$titleObj->userCanRead() ) {
470 - $this->dieUsage( "No read permission for $titleString", 'pi_titleaccessdenied' );
471 - }
472 - $linkBatch->addObj( $titleObj );
473 -
474 - // Make sure we remember the original title that was given to us
475 - // This way the caller can correlate new titles with the originally requested if they change namespaces, etc
476 - if( $titleString !== $titleObj->getPrefixedText() ) {
477 - $this->normalizedTitles[$titleString] = $titleObj;
478 - }
479470 }
480 - if ( $linkBatch->isEmpty() ) {
481 - $this->dieUsage( "no titles could be found", 'pi_novalidtitles' );
482 - }
483 - // Create a list of pages to query
484 - $where[] = $linkBatch->constructSet( 'page', $this->db );
485 - $this->requestsize += $linkBatch->getSize();
486471
487 - // we don't need the batch any more, data can be destroyed
488 - $nonexistentPages = &$linkBatch->data;
489 - } else {
490 - $nonexistentPages = array(); // empty data to keep unset() happy
491 - }
492 - //
493 - // List of Page IDs
494 - //
495 - $pageids = $this->addRaw( 'pageids', $wgRequest->getVal('pageids') );
496 - if ( $pageids !== null ) {
497 - $pageids = explode( '|', $pageids );
498 - $pageids = array_map( 'intval', $pageids );
499 - $pageids = array_unique($pageids);
500 - sort( $pageids, SORT_NUMERIC );
501 - if( $pageids[0] <= 0 ) {
502 - $this->dieUsage( "pageids contains a bad id", 'pi_badpageid' );
 472+ // Add entries for non-existent page titles
 473+ $i = -1;
 474+ if( $nonexistentPages !== null ) {
 475+ foreach( $nonexistentPages as $namespace => &$stuff ) {
 476+ foreach( $stuff as $dbk => &$arbitrary ) {
 477+ $title = Title::makeTitle( $namespace, $dbk );
 478+ // Must do this check even for non-existent pages, as some generators can give related information
 479+ if ( !$title->userCanRead() ) {
 480+ $this->dieUsage( "No read permission for $titleString", 'pi_nopageaccessdenied' );
 481+ }
 482+ $data = &$this->data['pages'][$i];
 483+ $this->pageIdByText[$title->getPrefixedText()] = $i;
 484+ $data['_obj'] = $title;
 485+ $data['title'] = $title->getPrefixedText();
 486+ $data['ns'] = $title->getNamespace();
 487+ $data['id'] = 0;
 488+ $i--;
 489+ }
 490+ }
503491 }
504 - $where['page_id'] = $pageids;
505 - $this->requestsize += count($pageids);
506 - }
507 -
508 - // Do we have anything to do?
509 - if( $this->requestsize == 0 ) {
510 - // Do not end profiling here, as it will introduce an element to the data object, and the usage screen may not be shown.
511 - return false; // Nothing to do for any of the page generators
512 - }
513 -
514 - //
515 - // User restrictions
516 - //
517 - $this->validateLimit( 'pi_botquerytoobig', $this->requestsize, 500, 20000 );
518 -
519 - //
520 - // Make sure that this->data['pages'] is empty
521 - //
522 - if( array_key_exists('pages', $this->data) ) {
523 - die( "internal error - 'pages' should not yet exist" );
524 - }
525 - $this->data['pages'] = array();
526492
527 - //
528 - // Query page information with the given lists of titles & pageIDs
529 - //
530 - $this->redirectPageIds = array();
531 - $this->startDbProfiling();
532 - $res = $this->db->select( 'page',
533 - array( 'page_id', 'page_namespace', 'page_title', 'page_is_redirect', 'page_touched', 'page_latest' ),
534 - $this->db->makeList( $where, LIST_OR ),
535 - $this->classname . '::genPageInfo' );
536 - $this->endDbProfiling('pageInfo');
537 - while( $row = $this->db->fetchObject( $res ) ) {
538 - $title = Title::makeTitle( $row->page_namespace, $row->page_title );
539 - if ( !$title->userCanRead() ) {
540 - $this->db->freeResult( $res );
541 - $this->dieUsage( "No read permission for $titleString", 'pi_pageidaccessdenied' );
 493+ // When normalized title differs from what was given, append the given title(s)
 494+ foreach( $this->normalizedTitles as $givenTitle => &$title ) {
 495+ $data = &$this->data['pages'][$i--];
 496+ $data['title'] = $givenTitle;
 497+ $data['normalizedTitle'] = $title->getPrefixedText();
542498 }
543 - $data = &$this->data['pages'][$row->page_id];
544 - $this->pageIdByText[$title->getPrefixedText()] = $row->page_id;
545 - $data['_obj'] = $title;
546 - $data['ns'] = $title->getNamespace();
547 - $data['title'] = $title->getPrefixedText();
548 - $data['id'] = $row->page_id;
549 - $data['touched'] = $row->page_touched;
550 - $data['revid'] = $row->page_latest;
551 - if ( $row->page_is_redirect ) {
552 - $data['redirect'] = '';
553 - $this->redirectPageIds[] = $row->page_id;
554 - }
555 -
556 - // Strike out link
557 - unset( $nonexistentPages[$row->page_namespace][$row->page_title] );
558499 }
559 - $this->db->freeResult( $res );
560 -
561 - //
562 - // At this point we assume that this->data['pages'] contains ONLY valid existing entries.
563 - // Create lists that can later be used to filter other tables by page Id or other useful query strings
564 - //
565 - $this->existingPageIds = array_keys( $this->data['pages'] );
566 - $this->nonRedirPageIds = array_diff($this->existingPageIds, $this->redirectPageIds);
567 -
568 - //
569 - // Create records for non-existent page IDs
570 - //
571 - if( $pageids !== null ) {
572 - foreach( array_diff_key($pageids, $this->existingPageIds) as $pageid ) {
573 - $data = &$this->data['pages'][$pageid];
574 - $data['id'] = 0;
575 - $data['bad_id'] = $pageid;
576 - }
577 - }
578 -
579 - $this->data['pages']['_element'] = 'page';
580 -
581 - //
582 - // Add entries for non-existent page titles
583 - //
584 - $i = -1;
585 - foreach( $nonexistentPages as $namespace => &$stuff ) {
586 - foreach( $stuff as $dbk => &$arbitrary ) {
587 - $title = Title::makeTitle( $namespace, $dbk );
588 - // Must do this check even for non-existent pages, as some generators can give related information
589 - if ( !$title->userCanRead() ) {
590 - $this->dieUsage( "No read permission for $titleString", 'pi_nopageaccessdenied' );
591 - }
592 - $data = &$this->data['pages'][$i];
593 - $this->pageIdByText[$title->getPrefixedText()] = $i;
594 - $data['_obj'] = $title;
595 - $data['title'] = $title->getPrefixedText();
596 - $data['ns'] = $title->getNamespace();
597 - $data['id'] = 0;
598 - $i--;
599 - }
600 - }
601 -
602 - //
603 - // Mark redirects as such. More information can be given with 'redirects' property
604 - //
605 - foreach( $this->redirectPageIds as $pageid ) {
606 - $this->data['pages'][$pageid]['redirect'] = '';
607 - }
608 -
609 - //
610 - // When normalized title differs from what was given, append the given title(s)
611 - //
612 - foreach( $this->normalizedTitles as $givenTitle => &$title ) {
613 - $pageId = $this->pageIdByText[$title->getPrefixedText()];
614 - $data = &$this->data['pages'][$pageId]['rawTitles'];
615 - $data['_element'] = 'title';
616 - $data[] = $givenTitle;
617 - }
618500 $this->endProfiling('pageInfo');
619 - return true; // success
620501 }
621502
622503
@@ -640,7 +521,7 @@
641522 $meta['case'] = $wgCapitalLinks ? 'first-letter' : 'case-sensitive'; // "case-insensitive" option is reserved for future
642523
643524 $this->data['meta']['site'] = $meta;
644 - $this->endProfiling($prop);
 525+ $this->endProfiling( $prop );
645526 }
646527
647528 /**
@@ -655,7 +536,7 @@
656537 $meta[$ns] = array( "id"=>$ns, "*" => $title );
657538 }
658539 $this->data['meta']['namespaces'] = $meta;
659 - $this->endProfiling($prop);
 540+ $this->endProfiling( $prop );
660541 }
661542
662543 /**
@@ -679,7 +560,7 @@
680561 }
681562
682563 $this->data['meta']['user'] = $meta;
683 - $this->endProfiling($prop);
 564+ $this->endProfiling( $prop );
684565 }
685566
686567 /**
@@ -731,14 +612,14 @@
732613 $this->classname . '::genMetaRecentChanges',
733614 $options
734615 );
735 - $this->endDbProfiling($prop);
 616+ $this->endDbProfiling( $prop );
736617 while ( $row = $this->db->fetchObject( $res ) ) {
737618 if( $row->rc_cur_id != 0 ) {
738619 $this->addRaw( 'pageids', $row->rc_cur_id );
739620 }
740621 }
741622 $this->db->freeResult( $res );
742 - $this->endProfiling($prop);
 623+ $this->endProfiling( $prop );
743624 }
744625
745626 /**
@@ -759,7 +640,7 @@
760641 $this->classname . '::genUserPages',
761642 array( 'ORDER BY' => 'user_name', 'LIMIT' => $uslimit )
762643 );
763 - $this->endDbProfiling($prop);
 644+ $this->endDbProfiling( $prop );
764645
765646 $userNS = $wgContLang->getNsText(NS_USER);
766647 if( !$userNS ) $userNS = 'User';
@@ -769,7 +650,7 @@
770651 $this->addRaw( 'titles', $userNS . $row->user_name );
771652 }
772653 $this->db->freeResult( $res );
773 - $this->endProfiling($prop);
 654+ $this->endProfiling( $prop );
774655 }
775656
776657 /**
@@ -782,7 +663,6 @@
783664 global $wgContLang;
784665 $this->startProfiling();
785666 extract( $this->getParams( $prop, $genInfo ));
786 -
787667 $this->validateLimit( 'aplimit', $aplimit, 50, 1000 );
788668
789669 $ns = $wgContLang->getNsText($apnamespace);
@@ -795,11 +675,11 @@
796676 $this->startDbProfiling();
797677 $res = $this->db->select(
798678 'page',
799 - 'page_title',
 679+ array( 'page_id', 'page_namespace', 'page_title', 'page_is_redirect', 'page_touched', 'page_latest' ),
800680 array( 'page_namespace' => intval($apnamespace), 'page_title>=' . $this->db->addQuotes($apfrom) ),
801681 $this->classname . '::genMetaAllPages',
802682 array( 'USE INDEX' => 'name_title', 'LIMIT' => $aplimit+1, 'ORDER BY' => 'page_namespace, page_title' ));
803 - $this->endDbProfiling($prop);
 683+ $this->endDbProfiling( $prop );
804684
805685 // Add found page ids to the list of requested titles - they will be auto-populated later
806686 $count = 0;
@@ -809,19 +689,16 @@
810690 $this->addStatusMessage( $prop, array('next' => $row->page_title) );
811691 break;
812692 }
813 - $this->addRaw( 'titles', $ns . $row->page_title );
 693+ $this->storePageInfo( $row );
814694 }
815695 $this->db->freeResult( $res );
816 - $this->endProfiling($prop);
 696+ $this->endProfiling( $prop );
817697 }
818698
819699 /**
820700 * Add pages by the namespace without language links to the output
821701 */
822702 function genMetaNoLangLinksPages(&$prop, &$genInfo) {
823 - //
824 - // TODO: This is very inefficient - we can get the actual page information, instead we make two identical query.
825 - //
826703 global $wgContLang;
827704 $this->startProfiling();
828705 extract( $this->getParams( $prop, $genInfo ));
@@ -832,7 +709,7 @@
833710 // Find all pages without any rows in the langlinks table
834711 //
835712 $sql = 'SELECT'
836 - . ' page_id, page_title'
 713+ . ' page_id, page_namespace, page_title, page_is_redirect, page_touched, page_latest'
837714 . " FROM $page LEFT JOIN $langlinks ON page_id = ll_from"
838715 . ' WHERE'
839716 . ' ll_from IS NULL AND page_namespace=' . intval($nlnamespace) . ' AND page_title>=' . $this->db->addQuotes($nlfrom)
@@ -841,7 +718,7 @@
842719
843720 $this->startDbProfiling();
844721 $res = $this->db->query( $sql, $this->classname . '::genMetaNoLangLinksPages' );
845 - $this->endDbProfiling($prop);
 722+ $this->endDbProfiling( $prop );
846723
847724 // Add found page ids to the list of requested titles - they will be auto-populated later
848725 $count = 0;
@@ -851,12 +728,56 @@
852729 $this->addStatusMessage( $prop, array('next' => $row->page_title) );
853730 break;
854731 }
855 - $this->addRaw( 'pageids', $row->page_id );
 732+ $this->storePageInfo( $row );
856733 }
857734 $this->db->freeResult( $res );
858 - $this->endProfiling($prop);
 735+ $this->endProfiling( $prop );
859736 }
860737
 738+ /**
 739+ * Add pages in a category
 740+ */
 741+ function genPagesInCategory(&$prop, &$genInfo) {
 742+ $this->startProfiling();
 743+ extract( $this->getParams( $prop, $genInfo ));
 744+
 745+ // Validate parameters
 746+ if( $cptitle === null ) {
 747+ $this->dieUsage( "Missing category title parameter cptitle", 'cp_missingcptitle' );
 748+ }
 749+ $categoryObj = &Title::newFromText( $cptitle );
 750+ if( !$categoryObj ||
 751+ ($categoryObj->getNamespace() !== NS_MAIN && $categoryObj->getNamespace() !== NS_CATEGORY) ||
 752+ $categoryObj->isExternal() ) {
 753+ $this->dieUsage( "bad category name $cptitle", 'cp_invalidcategory' );
 754+ }
 755+ $conds = array( 'cl_to' => $categoryObj->getDBkey() );
 756+ if ( $cpfrom != '' ) {
 757+ $conds[] = 'cl_sortkey >= ' . $this->db->addQuotes($cpfrom);
 758+ }
 759+ $this->validateLimit( 'cplimit', $cplimit, 500, 5000 );
 760+
 761+ $this->startDbProfiling();
 762+ $res = $this->db->select(
 763+ 'categorylinks',
 764+ array( 'cl_from', 'cl_sortkey' ),
 765+ $conds,
 766+ $this->classname . '::genPagesInCategory',
 767+ array( 'ORDER BY' => 'cl_sortkey', 'LIMIT' => $cplimit+1 ));
 768+ $this->endDbProfiling( $prop );
 769+
 770+ $count = 0;
 771+ while ( $row = $this->db->fetchObject( $res ) ) {
 772+ if( ++$count > $cplimit ) {
 773+ // We've reached the one extra which shows that there are additional pages to be had. Stop here...
 774+ $this->addStatusMessage( 'category', array('next' => $row->cl_sortkey) );
 775+ break;
 776+ }
 777+ $this->addRaw( 'pageids', $row->cl_from );
 778+ }
 779+ $this->db->freeResult( $res );
 780+ $this->endProfiling( $prop );
 781+ }
861782
862783 //
863784 // ************************************* PAGE INFO GENERATORS *************************************
@@ -905,7 +826,8 @@
906827
907828 $this->startDbProfiling();
908829 $res = $this->db->query( $sql, $this->classname . '::genRedirectInfo' );
909 - $this->endDbProfiling('redirects');
 830+ $this->endDbProfiling( $prop );
 831+
910832 while ( $row = $this->db->fetchObject( $res ) ) {
911833 $this->addPageSubElement( $row->a_id, 'redirect', 'to', $this->getLinkInfo( $row->b_namespace, $row->b_title, $row->b_id, $row->b_is_redirect ), false);
912834 if( $row->b_is_redirect ) {
@@ -913,7 +835,7 @@
914836 }
915837 }
916838 $this->db->freeResult( $res );
917 - $this->endProfiling($prop);
 839+ $this->endProfiling( $prop );
918840 }
919841
920842 var $genPageLinksSettings = array( // database column name prefix, output element name
@@ -939,7 +861,7 @@
940862 "{$prefix}_title to_title" ),
941863 array( "{$prefix}_from" => $this->nonRedirPageIds ),
942864 $this->classname . "::genPageLinks_{$code}" );
943 - $this->endDbProfiling($prop);
 865+ $this->endDbProfiling( $prop );
944866
945867 while ( $row = $this->db->fetchObject( $res ) ) {
946868 if( $langlinks ) {
@@ -950,7 +872,7 @@
951873 $this->addPageSubElement( $row->from_id, $prop, $code, $values);
952874 }
953875 $this->db->freeResult( $res );
954 - $this->endProfiling($prop);
 876+ $this->endProfiling( $prop );
955877 }
956878
957879 var $genPageBackLinksSettings = array( // database column name prefix, output element name
@@ -1079,7 +1001,7 @@
10801002 $where,
10811003 $this->classname . "::genPageBackLinks_{$code}",
10821004 $options );
1083 - $this->endDbProfiling($prop);
 1005+ $this->endDbProfiling( $prop );
10841006
10851007 $count = 0;
10861008 while ( $row = $this->db->fetchObject( $res ) ) {
@@ -1094,7 +1016,7 @@
10951017 $this->addPageSubElement( $pageId, $prop, $code, $values );
10961018 }
10971019 $this->db->freeResult( $res );
1098 - $this->endProfiling($prop);
 1020+ $this->endProfiling( $prop );
10991021 }
11001022
11011023 /**
@@ -1173,8 +1095,8 @@
11741096 }
11751097 $this->db->freeResult( $res );
11761098 }
1177 - $this->endDbProfiling($prop);
1178 - $this->endProfiling($prop);
 1099+ $this->endDbProfiling( $prop );
 1100+ $this->endProfiling( $prop );
11791101 }
11801102
11811103 /**
@@ -1207,8 +1129,8 @@
12081130 $this->addPageSubElement( $row->rev_page, $prop, '*', Revision::getRevisionText( $row ), false);
12091131 }
12101132 $this->db->freeResult( $res );
1211 - $this->endDbProfiling($prop); // Revision::getRevisionText is also a database call, so we include them in this scope
1212 - $this->endProfiling($prop);
 1133+ $this->endDbProfiling( $prop ); // Revision::getRevisionText is also a database call, so include it in this scope
 1134+ $this->endProfiling( $prop );
12131135 }
12141136
12151137 //
@@ -1216,6 +1138,93 @@
12171139 //
12181140
12191141 /**
 1142+ * Take $row with fields from 'page' table and create needed page entries in $this->data
 1143+ */
 1144+ function storePageInfo( &$row ) {
 1145+ $title = Title::makeTitle( $row->page_namespace, $row->page_title );
 1146+ if ( !$title->userCanRead() ) {
 1147+ $this->db->freeResult( $res );
 1148+ $this->dieUsage( "No read permission for $titleString", 'pi_pageidaccessdenied' );
 1149+ }
 1150+ $pageid = $row->page_id;
 1151+ $data = &$this->data['pages'][$pageid];
 1152+ $this->pageIdByText[$title->getPrefixedText()] = $pageid;
 1153+ $data['_obj'] = $title;
 1154+ $data['ns'] = $title->getNamespace();
 1155+ $data['title'] = $title->getPrefixedText();
 1156+ $data['id'] = $pageid;
 1157+ $data['touched'] = $row->page_touched;
 1158+ $data['revid'] = $row->page_latest;
 1159+
 1160+ $this->existingPageIds[] = $pageid;
 1161+ if ( $row->page_is_redirect ) {
 1162+ $data['redirect'] = '';
 1163+ $this->redirectPageIds[] = $pageid;
 1164+ } else {
 1165+ $this->nonRedirPageIds[] = $pageid;
 1166+ }
 1167+ }
 1168+
 1169+ /**
 1170+ * Process the list of given titles, update $where and $this->requestsize, and return the data of the LinkBatch object
 1171+ */
 1172+ function parseTitles( &$where ) {
 1173+ global $wgRequest;
 1174+ $titles = $this->addRaw( 'titles', $wgRequest->getVal('titles') );
 1175+ if( $titles !== null ) {
 1176+ $titles = explode( '|', $titles );
 1177+ $linkBatch = new LinkBatch;
 1178+ foreach ( $titles as &$titleString ) {
 1179+ $titleObj = &Title::newFromText( $titleString );
 1180+ if ( !$titleObj ) {
 1181+ $this->dieUsage( "bad title $titleString", 'pi_invalidtitle' );
 1182+ }
 1183+ if ( !$titleObj->userCanRead() ) {
 1184+ $this->dieUsage( "No read permission for $titleString", 'pi_titleaccessdenied' );
 1185+ }
 1186+ $linkBatch->addObj( $titleObj );
 1187+
 1188+ // Make sure we remember the original title that was given to us
 1189+ // This way the caller can correlate new titles with the originally requested if they change namespaces, etc
 1190+ if( $titleString !== $titleObj->getPrefixedText() ) {
 1191+ $this->normalizedTitles[$titleString] = $titleObj;
 1192+ }
 1193+ }
 1194+ if ( $linkBatch->isEmpty() ) {
 1195+ $this->dieUsage( "no valid titles were given", 'pi_novalidtitles' );
 1196+ }
 1197+ // Create a list of pages to query
 1198+ $where[] = $linkBatch->constructSet( 'page', $this->db );
 1199+ $this->requestsize += $linkBatch->getSize();
 1200+
 1201+ // we don't need the batch any more, data can be destroyed
 1202+ return $linkBatch->data;
 1203+ } else {
 1204+ return null;
 1205+ }
 1206+ }
 1207+
 1208+ /**
 1209+ * Process the list of given titles, update $where and $this->requestsize, and return the data of the LinkBatch object
 1210+ */
 1211+ function parsePageIds( &$where ) {
 1212+ global $wgRequest;
 1213+ $pageids = $this->addRaw( 'pageids', $wgRequest->getVal('pageids') );
 1214+ if ( $pageids !== null ) {
 1215+ $pageids = explode( '|', $pageids );
 1216+ $pageids = array_map( 'intval', $pageids );
 1217+ $pageids = array_unique($pageids);
 1218+ sort( $pageids, SORT_NUMERIC );
 1219+ if( $pageids[0] <= 0 ) {
 1220+ $this->dieUsage( "'pageids' contains a bad id", 'pi_badpageid' );
 1221+ }
 1222+ $where['page_id'] = $pageids;
 1223+ $this->requestsize += count($pageids);
 1224+ }
 1225+ return $pageids;
 1226+ }
 1227+
 1228+ /**
12201229 * From two parameter arrays, makes an array of the values provided by the user.
12211230 */
12221231 function getParams( &$property, &$generator ) {
@@ -1410,10 +1419,6 @@
14111420 " what - What information the server should return. See properties section.",
14121421 " titles - A list of titles, separated by the pipe '|' symbol.",
14131422 " pageids - A list of page ids, separated by the pipe '|' symbol.",
1414 - " category - A category name, either with or without the 'Category:' prefix.",
1415 - " When present, all pages in the given category will be included in the output.",
1416 - " cplimit - How many total pages (in category) to return",
1417 - " cpfrom - The category sort key to continue paging. Starts at the begining by default",
14181423 " noprofile - When present, each sql query execution time will be hidden. (not implemented)",
14191424 "",
14201425 "*Examples*",
@@ -1423,10 +1428,7 @@
14241429 " query.php?format=xml&what=revisions&titles=Main_Page&rvlimit=100&rvstart=20060401000000&rvcomments",
14251430 " Get a list of 100 last revisions of the main page with comments, but only if it happened after midnight April 1st 2006",
14261431 "",
1427 - " query.php?format=xml&category=Days",
1428 - " Get a list of pages that belong to the category Days",
14291432 "",
1430 - "",
14311433 "*Supported Formats*",
14321434 $formats,
14331435 "",
@@ -1438,11 +1440,11 @@
14391441 "",
14401442 "*Credits*",
14411443 " This feature is maintained by Yuri Astrakhan (FirstnameLastname@gmail.com)",
1442 - " You can also leave your comments and suggestions at http://en.wikipedia.org/wiki/User_talk:Yurik",
 1444+ " Please leave your comments and suggestions at http://en.wikipedia.org/wiki/User_talk:Yurik",
14431445 "",
14441446 " This extension came as the result of IRC discussion between Yuri Astrakhan (en:Yurik), Tim Starling (en:Tim Starling), and Daniel Kinzler(de:Duesentrieb)",
1445 - " The extension was first implemented by Tim to provide interlanguage links and history.",
1446 - " It was later completelly rewritten by Yuri to allow for modular properties, meta information, and various formatting options.",
 1447+ " The extension was first implemented by Tim to provide interlanguage links and history summary.",
 1448+ " It was later completelly rewritten by Yuri, introducing the rest of properties, meta information, and various formatting options.",
14471449 "",
14481450 "*User Status*",
14491451 " You are " . ($wgUser->isAnon() ? "an anonymous" : "a logged-in") . " " . ($wgUser->isBot() ? "bot" : "user") . " " . $wgUser->getName(),
@@ -1552,7 +1554,6 @@
15531555 * Prints data in html format. Escapes all unsafe characters. Adds an HTML warning in the begining.
15541556 */
15551557 function printHTML( &$data ) {
1556 - global $wgRequest;
15571558 ?>
15581559 <html>
15591560 <head>

Status & tagging log