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 ApiQueryCategoryMembers extends ApiQueryGeneratorBase {
00037
00038 public function __construct($query, $moduleName) {
00039 parent :: __construct($query, $moduleName, 'cm');
00040 }
00041
00042 public function execute() {
00043 $this->run();
00044 }
00045
00046 public function getCacheMode( $params ) {
00047 return 'public';
00048 }
00049
00050 public function executeGenerator($resultPageSet) {
00051 $this->run($resultPageSet);
00052 }
00053
00054 private function run($resultPageSet = null) {
00055
00056 $params = $this->extractRequestParams();
00057
00058 if ( !isset($params['title']) || is_null($params['title']) )
00059 $this->dieUsage("The cmtitle parameter is required", 'notitle');
00060 $categoryTitle = Title::newFromText($params['title']);
00061
00062 if ( is_null( $categoryTitle ) || $categoryTitle->getNamespace() != NS_CATEGORY )
00063 $this->dieUsage("The category name you entered is not valid", 'invalidcategory');
00064
00065 $prop = array_flip($params['prop']);
00066 $fld_ids = isset($prop['ids']);
00067 $fld_title = isset($prop['title']);
00068 $fld_sortkey = isset($prop['sortkey']);
00069 $fld_timestamp = isset($prop['timestamp']);
00070
00071 if (is_null($resultPageSet)) {
00072 $this->addFields(array('cl_from', 'cl_sortkey', 'page_namespace', 'page_title'));
00073 $this->addFieldsIf('page_id', $fld_ids);
00074 } else {
00075 $this->addFields($resultPageSet->getPageTableFields());
00076 $this->addFields(array('cl_from', 'cl_sortkey'));
00077 }
00078
00079 $this->addFieldsIf('cl_timestamp', $fld_timestamp || $params['sort'] == 'timestamp');
00080 $this->addTables(array('page','categorylinks'));
00081
00082 if($params['sort'] == 'timestamp')
00083 $this->addOption('USE INDEX', 'cl_timestamp');
00084 else
00085 $this->addOption('USE INDEX', 'cl_sortkey');
00086
00087 $this->addWhere('cl_from=page_id');
00088 $this->setContinuation($params['continue'], $params['dir']);
00089 $this->addWhereFld('cl_to', $categoryTitle->getDBkey());
00090 $this->addWhereFld('page_namespace', $params['namespace']);
00091 if($params['sort'] == 'timestamp')
00092 $this->addWhereRange('cl_timestamp', ($params['dir'] == 'asc' ? 'newer' : 'older'), $params['start'], $params['end']);
00093 else
00094 {
00095 $this->addWhereRange('cl_sortkey', ($params['dir'] == 'asc' ? 'newer' : 'older'), $params['startsortkey'], $params['endsortkey']);
00096 $this->addWhereRange('cl_from', ($params['dir'] == 'asc' ? 'newer' : 'older'), null, null);
00097 }
00098
00099 $limit = $params['limit'];
00100 $this->addOption('LIMIT', $limit +1);
00101
00102 $db = $this->getDB();
00103
00104 $data = array ();
00105 $count = 0;
00106 $lastSortKey = null;
00107 $res = $this->select(__METHOD__);
00108 while ($row = $db->fetchObject($res)) {
00109 if (++ $count > $limit) {
00110
00111
00112 if ($params['sort'] == 'timestamp')
00113 $this->setContinueEnumParameter('start', wfTimestamp(TS_ISO_8601, $row->cl_timestamp));
00114 else
00115 $this->setContinueEnumParameter('continue', $this->getContinueStr($row, $lastSortKey));
00116 break;
00117 }
00118
00119 if (is_null($resultPageSet)) {
00120 $vals = array();
00121 if ($fld_ids)
00122 $vals['pageid'] = intval($row->page_id);
00123 if ($fld_title) {
00124 $title = Title :: makeTitle($row->page_namespace, $row->page_title);
00125 ApiQueryBase::addTitleInfo($vals, $title);
00126 }
00127 if ($fld_sortkey)
00128 $vals['sortkey'] = $row->cl_sortkey;
00129 if ($fld_timestamp)
00130 $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $row->cl_timestamp);
00131 $fit = $this->getResult()->addValue(array('query', $this->getModuleName()),
00132 null, $vals);
00133 if(!$fit)
00134 {
00135 if ($params['sort'] == 'timestamp')
00136 $this->setContinueEnumParameter('start', wfTimestamp(TS_ISO_8601, $row->cl_timestamp));
00137 else
00138 $this->setContinueEnumParameter('continue', $this->getContinueStr($row, $lastSortKey));
00139 break;
00140 }
00141 } else {
00142 $resultPageSet->processDbRow($row);
00143 }
00144 $lastSortKey = $row->cl_sortkey;
00145 }
00146 $db->freeResult($res);
00147
00148 if (is_null($resultPageSet)) {
00149 $this->getResult()->setIndexedTagName_internal(
00150 array('query', $this->getModuleName()), 'cm');
00151 }
00152 }
00153
00154 private function getContinueStr($row, $lastSortKey) {
00155 $ret = $row->cl_sortkey . '|';
00156 if ($row->cl_sortkey == $lastSortKey)
00157 $ret .= $row->cl_from;
00158 return $ret;
00159 }
00160
00164 private function setContinuation($continue, $dir) {
00165 if (is_null($continue))
00166 return;
00167
00168 $pos = strrpos($continue, '|');
00169 $sortkey = substr($continue, 0, $pos);
00170 $fromstr = substr($continue, $pos + 1);
00171 $from = intval($fromstr);
00172
00173 if ($from == 0 && strlen($fromstr) > 0)
00174 $this->dieUsage("Invalid continue param. You should pass the original value returned by the previous query", "badcontinue");
00175
00176 $encSortKey = $this->getDB()->addQuotes($sortkey);
00177 $encFrom = $this->getDB()->addQuotes($from);
00178
00179 $op = ($dir == 'desc' ? '<' : '>');
00180
00181 if ($from != 0) {
00182
00183 $this->addWhere( "cl_sortkey$op$encSortKey OR (cl_sortkey=$encSortKey AND cl_from$op=$encFrom)" );
00184 } else {
00185 $this->addWhere( "cl_sortkey$op=$encSortKey" );
00186 }
00187 }
00188
00189 public function getAllowedParams() {
00190 return array (
00191 'title' => null,
00192 'prop' => array (
00193 ApiBase :: PARAM_DFLT => 'ids|title',
00194 ApiBase :: PARAM_ISMULTI => true,
00195 ApiBase :: PARAM_TYPE => array (
00196 'ids',
00197 'title',
00198 'sortkey',
00199 'timestamp',
00200 )
00201 ),
00202 'namespace' => array (
00203 ApiBase :: PARAM_ISMULTI => true,
00204 ApiBase :: PARAM_TYPE => 'namespace',
00205 ),
00206 'continue' => null,
00207 'limit' => array (
00208 ApiBase :: PARAM_TYPE => 'limit',
00209 ApiBase :: PARAM_DFLT => 10,
00210 ApiBase :: PARAM_MIN => 1,
00211 ApiBase :: PARAM_MAX => ApiBase :: LIMIT_BIG1,
00212 ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2
00213 ),
00214 'sort' => array(
00215 ApiBase :: PARAM_DFLT => 'sortkey',
00216 ApiBase :: PARAM_TYPE => array(
00217 'sortkey',
00218 'timestamp'
00219 )
00220 ),
00221 'dir' => array(
00222 ApiBase :: PARAM_DFLT => 'asc',
00223 ApiBase :: PARAM_TYPE => array(
00224 'asc',
00225 'desc'
00226 )
00227 ),
00228 'start' => array(
00229 ApiBase :: PARAM_TYPE => 'timestamp'
00230 ),
00231 'end' => array(
00232 ApiBase :: PARAM_TYPE => 'timestamp'
00233 ),
00234 'startsortkey' => null,
00235 'endsortkey' => null,
00236 );
00237 }
00238
00239 public function getParamDescription() {
00240 return array (
00241 'title' => 'Which category to enumerate (required). Must include Category: prefix',
00242 'prop' => 'What pieces of information to include',
00243 'namespace' => 'Only include pages in these namespaces',
00244 'sort' => 'Property to sort by',
00245 'dir' => 'In which direction to sort',
00246 'start' => 'Timestamp to start listing from. Can only be used with cmsort=timestamp',
00247 'end' => 'Timestamp to end listing at. Can only be used with cmsort=timestamp',
00248 'startsortkey' => 'Sortkey to start listing from. Can only be used with cmsort=sortkey',
00249 'endsortkey' => 'Sortkey to end listing at. Can only be used with cmsort=sortkey',
00250 'continue' => 'For large categories, give the value retured from previous query',
00251 'limit' => 'The maximum number of pages to return.',
00252 );
00253 }
00254
00255 public function getDescription() {
00256 return 'List all pages in a given category';
00257 }
00258
00259 protected function getExamples() {
00260 return array (
00261 "Get first 10 pages in [[Category:Physics]]:",
00262 " api.php?action=query&list=categorymembers&cmtitle=Category:Physics",
00263 "Get page info about first 10 pages in [[Category:Physics]]:",
00264 " api.php?action=query&generator=categorymembers&gcmtitle=Category:Physics&prop=info",
00265 );
00266 }
00267
00268 public function getVersion() {
00269 return __CLASS__ . ': $Id: ApiQueryCategoryMembers.php 69986 2010-07-27 03:57:39Z tstarling $';
00270 }
00271 }