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