[ Index ] |
PHP Cross Reference of MediaWiki-1.24.0 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * 4 * 5 * Created on July 7, 2007 6 * 7 * Copyright © 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 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 22 * http://www.gnu.org/copyleft/gpl.html 23 * 24 * @file 25 */ 26 27 /** 28 * Query module to enumerate links from all pages together. 29 * 30 * @ingroup API 31 */ 32 class ApiQueryAllLinks extends ApiQueryGeneratorBase { 33 34 private $table, $tablePrefix, $indexTag, 35 $description, $descriptionWhat, $descriptionTargets, $descriptionLinking; 36 private $fieldTitle = 'title'; 37 private $dfltNamespace = NS_MAIN; 38 private $hasNamespace = true; 39 private $useIndex = null; 40 private $props = array(), $propHelp = array(); 41 42 public function __construct( ApiQuery $query, $moduleName ) { 43 switch ( $moduleName ) { 44 case 'alllinks': 45 $prefix = 'al'; 46 $this->table = 'pagelinks'; 47 $this->tablePrefix = 'pl_'; 48 $this->useIndex = 'pl_namespace'; 49 $this->indexTag = 'l'; 50 $this->description = 'Enumerate all links that point to a given namespace'; 51 $this->descriptionWhat = 'link'; 52 $this->descriptionTargets = 'linked titles'; 53 $this->descriptionLinking = 'linking'; 54 break; 55 case 'alltransclusions': 56 $prefix = 'at'; 57 $this->table = 'templatelinks'; 58 $this->tablePrefix = 'tl_'; 59 $this->dfltNamespace = NS_TEMPLATE; 60 $this->useIndex = 'tl_namespace'; 61 $this->indexTag = 't'; 62 $this->description = 63 'List all transclusions (pages embedded using {{x}}), including non-existing'; 64 $this->descriptionWhat = 'transclusion'; 65 $this->descriptionTargets = 'transcluded titles'; 66 $this->descriptionLinking = 'transcluding'; 67 break; 68 case 'allfileusages': 69 $prefix = 'af'; 70 $this->table = 'imagelinks'; 71 $this->tablePrefix = 'il_'; 72 $this->fieldTitle = 'to'; 73 $this->dfltNamespace = NS_FILE; 74 $this->hasNamespace = false; 75 $this->indexTag = 'f'; 76 $this->description = 'List all file usages, including non-existing'; 77 $this->descriptionWhat = 'file'; 78 $this->descriptionTargets = 'file titles'; 79 $this->descriptionLinking = 'using'; 80 break; 81 case 'allredirects': 82 $prefix = 'ar'; 83 $this->table = 'redirect'; 84 $this->tablePrefix = 'rd_'; 85 $this->indexTag = 'r'; 86 $this->description = 'List all redirects to a namespace'; 87 $this->descriptionWhat = 'redirect'; 88 $this->descriptionTargets = 'target pages'; 89 $this->descriptionLinking = 'redirecting'; 90 $this->props = array( 91 'fragment' => 'rd_fragment', 92 'interwiki' => 'rd_interwiki', 93 ); 94 $this->propHelp = array( 95 ' fragment - Adds the fragment from the redirect, if any', 96 ' interwiki - Adds the interwiki prefix from the redirect, if any', 97 ); 98 break; 99 default: 100 ApiBase::dieDebug( __METHOD__, 'Unknown module name' ); 101 } 102 103 parent::__construct( $query, $moduleName, $prefix ); 104 } 105 106 public function execute() { 107 $this->run(); 108 } 109 110 public function getCacheMode( $params ) { 111 return 'public'; 112 } 113 114 public function executeGenerator( $resultPageSet ) { 115 $this->run( $resultPageSet ); 116 } 117 118 /** 119 * @param ApiPageSet $resultPageSet 120 * @return void 121 */ 122 private function run( $resultPageSet = null ) { 123 $db = $this->getDB(); 124 $params = $this->extractRequestParams(); 125 126 $pfx = $this->tablePrefix; 127 $fieldTitle = $this->fieldTitle; 128 $prop = array_flip( $params['prop'] ); 129 $fld_ids = isset( $prop['ids'] ); 130 $fld_title = isset( $prop['title'] ); 131 if ( $this->hasNamespace ) { 132 $namespace = $params['namespace']; 133 } else { 134 $namespace = $this->dfltNamespace; 135 } 136 137 if ( $params['unique'] ) { 138 $matches = array_intersect_key( $prop, $this->props + array( 'ids' => 1 ) ); 139 if ( $matches ) { 140 $p = $this->getModulePrefix(); 141 $this->dieUsage( 142 "Cannot use {$p}prop=" . join( '|', array_keys( $matches ) ) . " with {$p}unique", 143 'params' 144 ); 145 } 146 $this->addOption( 'DISTINCT' ); 147 } 148 149 $this->addTables( $this->table ); 150 if ( $this->hasNamespace ) { 151 $this->addWhereFld( $pfx . 'namespace', $namespace ); 152 } 153 154 $continue = !is_null( $params['continue'] ); 155 if ( $continue ) { 156 $continueArr = explode( '|', $params['continue'] ); 157 $op = $params['dir'] == 'descending' ? '<' : '>'; 158 if ( $params['unique'] ) { 159 $this->dieContinueUsageIf( count( $continueArr ) != 1 ); 160 $continueTitle = $db->addQuotes( $continueArr[0] ); 161 $this->addWhere( "{$pfx}{$fieldTitle} $op= $continueTitle" ); 162 } else { 163 $this->dieContinueUsageIf( count( $continueArr ) != 2 ); 164 $continueTitle = $db->addQuotes( $continueArr[0] ); 165 $continueFrom = intval( $continueArr[1] ); 166 $this->addWhere( 167 "{$pfx}{$fieldTitle} $op $continueTitle OR " . 168 "({$pfx}{$fieldTitle} = $continueTitle AND " . 169 "{$pfx}from $op= $continueFrom)" 170 ); 171 } 172 } 173 174 // 'continue' always overrides 'from' 175 $from = ( $continue || $params['from'] === null ? null : 176 $this->titlePartToKey( $params['from'], $namespace ) ); 177 $to = ( $params['to'] === null ? null : 178 $this->titlePartToKey( $params['to'], $namespace ) ); 179 $this->addWhereRange( $pfx . $fieldTitle, 'newer', $from, $to ); 180 181 if ( isset( $params['prefix'] ) ) { 182 $this->addWhere( $pfx . $fieldTitle . $db->buildLike( $this->titlePartToKey( 183 $params['prefix'], $namespace ), $db->anyString() ) ); 184 } 185 186 $this->addFields( array( 'pl_title' => $pfx . $fieldTitle ) ); 187 $this->addFieldsIf( array( 'pl_from' => $pfx . 'from' ), !$params['unique'] ); 188 foreach ( $this->props as $name => $field ) { 189 $this->addFieldsIf( $field, isset( $prop[$name] ) ); 190 } 191 192 if ( $this->useIndex ) { 193 $this->addOption( 'USE INDEX', $this->useIndex ); 194 } 195 $limit = $params['limit']; 196 $this->addOption( 'LIMIT', $limit + 1 ); 197 198 $sort = ( $params['dir'] == 'descending' ? ' DESC' : '' ); 199 $orderBy = array(); 200 $orderBy[] = $pfx . $fieldTitle . $sort; 201 if ( !$params['unique'] ) { 202 $orderBy[] = $pfx . 'from' . $sort; 203 } 204 $this->addOption( 'ORDER BY', $orderBy ); 205 206 $res = $this->select( __METHOD__ ); 207 208 $pageids = array(); 209 $titles = array(); 210 $count = 0; 211 $result = $this->getResult(); 212 foreach ( $res as $row ) { 213 if ( ++$count > $limit ) { 214 // We've reached the one extra which shows that there are 215 // additional pages to be had. Stop here... 216 if ( $params['unique'] ) { 217 $this->setContinueEnumParameter( 'continue', $row->pl_title ); 218 } else { 219 $this->setContinueEnumParameter( 'continue', $row->pl_title . '|' . $row->pl_from ); 220 } 221 break; 222 } 223 224 if ( is_null( $resultPageSet ) ) { 225 $vals = array(); 226 if ( $fld_ids ) { 227 $vals['fromid'] = intval( $row->pl_from ); 228 } 229 if ( $fld_title ) { 230 $title = Title::makeTitle( $namespace, $row->pl_title ); 231 ApiQueryBase::addTitleInfo( $vals, $title ); 232 } 233 foreach ( $this->props as $name => $field ) { 234 if ( isset( $prop[$name] ) && $row->$field !== null && $row->$field !== '' ) { 235 $vals[$name] = $row->$field; 236 } 237 } 238 $fit = $result->addValue( array( 'query', $this->getModuleName() ), null, $vals ); 239 if ( !$fit ) { 240 if ( $params['unique'] ) { 241 $this->setContinueEnumParameter( 'continue', $row->pl_title ); 242 } else { 243 $this->setContinueEnumParameter( 'continue', $row->pl_title . '|' . $row->pl_from ); 244 } 245 break; 246 } 247 } elseif ( $params['unique'] ) { 248 $titles[] = Title::makeTitle( $namespace, $row->pl_title ); 249 } else { 250 $pageids[] = $row->pl_from; 251 } 252 } 253 254 if ( is_null( $resultPageSet ) ) { 255 $result->setIndexedTagName_internal( array( 'query', $this->getModuleName() ), $this->indexTag ); 256 } elseif ( $params['unique'] ) { 257 $resultPageSet->populateFromTitles( $titles ); 258 } else { 259 $resultPageSet->populateFromPageIDs( $pageids ); 260 } 261 } 262 263 public function getAllowedParams() { 264 $allowedParams = array( 265 'continue' => null, 266 'from' => null, 267 'to' => null, 268 'prefix' => null, 269 'unique' => false, 270 'prop' => array( 271 ApiBase::PARAM_ISMULTI => true, 272 ApiBase::PARAM_DFLT => 'title', 273 ApiBase::PARAM_TYPE => array_merge( 274 array( 'ids', 'title' ), array_keys( $this->props ) 275 ), 276 ), 277 'namespace' => array( 278 ApiBase::PARAM_DFLT => $this->dfltNamespace, 279 ApiBase::PARAM_TYPE => 'namespace' 280 ), 281 'limit' => array( 282 ApiBase::PARAM_DFLT => 10, 283 ApiBase::PARAM_TYPE => 'limit', 284 ApiBase::PARAM_MIN => 1, 285 ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1, 286 ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2 287 ), 288 'dir' => array( 289 ApiBase::PARAM_DFLT => 'ascending', 290 ApiBase::PARAM_TYPE => array( 291 'ascending', 292 'descending' 293 ) 294 ), 295 ); 296 if ( !$this->hasNamespace ) { 297 unset( $allowedParams['namespace'] ); 298 } 299 300 return $allowedParams; 301 } 302 303 public function getParamDescription() { 304 $p = $this->getModulePrefix(); 305 $what = $this->descriptionWhat; 306 $targets = $this->descriptionTargets; 307 $linking = $this->descriptionLinking; 308 $paramDescription = array( 309 'from' => "The title of the $what to start enumerating from", 310 'to' => "The title of the $what to stop enumerating at", 311 'prefix' => "Search for all $targets that begin with this value", 312 'unique' => array( 313 "Only show distinct $targets. Cannot be used with {$p}prop=" . 314 join( '|', array_keys( array( 'ids' => 1 ) + $this->props ) ) . '.', 315 'When used as a generator, yields target pages instead of source pages.', 316 ), 317 'prop' => array( 318 'What pieces of information to include', 319 " ids - Adds the pageid of the $linking page (Cannot be used with {$p}unique)", 320 " title - Adds the title of the $what", 321 ), 322 'namespace' => 'The namespace to enumerate', 323 'limit' => 'How many total items to return', 324 'continue' => 'When more results are available, use this to continue', 325 'dir' => 'The direction in which to list', 326 ); 327 foreach ( $this->propHelp as $help ) { 328 $paramDescription['prop'][] = "$help (Cannot be used with {$p}unique)"; 329 } 330 if ( !$this->hasNamespace ) { 331 unset( $paramDescription['namespace'] ); 332 } 333 334 return $paramDescription; 335 } 336 337 public function getDescription() { 338 return $this->description; 339 } 340 341 public function getExamples() { 342 $p = $this->getModulePrefix(); 343 $name = $this->getModuleName(); 344 $what = $this->descriptionWhat; 345 $targets = $this->descriptionTargets; 346 347 return array( 348 "api.php?action=query&list={$name}&{$p}from=B&{$p}prop=ids|title" 349 => "List $targets with page ids they are from, including missing ones. Start at B", 350 "api.php?action=query&list={$name}&{$p}unique=&{$p}from=B" 351 => "List unique $targets", 352 "api.php?action=query&generator={$name}&g{$p}unique=&g{$p}from=B" 353 => "Gets all $targets, marking the missing ones", 354 "api.php?action=query&generator={$name}&g{$p}from=B" 355 => "Gets pages containing the {$what}s", 356 ); 357 } 358 359 public function getHelpUrls() { 360 $name = ucfirst( $this->getModuleName() ); 361 362 return "https://www.mediawiki.org/wiki/API:{$name}"; 363 } 364 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 14:03:12 2014 | Cross-referenced by PHPXref 0.7.1 |