API: Add more parameter types and improve info
[lhc/web/wiklou.git] / includes / api / ApiPageSet.php
index e53e2b2..d67b184 100644 (file)
@@ -58,7 +58,7 @@ class ApiPageSet extends ApiBase {
        private $mGoodTitles = array();
        private $mMissingPages = array(); // [ns][dbkey] => fake page_id
        private $mMissingTitles = array();
-       private $mInvalidTitles = array();
+       private $mInvalidTitles = array(); // [fake_page_id] => array( 'title' => $title, 'invalidreason' => $reason )
        private $mMissingPageIDs = array();
        private $mRedirectTitles = array();
        private $mSpecialTitles = array();
@@ -96,7 +96,7 @@ class ApiPageSet extends ApiBase {
                                $v = $val;
                        }
                        if ( $flag !== null ) {
-                               $v[$flag] = '';
+                               $v[$flag] = true;
                        }
                        $result[] = $v;
                }
@@ -115,11 +115,9 @@ class ApiPageSet extends ApiBase {
                $this->mAllowGenerator = ( $flags & ApiPageSet::DISABLE_GENERATORS ) == 0;
                $this->mDefaultNamespace = $defaultNamespace;
 
-               $this->profileIn();
                $this->mParams = $this->extractRequestParams();
                $this->mResolveRedirects = $this->mParams['redirects'];
                $this->mConvertTitles = $this->mParams['converttitles'];
-               $this->profileOut();
        }
 
        /**
@@ -143,17 +141,12 @@ class ApiPageSet extends ApiBase {
         *    relevant parameters as used
         */
        private function executeInternal( $isDryRun ) {
-               $this->profileIn();
-
                $generatorName = $this->mAllowGenerator ? $this->mParams['generator'] : null;
                if ( isset( $generatorName ) ) {
                        $dbSource = $this->mDbSource;
-                       $isQuery = $dbSource instanceof ApiQuery;
-                       if ( !$isQuery ) {
+                       if ( !$dbSource instanceof ApiQuery ) {
                                // If the parent container of this pageset is not ApiQuery, we must create it to run generator
                                $dbSource = $this->getMain()->getModuleManager()->getModule( 'query' );
-                               // Enable profiling for query module because it will be used for db sql profiling
-                               $dbSource->profileIn();
                        }
                        $generator = $dbSource->getModuleManager()->getModule( $generatorName, null, true );
                        if ( $generator === null ) {
@@ -174,9 +167,6 @@ class ApiPageSet extends ApiBase {
                        $tmpPageSet->executeInternal( $isDryRun );
 
                        // populate this pageset with the generator output
-                       $this->profileOut();
-                       $generator->profileIn();
-
                        if ( !$isDryRun ) {
                                $generator->executeGenerator( $this );
                                Hooks::run( 'APIQueryGeneratorAfterExecute', array( &$generator, &$this ) );
@@ -187,17 +177,10 @@ class ApiPageSet extends ApiBase {
                                        $main->getVal( $generator->encodeParamName( $paramName ) );
                                }
                        }
-                       $generator->profileOut();
-                       $this->profileIn();
 
                        if ( !$isDryRun ) {
                                $this->resolvePendingRedirects();
                        }
-
-                       if ( !$isQuery ) {
-                               // If this pageset is not part of the query, we called profileIn() above
-                               $dbSource->profileOut();
-                       }
                } else {
                        // Only one of the titles/pageids/revids is allowed at the same time
                        $dataSource = null;
@@ -241,7 +224,6 @@ class ApiPageSet extends ApiBase {
                                }
                        }
                }
-               $this->profileOut();
        }
 
        /**
@@ -414,9 +396,22 @@ class ApiPageSet extends ApiBase {
        /**
         * Titles that were deemed invalid by Title::newFromText()
         * The array's index will be unique and negative for each item
+        * @deprecated since 1.26, use self::getInvalidTitlesAndReasons()
         * @return string[] Array of strings (not Title objects)
         */
        public function getInvalidTitles() {
+               wfDeprecated( __METHOD__, '1.26' );
+               return array_map( function ( $t ) {
+                       return $t['title'];
+               }, $this->mInvalidTitles );
+       }
+
+       /**
+        * Titles that were deemed invalid by Title::newFromText()
+        * The array's index will be unique and negative for each item
+        * @return array[] Array of arrays with 'title' and 'invalidreason' properties
+        */
+       public function getInvalidTitlesAndReasons() {
                return $this->mInvalidTitles;
        }
 
@@ -460,7 +455,7 @@ class ApiPageSet extends ApiBase {
                        $values[] = $r;
                }
                if ( !empty( $values ) && $result ) {
-                       $result->setIndexedTagName( $values, 'r' );
+                       ApiResult::setIndexedTagName( $values, 'r' );
                }
 
                return $values;
@@ -491,7 +486,7 @@ class ApiPageSet extends ApiBase {
                        );
                }
                if ( !empty( $values ) && $result ) {
-                       $result->setIndexedTagName( $values, 'n' );
+                       ApiResult::setIndexedTagName( $values, 'n' );
                }
 
                return $values;
@@ -522,7 +517,7 @@ class ApiPageSet extends ApiBase {
                        );
                }
                if ( !empty( $values ) && $result ) {
-                       $result->setIndexedTagName( $values, 'c' );
+                       ApiResult::setIndexedTagName( $values, 'c' );
                }
 
                return $values;
@@ -559,7 +554,7 @@ class ApiPageSet extends ApiBase {
                        $values[] = $item;
                }
                if ( !empty( $values ) && $result ) {
-                       $result->setIndexedTagName( $values, 'i' );
+                       ApiResult::setIndexedTagName( $values, 'i' );
                }
 
                return $values;
@@ -570,7 +565,7 @@ class ApiPageSet extends ApiBase {
         *
         * @param array $invalidChecks List of types of invalid titles to include.
         *   Recognized values are:
-        *   - invalidTitles: Titles from $this->getInvalidTitles()
+        *   - invalidTitles: Titles and reasons from $this->getInvalidTitlesAndReasons()
         *   - special: Titles from $this->getSpecialTitles()
         *   - missingIds: ids from $this->getMissingPageIDs()
         *   - missingRevIds: ids from $this->getMissingRevisionIDs()
@@ -584,7 +579,7 @@ class ApiPageSet extends ApiBase {
        ) {
                $result = array();
                if ( in_array( "invalidTitles", $invalidChecks ) ) {
-                       self::addValues( $result, $this->getInvalidTitles(), 'invalid', 'title' );
+                       self::addValues( $result, $this->getInvalidTitlesAndReasons(), 'invalid' );
                }
                if ( in_array( "special", $invalidChecks ) ) {
                        self::addValues( $result, $this->getSpecialTitles(), 'special', 'title' );
@@ -651,7 +646,7 @@ class ApiPageSet extends ApiBase {
                        );
                }
                if ( !empty( $values ) && $result ) {
-                       $result->setIndexedTagName( $values, 'rev' );
+                       ApiResult::setIndexedTagName( $values, 'rev' );
                }
 
                return $values;
@@ -678,9 +673,7 @@ class ApiPageSet extends ApiBase {
         * @param array $titles Array of Title objects
         */
        public function populateFromTitles( $titles ) {
-               $this->profileIn();
                $this->initFromTitles( $titles );
-               $this->profileOut();
        }
 
        /**
@@ -688,9 +681,7 @@ class ApiPageSet extends ApiBase {
         * @param array $pageIDs Array of page IDs
         */
        public function populateFromPageIDs( $pageIDs ) {
-               $this->profileIn();
                $this->initFromPageIds( $pageIDs );
-               $this->profileOut();
        }
 
        /**
@@ -703,9 +694,7 @@ class ApiPageSet extends ApiBase {
         * @param ResultWrapper $queryResult Query result object
         */
        public function populateFromQueryResult( $db, $queryResult ) {
-               $this->profileIn();
                $this->initFromQueryResult( $queryResult );
-               $this->profileOut();
        }
 
        /**
@@ -713,9 +702,7 @@ class ApiPageSet extends ApiBase {
         * @param array $revIDs Array of revision IDs
         */
        public function populateFromRevisionIDs( $revIDs ) {
-               $this->profileIn();
                $this->initFromRevIDs( $revIDs );
-               $this->profileOut();
        }
 
        /**
@@ -778,10 +765,8 @@ class ApiPageSet extends ApiBase {
                $set = $linkBatch->constructSet( 'page', $db );
 
                // Get pageIDs data from the `page` table
-               $this->profileDBIn();
                $res = $db->select( 'page', $this->getPageTableFields(), $set,
                        __METHOD__ );
-               $this->profileDBOut();
 
                // Hack: get the ns:titles stored in array(ns => array(titles)) format
                $this->initFromQueryResult( $res, $linkBatch->data, true ); // process Titles
@@ -812,10 +797,8 @@ class ApiPageSet extends ApiBase {
                        $db = $this->getDB();
 
                        // Get pageIDs data from the `page` table
-                       $this->profileDBIn();
                        $res = $db->select( 'page', $this->getPageTableFields(), $set,
                                __METHOD__ );
-                       $this->profileDBOut();
                }
 
                $this->initFromQueryResult( $res, $remaining, false ); // process PageIDs
@@ -921,7 +904,6 @@ class ApiPageSet extends ApiBase {
                        $where = array( 'rev_id' => $revids, 'rev_page = page_id' );
 
                        // Get pageIDs data from the `page` table
-                       $this->profileDBIn();
                        $res = $db->select( $tables, $fields, $where, __METHOD__ );
                        foreach ( $res as $row ) {
                                $revid = intval( $row->rev_id );
@@ -931,7 +913,6 @@ class ApiPageSet extends ApiBase {
                                $pageids[$pageid] = '';
                                unset( $remaining[$revid] );
                        }
-                       $this->profileDBOut();
                }
 
                $this->mMissingRevIDs = array_keys( $remaining );
@@ -948,7 +929,6 @@ class ApiPageSet extends ApiBase {
                        $fields = array( 'ar_rev_id', 'ar_namespace', 'ar_title' );
                        $where = array( 'ar_rev_id' => $this->mMissingRevIDs );
 
-                       $this->profileDBIn();
                        $res = $db->select( $tables, $fields, $where, __METHOD__ );
                        $titles = array();
                        foreach ( $res as $row ) {
@@ -956,7 +936,6 @@ class ApiPageSet extends ApiBase {
                                $titles[$revid] = Title::makeTitle( $row->ar_namespace, $row->ar_title );
                                unset( $remaining[$revid] );
                        }
-                       $this->profileDBOut();
 
                        $this->initFromTitles( $titles );
 
@@ -1012,9 +991,7 @@ class ApiPageSet extends ApiBase {
                                }
 
                                // Get pageIDs data from the `page` table
-                               $this->profileDBIn();
                                $res = $db->select( 'page', $pageFlds, $set, __METHOD__ );
-                               $this->profileDBOut();
 
                                // Hack: get the ns:titles stored in array(ns => array(titles)) format
                                $this->initFromQueryResult( $res, $linkBatch->data, true );
@@ -1033,7 +1010,6 @@ class ApiPageSet extends ApiBase {
                $lb = new LinkBatch();
                $db = $this->getDB();
 
-               $this->profileDBIn();
                $res = $db->select(
                        'redirect',
                        array(
@@ -1045,7 +1021,6 @@ class ApiPageSet extends ApiBase {
                        ), array( 'rd_from' => array_keys( $this->mPendingRedirectIDs ) ),
                        __METHOD__
                );
-               $this->profileDBOut();
                foreach ( $res as $row ) {
                        $rdfrom = intval( $row->rd_from );
                        $from = $this->mPendingRedirectIDs[$rdfrom]->getPrefixedText();
@@ -1115,17 +1090,21 @@ class ApiPageSet extends ApiBase {
 
                foreach ( $titles as $title ) {
                        if ( is_string( $title ) ) {
-                               $titleObj = Title::newFromText( $title, $this->mDefaultNamespace );
+                               try {
+                                       $titleObj = Title::newFromTextThrow( $title, $this->mDefaultNamespace );
+                               } catch ( MalformedTitleException $ex ) {
+                                       // Handle invalid titles gracefully
+                                       $this->mAllPages[0][$title] = $this->mFakePageId;
+                                       $this->mInvalidTitles[$this->mFakePageId] = array(
+                                               'title' => $title,
+                                               'invalidreason' => $ex->getMessage(),
+                                       );
+                                       $this->mFakePageId--;
+                                       continue; // There's nothing else we can do
+                               }
                        } else {
                                $titleObj = $title;
                        }
-                       if ( !$titleObj ) {
-                               // Handle invalid titles gracefully
-                               $this->mAllPages[0][$title] = $this->mFakePageId;
-                               $this->mInvalidTitles[$this->mFakePageId] = $title;
-                               $this->mFakePageId--;
-                               continue; // There's nothing else we can do
-                       }
                        $unconvertedTitle = $titleObj->getPrefixedText();
                        $titleWasConverted = false;
                        if ( $titleObj->isExternal() ) {
@@ -1226,17 +1205,20 @@ class ApiPageSet extends ApiBase {
         */
        public function populateGeneratorData( &$result, array $path = array() ) {
                if ( $result instanceof ApiResult ) {
-                       $data = $result->getData();
+                       $data = $result->getResultData( $path );
+                       if ( $data === null ) {
+                               return true;
+                       }
                } else {
                        $data = &$result;
-               }
-               foreach ( $path as $key ) {
-                       if ( !isset( $data[$key] ) ) {
-                               // Path isn't in $result, so nothing to add, so everything
-                               // "fits"
-                               return true;
+                       foreach ( $path as $key ) {
+                               if ( !isset( $data[$key] ) ) {
+                                       // Path isn't in $result, so nothing to add, so everything
+                                       // "fits"
+                                       return true;
+                               }
+                               $data = &$data[$key];
                        }
-                       $data = &$data[$key];
                }
                foreach ( $this->mGeneratorData as $ns => $dbkeys ) {
                        if ( $ns === -1 ) {
@@ -1322,8 +1304,8 @@ class ApiPageSet extends ApiBase {
                        ),
                        'generator' => array(
                                ApiBase::PARAM_TYPE => null,
-                               ApiBase::PARAM_VALUE_LINKS => array(),
                                ApiBase::PARAM_HELP_MSG => 'api-pageset-param-generator',
+                               ApiBase::PARAM_SUBMODULE_PARAM_PREFIX => 'g',
                        ),
                        'redirects' => array(
                                ApiBase::PARAM_DFLT => false,
@@ -1349,10 +1331,8 @@ class ApiPageSet extends ApiBase {
                if ( !$this->mAllowGenerator ) {
                        unset( $result['generator'] );
                } elseif ( $flags & ApiBase::GET_VALUES_FOR_HELP ) {
-                       foreach ( $this->getGenerators() as $g ) {
-                               $result['generator'][ApiBase::PARAM_TYPE][] = $g;
-                               $result['generator'][ApiBase::PARAM_VALUE_LINKS][$g] = "Special:ApiHelp/query+$g";
-                       }
+                       $result['generator'][ApiBase::PARAM_TYPE] = 'submodule';
+                       $result['generator'][ApiBase::PARAM_SUBMODULE_MAP] = $this->getGenerators();
                }
 
                return $result;
@@ -1373,13 +1353,14 @@ class ApiPageSet extends ApiBase {
                                $query = $this->getMain()->getModuleManager()->getModule( 'query' );
                        }
                        $gens = array();
+                       $prefix = $query->getModulePath() . '+';
                        $mgr = $query->getModuleManager();
                        foreach ( $mgr->getNamesWithClasses() as $name => $class ) {
                                if ( is_subclass_of( $class, 'ApiQueryGeneratorBase' ) ) {
-                                       $gens[] = $name;
+                                       $gens[$name] = $prefix . $name;
                                }
                        }
-                       sort( $gens );
+                       ksort( $gens );
                        self::$generators = $gens;
                }