From: Yuri Astrakhan Date: Mon, 14 May 2007 05:28:06 +0000 (+0000) Subject: * New properties: links, templates, images, langlinks X-Git-Tag: 1.31.0-rc.0~52927 X-Git-Url: http://git.cyclocoop.org/data/%24self?a=commitdiff_plain;h=0e68016b728d7767caecc378612308832f8f3102;p=lhc%2Fweb%2Fwiklou.git * New properties: links, templates, images, langlinks * Breaking Change: imagelinks renamed into imageusage (il->iu) * Bug fix: incorrect generator behavior in some cases --- diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 67d0beba14..a808ed0bb5 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -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 - + == 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 diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php index 82f5b3e809..aee83f1c84 100644 --- a/includes/AutoLoader.php +++ b/includes/AutoLoader.php @@ -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', diff --git a/includes/api/ApiBase.php b/includes/api/ApiBase.php index a8b1939958..cd20e3eef3 100644 --- a/includes/api/ApiBase.php +++ b/includes/api/ApiBase.php @@ -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
Debuging value '$location':\n\n";
+		var_export($value);
+		print "\n
\n"; + } public abstract function getVersion(); diff --git a/includes/api/ApiMain.php b/includes/api/ApiMain.php index c4d5a83930..ca1e8996b0 100644 --- a/includes/api/ApiMain.php +++ b/includes/api/ApiMain.php @@ -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' ); /** diff --git a/includes/api/ApiPageSet.php b/includes/api/ApiPageSet.php index a99ec218e2..fc6ed7a856 100644 --- a/includes/api/ApiPageSet.php +++ b/includes/api/ApiPageSet.php @@ -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 ( diff --git a/includes/api/ApiQuery.php b/includes/api/ApiQuery.php index a42dec2349..39bd7fefef 100644 --- a/includes/api/ApiQuery.php +++ b/includes/api/ApiQuery.php @@ -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); diff --git a/includes/api/ApiQueryBacklinks.php b/includes/api/ApiQueryBacklinks.php index 677ead4780..c3d5042323 100644 --- a/includes/api/ApiQueryBacklinks.php +++ b/includes/api/ApiQueryBacklinks.php @@ -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" ) ); diff --git a/includes/api/ApiQueryBase.php b/includes/api/ApiQueryBase.php index bc8c483f74..89b2b6d71b 100644 --- a/includes/api/ApiQueryBase.php +++ b/includes/api/ApiQueryBase.php @@ -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 index 0000000000..923903f192 --- /dev/null +++ b/includes/api/ApiQueryImages.php @@ -0,0 +1,122 @@ + + * + * 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 index 0000000000..073b53ec0f --- /dev/null +++ b/includes/api/ApiQueryLangLinks.php @@ -0,0 +1,100 @@ + + * + * 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 index 0000000000..ff216de0e4 --- /dev/null +++ b/includes/api/ApiQueryLinks.php @@ -0,0 +1,142 @@ + + * + * 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$'; + } +} +?>