* API: revisions module fixes
authorYuri Astrakhan <yurik@users.mediawiki.org>
Fri, 29 Sep 2006 07:29:13 +0000 (07:29 +0000)
committerYuri Astrakhan <yurik@users.mediawiki.org>
Fri, 29 Sep 2006 07:29:13 +0000 (07:29 +0000)
includes/api/ApiPageSet.php
includes/api/ApiQuery.php
includes/api/ApiQueryRevisions.php

index 0a32b9a..7854e94 100644 (file)
@@ -83,7 +83,7 @@ class ApiPageSet extends ApiQueryBase {
         * Returns the number of unique pages (not revisions) in the set.
         */
        public function getPageCount() {
-               return count($this->getGoodTitles());   
+               return count($this->getGoodTitles());
        }
 
        /**
@@ -176,7 +176,7 @@ class ApiPageSet extends ApiQueryBase {
                                'pl_from' => array_keys($redirectIds
                        )), __CLASS__ . '::' . __FUNCTION__);
                        $this->profileDBOut();
-                       
+
                        while ($row = $db->fetchObject($res)) {
 
                                // Bug 7304 workaround 
@@ -199,9 +199,9 @@ class ApiPageSet extends ApiQueryBase {
                        }
                        $db->freeResult($res);
                }
-               $this->profileOut();            
+               $this->profileOut();
        }
-       
+
        /**
         * Given an array of title strings, convert them into Title objects.
         * This method validates access rights for the title, 
@@ -237,6 +237,10 @@ class ApiPageSet extends ApiQueryBase {
                return $linkBatch;
        }
 
+       public function populatePageIDs($pageids) {
+               $this->dieUsage(__FUNCTION__ . " is not implemented", 'notimplemented');
+       }
+
        public function execute() {
                $this->dieDebug("execute() is not supported on this object");
        }
index 20ec0e8..5bddbac 100644 (file)
@@ -96,44 +96,24 @@ class ApiQuery extends ApiBase {
         * #5 Execute all requested modules\r
         */\r
        public function execute() {\r
-               $meta = $prop = $list = $generator = $titles = $pageids = $revids = null;\r
+               $meta = $prop = $list = $generator = $titles = $pageids = null;\r
                $redirects = null;\r
                extract($this->extractRequestParams());\r
 \r
                //\r
                // Create and initialize PageSet\r
                //\r
-               // Only one of the titles/pageids/revids is allowed at the same time\r
                $dataSource = null;\r
-               if (isset ($titles))\r
-                       $dataSource = 'titles';\r
-               if (isset ($pageids)) {\r
-                       if (isset ($dataSource))\r
-                               $this->dieUsage("Cannot use 'pageids' at the same time as '$dataSource'", 'multisource');\r
-                       $dataSource = 'pageids';\r
-               }\r
-               if (isset ($revids)) {\r
-                       if (isset ($dataSource))\r
-                               $this->dieUsage("Cannot use 'revids' at the same time as '$dataSource'", 'multisource');\r
-                       $dataSource = 'revids';\r
-               }\r
+               if (isset ($titles) && isset($pageids))\r
+                       $this->dieUsage("At present you may not use titles= and pageids= at the same time", 'multisource');\r
 \r
                $this->mData = new ApiPageSet($this, $redirects);\r
 \r
-               switch ($dataSource) {\r
-                       case 'titles' :\r
-                               $this->mData->populateTitles($titles);\r
-                               break;\r
-                       case 'pageids' :\r
-                               $this->mData->populatePageIDs($pageids);\r
-                               break;\r
-                       case 'titles' :\r
-                               $this->mData->populateRevIDs($revids);\r
-                               break;\r
-                       default :\r
-                               // Do nothing - some queries do not need any of the data sources.\r
-                               break;\r
-               }\r
+               if (isset($titles))\r
+                       $this->mData->populateTitles($titles);\r
+\r
+               if (isset($pageids))\r
+                       $this->mData->populatePageIDs($pageids);\r
 \r
                //\r
                // If generator is provided, get a new dataset to work on\r
@@ -159,7 +139,8 @@ class ApiQuery extends ApiBase {
                foreach ($this->mData->getNormalizedTitles() as $rawTitleStr => $titleStr) {\r
                        $this->getResult()->addMessage('query', 'normalized', array (\r
                                'from' => $rawTitleStr,\r
-                               'to' => $titleStr\r
+                               'to' => $titleStr,\r
+                               '*' => ''\r
                        ), 'n');\r
                }\r
 \r
@@ -168,7 +149,8 @@ class ApiQuery extends ApiBase {
                        foreach ($this->mData->getRedirectTitles() as $titleStrFrom => $titleStrTo) {\r
                                $this->getResult()->addMessage('query', 'redirects', array (\r
                                        'from' => $titleStrFrom,\r
-                                       'to' => $titleStrTo\r
+                                       'to' => $titleStrTo,\r
+                                       '*' => ''\r
                                ), 'r');\r
                        }\r
                }\r
@@ -224,10 +206,6 @@ class ApiQuery extends ApiBase {
                        //                              GN_ENUM_TYPE => 'integer',\r
                        //                              GN_ENUM_ISMULTI => true\r
                        //                      ),\r
-                       //                      'revids' => array (\r
-                       //                              GN_ENUM_TYPE => 'integer',\r
-                       //                              GN_ENUM_ISMULTI => true\r
-                       //                      ),\r
                        'redirects' => false\r
                );\r
        }\r
@@ -280,7 +258,6 @@ class ApiQuery extends ApiBase {
                        'generator' => 'Use the output of a list as the input for other prop/list/meta items',\r
                        'titles' => 'A list of titles to work on',\r
                        'pageids' => 'A list of page IDs to work on',\r
-                       'revids' => 'A list of revision IDs to work on',\r
                        'redirects' => 'Automatically resolve redirects'\r
                );\r
        }\r
index d3129b0..4be5d7a 100644 (file)
@@ -36,7 +36,7 @@ class ApiQueryRevisions extends ApiQueryBase {
        }
 
        public function execute() {
-               $rvlimit = $rvstartid = $rvendid = $rvstart = $rvend = $rvdir = $rvprop = null;
+               $rvrevids = $rvlimit = $rvstartid = $rvendid = $rvstart = $rvend = $rvdir = $rvprop = null;
                extract($this->extractRequestParams());
 
                //
@@ -46,16 +46,30 @@ class ApiQueryRevisions extends ApiQueryBase {
                // true when ordered by timestamp from older to newer, false otherwise
                $dirNewer = ($rvdir === 'newer');
 
-               // If any of those parameters are used, we work with single page only
-               $singePageMode = ($rvlimit !== 0 || $rvstartid !== 0 || $rvendid !== 0 || $dirNewer || isset ($rvstart) || isset ($rvend));
+               // If any of those parameters are used, we can only work with a single page
+               // Enumerating revisions on multiple pages make it extremelly 
+               // difficult to manage continuations and require additional sql indexes  
+               $enumRevMode = ($rvlimit !== 0 || $rvstartid !== 0 || $rvendid !== 0 || $dirNewer || isset ($rvstart) || isset ($rvend));
 
                if ($rvstartid !== 0 || $rvendid !== 0)
                        $this->dieUsage('rvstartid/rvendid not implemented', 'notimplemented');
 
                $data = $this->getData();
                $pageCount = $data->getPageCount();
-               if ($singePageMode && $pageCount > 1)
-                       $this->dieUsage('You have supplied multiple pages, but the specified revisions parameters may only be used with one page.', 'rv_multpages');
+
+               if (!empty ($rvrevids)) {
+                       if ($pageCount > 0)
+                               $this->dieUsage('The rvrevids= parameter may not be used with titles, pageids, and generator options.', 'rv_rvrevids');
+
+                       if ($enumRevMode)
+                               $this->dieUsage('The rvrevids= parameter may not be used with the list options (rvlimit, rvstartid, rvendid, dirNewer, rvstart, rvend).', 'rv_rvrevids');
+               } else {
+                       if ($pageCount < 1)
+                               $this->dieUsage('No pages were given. Please use titles, pageids or a generator to provide page(s) to work on.', 'rv_no_pages');
+
+                       if ($enumRevMode && $pageCount > 1)
+                               $this->dieUsage('titles, pageids or a generator was used to supply multiple pages, but the rvlimit, rvstartid, rvendid, dirNewer, rvstart, and rvend parameters may only be used on a single page.', 'rv_multpages');
+               }
 
                $tables = array (
                        'revision'
@@ -97,6 +111,7 @@ class ApiQueryRevisions extends ApiQueryBase {
                                                $fields[] = 'old_id';
                                                $fields[] = 'old_text';
                                                $fields[] = 'old_flags';
+                        $showContent = true;
                                                break;
                                        default :
                                                $this->dieDebug("unknown rvprop $prop");
@@ -104,25 +119,43 @@ class ApiQueryRevisions extends ApiQueryBase {
                        }
                }
 
-               if (isset ($rvstart))
-                       $conds[] = 'rev_timestamp >= ' . $this->prepareTimestamp($rvstart);
-               if (isset ($rvend))
-                       $conds[] = 'rev_timestamp <= ' . $this->prepareTimestamp($rvend);
+               $userMax = ($showContent ? 50 : 500);
+               $botMax = ($showContent ? 200 : 10000);
+
+               if ($enumRevMode) {
 
-               if ($singePageMode) {
+                       if (isset ($rvstart))
+                               $conds[] = 'rev_timestamp >= ' . $this->prepareTimestamp($rvstart);
+                       if (isset ($rvend))
+                               $conds[] = 'rev_timestamp <= ' . $this->prepareTimestamp($rvend);
+
+                       // must manually initialize unset rvlimit
                        if (!isset ($rvlimit))
                                $rvlimit = 10;
 
-                       $options['LIMIT'] = $rvlimit + 1;
                        $options['ORDER BY'] = 'rev_timestamp' . ($dirNewer ? '' : ' DESC');
-                       
-                       // get the first (and only) pageid => title pair
-                       foreach($data->getGoodTitles() as $pageId => $titleObj) {
-                               $conds['rev_page'] = $pageId;
-                               break;
-                       }
+
+                       $this->validateLimit('rvlimit', $rvlimit, 1, $userMax, $botMax);
+
+                       // There is only one ID
+                       $conds['rev_page'] = array_keys($data->getGoodTitles());
+
+               } else {
+                       // When working in multi-page non-enumeration mode,
+                       // limit to the latest revision only
+                       $tables[] = 'page';
+                       $conds[] = 'page_id=rev_page';
+                       $conds[] = 'page_latest=rev_id';
+                       $this->validateLimit('page_count', $pageCount, 1, $userMax, $botMax);
+
+                       // Get all page IDs
+                       $conds['page_id'] = array_keys($data->getGoodTitles());
+            
+            $rvlimit = $pageCount; // assumption testing -- we should never get more then $pageCount rows.
                }
 
+        $options['LIMIT'] = $rvlimit +1;
+
                $db = $this->getDB();
                $this->profileDBIn();
                $res = $db->select($tables, $fields, $conds, __CLASS__ . '::' . __FUNCTION__, $options);
@@ -134,31 +167,32 @@ class ApiQueryRevisions extends ApiQueryBase {
 
                        if (++ $count > $rvlimit) {
                                // We've reached the one extra which shows that there are additional pages to be had. Stop here...
+                if (!$enumRevMode)
+                    $this->dieDebug('Got more rows then expected'); // bug report
+                
                                $startStr = 'rvstartid=' . $row->rev_id;
-                               $msg = array ('continue' => $startStr );
+                               $msg = array (
+                                       'continue' => $startStr
+                               );
                                $this->getResult()->addMessage('query-status', 'revisions', $msg);
                                break;
                        }
 
-
-                       $revid = intval($row->rev_id);
-                       $pageid = intval($row->rev_page);
-
                        $vals = array (
-                               'revid' => $revid,
+                               'revid' => intval($row->rev_id),
                                'oldid' => intval($row->rev_text_id
                        ));
 
-                       if( $row->rev_minor_edit ) {
+                       if ($row->rev_minor_edit) {
                                $vals['minor'] = '';
                        }
-       
+
                        if ($showTimestamp)
                                $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $row->rev_timestamp);
-       
+
                        if ($showUser) {
                                $vals['user'] = $row->rev_user_text;
-                               if( !$row->rev_user )
+                               if (!$row->rev_user)
                                        $vals['anon'] = '';
                        }
 
@@ -167,13 +201,13 @@ class ApiQueryRevisions extends ApiQueryBase {
 
                        if ($showContent) {
                                $vals['xml:space'] = 'preserve';
-                               $vals['*'] = Revision::getRevisionText( $row );
+                               $vals['*'] = Revision :: getRevisionText($row);
                        } else {
-                               $vals['*'] = '';        // Force all elements to be attributes
+                               $vals['*'] = ''; // Force all elements to be attributes
                        }
 
-                       $data[$pageid]['revisions']['_element'] = 'rv';
-                       $data[$pageid]['revisions'][$revid] = $vals;
+                       $data[$row->rev_page]['revisions']['_element'] = 'rv';
+                       $data[$row->rev_page]['revisions'][$row->rev_id] = $vals;
                }
                $db->freeResult($res);
 
@@ -182,6 +216,10 @@ class ApiQueryRevisions extends ApiQueryBase {
 
        protected function getAllowedParams() {
                return array (
+                       'rvrevids' => array (
+                               GN_ENUM_ISMULTI => true,
+                               GN_ENUM_TYPE => 'integer'
+                       ),
                        'rvlimit' => array (
                                GN_ENUM_DFLT => 0,
                                GN_ENUM_TYPE => 'limit',