Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 59 additions & 20 deletions includes/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,15 @@
use function str_starts_with;
use function strtotime;
use function substr;
use function version_compare;
use function wfMessage;
use const MW_VERSION;
use const NS_CATEGORY;
use const NS_FILE;
use const NS_MAIN;
use const PREG_SPLIT_DELIM_CAPTURE;
use const PREG_SPLIT_NO_EMPTY;
use const SCHEMA_COMPAT_READ_NEW;

class Query {

Expand Down Expand Up @@ -345,25 +348,48 @@ public static function getSubcategories( string $categoryName, int $depth ): arr
->getReplicaDatabase( group: 'dpl4' );

if ( $depth > 2 ) {
// Hard constrain depth because lots of recursion is bad.
// Recursive limit to prevent full-blown explosion
$depth = 2;
}

$categories = $dbr->newSelectQueryBuilder()
->select( 'page_title' )
->from( 'page' )
->join( 'categorylinks', 'cl', 'p.page_id = cl.cl_from' )
->where( [
'p.page_namespace' => NS_CATEGORY,
'cl.cl_to' => str_replace( ' ', '_', $categoryName ),
] )
->caller( __METHOD__ )
$dbKey = str_replace( ' ', '_', $categoryName );

$isNewSchema = false;
if ( version_compare( MW_VERSION, '1.45', '>=' ) ) {
$config = Config::getInstance();
$schemaStage = $config->get( 'CategoryLinksSchemaMigrationStage' );
$isNewSchema = $schemaStage & SCHEMA_COMPAT_READ_NEW;
}

$queryBuilder = $dbr->newSelectQueryBuilder()
->select( 'p.page_title' )
->from( 'page', 'p' )
->where( [ 'p.page_namespace' => NS_CATEGORY ] )
->distinct()
->fetchFieldValues();
->caller( __METHOD__ );

if ( $isNewSchema ) {
$queryBuilder
->join( 'categorylinks', 'cl', 'p.page_id = cl.cl_from' )
->join( 'linktarget', 'lt', 'cl.cl_target_id = lt.lt_id' )
->andWhere( [
'lt.lt_namespace' => NS_CATEGORY,
'lt.lt_title' => $dbKey,
] );
} else {
$queryBuilder
->join( 'categorylinks', 'cl', 'p.page_id = cl.cl_from' )
->andWhere( [ 'cl.cl_to' => $dbKey ] );
}

$categories = $queryBuilder->fetchFieldValues();

foreach ( $categories as $category ) {
if ( $depth > 1 ) {
$categories = array_merge( $categories, self::getSubcategories( $category, $depth - 1 ) );
$categories = array_merge(
$categories,
self::getSubcategories( $category, $depth - 1 )
);
}
}

Expand Down Expand Up @@ -704,18 +730,31 @@ private function _allrevisionssince( string $option ): void {
* Set SQL for 'articlecategory' parameter.
*/
private function _articlecategory( string $option ): void {
$subquery = $this->queryBuilder->newSubquery()
$dbKey = str_replace( ' ', '_', $option );
$isNewSchema = false;
if ( version_compare( MW_VERSION, '1.45', '>=' ) ) {
$schemaStage = $this->config->get( 'CategoryLinksSchemaMigrationStage' );
$isNewSchema = $schemaStage & SCHEMA_COMPAT_READ_NEW;
}

$builder = $this->queryBuilder->newSubquery()
->select( 'p2.page_title' )
->from( 'page', 'p2' )
->join( 'categorylinks', 'clstc', 'clstc.cl_from = p2.page_id' )
->where( [
'clstc.cl_to' => $option,
'p2.page_namespace' => NS_MAIN,
] )
->caller( __METHOD__ )
->getSQL();
->where( [ 'p2.page_namespace' => NS_MAIN ] )
->caller( __METHOD__ );

if ( $isNewSchema ) {
$builder->join( 'linktarget', 'lt', 'lt.lt_id = clstc.cl_target_id' );
$builder->andWhere( [
'lt.lt_namespace' => NS_CATEGORY,
'lt.lt_title' => $dbKey,
] );
} else {
$builder->andWhere( [ 'clstc.cl_to' => $dbKey ] );
}

$this->queryBuilder->where( "p.page_title IN ($subquery)" );
$this->queryBuilder->where( 'p.page_title IN (' . $builder->getSQL() . ')' );
}

/**
Expand Down