MediaWiki
REL1_21
|
00001 <?php 00032 class ApiQueryAllLinks extends ApiQueryGeneratorBase { 00033 00034 public function __construct( $query, $moduleName ) { 00035 switch ( $moduleName ) { 00036 case 'alllinks': 00037 $prefix = 'al'; 00038 $this->table = 'pagelinks'; 00039 $this->tablePrefix = 'pl_'; 00040 $this->dfltNamespace = NS_MAIN; 00041 $this->indexTag = 'l'; 00042 $this->description = 'Enumerate all links that point to a given namespace'; 00043 $this->descriptionLink = 'link'; 00044 $this->descriptionLinked = 'linked'; 00045 $this->descriptionLinking = 'linking'; 00046 break; 00047 case 'alltransclusions': 00048 $prefix = 'at'; 00049 $this->table = 'templatelinks'; 00050 $this->tablePrefix = 'tl_'; 00051 $this->dfltNamespace = NS_TEMPLATE; 00052 $this->indexTag = 't'; 00053 $this->description = 'List all transclusions (pages embedded using {{x}}), including non-existing'; 00054 $this->descriptionLink = 'transclusion'; 00055 $this->descriptionLinked = 'transcluded'; 00056 $this->descriptionLinking = 'transcluding'; 00057 break; 00058 default: 00059 ApiBase::dieDebug( __METHOD__, 'Unknown module name' ); 00060 } 00061 00062 parent::__construct( $query, $moduleName, $prefix ); 00063 } 00064 00065 public function execute() { 00066 $this->run(); 00067 } 00068 00069 public function getCacheMode( $params ) { 00070 return 'public'; 00071 } 00072 00073 public function executeGenerator( $resultPageSet ) { 00074 $this->run( $resultPageSet ); 00075 } 00076 00081 private function run( $resultPageSet = null ) { 00082 $db = $this->getDB(); 00083 $params = $this->extractRequestParams(); 00084 00085 $pfx = $this->tablePrefix; 00086 $prop = array_flip( $params['prop'] ); 00087 $fld_ids = isset( $prop['ids'] ); 00088 $fld_title = isset( $prop['title'] ); 00089 00090 if ( $params['unique'] ) { 00091 if ( $fld_ids ) { 00092 $this->dieUsage( 00093 "{$this->getModuleName()} cannot return corresponding page ids in unique {$this->descriptionLink}s mode", 00094 'params' ); 00095 } 00096 $this->addOption( 'DISTINCT' ); 00097 } 00098 00099 $this->addTables( $this->table ); 00100 $this->addWhereFld( $pfx . 'namespace', $params['namespace'] ); 00101 00102 $continue = !is_null( $params['continue'] ); 00103 if ( $continue ) { 00104 $continueArr = explode( '|', $params['continue'] ); 00105 $op = $params['dir'] == 'descending' ? '<' : '>'; 00106 if ( $params['unique'] ) { 00107 $this->dieContinueUsageIf( count( $continueArr ) != 1 ); 00108 $continueTitle = $db->addQuotes( $continueArr[0] ); 00109 $this->addWhere( "{$pfx}title $op= $continueTitle" ); 00110 } else { 00111 $this->dieContinueUsageIf( count( $continueArr ) != 2 ); 00112 $continueTitle = $db->addQuotes( $continueArr[0] ); 00113 $continueFrom = intval( $continueArr[1] ); 00114 $this->addWhere( 00115 "{$pfx}title $op $continueTitle OR " . 00116 "({$pfx}title = $continueTitle AND " . 00117 "{$pfx}from $op= $continueFrom)" 00118 ); 00119 } 00120 } 00121 00122 // 'continue' always overrides 'from' 00123 $from = ( $continue || is_null( $params['from'] ) ? null : $this->titlePartToKey( $params['from'] ) ); 00124 $to = ( is_null( $params['to'] ) ? null : $this->titlePartToKey( $params['to'] ) ); 00125 $this->addWhereRange( $pfx . 'title', 'newer', $from, $to ); 00126 00127 if ( isset( $params['prefix'] ) ) { 00128 $this->addWhere( $pfx . 'title' . $db->buildLike( $this->titlePartToKey( $params['prefix'] ), $db->anyString() ) ); 00129 } 00130 00131 $this->addFields( array( 'pl_title' => $pfx . 'title' ) ); 00132 $this->addFieldsIf( array( 'pl_from' => $pfx . 'from' ), !$params['unique'] ); 00133 00134 $this->addOption( 'USE INDEX', $pfx . 'namespace' ); 00135 $limit = $params['limit']; 00136 $this->addOption( 'LIMIT', $limit + 1 ); 00137 00138 $sort = ( $params['dir'] == 'descending' ? ' DESC' : '' ); 00139 $orderBy = array(); 00140 $orderBy[] = $pfx . 'title' . $sort; 00141 if ( !$params['unique'] ) { 00142 $orderBy[] = $pfx . 'from' . $sort; 00143 } 00144 $this->addOption( 'ORDER BY', $orderBy ); 00145 00146 $res = $this->select( __METHOD__ ); 00147 00148 $pageids = array(); 00149 $titles = array(); 00150 $count = 0; 00151 $result = $this->getResult(); 00152 foreach ( $res as $row ) { 00153 if ( ++ $count > $limit ) { 00154 // We've reached the one extra which shows that there are additional pages to be had. Stop here... 00155 if ( $params['unique'] ) { 00156 $this->setContinueEnumParameter( 'continue', $row->pl_title ); 00157 } else { 00158 $this->setContinueEnumParameter( 'continue', $row->pl_title . '|' . $row->pl_from ); 00159 } 00160 break; 00161 } 00162 00163 if ( is_null( $resultPageSet ) ) { 00164 $vals = array(); 00165 if ( $fld_ids ) { 00166 $vals['fromid'] = intval( $row->pl_from ); 00167 } 00168 if ( $fld_title ) { 00169 $title = Title::makeTitle( $params['namespace'], $row->pl_title ); 00170 ApiQueryBase::addTitleInfo( $vals, $title ); 00171 } 00172 $fit = $result->addValue( array( 'query', $this->getModuleName() ), null, $vals ); 00173 if ( !$fit ) { 00174 if ( $params['unique'] ) { 00175 $this->setContinueEnumParameter( 'continue', $row->pl_title ); 00176 } else { 00177 $this->setContinueEnumParameter( 'continue', $row->pl_title . '|' . $row->pl_from ); 00178 } 00179 break; 00180 } 00181 } elseif ( $params['unique'] ) { 00182 $titles[] = Title::makeTitle( $params['namespace'], $row->pl_title ); 00183 } else { 00184 $pageids[] = $row->pl_from; 00185 } 00186 } 00187 00188 if ( is_null( $resultPageSet ) ) { 00189 $result->setIndexedTagName_internal( array( 'query', $this->getModuleName() ), $this->indexTag ); 00190 } elseif ( $params['unique'] ) { 00191 $resultPageSet->populateFromTitles( $titles ); 00192 } else { 00193 $resultPageSet->populateFromPageIDs( $pageids ); 00194 } 00195 } 00196 00197 public function getAllowedParams() { 00198 return array( 00199 'continue' => null, 00200 'from' => null, 00201 'to' => null, 00202 'prefix' => null, 00203 'unique' => false, 00204 'prop' => array( 00205 ApiBase::PARAM_ISMULTI => true, 00206 ApiBase::PARAM_DFLT => 'title', 00207 ApiBase::PARAM_TYPE => array( 00208 'ids', 00209 'title' 00210 ) 00211 ), 00212 'namespace' => array( 00213 ApiBase::PARAM_DFLT => $this->dfltNamespace, 00214 ApiBase::PARAM_TYPE => 'namespace' 00215 ), 00216 'limit' => array( 00217 ApiBase::PARAM_DFLT => 10, 00218 ApiBase::PARAM_TYPE => 'limit', 00219 ApiBase::PARAM_MIN => 1, 00220 ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1, 00221 ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2 00222 ), 00223 'dir' => array( 00224 ApiBase::PARAM_DFLT => 'ascending', 00225 ApiBase::PARAM_TYPE => array( 00226 'ascending', 00227 'descending' 00228 ) 00229 ), 00230 ); 00231 } 00232 00233 public function getParamDescription() { 00234 $p = $this->getModulePrefix(); 00235 $link = $this->descriptionLink; 00236 $linking = $this->descriptionLinking; 00237 return array( 00238 'from' => "The title of the $link to start enumerating from", 00239 'to' => "The title of the $link to stop enumerating at", 00240 'prefix' => "Search for all $link titles that begin with this value", 00241 'unique' => array( 00242 "Only show distinct $link titles. Cannot be used with {$p}prop=ids.", 00243 'When used as a generator, yields target pages instead of source pages.', 00244 ), 00245 'prop' => array( 00246 'What pieces of information to include', 00247 " ids - Adds the pageid of the $linking page (Cannot be used with {$p}unique)", 00248 " title - Adds the title of the $link", 00249 ), 00250 'namespace' => 'The namespace to enumerate', 00251 'limit' => "How many total items to return", 00252 'continue' => 'When more results are available, use this to continue', 00253 'dir' => 'The direction in which to list', 00254 ); 00255 } 00256 00257 public function getResultProperties() { 00258 return array( 00259 'ids' => array( 00260 'fromid' => 'integer' 00261 ), 00262 'title' => array( 00263 'ns' => 'namespace', 00264 'title' => 'string' 00265 ) 00266 ); 00267 } 00268 00269 public function getDescription() { 00270 return $this->description; 00271 } 00272 00273 public function getPossibleErrors() { 00274 $m = $this->getModuleName(); 00275 $link = $this->descriptionLink; 00276 return array_merge( parent::getPossibleErrors(), array( 00277 array( 'code' => 'params', 'info' => "{$m} cannot return corresponding page ids in unique {$link}s mode" ), 00278 ) ); 00279 } 00280 00281 public function getExamples() { 00282 $p = $this->getModulePrefix(); 00283 $link = $this->descriptionLink; 00284 $linked = $this->descriptionLinked; 00285 return array( 00286 "api.php?action=query&list=all{$link}s&{$p}from=B&{$p}prop=ids|title" 00287 => "List $linked titles with page ids they are from, including missing ones. Start at B", 00288 "api.php?action=query&list=all{$link}s&{$p}unique=&{$p}from=B" 00289 => "List unique $linked titles", 00290 "api.php?action=query&generator=all{$link}s&g{$p}unique=&g{$p}from=B" 00291 => "Gets all $link targets, marking the missing ones", 00292 "api.php?action=query&generator=all{$link}s&g{$p}from=B" 00293 => "Gets pages containing the {$link}s", 00294 ); 00295 } 00296 00297 public function getHelpUrls() { 00298 return "https://www.mediawiki.org/wiki/API:All{$this->descriptionLink}s"; 00299 } 00300 }