* New properties: links, templates, images, langlinks
authorYuri Astrakhan <yurik@users.mediawiki.org>
Mon, 14 May 2007 05:28:06 +0000 (05:28 +0000)
committerYuri Astrakhan <yurik@users.mediawiki.org>
Mon, 14 May 2007 05:28:06 +0000 (05:28 +0000)
* Breaking Change: imagelinks renamed into imageusage (il->iu)
* Bug fix: incorrect generator behavior in some cases

RELEASE-NOTES
includes/AutoLoader.php
includes/api/ApiBase.php
includes/api/ApiMain.php
includes/api/ApiPageSet.php
includes/api/ApiQuery.php
includes/api/ApiQueryBacklinks.php
includes/api/ApiQueryBase.php
includes/api/ApiQueryImages.php [new file with mode: 0644]
includes/api/ApiQueryLangLinks.php [new file with mode: 0644]
includes/api/ApiQueryLinks.php [new file with mode: 0644]

index 67d0beb..a808ed0 100644 (file)
@@ -28,7 +28,7 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
 * Bulk mail options ($wgEnotifImpersonal, $wgEnotifUseJobQ) for large sites
 * Links to redirect pages in categories are wrapped in <span
   class="redirect-in-category"></span>
-
+  
 == Bugfixes since 1.10 ==
 
 * (bug 9712) Use Arabic comma in date/time formats for Arabic and Farsi
@@ -57,6 +57,15 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
 * (bug 9896) Documentation for $wgSquidServers and X-FORWARDED-FOR
 
 
+== MediaWiki API changes since 1.10 ==
+
+For the current progress and discussion, see http://meta.wikimedia.org/wiki/API
+
+* New properties: links, templates, images, langlinks
+* Breaking Change: imagelinks renamed into imageusage (il->iu)
+* Bug fix: incorrect generator behavior in some cases
+
+
 == Maintenance script changes since 1.10 ==
 
 * Add support for wgMaxTocLevel option in parserTests
index 82f5b3e..aee83f1 100644 (file)
@@ -291,7 +291,10 @@ function __autoload($className) {
                'ApiQueryBase' => 'includes/api/ApiQueryBase.php',
                'ApiQueryBacklinks' => 'includes/api/ApiQueryBacklinks.php',
                'ApiQueryContributions' => 'includes/api/ApiQueryUserContributions.php',
+               'ApiQueryImages' => 'includes/api/ApiQueryImages.php',
                'ApiQueryInfo' => 'includes/api/ApiQueryInfo.php',
+               'ApiQueryLangLinks' => 'includes/api/ApiQueryLangLinks.php',
+               'ApiQueryLinks' => 'includes/api/ApiQueryLinks.php',
                'ApiQueryLogEvents' => 'includes/api/ApiQueryLogEvents.php',
                'ApiQueryRecentChanges'=> 'includes/api/ApiQueryRecentChanges.php',
                'ApiQueryRevisions' => 'includes/api/ApiQueryRevisions.php',
index a8b1939..cd20e3e 100644 (file)
@@ -526,6 +526,12 @@ abstract class ApiBase {
                        ApiBase :: dieDebug(__METHOD__, 'called without calling profileDBOut() first');
                return $this->mDBTime;
        }
+       
+       public static function debugPrint($value, $name = 'unknown') {
+               print "\n\n<pre><b>Debuging value '$location':</b>\n\n";
+               var_export($value);
+               print "\n</pre>\n";
+       }
 
        public abstract function getVersion();
 
index c4d5a83..ca1e899 100644 (file)
@@ -45,9 +45,9 @@ class ApiMain extends ApiBase {
        private static $Modules = array (
                'help' => 'ApiHelp',
                'login' => 'ApiLogin',
+               'query' => 'ApiQuery',
                'opensearch' => 'ApiOpenSearch',
-               'feedwatchlist' => 'ApiFeedWatchlist',
-               'query' => 'ApiQuery'
+               'feedwatchlist' => 'ApiFeedWatchlist'           
        );
 
        /**
index a99ec21..fc6ed7a 100644 (file)
@@ -306,7 +306,7 @@ class ApiPageSet extends ApiQueryBase {
        private function initFromTitles($titles) {
 
                // Get validated and normalized title objects
-               $linkBatch = $this->processTitlesStrArray($titles);
+               $linkBatch = $this->processTitlesArray($titles);
                if($linkBatch->isEmpty())
                        return;
                        
@@ -541,12 +541,13 @@ class ApiPageSet extends ApiQueryBase {
         * 
         * @return LinkBatch of title objects.
         */
-       private function processTitlesStrArray($titles) {
+       private function processTitlesArray($titles) {
 
                $linkBatch = new LinkBatch();
 
-               foreach ($titles as $titleString) {
-                       $titleObj = Title :: newFromText($titleString);
+               foreach ($titles as $title) {
+                       
+                       $titleObj = is_string($title) ? Title :: newFromText($title) : $title;
 
                        // Validation
                        if (!$titleObj)
@@ -561,13 +562,17 @@ class ApiPageSet extends ApiQueryBase {
                        // Make sure we remember the original title that was given to us
                        // This way the caller can correlate new titles with the originally requested,
                        // i.e. namespace is localized or capitalization is different
-                       if ($titleString !== $titleObj->getPrefixedText()) {
-                               $this->mNormalizedTitles[$titleString] = $titleObj->getPrefixedText();
+                       if (is_string($title) && $title !== $titleObj->getPrefixedText()) {
+                               $this->mNormalizedTitles[$title] = $titleObj->getPrefixedText();
                        }
                }
 
                return $linkBatch;
        }
+       
+       public static function debugPrint($name = 'unknown') {
+               ApiBase::debugPrint($this->mAllPages, $name);
+       }
 
        protected function getAllowedParams() {
                return array (
index a42dec2..39bd7fe 100644 (file)
@@ -38,12 +38,14 @@ class ApiQuery extends ApiBase {
 
        private $mQueryPropModules = array (
                'info' => 'ApiQueryInfo',
-               'revisions' => 'ApiQueryRevisions'
+               'revisions' => 'ApiQueryRevisions',
+               'links' => 'ApiQueryLinks',
+               'langlinks' => 'ApiQueryLangLinks',
+               'images' => 'ApiQueryImages',
+               'templates' => 'ApiQueryLinks',
        );
        //      'categories' => 'ApiQueryCategories',
        //      'imageinfo' => 'ApiQueryImageinfo',
-       //      'langlinks' => 'ApiQueryLanglinks',
-       //      'links' => 'ApiQueryLinks',
        //      'templates' => 'ApiQueryTemplates',
 
        private $mQueryListModules = array (
@@ -53,12 +55,10 @@ class ApiQuery extends ApiBase {
                'recentchanges' => 'ApiQueryRecentChanges',
                'backlinks' => 'ApiQueryBacklinks',
                'embeddedin' => 'ApiQueryBacklinks',
-               'imagelinks' => 'ApiQueryBacklinks',
+               'imageusage' => 'ApiQueryBacklinks',
                'usercontribs' => 'ApiQueryContributions'
        );
        //      'categorymembers' => 'ApiQueryCategorymembers',
-       //      'embeddedin' => 'ApiQueryEmbeddedin',
-       //      'imagelinks' => 'ApiQueryImagelinks',
        //      'recentchanges' => 'ApiQueryRecentchanges',
        //      'users' => 'ApiQueryUsers',
        //      'watchlist' => 'ApiQueryWatchlist',
@@ -132,15 +132,15 @@ class ApiQuery extends ApiBase {
                }
 
                //
-               // If given, execute generator to substitute user supplied data with generated data.  
+               // Populate page information for the given pageSet
                //
-               if (isset ($generator))
-                       $this->executeGeneratorModule($generator, $redirects);
+               $this->mPageSet->execute();
 
                //
-               // Populate page information for the given pageSet
+               // If given, execute generator to substitute user supplied data with generated data.  
                //
-               $this->mPageSet->execute();
+               if (isset ($generator))
+                       $this->executeGeneratorModule($generator, $redirects);
 
                //
                // Record page information (title, namespace, if exists, etc)
@@ -250,9 +250,8 @@ class ApiQuery extends ApiBase {
                        ApiBase :: dieDebug(__METHOD__, "Unknown generator=$generatorName");
                }
 
-               // Use current pageset as the result, and create a new one just for the generator 
-               $resultPageSet = $this->mPageSet;
-               $this->mPageSet = new ApiPageSet($this, $redirects);
+               // Generator results 
+               $resultPageSet = new ApiPageSet($this, $redirects);
 
                // Create and execute the generator
                $generator = new $className ($this, $generatorName);
@@ -262,9 +261,6 @@ class ApiQuery extends ApiBase {
                $generator->setGeneratorMode();
                $generator->requestExtraData();
 
-               // execute current pageSet to get the data for the generator module
-               $this->mPageSet->execute();
-
                // populate resultPageSet with the generator output
                $generator->profileIn();
                $generator->executeGenerator($resultPageSet);
index 677ead4..c3d5042 100644 (file)
@@ -47,8 +47,8 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
                        'prefix' => 'tl',
                        'linktbl' => 'templatelinks'
                ),
-               'imagelinks' => array (
-                       'code' => 'il',
+               'imageusage' => array (
+                       'code' => 'iu',
                        'prefix' => 'il',
                        'linktbl' => 'imagelinks'
                )
@@ -67,7 +67,7 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
                );
                $this->bl_code = $code;
 
-               $this->hasNS = $moduleName !== 'imagelinks';
+               $this->hasNS = $moduleName !== 'imageusage';
                if ($this->hasNS) {
                        $this->bl_title = $prefix . '_title';
                        $this->bl_sort = "{$this->bl_ns}, {$this->bl_title}, {$this->bl_from}";
@@ -97,7 +97,7 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
                extract($this->extractRequestParams());
 
                if ($redirect)
-                       ApiBase :: dieDebug(__METHOD__, 'Redirect is not yet been implemented', 'notimplemented');
+                       ApiBase :: dieDebug(__METHOD__, 'Redirect has not been implemented', 'notimplemented');
 
                $this->processContinue($continue, $redirect);
 
@@ -327,7 +327,7 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
                                return 'Find all pages that link to the given page';
                        case 'embeddedin' :
                                return 'Find all pages that embed (transclude) the given title';
-                       case 'imagelinks' :
+                       case 'imageusage' :
                                return 'Find all pages that use the given image title.';
                        default :
                                ApiBase :: dieDebug(__METHOD__, 'Unknown module name');
@@ -344,9 +344,9 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
                                "api.php?action=query&list=embeddedin&titles=Template:Stub",
                                "api.php?action=query&generator=embeddedin&titles=Template:Stub&prop=info"
                        ),
-                       'imagelinks' => array (
-                               "api.php?action=query&list=imagelinks&titles=Image:Albert%20Einstein%20Head.jpg",
-                               "api.php?action=query&generator=imagelinks&titles=Image:Albert%20Einstein%20Head.jpg&prop=info"
+                       'imageusage' => array (
+                               "api.php?action=query&list=imageusage&titles=Image:Albert%20Einstein%20Head.jpg",
+                               "api.php?action=query&generator=imageusage&titles=Image:Albert%20Einstein%20Head.jpg&prop=info"
                        )
                );
 
index bc8c483..89b2b6d 100644 (file)
@@ -134,12 +134,8 @@ abstract class ApiQueryBase extends ApiBase {
 
                // Title
                $title = ApiQueryBase :: addRowInfo_title($row, $prefix . '_namespace', $prefix . '_title');
-               if ($title) {
-                       if (!$title->userCanRead())
-                               return false;
-                       $vals['ns'] = $title->getNamespace();
-                       $vals['title'] = $title->getPrefixedText();
-               }
+               if ($title)
+                       ApiQueryBase :: addTitleInfo($vals, $title);
 
                switch ($prefix) {
 
@@ -279,6 +275,11 @@ abstract class ApiQueryBase extends ApiBase {
                return $vals;
        }
 
+       protected static function addTitleInfo(&$arr, $title) {
+               $arr['ns'] = $title->getNamespace();
+               $arr['title'] = $title->getPrefixedText();
+       }
+       
        private static function addRowInfo_title($row, $nsfld, $titlefld) {
                if ( isset( $row-> $nsfld ) ) {
                        $ns = $row-> $nsfld;
diff --git a/includes/api/ApiQueryImages.php b/includes/api/ApiQueryImages.php
new file mode 100644 (file)
index 0000000..923903f
--- /dev/null
@@ -0,0 +1,122 @@
+<?php
+
+/*
+ * Created on May 13, 2007
+ *
+ * API for MediaWiki 1.8+
+ *
+ * Copyright (C) 2006 Yuri Astrakhan <FirstnameLastname@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+if (!defined('MEDIAWIKI')) {
+       // Eclipse helper - will be ignored in production
+       require_once ("ApiQueryBase.php");
+}
+
+/**
+ * @addtogroup API
+ */
+class ApiQueryImages extends ApiQueryGeneratorBase {
+
+       public function __construct($query, $moduleName) {
+               parent :: __construct($query, $moduleName, 'im');
+       }
+
+       public function execute() {
+               $this->run();
+       }
+
+       public function executeGenerator($resultPageSet) {
+               $this->run($resultPageSet);
+       }
+
+       private function run($resultPageSet = null) {
+
+               $this->addFields(array (
+                       'il_from',
+                       'il_to'
+               ));
+
+               $this->addTables('imagelinks');
+               $this->addWhereFld('il_from', array_keys($this->getPageSet()->getGoodTitles()));
+               $this->addOption('ORDER BY', "il_from, il_to");
+
+               $db = $this->getDB();
+               $res = $this->select(__METHOD__);
+
+               if (is_null($resultPageSet)) {
+                       
+                       $data = array();
+                       $lastId = 0;    // database has no ID 0 
+                       while ($row = $db->fetchObject($res)) {
+                               if ($lastId != $row->il_from) {
+                                       if($lastId != 0) {
+                                               $this->addPageSubItems($lastId, $data);
+                                               $data = array();
+                                       }
+                                       $lastId = $row->il_from;
+                               }
+                               
+                               $entry = array();
+                               $title = Title :: makeTitle(NS_IMAGE, $row->il_to);
+                               $vals = ApiQueryBase :: addTitleInfo($entry, $title);
+                               $data[] = $entry;
+                       }
+
+                       if($lastId != 0) {
+                               $this->addPageSubItems($lastId, $data);
+                       }
+
+               } else {
+
+                       $titles = array();
+                       while ($row = $db->fetchObject($res)) {
+                               $titles[] = Title :: makeTitle(NS_IMAGE, $row->il_to);
+                       }
+                       $resultPageSet->populateFromTitles($titles);
+               }
+
+               $db->freeResult($res);
+       }
+
+       private function addPageSubItems($pageId, $data) {
+               $result = $this->getResult();
+               $result->setIndexedTagName($data, 'i');
+               $result->addValue(array ('query', 'pages', intval($pageId)),
+                       'images',
+                       $data);
+       }
+
+       protected function getDescription() {
+               return 'Returns all links from the given page(s)';
+       }
+
+       protected function getExamples() {
+               return array (
+                               "Get a list of images used in the [[Main Page]]:",
+                               "  api.php?action=query&prop=images&titles=Main%20Page",
+                               "Get information about all images used in the [[Main Page]]:",
+                               "  api.php?action=query&generator=images&titles=Main%20Page&prop=info"
+                       );
+       }
+
+       public function getVersion() {
+               return __CLASS__ . ': $Id$';
+       }
+}
+?>
diff --git a/includes/api/ApiQueryLangLinks.php b/includes/api/ApiQueryLangLinks.php
new file mode 100644 (file)
index 0000000..073b53e
--- /dev/null
@@ -0,0 +1,100 @@
+<?php
+
+/*
+ * Created on May 13, 2007
+ *
+ * API for MediaWiki 1.8+
+ *
+ * Copyright (C) 2006 Yuri Astrakhan <FirstnameLastname@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+if (!defined('MEDIAWIKI')) {
+       // Eclipse helper - will be ignored in production
+       require_once ("ApiQueryBase.php");
+}
+
+/**
+ * @addtogroup API
+ */
+class ApiQueryLangLinks extends ApiQueryBase {
+
+       public function __construct($query, $moduleName) {
+               parent :: __construct($query, $moduleName, 'll');
+       }
+
+       public function execute() {
+               $this->addFields(array (
+                       'll_from',
+                       'll_lang',
+                       'll_title'
+               ));
+
+               $this->addTables('langlinks');
+               $this->addWhereFld('ll_from', array_keys($this->getPageSet()->getGoodTitles()));
+               $this->addOption('ORDER BY', "ll_from, ll_lang");
+               $res = $this->select(__METHOD__);
+
+               $data = array();
+               $lastId = 0;    // database has no ID 0 
+               $db = $this->getDB();
+               while ($row = $db->fetchObject($res)) {
+
+                       if ($lastId != $row->ll_from) {
+                               if($lastId != 0) {
+                                       $this->addPageSubItems($lastId, $data);
+                                       $data = array();
+                               }
+                               $lastId = $row->ll_from;
+                       }
+
+                       $entry = array('lang'=>$row->ll_lang);
+                       ApiResult :: setContent($entry, $row->ll_title);
+                       $data[] = $entry;
+               }
+
+               if($lastId != 0) {
+                       $this->addPageSubItems($lastId, $data);
+               }
+
+               $db->freeResult($res);
+       }
+
+       private function addPageSubItems($pageId, $data) {
+               $result = $this->getResult();
+               $result->setIndexedTagName($data, 'll');
+               $result->addValue(array ('query', 'pages', intval($pageId)),
+                       'langlinks',
+                       $data);
+       }
+
+       protected function getDescription() {
+               return 'Returns all interlanguage links from the given page(s)';
+       }
+
+       protected function getExamples() {
+               return array (
+                               "Get interlanguage links from the [[Main Page]]:",
+                               "  api.php?action=query&prop=langlinks&titles=Main%20Page&redirects",
+                       );
+       }
+
+       public function getVersion() {
+               return __CLASS__ . ': $Id$';
+       }
+}
+?>
diff --git a/includes/api/ApiQueryLinks.php b/includes/api/ApiQueryLinks.php
new file mode 100644 (file)
index 0000000..ff216de
--- /dev/null
@@ -0,0 +1,142 @@
+<?php
+
+/*
+ * Created on May 12, 2007
+ *
+ * API for MediaWiki 1.8+
+ *
+ * Copyright (C) 2006 Yuri Astrakhan <FirstnameLastname@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+if (!defined('MEDIAWIKI')) {
+       // Eclipse helper - will be ignored in production
+       require_once ("ApiQueryBase.php");
+}
+
+/**
+ * @addtogroup API
+ */
+class ApiQueryLinks extends ApiQueryGeneratorBase {
+
+       const LINKS = 'links';
+       const TEMPLATES = 'templates';
+
+       private $table, $prefix, $description;
+
+       public function __construct($query, $moduleName) {
+               
+               switch ($moduleName) {
+                       case self::LINKS :
+                               $this->table = 'pagelinks';
+                               $this->prefix = 'pl';
+                               $this->description = 'link';
+                               break;
+                       case self::TEMPLATES :
+                               $this->table = 'templatelinks';
+                               $this->prefix = 'tl';
+                               $this->description = 'template';
+                               break;
+                       default :
+                               ApiBase :: dieDebug(__METHOD__, 'Unknown module name');
+               }
+
+               parent :: __construct($query, $moduleName, $this->prefix);
+       }
+
+       public function execute() {
+               $this->run();
+       }
+
+       public function executeGenerator($resultPageSet) {
+               $this->run($resultPageSet);
+       }
+
+       private function run($resultPageSet = null) {
+
+               $this->addFields(array (
+                       $this->prefix . '_from pl_from',
+                       $this->prefix . '_namespace pl_namespace',
+                       $this->prefix . '_title pl_title'
+               ));
+
+               $this->addTables($this->table);
+               $this->addWhereFld($this->prefix . '_from', array_keys($this->getPageSet()->getGoodTitles()));
+               $this->addOption('ORDER BY', str_replace('pl_', $this->prefix . '_', 'pl_from, pl_namespace, pl_title'));
+
+               $db = $this->getDB();
+               $res = $this->select(__METHOD__);
+
+               if (is_null($resultPageSet)) {
+                       
+                       $data = array();
+                       $lastId = 0;    // database has no ID 0 
+                       while ($row = $db->fetchObject($res)) {
+                               if ($lastId != $row->pl_from) {
+                                       if($lastId != 0) {
+                                               $this->addPageSubItems($lastId, $data);
+                                               $data = array();
+                                       }
+                                       $lastId = $row->pl_from;
+                               }
+                               $vals = $this->addRowInfo('pl', $row);
+                               if ($vals)
+                                       $data[] = $vals;
+                       }
+
+                       if($lastId != 0) {
+                               $this->addPageSubItems($lastId, $data);
+                       }
+
+               } else {
+
+                       $titles = array();
+                       while ($row = $db->fetchObject($res)) {
+                               $titles[] = Title :: makeTitle($row->pl_namespace, $row->pl_title);
+                       }
+                       $resultPageSet->populateFromTitles($titles);
+               }
+
+               $db->freeResult($res);
+       }
+
+       private function addPageSubItems($pageId, $data) {
+               $result = $this->getResult();
+               $result->setIndexedTagName($data, $this->prefix);
+               $result->addValue(array ('query', 'pages', intval($pageId)),
+                       $this->getModuleName(),
+                       $data);
+       }
+
+       protected function getDescription() {
+               return "Returns all {$this->description}s from the given page(s)";
+       }
+
+       protected function getExamples() {
+               return array (
+                               "Get {$this->description}s from the [[Main Page]]:",
+                               "  api.php?action=query&prop={$this->getModuleName()}&titles=Main%20Page",
+                               "Get information about the {$this->description} pages in the [[Main Page]]:",
+                               "  api.php?action=query&generator={$this->getModuleName()}&titles=Main%20Page&prop=info"
+                       );
+       }
+
+       public function getVersion() {
+               return __CLASS__ . ': $Id$';
+       }
+}
+?>