00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 if (!defined('MEDIAWIKI')) {
00027
00028 require_once ("ApiQueryBase.php");
00029 }
00030
00036 class ApiQueryLinks extends ApiQueryGeneratorBase {
00037
00038 const LINKS = 'links';
00039 const TEMPLATES = 'templates';
00040
00041 private $table, $prefix, $description;
00042
00043 public function __construct($query, $moduleName) {
00044
00045 switch ($moduleName) {
00046 case self::LINKS :
00047 $this->table = 'pagelinks';
00048 $this->prefix = 'pl';
00049 $this->description = 'link';
00050 break;
00051 case self::TEMPLATES :
00052 $this->table = 'templatelinks';
00053 $this->prefix = 'tl';
00054 $this->description = 'template';
00055 break;
00056 default :
00057 ApiBase :: dieDebug(__METHOD__, 'Unknown module name');
00058 }
00059
00060 parent :: __construct($query, $moduleName, $this->prefix);
00061 }
00062
00063 public function execute() {
00064 $this->run();
00065 }
00066
00067 public function executeGenerator($resultPageSet) {
00068 $this->run($resultPageSet);
00069 }
00070
00071 private function run($resultPageSet = null) {
00072
00073 if ($this->getPageSet()->getGoodTitleCount() == 0)
00074 return;
00075
00076 $params = $this->extractRequestParams();
00077
00078 $this->addFields(array (
00079 $this->prefix . '_from AS pl_from',
00080 $this->prefix . '_namespace AS pl_namespace',
00081 $this->prefix . '_title AS pl_title'
00082 ));
00083
00084 $this->addTables($this->table);
00085 $this->addWhereFld($this->prefix . '_from', array_keys($this->getPageSet()->getGoodTitles()));
00086 $this->addWhereFld($this->prefix . '_namespace', $params['namespace']);
00087
00088 if(!is_null($params['continue'])) {
00089 $cont = explode('|', $params['continue']);
00090 if(count($cont) != 3)
00091 $this->dieUsage("Invalid continue param. You should pass the " .
00092 "original value returned by the previous query", "_badcontinue");
00093 $plfrom = intval($cont[0]);
00094 $plns = intval($cont[1]);
00095 $pltitle = $this->getDB()->strencode($this->titleToKey($cont[2]));
00096 $this->addWhere("{$this->prefix}_from > $plfrom OR ".
00097 "({$this->prefix}_from = $plfrom AND ".
00098 "({$this->prefix}_namespace > $plns OR ".
00099 "({$this->prefix}_namespace = $plns AND ".
00100 "{$this->prefix}_title >= '$pltitle')))");
00101 }
00102
00103 # Here's some MySQL craziness going on: if you use WHERE foo='bar'
00104 # and later ORDER BY foo MySQL doesn't notice the ORDER BY is pointless
00105 # but instead goes and filesorts, because the index for foo was used
00106 # already. To work around this, we drop constant fields in the WHERE
00107 # clause from the ORDER BY clause
00108 $order = array();
00109 if(count($this->getPageSet()->getGoodTitles()) != 1)
00110 $order[] = "{$this->prefix}_from";
00111 if(count($params['namespace']) != 1)
00112 $order[] = "{$this->prefix}_namespace";
00113 $order[] = "{$this->prefix}_title";
00114 $this->addOption('ORDER BY', implode(", ", $order));
00115 $this->addOption('USE INDEX', "{$this->prefix}_from");
00116 $this->addOption('LIMIT', $params['limit'] + 1);
00117
00118 $db = $this->getDB();
00119 $res = $this->select(__METHOD__);
00120
00121 if (is_null($resultPageSet)) {
00122 $count = 0;
00123 while ($row = $db->fetchObject($res)) {
00124 if(++$count > $params['limit']) {
00125
00126
00127 $this->setContinueEnumParameter('continue',
00128 "{$row->pl_from}|{$row->pl_namespace}|" .
00129 $this->keyToTitle($row->pl_title));
00130 break;
00131 }
00132 $vals = array();
00133 ApiQueryBase :: addTitleInfo($vals, Title :: makeTitle($row->pl_namespace, $row->pl_title));
00134 $fit = $this->addPageSubItem($row->pl_from, $vals);
00135 if(!$fit)
00136 {
00137 $this->setContinueEnumParameter('continue',
00138 "{$row->pl_from}|{$row->pl_namespace}|" .
00139 $this->keyToTitle($row->pl_title));
00140 break;
00141 }
00142 }
00143 } else {
00144
00145 $titles = array();
00146 $count = 0;
00147 while ($row = $db->fetchObject($res)) {
00148 if(++$count > $params['limit']) {
00149
00150
00151 $this->setContinueEnumParameter('continue',
00152 "{$row->pl_from}|{$row->pl_namespace}|" .
00153 $this->keyToTitle($row->pl_title));
00154 break;
00155 }
00156 $titles[] = Title :: makeTitle($row->pl_namespace, $row->pl_title);
00157 }
00158 $resultPageSet->populateFromTitles($titles);
00159 }
00160
00161 $db->freeResult($res);
00162 }
00163
00164 public function getAllowedParams()
00165 {
00166 return array(
00167 'namespace' => array(
00168 ApiBase :: PARAM_TYPE => 'namespace',
00169 ApiBase :: PARAM_ISMULTI => true
00170 ),
00171 'limit' => array(
00172 ApiBase :: PARAM_DFLT => 10,
00173 ApiBase :: PARAM_TYPE => 'limit',
00174 ApiBase :: PARAM_MIN => 1,
00175 ApiBase :: PARAM_MAX => ApiBase :: LIMIT_BIG1,
00176 ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2
00177 ),
00178 'continue' => null,
00179 );
00180 }
00181
00182 public function getParamDescription()
00183 {
00184 return array(
00185 'namespace' => "Show {$this->description}s in this namespace(s) only",
00186 'limit' => "How many {$this->description}s to return",
00187 'continue' => 'When more results are available, use this to continue',
00188 );
00189 }
00190
00191 public function getDescription() {
00192 return "Returns all {$this->description}s from the given page(s)";
00193 }
00194
00195 protected function getExamples() {
00196 return array (
00197 "Get {$this->description}s from the [[Main Page]]:",
00198 " api.php?action=query&prop={$this->getModuleName()}&titles=Main%20Page",
00199 "Get information about the {$this->description} pages in the [[Main Page]]:",
00200 " api.php?action=query&generator={$this->getModuleName()}&titles=Main%20Page&prop=info",
00201 "Get {$this->description}s from the Main Page in the User and Template namespaces:",
00202 " api.php?action=query&prop={$this->getModuleName()}&titles=Main%20Page&{$this->prefix}namespace=2|10"
00203 );
00204 }
00205
00206 public function getVersion() {
00207 return __CLASS__ . ': $Id: ApiQueryLinks.php 46845 2009-02-05 14:30:59Z catrope $';
00208 }
00209 }