ApiQueryLinks.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. <?php
  2. /*
  3. * Created on May 12, 2007
  4. *
  5. * API for MediaWiki 1.8+
  6. *
  7. * Copyright (C) 2006 Yuri Astrakhan <Firstname><Lastname>@gmail.com
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License along
  20. * with this program; if not, write to the Free Software Foundation, Inc.,
  21. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  22. * http://www.gnu.org/copyleft/gpl.html
  23. */
  24. if (!defined('MEDIAWIKI')) {
  25. // Eclipse helper - will be ignored in production
  26. require_once ("ApiQueryBase.php");
  27. }
  28. /**
  29. * A query module to list all wiki links on a given set of pages.
  30. *
  31. * @ingroup API
  32. */
  33. class ApiQueryLinks extends ApiQueryGeneratorBase {
  34. const LINKS = 'links';
  35. const TEMPLATES = 'templates';
  36. private $table, $prefix, $description;
  37. public function __construct($query, $moduleName) {
  38. switch ($moduleName) {
  39. case self::LINKS :
  40. $this->table = 'pagelinks';
  41. $this->prefix = 'pl';
  42. $this->description = 'link';
  43. break;
  44. case self::TEMPLATES :
  45. $this->table = 'templatelinks';
  46. $this->prefix = 'tl';
  47. $this->description = 'template';
  48. break;
  49. default :
  50. ApiBase :: dieDebug(__METHOD__, 'Unknown module name');
  51. }
  52. parent :: __construct($query, $moduleName, $this->prefix);
  53. }
  54. public function execute() {
  55. $this->run();
  56. }
  57. public function executeGenerator($resultPageSet) {
  58. $this->run($resultPageSet);
  59. }
  60. private function run($resultPageSet = null) {
  61. if ($this->getPageSet()->getGoodTitleCount() == 0)
  62. return; // nothing to do
  63. $params = $this->extractRequestParams();
  64. $this->addFields(array (
  65. $this->prefix . '_from AS pl_from',
  66. $this->prefix . '_namespace AS pl_namespace',
  67. $this->prefix . '_title AS pl_title'
  68. ));
  69. $this->addTables($this->table);
  70. $this->addWhereFld($this->prefix . '_from', array_keys($this->getPageSet()->getGoodTitles()));
  71. $this->addWhereFld($this->prefix . '_namespace', $params['namespace']);
  72. if(!is_null($params['continue'])) {
  73. $cont = explode('|', $params['continue']);
  74. if(count($cont) != 3)
  75. $this->dieUsage("Invalid continue param. You should pass the " .
  76. "original value returned by the previous query", "_badcontinue");
  77. $plfrom = intval($cont[0]);
  78. $plns = intval($cont[1]);
  79. $pltitle = $this->getDB()->strencode($this->titleToKey($cont[2]));
  80. $this->addWhere("{$this->prefix}_from > $plfrom OR ".
  81. "({$this->prefix}_from = $plfrom AND ".
  82. "({$this->prefix}_namespace > $plns OR ".
  83. "({$this->prefix}_namespace = $plns AND ".
  84. "{$this->prefix}_title >= '$pltitle')))");
  85. }
  86. # Here's some MySQL craziness going on: if you use WHERE foo='bar'
  87. # and later ORDER BY foo MySQL doesn't notice the ORDER BY is pointless
  88. # but instead goes and filesorts, because the index for foo was used
  89. # already. To work around this, we drop constant fields in the WHERE
  90. # clause from the ORDER BY clause
  91. $order = array();
  92. if(count($this->getPageSet()->getGoodTitles()) != 1)
  93. $order[] = "{$this->prefix}_from";
  94. if(count($params['namespace']) != 1)
  95. $order[] = "{$this->prefix}_namespace";
  96. $order[] = "{$this->prefix}_title";
  97. $this->addOption('ORDER BY', implode(", ", $order));
  98. $this->addOption('USE INDEX', "{$this->prefix}_from");
  99. $this->addOption('LIMIT', $params['limit'] + 1);
  100. $db = $this->getDB();
  101. $res = $this->select(__METHOD__);
  102. if (is_null($resultPageSet)) {
  103. $count = 0;
  104. while ($row = $db->fetchObject($res)) {
  105. if(++$count > $params['limit']) {
  106. // We've reached the one extra which shows that
  107. // there are additional pages to be had. Stop here...
  108. $this->setContinueEnumParameter('continue',
  109. "{$row->pl_from}|{$row->pl_namespace}|" .
  110. $this->keyToTitle($row->pl_title));
  111. break;
  112. }
  113. $vals = array();
  114. ApiQueryBase :: addTitleInfo($vals, Title :: makeTitle($row->pl_namespace, $row->pl_title));
  115. $fit = $this->addPageSubItem($row->pl_from, $vals);
  116. if(!$fit)
  117. {
  118. $this->setContinueEnumParameter('continue',
  119. "{$row->pl_from}|{$row->pl_namespace}|" .
  120. $this->keyToTitle($row->pl_title));
  121. break;
  122. }
  123. }
  124. } else {
  125. $titles = array();
  126. $count = 0;
  127. while ($row = $db->fetchObject($res)) {
  128. if(++$count > $params['limit']) {
  129. // We've reached the one extra which shows that
  130. // there are additional pages to be had. Stop here...
  131. $this->setContinueEnumParameter('continue',
  132. "{$row->pl_from}|{$row->pl_namespace}|" .
  133. $this->keyToTitle($row->pl_title));
  134. break;
  135. }
  136. $titles[] = Title :: makeTitle($row->pl_namespace, $row->pl_title);
  137. }
  138. $resultPageSet->populateFromTitles($titles);
  139. }
  140. $db->freeResult($res);
  141. }
  142. public function getAllowedParams()
  143. {
  144. return array(
  145. 'namespace' => array(
  146. ApiBase :: PARAM_TYPE => 'namespace',
  147. ApiBase :: PARAM_ISMULTI => true
  148. ),
  149. 'limit' => array(
  150. ApiBase :: PARAM_DFLT => 10,
  151. ApiBase :: PARAM_TYPE => 'limit',
  152. ApiBase :: PARAM_MIN => 1,
  153. ApiBase :: PARAM_MAX => ApiBase :: LIMIT_BIG1,
  154. ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2
  155. ),
  156. 'continue' => null,
  157. );
  158. }
  159. public function getParamDescription()
  160. {
  161. return array(
  162. 'namespace' => "Show {$this->description}s in this namespace(s) only",
  163. 'limit' => "How many {$this->description}s to return",
  164. 'continue' => 'When more results are available, use this to continue',
  165. );
  166. }
  167. public function getDescription() {
  168. return "Returns all {$this->description}s from the given page(s)";
  169. }
  170. protected function getExamples() {
  171. return array (
  172. "Get {$this->description}s from the [[Main Page]]:",
  173. " api.php?action=query&prop={$this->getModuleName()}&titles=Main%20Page",
  174. "Get information about the {$this->description} pages in the [[Main Page]]:",
  175. " api.php?action=query&generator={$this->getModuleName()}&titles=Main%20Page&prop=info",
  176. "Get {$this->description}s from the Main Page in the User and Template namespaces:",
  177. " api.php?action=query&prop={$this->getModuleName()}&titles=Main%20Page&{$this->prefix}namespace=2|10"
  178. );
  179. }
  180. public function getVersion() {
  181. return __CLASS__ . ': $Id: ApiQueryLinks.php 46845 2009-02-05 14:30:59Z catrope $';
  182. }
  183. }