15use Wikimedia\Timestamp\TimestampFormat as TS;
25 parent::__construct( $query, $moduleName,
'cl' );
39 $this->run( $resultPageSet );
45 private function run( $resultPageSet =
null ) {
47 if ( $pages === [] ) {
52 $prop = array_fill_keys( (array)$params[
'prop'],
true );
53 $show = array_fill_keys( (array)$params[
'show'],
true );
56 if ( $params[
'categories'] ) {
57 foreach ( $params[
'categories'] as $cat ) {
58 $title = Title::newFromText( $cat );
59 if ( !$title || $title->getNamespace() !==
NS_CATEGORY ) {
62 $cats[] = $title->getDBkey();
73 $hiddenCategories = [];
74 $needHidden = isset( $prop[
'hidden'] ) || isset( $show[
'!hidden'] ) || isset( $show[
'hidden'] );
75 $needFiltering = isset( $show[
'hidden'] ) || isset( $show[
'!hidden'] );
78 if ( $params[
'continue'] !==
null ) {
80 $continueFrom = [ $cont[0], $cont[1] ];
86 $categoryLinksDb = $this->
getDB();
88 $fields = [
'cl_from',
'lt_title' ];
89 if ( isset( $prop[
'sortkey'] ) ) {
90 $fields[] =
'cl_sortkey';
91 $fields[] =
'cl_sortkey_prefix';
93 if ( isset( $prop[
'timestamp'] ) ) {
94 $fields[] =
'cl_timestamp';
100 while ( count( $filteredRows ) < $params[
'limit'] + 1 ) {
101 if ( $loopCount > $maxLoops ) {
106 $queryBuilder = $categoryLinksDb->newSelectQueryBuilder()
108 ->from(
'categorylinks' )
109 ->join(
'linktarget',
null,
'cl_target_id = lt_id' )
110 ->where( [
'cl_from' => array_keys( $pages ),
'lt_namespace' =>
NS_CATEGORY ] )
111 ->caller( __METHOD__ );
113 if ( $cats !== [] ) {
114 $queryBuilder->andWhere( [
'lt_title' => $cats ] );
117 if ( $continueFrom !==
null ) {
119 if ( $isFirstBatch ) {
120 $op =
$params[
'dir'] ==
'descending' ?
'<=' :
'>=';
122 $op =
$params[
'dir'] ==
'descending' ?
'<' :
'>';
124 $queryBuilder->andWhere( $categoryLinksDb->buildComparison( $op, [
125 'cl_from' => $continueFrom[0],
126 'lt_title' => $continueFrom[1],
130 $sort = (
$params[
'dir'] ==
'descending' ?
' DESC' :
'' );
131 if ( count( $pages ) === 1 ) {
132 $queryBuilder->orderBy(
'lt_title' . $sort );
134 $queryBuilder->orderBy( [
'cl_from' . $sort,
'lt_title' . $sort ] );
136 $queryBuilder->limit( $params[
'limit'] + 1 );
138 $res = $queryBuilder->fetchResultSet();
140 $isFirstBatch =
false;
145 foreach ( $res as $row ) {
147 $categories[] = $row->lt_title;
150 if ( $categories === [] ) {
156 $hiddenQueryBuilder = $db->newSelectQueryBuilder()
157 ->select( [
'pp_page',
'pp_propname',
'page_title' ] )
158 ->from(
'page_props' )
159 ->join(
'page',
null,
'page_id = pp_page' )
161 'pp_propname' =>
'hiddencat',
163 'page_title' => $categories
165 ->caller( __METHOD__ );
167 $hiddenRes = $hiddenQueryBuilder->fetchResultSet();
169 foreach ( $hiddenRes as $hiddenRow ) {
170 $hiddenCategories[$hiddenRow->page_title] =
true;
174 if ( $needFiltering ) {
175 foreach ( $batchRows as $row ) {
176 if ( isset( $show[
'hidden'] ) === isset( $hiddenCategories[$row->lt_title] ) ) {
177 $filteredRows[] = $row;
181 $filteredRows = array_merge( $filteredRows, $batchRows );
184 if ( count( $batchRows ) < $params[
'limit'] + 1 ) {
189 $lastRow = end( $batchRows );
190 $continueFrom = [ $lastRow->cl_from, $lastRow->lt_title ];
196 if ( $resultPageSet ===
null ) {
197 foreach ( $filteredRows as $row ) {
198 if ( ++$count > $params[
'limit'] ) {
208 if ( isset( $prop[
'sortkey'] ) ) {
209 $vals[
'sortkey'] = bin2hex( $row->cl_sortkey );
210 $vals[
'sortkeyprefix'] = $row->cl_sortkey_prefix;
212 if ( isset( $prop[
'timestamp'] ) ) {
213 $vals[
'timestamp'] =
wfTimestamp( TS::ISO_8601, $row->cl_timestamp );
215 if ( isset( $prop[
'hidden'] ) ) {
216 $vals[
'hidden'] = isset( $hiddenCategories[$row->lt_title] );
227 foreach ( $filteredRows as $row ) {
228 if ( ++$count > $params[
'limit'] ) {
237 $resultPageSet->populateFromTitles( $titles );
245 ParamValidator::PARAM_ISMULTI =>
true,
246 ParamValidator::PARAM_TYPE => [
254 ParamValidator::PARAM_ISMULTI =>
true,
255 ParamValidator::PARAM_TYPE => [
261 ParamValidator::PARAM_DEFAULT => 10,
262 ParamValidator::PARAM_TYPE =>
'limit',
263 IntegerDef::PARAM_MIN => 1,
271 ParamValidator::PARAM_ISMULTI =>
true,
274 ParamValidator::PARAM_DEFAULT =>
'ascending',
275 ParamValidator::PARAM_TYPE => [
286 'action=query&prop=categories&titles=Albert%20Einstein'
287 =>
'apihelp-query+categories-example-simple',
288 'action=query&generator=categories&titles=Albert%20Einstein&prop=info'
289 =>
'apihelp-query+categories-example-generator',
295 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Categories';
300class_alias( ApiQueryCategories::class,
'ApiQueryCategories' );
wfEscapeWikiText( $input)
Escapes the given text so that it may be output using addWikiText() without any linking,...
wfTimestamp( $outputtype=TS::UNIX, $ts=0)
Get a timestamp string in one of various formats.