2020-11-22 20:00:48 +00:00
< ? php
2021-10-01 22:52:30 +00:00
2022-03-13 19:57:34 +00:00
namespace MediaWiki\Extension\DynamicPageList3 ;
2020-11-22 20:00:48 +00:00
2021-10-01 22:52:30 +00:00
use DateInterval ;
use DateTime ;
use Exception ;
2022-03-20 17:15:43 +00:00
use ExtensionRegistry ;
2021-05-30 18:33:21 +00:00
use MediaWiki\MediaWikiServices ;
2021-10-06 18:44:11 +00:00
use MediaWiki\User\UserFactory ;
2021-10-01 22:52:30 +00:00
use MWException ;
2022-03-13 18:28:30 +00:00
use PoolCounterWorkViaCallback ;
use WANObjectCache ;
use WikiMap ;
use Wikimedia\Rdbms\Database ;
2021-10-01 22:52:30 +00:00
use Wikimedia\Rdbms\IDatabase ;
2021-05-30 18:33:21 +00:00
2020-11-22 20:00:48 +00:00
class Query {
/**
* Parameters Object
*
2021-10-01 22:52:30 +00:00
* @ var Parameters
2020-11-22 20:00:48 +00:00
*/
private $parameters ;
/**
* Mediawiki DB Object
*
2021-10-01 22:52:30 +00:00
* @ var IDatabase
2020-11-22 20:00:48 +00:00
*/
2022-03-13 18:28:30 +00:00
private $dbr ;
2020-11-22 20:00:48 +00:00
/**
* Array of prefixed and escaped table names .
*
2021-02-22 23:48:01 +00:00
* @ var array
2020-11-22 20:00:48 +00:00
*/
private $tableNames = [];
/**
* Parameters that have already been processed .
*
2021-02-22 23:48:01 +00:00
* @ var array
2020-11-22 20:00:48 +00:00
*/
private $parametersProcessed = [];
/**
* Select Fields
*
2021-02-22 23:48:01 +00:00
* @ var array
2020-11-22 20:00:48 +00:00
*/
private $select = [];
/**
* The generated SQL Query .
*
2021-02-22 23:48:01 +00:00
* @ var string
2020-11-22 20:00:48 +00:00
*/
private $sqlQuery = '' ;
/**
* Selected Fields - An array to look up keys against for speed optimization .
*
2021-02-22 23:48:01 +00:00
* @ var array
2020-11-22 20:00:48 +00:00
*/
private $selectedFields = [];
/**
* Prefixed and escaped table names .
*
2021-02-22 23:48:01 +00:00
* @ var array
2020-11-22 20:00:48 +00:00
*/
private $tables = [];
/**
* Where Clauses
*
2021-02-22 23:48:01 +00:00
* @ var array
2020-11-22 20:00:48 +00:00
*/
private $where = [];
/**
* Group By Clauses
*
2021-02-22 23:48:01 +00:00
* @ var array
2020-11-22 20:00:48 +00:00
*/
private $groupBy = [];
/**
* Order By Clauses
*
2021-02-22 23:48:01 +00:00
* @ var array
2020-11-22 20:00:48 +00:00
*/
private $orderBy = [];
/**
* Join Clauses
*
2021-02-22 23:48:01 +00:00
* @ var array
2020-11-22 20:00:48 +00:00
*/
private $join = [];
/**
* Limit
*
2021-10-01 22:52:30 +00:00
* @ var int | bool
2020-11-22 20:00:48 +00:00
*/
private $limit = false ;
/**
* Offset
*
2021-10-01 22:52:30 +00:00
* @ var int | bool
2020-11-22 20:00:48 +00:00
*/
private $offset = false ;
/**
* Order By Direction
*
2021-02-22 23:48:01 +00:00
* @ var string
2020-11-22 20:00:48 +00:00
*/
private $direction = 'ASC' ;
/**
* Distinct Results
*
2021-02-22 23:48:01 +00:00
* @ var bool
2020-11-22 20:00:48 +00:00
*/
private $distinct = true ;
/**
* Character Set Collation
*
2021-10-01 22:52:30 +00:00
* @ var string | bool
2020-11-22 20:00:48 +00:00
*/
private $collation = false ;
/**
* Was the revision auxiliary table select added for firstedit and lastedit ?
*
2021-02-22 23:48:01 +00:00
* @ var bool
2020-11-22 20:00:48 +00:00
*/
private $revisionAuxWhereAdded = false ;
2021-10-06 18:44:11 +00:00
/**
* UserFactory object
*
* @ var UserFactory
*/
private $userFactory ;
2020-11-22 20:00:48 +00:00
/**
2021-10-01 22:52:30 +00:00
* @ param Parameters $parameters
2021-10-06 18:44:11 +00:00
*/
public function __construct ( Parameters $parameters ) {
2020-11-22 20:00:48 +00:00
$this -> parameters = $parameters ;
$this -> tableNames = self :: getTableNames ();
2022-12-07 00:10:46 +00:00
$this -> dbr = MediaWikiServices :: getInstance () -> getDBLoadBalancer () -> getConnection ( DB_REPLICA , 'dpl' );
2021-10-06 18:44:11 +00:00
$this -> userFactory = MediaWikiServices :: getInstance () -> getUserFactory ();
2020-11-22 20:00:48 +00:00
}
/**
2022-03-13 18:28:30 +00:00
* Start a query build . Returns found rows .
2020-11-22 20:00:48 +00:00
*
2021-10-01 22:52:30 +00:00
* @ param bool $calcRows
2022-03-21 21:37:02 +00:00
* @ param ? int & $foundRows
2022-06-24 16:24:49 +00:00
* @ param string $profilingContext Used to see the origin of a query in the profiling
2022-03-13 18:28:30 +00:00
* @ return array | bool
2020-11-22 20:00:48 +00:00
*/
2022-06-24 16:24:49 +00:00
public function buildAndSelect ( bool $calcRows = false , ? int & $foundRows = null , $profilingContext = '' ) {
2022-03-20 23:14:44 +00:00
global $wgNonincludableNamespaces , $wgDebugDumpSql ;
2020-11-22 20:00:48 +00:00
$options = [];
$parameters = $this -> parameters -> getAllParameters ();
2021-02-22 23:48:01 +00:00
foreach ( $parameters as $parameter => $option ) {
2021-12-17 01:23:18 +00:00
$function = '_' . $parameter ;
// Some parameters do not modify the query so we check if the function to modify the query exists first.
2020-11-22 20:00:48 +00:00
$success = true ;
2021-02-22 23:48:01 +00:00
if ( method_exists ( $this , $function ) ) {
$success = $this -> $function ( $option );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( $success === false ) {
2021-10-01 22:52:30 +00:00
throw new MWException ( __METHOD__ . " : SQL Build Error returned from { $function } for " . serialize ( $option ) . " . " );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$this -> parametersProcessed [ $parameter ] = true ;
}
2021-02-22 23:48:01 +00:00
if ( ! $this -> parameters -> getParameter ( 'openreferences' ) ) {
2021-10-01 22:52:30 +00:00
// Add things that are always part of the query.
2021-02-22 23:48:01 +00:00
$this -> addTable ( 'page' , $this -> tableNames [ 'page' ] );
2020-11-22 20:00:48 +00:00
$this -> addSelect (
[
2021-12-15 20:22:38 +00:00
'page_namespace' => $this -> tableNames [ 'page' ] . '.page_namespace' ,
'page_id' => $this -> tableNames [ 'page' ] . '.page_id' ,
'page_title' => $this -> tableNames [ 'page' ] . '.page_title'
2020-11-22 20:00:48 +00:00
]
);
}
2021-10-01 22:52:30 +00:00
// Always add nonincludeable namespaces.
2021-02-22 23:48:01 +00:00
if ( is_array ( $wgNonincludableNamespaces ) && count ( $wgNonincludableNamespaces ) ) {
2020-11-22 20:00:48 +00:00
$this -> addNotWhere (
[
$this -> tableNames [ 'page' ] . '.page_namespace' => $wgNonincludableNamespaces
]
);
}
2021-02-22 23:48:01 +00:00
if ( $this -> offset !== false ) {
2020-11-22 20:00:48 +00:00
$options [ 'OFFSET' ] = $this -> offset ;
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( $this -> limit !== false ) {
2020-11-22 20:00:48 +00:00
$options [ 'LIMIT' ] = $this -> limit ;
2022-03-20 02:52:03 +00:00
} elseif ( $this -> offset !== false ) {
2021-09-25 02:56:23 +00:00
$options [ 'LIMIT' ] = $this -> parameters -> getParameter ( 'count' );
2020-11-22 20:00:48 +00:00
}
2021-02-22 23:48:01 +00:00
if ( $this -> parameters -> getParameter ( 'openreferences' ) ) {
2022-03-20 22:42:03 +00:00
if ( count ( $this -> parameters -> getParameter ( 'imagecontainer' ) ? ? [] ) > 0 ) {
2022-08-11 20:51:06 +00:00
$this -> addSelect (
[
'il_to' ,
]
);
2020-11-22 20:00:48 +00:00
$tables = [
2021-12-15 20:22:38 +00:00
'ic' => 'imagelinks'
2020-11-22 20:00:48 +00:00
];
} else {
2022-03-20 22:42:03 +00:00
if ( $this -> parameters -> getParameter ( 'openreferences' ) === 'missing' ) {
$this -> addSelect (
[
'page_namespace' ,
'page_id' ,
'page_title' ,
'pl_namespace' ,
'pl_title' ,
]
);
$this -> addWhere (
[
'page_namespace' => null ,
]
);
$this -> addJoin (
'page' ,
[
'LEFT JOIN' ,
[
'page_namespace = pl_namespace' ,
'page_title = pl_title' ,
],
]
);
$tables = [
'page' ,
'pagelinks' ,
];
} else {
$this -> addSelect (
[
'pl_namespace' ,
'pl_title' ,
]
);
$tables = [
'pagelinks' ,
];
}
2020-11-22 20:00:48 +00:00
}
} else {
$tables = $this -> tables ;
2021-02-22 23:48:01 +00:00
if ( count ( $this -> groupBy ) ) {
2020-11-22 20:00:48 +00:00
$options [ 'GROUP BY' ] = $this -> groupBy ;
}
2021-02-22 23:48:01 +00:00
if ( count ( $this -> orderBy ) ) {
2020-11-22 20:00:48 +00:00
$options [ 'ORDER BY' ] = $this -> orderBy ;
2021-02-22 23:48:01 +00:00
foreach ( $options [ 'ORDER BY' ] as $key => $value ) {
2021-12-17 01:23:18 +00:00
$options [ 'ORDER BY' ][ $key ] .= ' ' . $this -> direction ;
2020-11-22 20:00:48 +00:00
}
}
}
2021-02-22 23:48:01 +00:00
if ( $this -> parameters -> getParameter ( 'goal' ) == 'categories' ) {
2020-11-22 20:00:48 +00:00
$categoriesGoal = true ;
2022-03-13 18:28:30 +00:00
$fields = [
2020-11-22 20:00:48 +00:00
$this -> tableNames [ 'page' ] . '.page_id'
];
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$options [] = 'DISTINCT' ;
} else {
2021-02-22 23:48:01 +00:00
if ( $calcRows ) {
2020-11-22 20:00:48 +00:00
$options [] = 'SQL_CALC_FOUND_ROWS' ;
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( $this -> distinct ) {
2020-11-22 20:00:48 +00:00
$options [] = 'DISTINCT' ;
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$categoriesGoal = false ;
2022-03-13 18:28:30 +00:00
$fields = $this -> select ;
2020-11-22 20:00:48 +00:00
}
$queryError = false ;
try {
2021-02-22 23:48:01 +00:00
if ( $categoriesGoal ) {
2022-03-13 18:28:30 +00:00
$res = $this -> dbr -> select (
2020-11-22 20:00:48 +00:00
$tables ,
2022-03-13 18:28:30 +00:00
$fields ,
2020-11-22 20:00:48 +00:00
$this -> where ,
__METHOD__ ,
$options ,
$this -> join
);
2021-10-01 22:52:30 +00:00
$pageIds = [];
2022-03-13 18:28:30 +00:00
foreach ( $res as $row ) {
$pageIds [] = $row -> page_id ;
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2022-03-13 18:28:30 +00:00
$query = $this -> dbr -> selectSQLText (
2020-11-22 20:00:48 +00:00
[
2021-10-01 22:52:30 +00:00
'clgoal' => 'categorylinks'
2020-11-22 20:00:48 +00:00
],
[
'clgoal.cl_to'
],
[
2021-10-01 22:52:30 +00:00
'clgoal.cl_from' => $pageIds
2020-11-22 20:00:48 +00:00
],
__METHOD__ ,
[
2021-10-01 22:52:30 +00:00
'ORDER BY' => 'clgoal.cl_to ' . $this -> direction
2020-11-22 20:00:48 +00:00
]
);
} else {
2022-03-13 18:28:30 +00:00
$query = $this -> dbr -> selectSQLText (
2020-11-22 20:00:48 +00:00
$tables ,
2022-03-13 18:28:30 +00:00
$fields ,
2020-11-22 20:00:48 +00:00
$this -> where ,
__METHOD__ ,
$options ,
$this -> join
);
}
2022-03-20 23:14:44 +00:00
if ( Hooks :: getDebugLevel () >= 4 && $wgDebugDumpSql ) {
$this -> sqlQuery = $query ;
}
2021-02-22 23:48:01 +00:00
} catch ( Exception $e ) {
2022-03-13 19:57:34 +00:00
throw new MWException ( __METHOD__ . ': ' . wfMessage ( 'dpl_query_error' , Hooks :: getVersion (), $this -> dbr -> lastError () ) -> text () );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2022-03-13 18:28:30 +00:00
// Partially taken from intersection
$queryCacheTime = Config :: getSetting ( 'queryCacheTime' );
$maxQueryTime = Config :: getSetting ( 'maxQueryTime' );
if ( $maxQueryTime ) {
$options [ 'MAX_EXECUTION_TIME' ] = $maxQueryTime ;
}
2022-06-24 16:24:49 +00:00
$qname = __METHOD__ ;
if ( ! empty ( $profilingContext ) ) {
$qname .= ' - ' . $profilingContext ;
}
2022-03-13 18:28:30 +00:00
$where = $this -> where ;
$join = $this -> join ;
2022-03-21 21:37:02 +00:00
$db = $this -> dbr ;
$doQuery = static function () use ( $qname , $db , $tables , $fields , $where , $options , $join , $calcRows , & $foundRows ) {
$res = $db -> select ( $tables , $fields , $where , $qname , $options , $join );
if ( $calcRows ) {
$calcRowsResult = $db -> query ( 'SELECT FOUND_ROWS() AS count;' , $qname );
$total = $calcRowsResult -> fetchRow ();
$foundRows = ( int ) $total [ 'count' ];
}
2022-03-13 18:28:30 +00:00
return iterator_to_array ( $res );
};
$poolCounterKey = 'nowait:dpl3-query:' . WikiMap :: getCurrentWikiId ();
$worker = new PoolCounterWorkViaCallback ( 'DPL3' , $poolCounterKey , [
'doWork' => $doQuery ,
] );
if ( $queryCacheTime <= 0 ) {
return $worker -> execute ();
2020-11-22 20:00:48 +00:00
}
2022-03-13 18:28:30 +00:00
$cache = MediaWikiServices :: getInstance () -> getMainWANObjectCache ();
return $cache -> getWithSetCallback (
$cache -> makeKey ( 'DPL3Query' , hash ( 'sha256' , $query ) ),
$queryCacheTime ,
2022-03-21 21:37:02 +00:00
static function ( $oldVal , & $ttl , & $setOpts ) use ( $worker , $db ){
$setOpts += Database :: getCacheSetOptions ( $db );
2022-03-13 18:28:30 +00:00
$res = $worker -> execute ();
if ( $res === false ) {
// Do not cache errors.
$ttl = WANObjectCache :: TTL_UNCACHEABLE ;
// If we have oldVal, prefer it to error
if ( is_array ( $oldVal ) ) {
return $oldVal ;
}
}
return $res ;
},
[
'lowTTL' => min ( $cache :: TTL_MINUTE , floor ( $queryCacheTime * 0.75 ) ),
'pcTTL' => min ( $cache :: TTL_PROC_LONG , $queryCacheTime )
]
);
2020-11-22 20:00:48 +00:00
}
/**
* Returns the generated SQL Query
*
2021-10-01 22:52:30 +00:00
* @ return string
2020-11-22 20:00:48 +00:00
*/
public function getSqlQuery () {
return $this -> sqlQuery ;
}
/**
* Return prefixed and quoted tables that are needed .
*
2021-10-01 22:52:30 +00:00
* @ return array
2020-11-22 20:00:48 +00:00
*/
public static function getTableNames () {
2022-12-07 00:10:46 +00:00
$dbr = MediaWikiServices :: getInstance () -> getDBLoadBalancer () -> getConnection ( DB_REPLICA , 'dpl' );
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$tables = [
'categorylinks' ,
'dpl_clview' ,
'externallinks' ,
'flaggedpages' ,
'imagelinks' ,
2022-12-07 00:10:46 +00:00
'linktarget' ,
2020-11-22 20:00:48 +00:00
'page' ,
'pagelinks' ,
'recentchanges' ,
'revision' ,
'templatelinks'
];
$tableNames = [];
2021-02-22 23:48:01 +00:00
foreach ( $tables as $table ) {
2022-03-13 18:28:30 +00:00
$tableNames [ $table ] = $dbr -> tableName ( $table );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
return $tableNames ;
}
/**
* Add a table to the output .
*
2021-10-01 22:52:30 +00:00
* @ param string $table
* @ param string $alias
* @ return bool
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
public function addTable ( $table , $alias ) {
if ( empty ( $table ) ) {
2021-10-01 22:52:30 +00:00
throw new MWException ( __METHOD__ . ': An empty table name was passed.' );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( empty ( $alias ) || is_numeric ( $alias ) ) {
2021-10-01 22:52:30 +00:00
throw new MWException ( __METHOD__ . ': An empty or numeric table alias was passed.' );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( ! isset ( $this -> tables [ $alias ] ) ) {
2022-03-13 18:28:30 +00:00
$this -> tables [ $alias ] = $this -> dbr -> tableName ( $table );
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
return true ;
} else {
return false ;
}
}
2021-10-01 22:52:30 +00:00
/**
* Add multiple tables to the output .
*
2022-12-07 00:10:46 +00:00
* @ param array $tablesByAlias [ table => alias ]
2021-10-01 22:52:30 +00:00
*/
public function addTables ( array $tablesByAlias ) {
2022-12-07 00:10:46 +00:00
foreach ( $tablesByAlias as $table => $alias ) {
2021-10-01 22:52:30 +00:00
$this -> addTable ( $table , $alias );
}
}
2020-11-22 20:00:48 +00:00
/**
* Add a where clause to the output .
2021-10-01 22:52:30 +00:00
* Where clauses get imploded together with AND at the end . Any custom where clauses should be preformed before placed into here .
2020-11-22 20:00:48 +00:00
*
2021-10-01 22:52:30 +00:00
* @ param array | string $where
* @ return bool
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
public function addWhere ( $where ) {
if ( empty ( $where ) ) {
2021-10-01 22:52:30 +00:00
throw new MWException ( __METHOD__ . ': An empty where clause was passed.' );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( is_string ( $where ) ) {
2020-11-22 20:00:48 +00:00
$this -> where [] = $where ;
2021-02-22 23:48:01 +00:00
} elseif ( is_array ( $where ) ) {
$this -> where = array_merge ( $this -> where , $where );
2020-11-22 20:00:48 +00:00
} else {
2021-10-01 22:52:30 +00:00
throw new MWException ( __METHOD__ . ': An invalid where clause was passed.' );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
return true ;
}
/**
* Add a where clause to the output that uses NOT IN or !=.
*
2021-10-01 22:52:30 +00:00
* @ param array $where
* @ return bool
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
public function addNotWhere ( $where ) {
if ( empty ( $where ) ) {
2021-10-01 22:52:30 +00:00
throw new MWException ( __METHOD__ . ': An empty not where clause was passed.' );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( is_array ( $where ) ) {
foreach ( $where as $field => $values ) {
2022-03-13 18:28:30 +00:00
$this -> where [] = $field . ( count ( $values ) > 1 ? ' NOT IN(' . $this -> dbr -> makeList ( $values ) . ')' : ' != ' . $this -> dbr -> addQuotes ( current ( $values ) ) );
2020-11-22 20:00:48 +00:00
}
} else {
2021-12-17 01:23:18 +00:00
throw new MWException ( __METHOD__ . ': An invalid NOT WHERE clause was passed.' );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
return true ;
}
/**
* Add a field to select .
* Will ignore duplicate values if the exact same alias and exact same field are passed .
*
2021-10-01 22:52:30 +00:00
* @ param array $fields
* @ return bool
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
public function addSelect ( $fields ) {
if ( ! is_array ( $fields ) ) {
2021-10-01 22:52:30 +00:00
throw new MWException ( __METHOD__ . ': A non-array was passed.' );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
foreach ( $fields as $alias => $field ) {
if ( ! is_numeric ( $alias ) && array_key_exists ( $alias , $this -> select ) && $this -> select [ $alias ] != $field ) {
2021-10-01 22:52:30 +00:00
// In case of a code bug that is overwriting an existing field alias throw an exception.
throw new MWException ( __METHOD__ . " : Attempted to overwrite existing field alias ` { $this -> select [ $alias ] } ` AS ` { $alias } ` with ` { $field } ` AS ` { $alias } `. " );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
// String alias and does not exist already.
2021-02-22 23:48:01 +00:00
if ( ! is_numeric ( $alias ) && ! array_key_exists ( $alias , $this -> select ) ) {
2020-11-22 20:00:48 +00:00
$this -> select [ $alias ] = $field ;
}
2021-10-01 22:52:30 +00:00
// Speed up by not using in_array() or array_key_exists(). Toss the field names into their own array as keys => true to exploit a speedy look up with isset().
2021-02-22 23:48:01 +00:00
if ( is_numeric ( $alias ) && ! isset ( $this -> selectedFields [ $field ] ) ) {
2020-11-22 20:00:48 +00:00
$this -> select [] = $field ;
$this -> selectedFields [ $field ] = true ;
}
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
return true ;
}
/**
* Add a GROUP BY clause to the output .
*
2021-10-01 22:52:30 +00:00
* @ param string $groupBy
* @ return bool
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
public function addGroupBy ( $groupBy ) {
if ( empty ( $groupBy ) ) {
2021-12-17 01:23:18 +00:00
throw new MWException ( __METHOD__ . ': An empty GROUP BY clause was passed.' );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$this -> groupBy [] = $groupBy ;
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
return true ;
}
/**
* Add a ORDER BY clause to the output .
*
2021-10-01 22:52:30 +00:00
* @ param string $orderBy
* @ return bool
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
public function addOrderBy ( $orderBy ) {
if ( empty ( $orderBy ) ) {
2021-12-17 01:23:18 +00:00
throw new MWException ( __METHOD__ . ': An empty ORDER BY clause was passed.' );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$this -> orderBy [] = $orderBy ;
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
return true ;
}
/**
* Add a JOIN clause to the output .
*
2021-10-01 22:52:30 +00:00
* @ param string $tableAlias
* @ param array $joinConditions
* @ return bool
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
public function addJoin ( $tableAlias , $joinConditions ) {
if ( empty ( $tableAlias ) || empty ( $joinConditions ) ) {
2021-12-17 01:23:18 +00:00
throw new MWException ( __METHOD__ . ': An empty JOIN clause was passed.' );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( isset ( $this -> join [ $tableAlias ] ) ) {
2021-12-17 01:23:18 +00:00
throw new MWException ( __METHOD__ . ': Attempted to overwrite existing JOIN clause.' );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$this -> join [ $tableAlias ] = $joinConditions ;
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
return true ;
}
2022-03-22 19:59:52 +00:00
/**
* @ param array $joins
*/
2021-10-01 22:52:30 +00:00
public function addJoins ( array $joins ) {
foreach ( $joins as $alias => $conds ) {
$this -> addJoin ( $alias , $conds );
}
}
2020-11-22 20:00:48 +00:00
/**
* Set the limit .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $limit
* @ return bool
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
public function setLimit ( $limit ) {
if ( is_numeric ( $limit ) ) {
2022-12-07 00:10:46 +00:00
$this -> limit = ( int ) $limit ;
2020-11-22 20:00:48 +00:00
} else {
$this -> limit = false ;
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
return true ;
}
/**
* Set the offset .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $offset
* @ return bool
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
public function setOffset ( $offset ) {
if ( is_numeric ( $offset ) ) {
2022-12-07 00:10:46 +00:00
$this -> offset = ( int ) $offset ;
2020-11-22 20:00:48 +00:00
} else {
$this -> offset = false ;
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
return true ;
}
/**
* Set the ORDER BY direction
*
2021-10-01 22:52:30 +00:00
* @ param string $direction
* @ return bool
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
public function setOrderDir ( $direction ) {
2020-11-22 20:00:48 +00:00
$this -> direction = $direction ;
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
return true ;
}
/**
* Set the character set collation .
*
2021-10-01 22:52:30 +00:00
* @ param string $collation
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
public function setCollation ( $collation ) {
2020-11-22 20:00:48 +00:00
$this -> collation = $collation ;
}
/**
* Return SQL prefixed collation .
*
2021-10-01 22:52:30 +00:00
* @ return string | null
2020-11-22 20:00:48 +00:00
*/
public function getCollateSQL () {
2021-02-22 23:48:01 +00:00
return ( $this -> collation !== false ? 'COLLATE ' . $this -> collation : null );
2020-11-22 20:00:48 +00:00
}
/**
* Recursively get and return an array of subcategories .
*
2021-10-01 22:52:30 +00:00
* @ param string $categoryName
* @ param int $depth
* @ return array
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
public static function getSubcategories ( $categoryName , $depth = 1 ) {
2022-12-07 00:10:46 +00:00
$dbr = MediaWikiServices :: getInstance () -> getDBLoadBalancer () -> getConnection ( DB_REPLICA , 'dpl' );
2020-11-22 20:00:48 +00:00
2021-02-22 23:48:01 +00:00
if ( $depth > 2 ) {
2021-10-01 22:52:30 +00:00
// Hard constrain depth because lots of recursion is bad.
2020-11-22 20:00:48 +00:00
$depth = 2 ;
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$categories = [];
2022-03-13 18:28:30 +00:00
$res = $dbr -> select (
2021-02-22 23:48:01 +00:00
[ 'page' , 'categorylinks' ],
[ 'page_title' ],
2020-11-22 20:00:48 +00:00
[
2022-12-07 00:10:46 +00:00
'page_namespace' => NS_CATEGORY ,
2021-12-16 22:18:01 +00:00
'cl_to' => str_replace ( ' ' , '_' , $categoryName )
2020-11-22 20:00:48 +00:00
],
__METHOD__ ,
2021-02-22 23:48:01 +00:00
[ 'DISTINCT' ],
2020-11-22 20:00:48 +00:00
[
'categorylinks' => [
'INNER JOIN' ,
2021-12-16 22:18:01 +00:00
'page_id = cl_from'
2020-11-22 20:00:48 +00:00
]
]
);
2021-10-01 22:52:30 +00:00
2022-03-13 18:28:30 +00:00
foreach ( $res as $row ) {
$categories [] = $row -> page_title ;
2021-02-22 23:48:01 +00:00
if ( $depth > 1 ) {
2022-03-13 18:28:30 +00:00
$categories = array_merge ( $categories , self :: getSubcategories ( $row -> page_title , $depth - 1 ) );
2020-11-22 20:00:48 +00:00
}
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$categories = array_unique ( $categories );
2022-03-13 18:28:30 +00:00
$res -> free ();
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
return $categories ;
}
/**
* Helper method to handle relative timestamps .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $inputDate
* @ return int | string
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function convertTimestamp ( $inputDate ) {
2020-11-22 20:00:48 +00:00
$timestamp = $inputDate ;
2021-02-22 23:48:01 +00:00
switch ( $inputDate ) {
2020-11-22 20:00:48 +00:00
case 'today' :
2021-02-22 23:48:01 +00:00
$timestamp = date ( 'YmdHis' );
2020-11-22 20:00:48 +00:00
break ;
case 'last hour' :
2021-10-01 22:52:30 +00:00
$date = new DateTime ();
$date -> sub ( new DateInterval ( 'P1H' ) );
2021-02-22 23:48:01 +00:00
$timestamp = $date -> format ( 'YmdHis' );
2020-11-22 20:00:48 +00:00
break ;
case 'last day' :
2021-10-01 22:52:30 +00:00
$date = new DateTime ();
$date -> sub ( new DateInterval ( 'P1D' ) );
2021-02-22 23:48:01 +00:00
$timestamp = $date -> format ( 'YmdHis' );
2020-11-22 20:00:48 +00:00
break ;
case 'last week' :
2021-10-01 22:52:30 +00:00
$date = new DateTime ();
$date -> sub ( new DateInterval ( 'P7D' ) );
2021-02-22 23:48:01 +00:00
$timestamp = $date -> format ( 'YmdHis' );
2020-11-22 20:00:48 +00:00
break ;
case 'last month' :
2021-10-01 22:52:30 +00:00
$date = new DateTime ();
$date -> sub ( new DateInterval ( 'P1M' ) );
2021-02-22 23:48:01 +00:00
$timestamp = $date -> format ( 'YmdHis' );
2020-11-22 20:00:48 +00:00
break ;
case 'last year' :
2021-10-01 22:52:30 +00:00
$date = new DateTime ();
$date -> sub ( new DateInterval ( 'P1Y' ) );
2021-02-22 23:48:01 +00:00
$timestamp = $date -> format ( 'YmdHis' );
2020-11-22 20:00:48 +00:00
break ;
}
2021-02-22 23:48:01 +00:00
if ( is_numeric ( $timestamp ) ) {
2022-03-13 18:28:30 +00:00
return $this -> dbr -> addQuotes ( $timestamp );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
return 0 ;
}
/**
* Set SQL for 'addauthor' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _addauthor ( $option ) {
2021-10-01 22:52:30 +00:00
// Addauthor can not be used with addlasteditor.
2021-02-22 23:48:01 +00:00
if ( ! isset ( $this -> parametersProcessed [ 'addlasteditor' ] ) || ! $this -> parametersProcessed [ 'addlasteditor' ] ) {
2022-12-07 00:10:46 +00:00
$this -> addTable ( 'revision' , 'rev' );
2021-10-06 18:44:11 +00:00
$this -> addWhere (
[
2022-12-07 00:10:46 +00:00
$this -> tableNames [ 'page' ] . '.page_id = rev.rev_page' ,
2023-04-24 04:17:58 +00:00
'rev.rev_timestamp = (SELECT MIN(rev_aux_min.rev_timestamp) FROM ' . $this -> tableNames [ 'revision' ] . ' AS rev_aux_min WHERE rev_aux_min.rev_page = page_id)'
2021-10-06 18:44:11 +00:00
]
2020-11-22 20:00:48 +00:00
);
2021-10-06 18:44:11 +00:00
$this -> _adduser ( null , 'rev' );
2020-11-22 20:00:48 +00:00
}
}
/**
* Set SQL for 'addcategories' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _addcategories ( $option ) {
$this -> addTable ( 'categorylinks' , 'cl_gc' );
2020-11-22 20:00:48 +00:00
$this -> addSelect (
[
'cats' => " GROUP_CONCAT(DISTINCT cl_gc.cl_to ORDER BY cl_gc.cl_to ASC SEPARATOR ' | ') "
]
);
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$this -> addJoin (
'cl_gc' ,
[
'LEFT OUTER JOIN' ,
'page_id = cl_gc.cl_from'
]
);
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$this -> addGroupBy ( $this -> tableNames [ 'page' ] . '.page_id' );
2020-11-22 20:00:48 +00:00
}
/**
* Set SQL for 'addcontribution' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _addcontribution ( $option ) {
2021-10-06 18:44:11 +00:00
$this -> addTable ( 'recentchanges' , 'rc' );
2021-12-17 01:23:18 +00:00
$this -> addSelect (
2021-10-06 18:44:11 +00:00
[
2021-12-15 20:22:38 +00:00
'contribution' => 'SUM(ABS(rc.rc_new_len - rc.rc_old_len))' ,
2021-12-17 01:23:18 +00:00
'contributor' => 'rc.rc_actor'
2021-10-06 18:44:11 +00:00
]
);
2020-11-22 20:00:48 +00:00
2021-10-06 18:44:11 +00:00
$this -> addWhere (
[
$this -> tableNames [ 'page' ] . '.page_id = rc.rc_cur_id'
]
);
2020-11-22 20:00:48 +00:00
2021-10-06 18:44:11 +00:00
$this -> addGroupBy ( 'rc.rc_cur_id' );
2020-11-22 20:00:48 +00:00
}
/**
* Set SQL for 'addeditdate' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _addeditdate ( $option ) {
2022-12-07 00:10:46 +00:00
$this -> addTable ( 'revision' , 'rev' );
$this -> addSelect ( [ 'rev.rev_timestamp' ] );
2021-10-06 18:44:11 +00:00
2020-11-22 20:00:48 +00:00
$this -> addWhere (
[
2022-12-07 00:10:46 +00:00
$this -> tableNames [ 'page' ] . '.page_id = rev.rev_page' ,
2020-11-22 20:00:48 +00:00
]
);
}
/**
* Set SQL for 'addfirstcategorydate' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _addfirstcategorydate ( $option ) {
2021-10-01 22:52:30 +00:00
// @TODO: This should be programmatically determining which categorylink table to use instead of assuming the first one.
2020-11-22 20:00:48 +00:00
$this -> addSelect (
[
2021-12-15 20:22:38 +00:00
'cl_timestamp' => " DATE_FORMAT(cl1.cl_timestamp, '%Y%m%d%H%i%s') "
2020-11-22 20:00:48 +00:00
]
);
}
/**
* Set SQL for 'addlasteditor' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _addlasteditor ( $option ) {
2021-10-01 22:52:30 +00:00
// Addlasteditor can not be used with addauthor.
2021-02-22 23:48:01 +00:00
if ( ! isset ( $this -> parametersProcessed [ 'addauthor' ] ) || ! $this -> parametersProcessed [ 'addauthor' ] ) {
2022-12-07 00:10:46 +00:00
$this -> addTable ( 'revision' , 'rev' );
2021-10-06 18:44:11 +00:00
$this -> addWhere (
[
2022-12-07 00:10:46 +00:00
$this -> tableNames [ 'page' ] . '.page_id = rev.rev_page' ,
2023-04-24 04:17:58 +00:00
'rev.rev_timestamp = (SELECT MAX(rev_aux_max.rev_timestamp) FROM ' . $this -> tableNames [ 'revision' ] . ' AS rev_aux_max WHERE rev_aux_max.rev_page = page_id)'
2021-10-06 18:44:11 +00:00
]
);
$this -> _adduser ( null , 'rev' );
2020-11-22 20:00:48 +00:00
}
}
/**
* Set SQL for 'addpagecounter' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _addpagecounter ( $option ) {
2022-03-20 17:15:43 +00:00
if ( ExtensionRegistry :: getInstance () -> isLoaded ( 'HitCounters' ) ) {
2021-02-22 23:48:01 +00:00
$this -> addTable ( 'hit_counter' , 'hit_counter' );
2020-11-22 20:00:48 +00:00
$this -> addSelect (
[
2021-12-17 01:23:18 +00:00
'page_counter' => 'hit_counter.page_counter'
2020-11-22 20:00:48 +00:00
]
);
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( ! isset ( $this -> join [ 'hit_counter' ] ) ) {
2020-11-22 20:00:48 +00:00
$this -> addJoin (
'hit_counter' ,
[
2021-12-17 01:23:18 +00:00
'LEFT JOIN' ,
'hit_counter.page_id = ' . $this -> tableNames [ 'page' ] . '.page_id'
2020-11-22 20:00:48 +00:00
]
);
}
}
}
/**
* Set SQL for 'addpagesize' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _addpagesize ( $option ) {
2020-11-22 20:00:48 +00:00
$this -> addSelect (
[
2021-12-17 01:23:18 +00:00
'page_len' => " { $this -> tableNames [ 'page' ] } .page_len "
2020-11-22 20:00:48 +00:00
]
);
}
/**
* Set SQL for 'addpagetoucheddate' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _addpagetoucheddate ( $option ) {
2020-11-22 20:00:48 +00:00
$this -> addSelect (
[
2021-12-17 01:23:18 +00:00
'page_touched' => " { $this -> tableNames [ 'page' ] } .page_touched "
2020-11-22 20:00:48 +00:00
]
);
}
2021-10-06 18:44:11 +00:00
/**
* Set SQL for 'adduser' parameter .
*
* @ param mixed $option
* @ param string $tableAlias
*/
private function _adduser ( $option , $tableAlias = '' ) {
$tableAlias = ( ! empty ( $tableAlias ) ? $tableAlias . '.' : '' );
$this -> addSelect (
[
2022-12-07 00:10:46 +00:00
$tableAlias . 'rev_actor' ,
2021-10-06 18:44:11 +00:00
]
);
}
2020-11-22 20:00:48 +00:00
/**
* Set SQL for 'allrevisionsbefore' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _allrevisionsbefore ( $option ) {
2022-12-07 00:10:46 +00:00
$this -> addTable ( 'revision' , 'rev' );
2020-11-22 20:00:48 +00:00
$this -> addSelect (
[
2022-12-07 00:10:46 +00:00
'rev.rev_id' ,
'rev.rev_timestamp'
2020-11-22 20:00:48 +00:00
]
);
2021-10-01 22:52:30 +00:00
2022-12-07 00:10:46 +00:00
$this -> addOrderBy ( 'rev.rev_id' );
2021-02-22 23:48:01 +00:00
$this -> setOrderDir ( 'DESC' );
2021-10-06 18:44:11 +00:00
2020-11-22 20:00:48 +00:00
$this -> addWhere (
[
2022-12-07 00:10:46 +00:00
$this -> tableNames [ 'page' ] . '.page_id = rev.rev_page' ,
'rev.rev_timestamp < ' . $this -> convertTimestamp ( $option )
2020-11-22 20:00:48 +00:00
]
);
}
/**
* Set SQL for 'allrevisionssince' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _allrevisionssince ( $option ) {
2022-12-07 00:10:46 +00:00
$this -> addTable ( 'revision' , 'rev' );
2020-11-22 20:00:48 +00:00
$this -> addSelect (
[
2022-12-07 00:10:46 +00:00
'rev.rev_id' ,
'rev.rev_timestamp'
2020-11-22 20:00:48 +00:00
]
);
2021-10-01 22:52:30 +00:00
2022-12-07 00:10:46 +00:00
$this -> addOrderBy ( 'rev.rev_id' );
2021-02-22 23:48:01 +00:00
$this -> setOrderDir ( 'DESC' );
2021-10-06 18:44:11 +00:00
2020-11-22 20:00:48 +00:00
$this -> addWhere (
[
2022-12-07 00:10:46 +00:00
$this -> tableNames [ 'page' ] . '.page_id = rev.rev_page' ,
'rev.rev_timestamp >= ' . $this -> convertTimestamp ( $option )
2020-11-22 20:00:48 +00:00
]
);
}
/**
* Set SQL for 'articlecategory' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _articlecategory ( $option ) {
2022-03-13 18:28:30 +00:00
$this -> addWhere ( " { $this -> tableNames [ 'page' ] } .page_title IN (SELECT p2.page_title FROM { $this -> tableNames [ 'page' ] } p2 INNER JOIN { $this -> tableNames [ 'categorylinks' ] } clstc ON (clstc.cl_from = p2.page_id AND clstc.cl_to = " . $this -> dbr -> addQuotes ( $option ) . " ) WHERE p2.page_namespace = 0) " );
2020-11-22 20:00:48 +00:00
}
/**
* Set SQL for 'categoriesminmax' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _categoriesminmax ( $option ) {
if ( is_numeric ( $option [ 0 ] ) ) {
2022-12-07 00:10:46 +00:00
$this -> addWhere ( ( int ) $option [ 0 ] . ' <= (SELECT count(*) FROM ' . $this -> tableNames [ 'categorylinks' ] . ' WHERE ' . $this -> tableNames [ 'categorylinks' ] . '.cl_from=page_id)' );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
if ( isset ( $option [ 1 ] ) && is_numeric ( $option [ 1 ] ) ) {
2022-12-07 00:10:46 +00:00
$this -> addWhere ( ( int ) $option [ 1 ] . ' >= (SELECT count(*) FROM ' . $this -> tableNames [ 'categorylinks' ] . ' WHERE ' . $this -> tableNames [ 'categorylinks' ] . '.cl_from=page_id)' );
2020-11-22 20:00:48 +00:00
}
}
/**
2021-10-01 22:52:30 +00:00
* Set SQL for 'category' parameter . This includes 'category' , 'categorymatch' , and 'categoryregexp' .
2020-11-22 20:00:48 +00:00
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _category ( $option ) {
2020-11-22 20:00:48 +00:00
$i = 0 ;
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
foreach ( $option as $comparisonType => $operatorTypes ) {
foreach ( $operatorTypes as $operatorType => $categoryGroups ) {
foreach ( $categoryGroups as $categories ) {
if ( ! is_array ( $categories ) ) {
2020-11-22 20:00:48 +00:00
continue ;
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$tableName = ( in_array ( '' , $categories ) ? 'dpl_clview' : 'categorylinks' );
if ( $operatorType == 'AND' ) {
foreach ( $categories as $category ) {
2020-11-22 20:00:48 +00:00
$i ++ ;
$tableAlias = " cl { $i } " ;
2021-02-22 23:48:01 +00:00
$this -> addTable ( $tableName , $tableAlias );
2020-11-22 20:00:48 +00:00
$this -> addJoin (
$tableAlias ,
[
'INNER JOIN' ,
2022-03-13 18:28:30 +00:00
" { $this -> tableNames [ 'page' ] } .page_id = { $tableAlias } .cl_from AND $tableAlias .cl_to { $comparisonType } " . $this -> dbr -> addQuotes ( str_replace ( ' ' , '_' , $category ) )
2020-11-22 20:00:48 +00:00
]
);
}
2021-02-22 23:48:01 +00:00
} elseif ( $operatorType == 'OR' ) {
2020-11-22 20:00:48 +00:00
$i ++ ;
$tableAlias = " cl { $i } " ;
2021-02-22 23:48:01 +00:00
$this -> addTable ( $tableName , $tableAlias );
2020-11-22 20:00:48 +00:00
$joinOn = " { $this -> tableNames [ 'page' ] } .page_id = { $tableAlias } .cl_from AND ( " ;
$ors = [];
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
foreach ( $categories as $category ) {
2022-03-13 18:28:30 +00:00
$ors [] = " { $tableAlias } .cl_to { $comparisonType } " . $this -> dbr -> addQuotes ( str_replace ( ' ' , '_' , $category ) );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$joinOn .= implode ( " { $operatorType } " , $ors );
2020-11-22 20:00:48 +00:00
$joinOn .= ')' ;
$this -> addJoin (
$tableAlias ,
[
'INNER JOIN' ,
$joinOn
]
);
}
}
}
}
}
/**
* Set SQL for 'notcategory' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _notcategory ( $option ) {
2020-11-22 20:00:48 +00:00
$i = 0 ;
2021-02-22 23:48:01 +00:00
foreach ( $option as $operatorType => $categories ) {
foreach ( $categories as $category ) {
2020-11-22 20:00:48 +00:00
$i ++ ;
$tableAlias = " ecl { $i } " ;
2021-02-22 23:48:01 +00:00
$this -> addTable ( 'categorylinks' , $tableAlias );
2020-11-22 20:00:48 +00:00
$this -> addJoin (
$tableAlias ,
[
'LEFT OUTER JOIN' ,
2022-03-13 18:28:30 +00:00
" { $this -> tableNames [ 'page' ] } .page_id = { $tableAlias } .cl_from AND { $tableAlias } .cl_to { $operatorType } " . $this -> dbr -> addQuotes ( str_replace ( ' ' , '_' , $category ) )
2020-11-22 20:00:48 +00:00
]
);
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$this -> addWhere (
[
2021-12-15 20:22:38 +00:00
" { $tableAlias } .cl_to " => null
2020-11-22 20:00:48 +00:00
]
);
}
}
}
/**
* Set SQL for 'createdby' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _createdby ( $option ) {
2021-10-06 18:44:11 +00:00
$this -> addTable ( 'revision' , 'creation_rev' );
2022-12-07 00:10:46 +00:00
$this -> _adduser ( null , 'creation_rev' );
2021-10-06 18:44:11 +00:00
$this -> addWhere (
[
2022-12-07 00:10:46 +00:00
$this -> dbr -> addQuotes ( $this -> userFactory -> newFromName ( $option ) -> getActorId () ) . ' = creation_rev.rev_actor' ,
'creation_rev.rev_page = page_id' ,
2021-10-06 18:44:11 +00:00
'creation_rev.rev_parent_id = 0'
]
);
2020-11-22 20:00:48 +00:00
}
/**
* Set SQL for 'distinct' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _distinct ( $option ) {
if ( $option == 'strict' || $option === true ) {
2020-11-22 20:00:48 +00:00
$this -> distinct = true ;
} else {
$this -> distinct = false ;
}
}
/**
* Set SQL for 'firstrevisionsince' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _firstrevisionsince ( $option ) {
2022-12-07 00:10:46 +00:00
$this -> addTable ( 'revision' , 'rev' );
2020-11-22 20:00:48 +00:00
$this -> addSelect (
[
2022-12-07 00:10:46 +00:00
'rev.rev_id' ,
'rev.rev_timestamp'
2020-11-22 20:00:48 +00:00
]
);
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
// tell the query optimizer not to look at rows that the following subquery will filter out anyway
$this -> addWhere (
[
2022-12-07 00:10:46 +00:00
$this -> tableNames [ 'page' ] . '.page_id = rev.rev_page' ,
'rev.rev_timestamp >= ' . $this -> dbr -> addQuotes ( $option )
2020-11-22 20:00:48 +00:00
]
);
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$this -> addWhere (
[
2022-12-07 00:10:46 +00:00
$this -> tableNames [ 'page' ] . '.page_id = rev.rev_page' ,
2023-04-24 04:17:58 +00:00
'rev.rev_timestamp = (SELECT MIN(rev_aux_snc.rev_timestamp) FROM ' . $this -> tableNames [ 'revision' ] . ' AS rev_aux_snc WHERE rev_aux_snc.rev_page=page_id AND rev_aux_snc.rev_timestamp >= ' . $this -> convertTimestamp ( $option ) . ')'
2020-11-22 20:00:48 +00:00
]
);
}
/**
* Set SQL for 'goal' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _goal ( $option ) {
if ( $option == 'categories' ) {
$this -> setLimit ( false );
$this -> setOffset ( false );
2020-11-22 20:00:48 +00:00
}
}
/**
* Set SQL for 'hiddencategories' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _hiddencategories ( $option ) {
2021-10-01 22:52:30 +00:00
// @TODO: Unfinished functionality! Never implemented by original author.
2020-11-22 20:00:48 +00:00
}
/**
* Set SQL for 'imagecontainer' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _imagecontainer ( $option ) {
2021-10-01 22:52:30 +00:00
$where = [];
2021-02-22 23:48:01 +00:00
$this -> addTable ( 'imagelinks' , 'ic' );
2020-11-22 20:00:48 +00:00
$this -> addSelect (
[
2021-12-15 20:22:38 +00:00
'sortkey' => 'ic.il_to'
2020-11-22 20:00:48 +00:00
]
);
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( ! $this -> parameters -> getParameter ( 'openreferences' ) ) {
2020-11-22 20:00:48 +00:00
$where = [
2022-12-07 00:10:46 +00:00
" { $this -> tableNames [ 'page' ] } .page_namespace = " . NS_FILE ,
2020-11-22 20:00:48 +00:00
" { $this -> tableNames [ 'page' ] } .page_title = ic.il_to "
];
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$ors = [];
2021-02-22 23:48:01 +00:00
foreach ( $option as $linkGroup ) {
foreach ( $linkGroup as $link ) {
if ( $this -> parameters -> getParameter ( 'ignorecase' ) ) {
2022-03-13 18:28:30 +00:00
$ors [] = 'LOWER(CAST(ic.il_from AS char) = LOWER(' . $this -> dbr -> addQuotes ( $link -> getArticleID () ) . ')' ;
2020-11-22 20:00:48 +00:00
} else {
2022-03-13 18:28:30 +00:00
$ors [] = 'ic.il_from = ' . $this -> dbr -> addQuotes ( $link -> getArticleID () );
2020-11-22 20:00:48 +00:00
}
}
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$where [] = '(' . implode ( ' OR ' , $ors ) . ')' ;
$this -> addWhere ( $where );
2020-11-22 20:00:48 +00:00
}
/**
* Set SQL for 'imageused' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _imageused ( $option ) {
2021-10-01 22:52:30 +00:00
$where = [];
2021-02-22 23:48:01 +00:00
if ( $this -> parameters -> getParameter ( 'distinct' ) == 'strict' ) {
$this -> addGroupBy ( 'page_title' );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$this -> addTable ( 'imagelinks' , 'il' );
2020-11-22 20:00:48 +00:00
$this -> addSelect (
[
2021-12-15 20:22:38 +00:00
'image_sel_title' => 'il.il_to'
2020-11-22 20:00:48 +00:00
]
);
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$where [] = $this -> tableNames [ 'page' ] . '.page_id = il.il_from' ;
$ors = [];
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
foreach ( $option as $linkGroup ) {
foreach ( $linkGroup as $link ) {
if ( $this -> parameters -> getParameter ( 'ignorecase' ) ) {
2022-03-13 18:28:30 +00:00
$ors [] = 'LOWER(CAST(il.il_to AS char)) = LOWER(' . $this -> dbr -> addQuotes ( $link -> getDBkey () ) . ')' ;
2020-11-22 20:00:48 +00:00
} else {
2022-03-13 18:28:30 +00:00
$ors [] = 'il.il_to = ' . $this -> dbr -> addQuotes ( $link -> getDBkey () );
2020-11-22 20:00:48 +00:00
}
}
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$where [] = '(' . implode ( ' OR ' , $ors ) . ')' ;
$this -> addWhere ( $where );
2020-11-22 20:00:48 +00:00
}
/**
* Set SQL for 'lastmodifiedby' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _lastmodifiedby ( $option ) {
2022-12-07 00:10:46 +00:00
$this -> addWhere ( $this -> dbr -> addQuotes ( $this -> userFactory -> newFromName ( $option ) -> getActorId () ) . ' = (SELECT rev_actor FROM ' . $this -> tableNames [ 'revision' ] . ' WHERE ' . $this -> tableNames [ 'revision' ] . '.rev_page=page_id ORDER BY ' . $this -> tableNames [ 'revision' ] . '.rev_timestamp DESC LIMIT 1)' );
2020-11-22 20:00:48 +00:00
}
/**
* Set SQL for 'lastrevisionbefore' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _lastrevisionbefore ( $option ) {
2022-12-07 00:10:46 +00:00
$this -> addTable ( 'revision' , 'rev' );
$this -> addSelect ( [ 'rev.rev_id' , 'rev.rev_timestamp' ] );
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
// tell the query optimizer not to look at rows that the following subquery will filter out anyway
$this -> addWhere (
[
2022-12-07 00:10:46 +00:00
$this -> tableNames [ 'page' ] . '.page_id = rev.rev_page' ,
'rev.rev_timestamp < ' . $this -> convertTimestamp ( $option )
2020-11-22 20:00:48 +00:00
]
);
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$this -> addWhere (
[
2022-12-07 00:10:46 +00:00
$this -> tableNames [ 'page' ] . '.page_id = rev.rev_page' ,
2023-04-24 04:17:58 +00:00
'rev.rev_timestamp = (SELECT MAX(rev_aux_bef.rev_timestamp) FROM ' . $this -> tableNames [ 'revision' ] . ' AS rev_aux_bef WHERE rev_aux_bef.rev_page=page_id AND rev_aux_bef.rev_timestamp < ' . $this -> convertTimestamp ( $option ) . ')'
2020-11-22 20:00:48 +00:00
]
);
}
/**
* Set SQL for 'linksfrom' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _linksfrom ( $option ) {
2021-10-01 22:52:30 +00:00
$where = [];
2021-02-22 23:48:01 +00:00
if ( $this -> parameters -> getParameter ( 'distinct' ) == 'strict' ) {
$this -> addGroupBy ( 'page_title' );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( $this -> parameters -> getParameter ( 'openreferences' ) ) {
2020-11-22 20:00:48 +00:00
$ors = [];
2021-02-22 23:48:01 +00:00
foreach ( $option as $linkGroup ) {
foreach ( $linkGroup as $link ) {
2020-11-22 20:00:48 +00:00
$ors [] = '(pl_from = ' . $link -> getArticleID () . ')' ;
}
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$where [] = '(' . implode ( ' OR ' , $ors ) . ')' ;
2020-11-22 20:00:48 +00:00
} else {
2021-02-22 23:48:01 +00:00
$this -> addTable ( 'pagelinks' , 'plf' );
$this -> addTable ( 'page' , 'pagesrc' );
2020-11-22 20:00:48 +00:00
$this -> addSelect (
[
'sel_title' => 'pagesrc.page_title' ,
'sel_ns' => 'pagesrc.page_namespace'
]
);
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$where = [
$this -> tableNames [ 'page' ] . '.page_namespace = plf.pl_namespace' ,
$this -> tableNames [ 'page' ] . '.page_title = plf.pl_title' ,
'pagesrc.page_id = plf.pl_from'
];
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$ors = [];
2021-02-22 23:48:01 +00:00
foreach ( $option as $linkGroup ) {
foreach ( $linkGroup as $link ) {
2020-11-22 20:00:48 +00:00
$ors [] = 'plf.pl_from = ' . $link -> getArticleID ();
}
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$where [] = '(' . implode ( ' OR ' , $ors ) . ')' ;
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$this -> addWhere ( $where );
2020-11-22 20:00:48 +00:00
}
/**
* Set SQL for 'linksto' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _linksto ( $option ) {
if ( $this -> parameters -> getParameter ( 'distinct' ) == 'strict' ) {
$this -> addGroupBy ( 'page_title' );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( count ( $option ) > 0 ) {
$this -> addTable ( 'pagelinks' , 'pl' );
$this -> addSelect ( [ 'sel_title' => 'pl.pl_title' , 'sel_ns' => 'pl.pl_namespace' ] );
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
foreach ( $option as $index => $linkGroup ) {
if ( $index == 0 ) {
2020-11-22 20:00:48 +00:00
$where = $this -> tableNames [ 'page' ] . '.page_id=pl.pl_from AND ' ;
$ors = [];
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
foreach ( $linkGroup as $link ) {
2022-12-07 00:10:46 +00:00
$_or = '(pl.pl_namespace=' . ( int ) $link -> getNamespace ();
2021-12-17 01:23:18 +00:00
if ( strpos ( $link -> getDBkey (), '%' ) >= 0 ) {
2020-11-22 20:00:48 +00:00
$operator = 'LIKE' ;
} else {
$operator = '=' ;
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( $this -> parameters -> getParameter ( 'ignorecase' ) ) {
2022-03-13 18:28:30 +00:00
$_or .= ' AND LOWER(CAST(pl.pl_title AS char)) ' . $operator . ' LOWER(' . $this -> dbr -> addQuotes ( $link -> getDBkey () ) . ')' ;
2020-11-22 20:00:48 +00:00
} else {
2022-03-13 18:28:30 +00:00
$_or .= ' AND pl.pl_title ' . $operator . ' ' . $this -> dbr -> addQuotes ( $link -> getDBkey () );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$_or .= ')' ;
$ors [] = $_or ;
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$where .= '(' . implode ( ' OR ' , $ors ) . ')' ;
2020-11-22 20:00:48 +00:00
} else {
$where = 'EXISTS(select pl_from FROM ' . $this -> tableNames [ 'pagelinks' ] . ' WHERE (' . $this -> tableNames [ 'pagelinks' ] . '.pl_from=page_id AND ' ;
$ors = [];
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
foreach ( $linkGroup as $link ) {
2022-12-07 00:10:46 +00:00
$_or = '(' . $this -> tableNames [ 'pagelinks' ] . '.pl_namespace=' . ( int ) $link -> getNamespace ();
2021-12-17 01:23:18 +00:00
if ( strpos ( $link -> getDBkey (), '%' ) >= 0 ) {
2020-11-22 20:00:48 +00:00
$operator = 'LIKE' ;
} else {
$operator = '=' ;
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( $this -> parameters -> getParameter ( 'ignorecase' ) ) {
2022-03-13 18:28:30 +00:00
$_or .= ' AND LOWER(CAST(' . $this -> tableNames [ 'pagelinks' ] . '.pl_title AS char)) ' . $operator . ' LOWER(' . $this -> dbr -> addQuotes ( $link -> getDBkey () ) . ')' ;
2020-11-22 20:00:48 +00:00
} else {
2022-03-13 18:28:30 +00:00
$_or .= ' AND ' . $this -> tableNames [ 'pagelinks' ] . '.pl_title ' . $operator . ' ' . $this -> dbr -> addQuotes ( $link -> getDBkey () );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$_or .= ')' ;
$ors [] = $_or ;
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$where .= '(' . implode ( ' OR ' , $ors ) . ')' ;
2020-11-22 20:00:48 +00:00
$where .= '))' ;
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$this -> addWhere ( $where );
2020-11-22 20:00:48 +00:00
}
}
}
/**
* Set SQL for 'notlinksfrom' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _notlinksfrom ( $option ) {
if ( $this -> parameters -> getParameter ( 'distinct' ) == 'strict' ) {
$this -> addGroupBy ( 'page_title' );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( $this -> parameters -> getParameter ( 'openreferences' ) ) {
2020-11-22 20:00:48 +00:00
$ands = [];
2021-02-22 23:48:01 +00:00
foreach ( $option as $linkGroup ) {
foreach ( $linkGroup as $link ) {
2022-12-07 00:10:46 +00:00
$ands [] = 'pl_from <> ' . ( int ) $link -> getArticleID () . ' ' ;
2020-11-22 20:00:48 +00:00
}
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$where = '(' . implode ( ' AND ' , $ands ) . ')' ;
2020-11-22 20:00:48 +00:00
} else {
$where = 'CONCAT(page_namespace,page_title) NOT IN (SELECT CONCAT(' . $this -> tableNames [ 'pagelinks' ] . '.pl_namespace,' . $this -> tableNames [ 'pagelinks' ] . '.pl_title) FROM ' . $this -> tableNames [ 'pagelinks' ] . ' WHERE ' ;
$ors = [];
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
foreach ( $option as $linkGroup ) {
foreach ( $linkGroup as $link ) {
2022-12-07 00:10:46 +00:00
$ors [] = $this -> tableNames [ 'pagelinks' ] . '.pl_from = ' . ( int ) $link -> getArticleID ();
2020-11-22 20:00:48 +00:00
}
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$where .= implode ( ' OR ' , $ors ) . ')' ;
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$this -> addWhere ( $where );
2020-11-22 20:00:48 +00:00
}
/**
* Set SQL for 'notlinksto' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _notlinksto ( $option ) {
if ( $this -> parameters -> getParameter ( 'distinct' ) == 'strict' ) {
$this -> addGroupBy ( 'page_title' );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( count ( $option ) ) {
2020-11-22 20:00:48 +00:00
$where = $this -> tableNames [ 'page' ] . '.page_id NOT IN (SELECT ' . $this -> tableNames [ 'pagelinks' ] . '.pl_from FROM ' . $this -> tableNames [ 'pagelinks' ] . ' WHERE ' ;
$ors = [];
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
foreach ( $option as $linkGroup ) {
foreach ( $linkGroup as $link ) {
2022-12-07 00:10:46 +00:00
$_or = '(' . $this -> tableNames [ 'pagelinks' ] . '.pl_namespace=' . ( int ) $link -> getNamespace ();
2021-12-17 01:23:18 +00:00
if ( strpos ( $link -> getDBkey (), '%' ) >= 0 ) {
2020-11-22 20:00:48 +00:00
$operator = 'LIKE' ;
} else {
$operator = '=' ;
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( $this -> parameters -> getParameter ( 'ignorecase' ) ) {
2022-03-13 18:28:30 +00:00
$_or .= ' AND LOWER(CAST(' . $this -> tableNames [ 'pagelinks' ] . '.pl_title AS char)) ' . $operator . ' LOWER(' . $this -> dbr -> addQuotes ( $link -> getDBkey () ) . '))' ;
2020-11-22 20:00:48 +00:00
} else {
2022-03-13 18:28:30 +00:00
$_or .= ' AND ' . $this -> tableNames [ 'pagelinks' ] . '.pl_title ' . $operator . ' ' . $this -> dbr -> addQuotes ( $link -> getDBkey () ) . ')' ;
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$ors [] = $_or ;
}
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$where .= '(' . implode ( ' OR ' , $ors ) . '))' ;
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
$this -> addWhere ( $where ? ? '' );
2020-11-22 20:00:48 +00:00
}
/**
* Set SQL for 'linkstoexternal' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _linkstoexternal ( $option ) {
if ( $this -> parameters -> getParameter ( 'distinct' ) == 'strict' ) {
$this -> addGroupBy ( 'page_title' );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( count ( $option ) > 0 ) {
$this -> addTable ( 'externallinks' , 'el' );
$this -> addSelect ( [ 'el_to' => 'el.el_to' ] );
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
foreach ( $option as $index => $linkGroup ) {
if ( $index == 0 ) {
2020-11-22 20:00:48 +00:00
$where = $this -> tableNames [ 'page' ] . '.page_id=el.el_from AND ' ;
$ors = [];
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
foreach ( $linkGroup as $link ) {
2022-03-13 18:28:30 +00:00
$ors [] = 'el.el_to LIKE ' . $this -> dbr -> addQuotes ( $link );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$where .= '(' . implode ( ' OR ' , $ors ) . ')' ;
2020-11-22 20:00:48 +00:00
} else {
$where = 'EXISTS(SELECT el_from FROM ' . $this -> tableNames [ 'externallinks' ] . ' WHERE (' . $this -> tableNames [ 'externallinks' ] . '.el_from=page_id AND ' ;
$ors = [];
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
foreach ( $linkGroup as $link ) {
2022-03-13 18:28:30 +00:00
$ors [] = $this -> tableNames [ 'externallinks' ] . '.el_to LIKE ' . $this -> dbr -> addQuotes ( $link );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$where .= '(' . implode ( ' OR ' , $ors ) . ')' ;
2020-11-22 20:00:48 +00:00
$where .= '))' ;
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$this -> addWhere ( $where );
2020-11-22 20:00:48 +00:00
}
}
}
/**
* Set SQL for 'maxrevisions' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _maxrevisions ( $option ) {
2022-12-07 00:10:46 +00:00
$this -> addWhere ( " ((SELECT count(rev_aux3.rev_page) FROM { $this -> tableNames [ 'revision' ] } AS rev_aux3 WHERE rev_aux3.rev_page = { $this -> tableNames [ 'page' ] } .page_id) <= { $option } ) " );
2020-11-22 20:00:48 +00:00
}
/**
* Set SQL for 'minoredits' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _minoredits ( $option ) {
if ( isset ( $option ) && $option == 'exclude' ) {
2022-03-17 15:38:47 +00:00
$this -> addTable ( 'revision' , 'revision' );
$this -> addWhere ( 'revision.rev_minor_edit = 0' );
2020-11-22 20:00:48 +00:00
}
}
/**
* Set SQL for 'minrevisions' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _minrevisions ( $option ) {
2022-12-07 00:10:46 +00:00
$this -> addWhere ( " ((SELECT count(rev_aux2.rev_page) FROM { $this -> tableNames [ 'revision' ] } AS rev_aux2 WHERE rev_aux2.rev_page = { $this -> tableNames [ 'page' ] } .page_id) >= { $option } ) " );
2020-11-22 20:00:48 +00:00
}
/**
* Set SQL for 'modifiedby' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _modifiedby ( $option ) {
2022-12-07 00:10:46 +00:00
$this -> addTable ( 'revision' , 'change_rev' );
2021-10-06 18:44:11 +00:00
2022-12-07 00:10:46 +00:00
$this -> addWhere ( $this -> dbr -> addQuotes ( $this -> userFactory -> newFromName ( $option ) -> getActorId () ) . ' = change_rev.rev_actor AND change_rev.rev_page = page_id' );
2020-11-22 20:00:48 +00:00
}
/**
* Set SQL for 'namespace' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _namespace ( $option ) {
if ( is_array ( $option ) && count ( $option ) ) {
if ( $this -> parameters -> getParameter ( 'openreferences' ) ) {
2020-11-22 20:00:48 +00:00
$this -> addWhere (
[
2021-12-15 20:22:38 +00:00
" { $this -> tableNames [ 'pagelinks' ] } .pl_namespace " => $option
2020-11-22 20:00:48 +00:00
]
);
} else {
$this -> addWhere (
[
2021-12-15 20:22:38 +00:00
" { $this -> tableNames [ 'page' ] } .page_namespace " => $option
2020-11-22 20:00:48 +00:00
]
);
}
}
}
/**
* Set SQL for 'notcreatedby' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _notcreatedby ( $option ) {
2021-10-06 18:44:11 +00:00
$this -> addTable ( 'revision' , 'no_creation_rev' );
2022-12-07 00:10:46 +00:00
$this -> addWhere ( $this -> dbr -> addQuotes ( $this -> userFactory -> newFromName ( $option ) -> getActorId () ) . ' != no_creation_rev.rev_actor AND no_creation_rev.rev_page = page_id AND no_creation_rev.rev_parent_id = 0' );
2020-11-22 20:00:48 +00:00
}
/**
* Set SQL for 'notlastmodifiedby' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _notlastmodifiedby ( $option ) {
2022-12-07 00:10:46 +00:00
$this -> addWhere ( $this -> dbr -> addQuotes ( $this -> userFactory -> newFromName ( $option ) -> getActorId () ) . ' != (SELECT rev_actor FROM ' . $this -> tableNames [ 'revision' ] . ' WHERE ' . $this -> tableNames [ 'revision' ] . '.rev_page=page_id ORDER BY ' . $this -> tableNames [ 'revision' ] . '.rev_timestamp DESC LIMIT 1)' );
2020-11-22 20:00:48 +00:00
}
/**
* Set SQL for 'notmodifiedby' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _notmodifiedby ( $option ) {
2022-12-07 00:10:46 +00:00
$this -> addWhere ( 'NOT EXISTS (SELECT 1 FROM ' . $this -> tableNames [ 'revision' ] . ' WHERE ' . $this -> tableNames [ 'revision' ] . '.rev_page=page_id AND ' . $this -> tableNames [ 'revision' ] . '.rev_actor = ' . $this -> dbr -> addQuotes ( $this -> userFactory -> newFromName ( $option ) -> getActorId () ) . ' LIMIT 1)' );
2020-11-22 20:00:48 +00:00
}
/**
* Set SQL for 'notnamespace' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _notnamespace ( $option ) {
if ( is_array ( $option ) && count ( $option ) ) {
if ( $this -> parameters -> getParameter ( 'openreferences' ) ) {
2020-11-22 20:00:48 +00:00
$this -> addNotWhere (
[
" { $this -> tableNames [ 'pagelinks' ] } .pl_namespace " => $option
]
);
} else {
$this -> addNotWhere (
[
" { $this -> tableNames [ 'page' ] } .page_namespace " => $option
]
);
}
}
}
/**
* Set SQL for 'count' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _count ( $option ) {
$this -> setLimit ( $option );
2020-11-22 20:00:48 +00:00
}
/**
* Set SQL for 'offset' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _offset ( $option ) {
$this -> setOffset ( $option );
2020-11-22 20:00:48 +00:00
}
/**
* Set SQL for 'order' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _order ( $option ) {
$orderMethod = $this -> parameters -> getParameter ( 'ordermethod' );
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( ! empty ( $orderMethod ) && is_array ( $orderMethod ) && $orderMethod [ 0 ] !== 'none' ) {
if ( $option === 'descending' || $option === 'desc' ) {
$this -> setOrderDir ( 'DESC' );
2020-11-22 20:00:48 +00:00
} else {
2021-02-22 23:48:01 +00:00
$this -> setOrderDir ( 'ASC' );
2020-11-22 20:00:48 +00:00
}
}
}
/**
* Set SQL for 'ordercollation' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
* @ return bool
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _ordercollation ( $option ) {
$option = mb_strtolower ( $option );
2020-11-22 20:00:48 +00:00
2022-03-13 18:28:30 +00:00
$res = $this -> dbr -> query ( 'SHOW CHARACTER SET' );
if ( ! $res ) {
2020-11-22 20:00:48 +00:00
return false ;
}
2022-03-13 18:28:30 +00:00
foreach ( $res as $row ) {
if ( $option == $row -> { 'Default collation' } ) {
2021-02-22 23:48:01 +00:00
$this -> setCollation ( $option );
2020-11-22 20:00:48 +00:00
break ;
}
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
return true ;
}
/**
* Set SQL for 'ordermethod' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2022-03-22 19:59:52 +00:00
* @ return bool
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _ordermethod ( $option ) {
if ( $this -> parameters -> getParameter ( 'goal' ) == 'categories' ) {
2021-10-01 22:52:30 +00:00
// No order methods for returning categories.
2020-11-22 20:00:48 +00:00
return true ;
}
2021-10-01 22:52:30 +00:00
$services = MediaWikiServices :: getInstance ();
$namespaces = $services -> getContentLanguage () -> getNamespaces ();
// $aStrictNs = array_slice( (array)Config::getSetting( 'allowedNamespaces' ), 1, count( Config::getSetting( 'allowedNamespaces' ) ), true );
2021-02-22 23:48:01 +00:00
$namespaces = array_slice ( $namespaces , 3 , count ( $namespaces ), true );
2020-11-22 20:00:48 +00:00
$_namespaceIdToText = " CASE { $this -> tableNames [ 'page' ] } .page_namespace " ;
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
foreach ( $namespaces as $id => $name ) {
2022-12-07 00:10:46 +00:00
$_namespaceIdToText .= ' WHEN ' . ( int ) $id . ' THEN ' . $this -> dbr -> addQuotes ( $name . ':' );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$_namespaceIdToText .= ' END' ;
$option = ( array ) $option ;
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
foreach ( $option as $orderMethod ) {
switch ( $orderMethod ) {
2020-11-22 20:00:48 +00:00
case 'category' :
2021-02-22 23:48:01 +00:00
$this -> addOrderBy ( 'cl_head.cl_to' );
2021-10-01 22:52:30 +00:00
$this -> addSelect ( [ 'cl_head.cl_to' ] );
2021-02-22 23:48:01 +00:00
if ( ( is_array ( $this -> parameters -> getParameter ( 'catheadings' ) ) && in_array ( '' , $this -> parameters -> getParameter ( 'catheadings' ) ) ) || ( is_array ( $this -> parameters -> getParameter ( 'catnotheadings' ) ) && in_array ( '' , $this -> parameters -> getParameter ( 'catnotheadings' ) ) ) ) {
2020-11-22 20:00:48 +00:00
$_clTableName = 'dpl_clview' ;
$_clTableAlias = $_clTableName ;
} else {
$_clTableName = 'categorylinks' ;
$_clTableAlias = 'cl_head' ;
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$this -> addTable ( $_clTableName , $_clTableAlias );
2020-11-22 20:00:48 +00:00
$this -> addJoin (
$_clTableAlias ,
[
2021-12-17 01:23:18 +00:00
'LEFT OUTER JOIN' ,
'page_id = cl_head.cl_from'
2020-11-22 20:00:48 +00:00
]
);
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( is_array ( $this -> parameters -> getParameter ( 'catheadings' ) ) && count ( $this -> parameters -> getParameter ( 'catheadings' ) ) ) {
2020-11-22 20:00:48 +00:00
$this -> addWhere (
[
2021-12-17 01:23:18 +00:00
'cl_head.cl_to' => $this -> parameters -> getParameter ( 'catheadings' )
2020-11-22 20:00:48 +00:00
]
);
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( is_array ( $this -> parameters -> getParameter ( 'catnotheadings' ) ) && count ( $this -> parameters -> getParameter ( 'catnotheadings' ) ) ) {
2020-11-22 20:00:48 +00:00
$this -> addNotWhere (
[
2021-02-22 23:48:01 +00:00
'cl_head.cl_to' => $this -> parameters -> getParameter ( 'catnotheadings' )
2020-11-22 20:00:48 +00:00
]
);
}
break ;
case 'categoryadd' :
2021-10-01 22:52:30 +00:00
// @TODO: See TODO in __addfirstcategorydate().
2021-02-22 23:48:01 +00:00
$this -> addOrderBy ( 'cl1.cl_timestamp' );
2020-11-22 20:00:48 +00:00
break ;
case 'counter' :
2022-03-20 17:15:43 +00:00
if ( ExtensionRegistry :: getInstance () -> isLoaded ( 'HitCounters' ) ) {
2021-10-01 22:52:30 +00:00
// If the "addpagecounter" parameter was not used the table and join need to be added now.
2021-02-22 23:48:01 +00:00
if ( ! array_key_exists ( 'hit_counter' , $this -> tables ) ) {
$this -> addTable ( 'hit_counter' , 'hit_counter' );
2020-11-22 20:00:48 +00:00
2021-02-22 23:48:01 +00:00
if ( ! isset ( $this -> join [ 'hit_counter' ] ) ) {
2020-11-22 20:00:48 +00:00
$this -> addJoin (
'hit_counter' ,
[
2021-12-17 01:23:18 +00:00
'LEFT JOIN' ,
'hit_counter.page_id = ' . $this -> tableNames [ 'page' ] . '.page_id'
2020-11-22 20:00:48 +00:00
]
);
}
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$this -> addOrderBy ( 'hit_counter.page_counter' );
2020-11-22 20:00:48 +00:00
}
break ;
case 'firstedit' :
2022-12-07 00:10:46 +00:00
$this -> addOrderBy ( 'rev.rev_timestamp' );
$this -> addTable ( 'revision' , 'rev' );
2021-10-06 18:44:11 +00:00
$this -> addSelect (
[
2022-12-07 00:10:46 +00:00
'rev.rev_timestamp'
2021-10-06 18:44:11 +00:00
]
);
if ( ! $this -> revisionAuxWhereAdded ) {
$this -> addWhere (
[
2022-12-07 00:10:46 +00:00
" { $this -> tableNames [ 'page' ] } .page_id = rev.rev_page " ,
2023-04-24 04:17:58 +00:00
" rev.rev_timestamp = (SELECT MIN(rev_aux.rev_timestamp) FROM { $this -> tableNames [ 'revision' ] } AS rev_aux WHERE rev_aux.rev_page = page_id) "
2021-10-06 18:44:11 +00:00
]
);
}
2021-10-01 22:52:30 +00:00
2021-10-06 18:44:11 +00:00
$this -> revisionAuxWhereAdded = true ;
2020-11-22 20:00:48 +00:00
break ;
case 'lastedit' :
2022-03-13 19:57:34 +00:00
if ( Hooks :: isLikeIntersection () ) {
2021-02-22 23:48:01 +00:00
$this -> addOrderBy ( 'page_touched' );
2020-11-22 20:00:48 +00:00
$this -> addSelect (
[
2021-12-17 01:23:18 +00:00
'page_touched' => " { $this -> tableNames [ 'page' ] } .page_touched "
2020-11-22 20:00:48 +00:00
]
);
} else {
2022-12-07 00:10:46 +00:00
$this -> addOrderBy ( 'rev.rev_timestamp' );
$this -> addTable ( 'revision' , 'rev' );
$this -> addSelect ( [ 'rev.rev_timestamp' ] );
2021-10-01 22:52:30 +00:00
2021-10-06 18:44:11 +00:00
if ( ! $this -> revisionAuxWhereAdded ) {
$this -> addWhere (
[
2022-12-07 00:10:46 +00:00
" { $this -> tableNames [ 'page' ] } .page_id = rev.rev_page " ,
2023-04-24 04:17:58 +00:00
" rev.rev_timestamp = (SELECT MAX(rev_aux.rev_timestamp) FROM { $this -> tableNames [ 'revision' ] } AS rev_aux WHERE rev_aux.rev_page = page_id) "
2021-10-06 18:44:11 +00:00
]
);
}
$this -> revisionAuxWhereAdded = true ;
2020-11-22 20:00:48 +00:00
}
break ;
case 'pagesel' :
2021-02-22 23:48:01 +00:00
$this -> addOrderBy ( 'sortkey' );
2020-11-22 20:00:48 +00:00
$this -> addSelect (
[
'sortkey' => 'CONCAT(pl.pl_namespace, pl.pl_title) ' . $this -> getCollateSQL ()
]
);
break ;
case 'pagetouched' :
2021-02-22 23:48:01 +00:00
$this -> addOrderBy ( 'page_touched' );
2020-11-22 20:00:48 +00:00
$this -> addSelect (
[
2021-12-17 01:23:18 +00:00
'page_touched' => " { $this -> tableNames [ 'page' ] } .page_touched "
2020-11-22 20:00:48 +00:00
]
);
break ;
case 'size' :
2021-02-22 23:48:01 +00:00
$this -> addOrderBy ( 'page_len' );
2020-11-22 20:00:48 +00:00
break ;
case 'sortkey' :
2021-02-22 23:48:01 +00:00
$this -> addOrderBy ( 'sortkey' );
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
// If cl_sortkey is null (uncategorized page), generate a sortkey in the usual way (full page name, underscores replaced with spaces).
// UTF-8 created problems with non-utf-8 MySQL databases
$replaceConcat = " REPLACE(CONCAT( { $_namespaceIdToText } , " . $this -> tableNames [ 'page' ] . " .page_title), '_', ' ') " ;
2021-02-22 23:48:01 +00:00
$category = ( array ) $this -> parameters -> getParameter ( 'category' );
$notCategory = ( array ) $this -> parameters -> getParameter ( 'notcategory' );
if ( count ( $category ) + count ( $notCategory ) > 0 ) {
if ( in_array ( 'category' , $this -> parameters -> getParameter ( 'ordermethod' ) ) ) {
2020-11-22 20:00:48 +00:00
$this -> addSelect (
[
'sortkey' => " IFNULL(cl_head.cl_sortkey, { $replaceConcat } ) " . $this -> getCollateSQL ()
]
);
} else {
2021-10-01 22:52:30 +00:00
// This runs on the assumption that at least one category parameter was used and that numbering starts at 1.
2020-11-22 20:00:48 +00:00
$this -> addSelect (
[
'sortkey' => " IFNULL(cl1.cl_sortkey, { $replaceConcat } ) " . $this -> getCollateSQL ()
]
);
}
} else {
$this -> addSelect (
[
'sortkey' => $replaceConcat . $this -> getCollateSQL ()
]
);
}
break ;
case 'titlewithoutnamespace' :
2021-02-22 23:48:01 +00:00
if ( $this -> parameters -> getParameter ( 'openreferences' ) ) {
2021-12-17 01:23:18 +00:00
$this -> addOrderBy ( 'pl_title' );
2020-11-22 20:00:48 +00:00
} else {
2021-12-17 01:23:18 +00:00
$this -> addOrderBy ( 'page_title' );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$this -> addSelect (
[
'sortkey' => " { $this -> tableNames [ 'page' ] } .page_title " . $this -> getCollateSQL ()
]
);
break ;
case 'title' :
2021-02-22 23:48:01 +00:00
$this -> addOrderBy ( 'sortkey' );
if ( $this -> parameters -> getParameter ( 'openreferences' ) ) {
2020-11-22 20:00:48 +00:00
$this -> addSelect (
[
2021-10-01 22:52:30 +00:00
'sortkey' => " REPLACE(CONCAT(IF(pl_namespace =0, '', CONCAT( " . $_namespaceIdToText . " , ':')), pl_title), '_', ' ') " . $this -> getCollateSQL ()
2020-11-22 20:00:48 +00:00
]
);
} else {
2021-10-01 22:52:30 +00:00
// Generate sortkey like for category links. UTF-8 created problems with non-utf-8 MySQL databases.
2020-11-22 20:00:48 +00:00
$this -> addSelect (
[
'sortkey' => " REPLACE(CONCAT(IF( " . $this -> tableNames [ 'page' ] . " .page_namespace = 0, '', CONCAT( " . $_namespaceIdToText . " , ':')), " . $this -> tableNames [ 'page' ] . " .page_title), '_', ' ') " . $this -> getCollateSQL ()
]
);
}
break ;
case 'user' :
2022-12-07 00:10:46 +00:00
$this -> addOrderBy ( 'rev.rev_actor' );
$this -> addTable ( 'revision' , 'rev' );
2021-10-01 22:52:30 +00:00
2021-10-06 18:44:11 +00:00
$this -> _adduser ( null , 'rev' );
2020-11-22 20:00:48 +00:00
break ;
case 'none' :
break ;
}
}
}
/**
* Set SQL for 'redirects' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _redirects ( $option ) {
if ( ! $this -> parameters -> getParameter ( 'openreferences' ) ) {
switch ( $option ) {
2020-11-22 20:00:48 +00:00
case 'only' :
$this -> addWhere (
[
2021-12-17 01:23:18 +00:00
$this -> tableNames [ 'page' ] . '.page_is_redirect' => 1
2020-11-22 20:00:48 +00:00
]
);
break ;
case 'exclude' :
$this -> addWhere (
[
2021-12-17 01:23:18 +00:00
$this -> tableNames [ 'page' ] . '.page_is_redirect' => 0
2020-11-22 20:00:48 +00:00
]
);
break ;
}
}
}
/**
* Set SQL for 'stablepages' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _stablepages ( $option ) {
if ( function_exists ( 'efLoadFlaggedRevs' ) ) {
2021-10-01 22:52:30 +00:00
// Do not add this again if 'qualitypages' has already added it.
2021-02-22 23:48:01 +00:00
if ( ! $this -> parametersProcessed [ 'qualitypages' ] ) {
2020-11-22 20:00:48 +00:00
$this -> addJoin (
'flaggedpages' ,
[
2021-12-17 01:23:18 +00:00
'LEFT JOIN' ,
'page_id = fp_page_id'
2020-11-22 20:00:48 +00:00
]
);
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
switch ( $option ) {
2020-11-22 20:00:48 +00:00
case 'only' :
$this -> addWhere (
[
'fp_stable IS NOT NULL'
]
);
break ;
case 'exclude' :
$this -> addWhere (
[
2021-12-15 20:22:38 +00:00
'fp_stable' => null
2020-11-22 20:00:48 +00:00
]
);
break ;
}
}
}
/**
* Set SQL for 'qualitypages' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _qualitypages ( $option ) {
if ( function_exists ( 'efLoadFlaggedRevs' ) ) {
2021-10-01 22:52:30 +00:00
// Do not add this again if 'stablepages' has already added it.
2021-02-22 23:48:01 +00:00
if ( ! $this -> parametersProcessed [ 'stablepages' ] ) {
2020-11-22 20:00:48 +00:00
$this -> addJoin (
'flaggedpages' ,
[
2021-12-17 01:23:18 +00:00
'LEFT JOIN' ,
'page_id = fp_page_id'
2020-11-22 20:00:48 +00:00
]
);
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
switch ( $option ) {
2020-11-22 20:00:48 +00:00
case 'only' :
2021-02-22 23:48:01 +00:00
$this -> addWhere ( 'fp_quality >= 1' );
2020-11-22 20:00:48 +00:00
break ;
case 'exclude' :
2021-02-22 23:48:01 +00:00
$this -> addWhere ( 'fp_quality = 0' );
2020-11-22 20:00:48 +00:00
break ;
}
}
}
/**
* Set SQL for 'title' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _title ( $option ) {
2020-11-22 20:00:48 +00:00
$ors = [];
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
foreach ( $option as $comparisonType => $titles ) {
foreach ( $titles as $title ) {
if ( $this -> parameters -> getParameter ( 'openreferences' ) ) {
if ( $this -> parameters -> getParameter ( 'ignorecase' ) ) {
2022-03-13 18:28:30 +00:00
$_or = " LOWER(CAST(pl_title AS char)) { $comparisonType } " . strtolower ( $this -> dbr -> addQuotes ( $title ) );
2020-11-22 20:00:48 +00:00
} else {
2022-03-13 18:28:30 +00:00
$_or = " pl_title { $comparisonType } " . $this -> dbr -> addQuotes ( $title );
2020-11-22 20:00:48 +00:00
}
} else {
2021-02-22 23:48:01 +00:00
if ( $this -> parameters -> getParameter ( 'ignorecase' ) ) {
2022-03-13 18:28:30 +00:00
$_or = " LOWER(CAST( { $this -> tableNames [ 'page' ] } .page_title AS char)) { $comparisonType } " . strtolower ( $this -> dbr -> addQuotes ( $title ) );
2020-11-22 20:00:48 +00:00
} else {
2022-03-13 18:28:30 +00:00
$_or = " { $this -> tableNames [ 'page' ] } .page_title { $comparisonType } " . $this -> dbr -> addQuotes ( $title );
2020-11-22 20:00:48 +00:00
}
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$ors [] = $_or ;
}
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$where = '(' . implode ( ' OR ' , $ors ) . ')' ;
$this -> addWhere ( $where );
2020-11-22 20:00:48 +00:00
}
/**
* Set SQL for 'nottitle' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _nottitle ( $option ) {
2020-11-22 20:00:48 +00:00
$ors = [];
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
foreach ( $option as $comparisonType => $titles ) {
foreach ( $titles as $title ) {
if ( $this -> parameters -> getParameter ( 'openreferences' ) ) {
if ( $this -> parameters -> getParameter ( 'ignorecase' ) ) {
2022-03-13 18:28:30 +00:00
$_or = " LOWER(CAST(pl_title AS char)) { $comparisonType } " . strtolower ( $this -> dbr -> addQuotes ( $title ) );
2020-11-22 20:00:48 +00:00
} else {
2022-03-13 18:28:30 +00:00
$_or = " pl_title { $comparisonType } " . $this -> dbr -> addQuotes ( $title );
2020-11-22 20:00:48 +00:00
}
} else {
2021-02-22 23:48:01 +00:00
if ( $this -> parameters -> getParameter ( 'ignorecase' ) ) {
2022-03-13 18:28:30 +00:00
$_or = " LOWER(CAST( { $this -> tableNames [ 'page' ] } .page_title AS char)) { $comparisonType } " . strtolower ( $this -> dbr -> addQuotes ( $title ) );
2020-11-22 20:00:48 +00:00
} else {
2022-03-13 18:28:30 +00:00
$_or = " { $this -> tableNames [ 'page' ] } .page_title { $comparisonType } " . $this -> dbr -> addQuotes ( $title );
2020-11-22 20:00:48 +00:00
}
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$ors [] = $_or ;
}
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$where = 'NOT (' . implode ( ' OR ' , $ors ) . ')' ;
$this -> addWhere ( $where );
2020-11-22 20:00:48 +00:00
}
/**
* Set SQL for 'titlegt' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _titlegt ( $option ) {
2022-02-06 23:27:50 +00:00
$operator = '>' ;
if ( substr ( $option , 0 , 2 ) === '=_' ) {
$option = substr ( $option , 2 );
$operator = '>=' ;
}
2021-10-01 22:52:30 +00:00
2022-02-06 23:27:50 +00:00
if ( $option === '' ) {
$operator = 'LIKE' ;
$option = '%' ;
}
2022-03-15 17:11:41 +00:00
$option = $this -> dbr -> addQuotes ( $option );
2022-02-06 23:27:50 +00:00
if ( $this -> parameters -> getParameter ( 'openreferences' ) ) {
$where = " (pl_title { $operator } { $option } ) " ;
} else {
$where = " ( { $this -> tableNames [ 'page' ] } .page_title { $operator } { $option } ) " ;
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$this -> addWhere ( $where );
2020-11-22 20:00:48 +00:00
}
/**
* Set SQL for 'titlelt' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _titlelt ( $option ) {
2022-02-06 23:27:50 +00:00
$operator = '<' ;
if ( substr ( $option , 0 , 2 ) === '=_' ) {
$option = substr ( $option , 2 );
$operator = '<=' ;
}
2021-10-01 22:52:30 +00:00
2022-02-06 23:27:50 +00:00
if ( $option === '' ) {
$operator = 'LIKE' ;
$option = '%' ;
}
2022-03-15 17:11:41 +00:00
$option = $this -> dbr -> addQuotes ( $option );
2022-02-06 23:27:50 +00:00
if ( $this -> parameters -> getParameter ( 'openreferences' ) ) {
$where = " (pl_title { $operator } { $option } ) " ;
} else {
$where = " ( { $this -> tableNames [ 'page' ] } .page_title { $operator } { $option } ) " ;
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$this -> addWhere ( $where );
2020-11-22 20:00:48 +00:00
}
/**
* Set SQL for 'usedby' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _usedby ( $option ) {
if ( $this -> parameters -> getParameter ( 'openreferences' ) ) {
2020-11-22 20:00:48 +00:00
$ors = [];
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
foreach ( $option as $linkGroup ) {
foreach ( $linkGroup as $link ) {
2022-12-07 00:10:46 +00:00
$ors [] = 'tpl_from = ' . ( int ) $link -> getArticleID ();
2020-11-22 20:00:48 +00:00
}
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$where = '(' . implode ( ' OR ' , $ors ) . ')' ;
2020-11-22 20:00:48 +00:00
} else {
2022-12-07 00:10:46 +00:00
$this -> addTables ( [
'linktarget' => 'lt' ,
'templatelinks' => 'tpl' ,
] );
$linksMigration = MediaWikiServices :: getInstance () -> getLinksMigration ();
2023-03-16 20:49:35 +00:00
[ $nsField , $titleField ] = $linksMigration -> getTitleFields ( 'templatelinks' );
2022-12-07 00:10:46 +00:00
2023-03-16 20:49:35 +00:00
$this -> addSelect ( [
'tpl_sel_title' => " { $this -> tableNames [ 'page' ] } .page_title " ,
'tpl_sel_ns' => " { $this -> tableNames [ 'page' ] } .page_namespace "
] );
$this -> addJoin (
'lt' ,
[ 'JOIN' , [ " page_title = $titleField " , " page_namespace = $nsField " ] ]
);
$this -> addJoin ( 'tpl' , [ 'JOIN' , 'lt_id = tl_target_id' , ]
);
2020-11-22 20:00:48 +00:00
$ors = [];
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
foreach ( $option as $linkGroup ) {
foreach ( $linkGroup as $link ) {
2022-12-07 00:10:46 +00:00
$ors [] = 'tpl.tl_from = ' . ( int ) $link -> getArticleID ();
2020-11-22 20:00:48 +00:00
}
}
2021-10-01 22:52:30 +00:00
2023-03-16 20:49:35 +00:00
$where = '(' . implode ( ' OR ' , $ors ) . ')' ;
2020-11-22 20:00:48 +00:00
}
2021-02-22 23:48:01 +00:00
$this -> addWhere ( $where );
2020-11-22 20:00:48 +00:00
}
/**
* Set SQL for 'uses' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _uses ( $option ) {
2022-12-07 00:10:46 +00:00
$this -> addTables ( [
'linktarget' => 'lt' ,
'templatelinks' => 'tl' ,
] );
$where = $this -> tableNames [ 'page' ] . '.page_id=tl.tl_from AND lt.lt_id = tl.tl_target_id AND (' ;
2020-11-22 20:00:48 +00:00
$ors = [];
2021-10-01 22:52:30 +00:00
2022-12-07 00:10:46 +00:00
$linksMigration = MediaWikiServices :: getInstance () -> getLinksMigration ();
2023-03-16 20:49:35 +00:00
[ $nsField , $titleField ] = $linksMigration -> getTitleFields ( 'templatelinks' );
2022-12-07 00:10:46 +00:00
2021-02-22 23:48:01 +00:00
foreach ( $option as $linkGroup ) {
foreach ( $linkGroup as $link ) {
2022-12-07 00:10:46 +00:00
$_or = '(lt.' . $nsField . '=' . ( int ) $link -> getNamespace ();
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( $this -> parameters -> getParameter ( 'ignorecase' ) ) {
2022-12-07 00:10:46 +00:00
$_or .= ' AND LOWER(CAST(lt.' . $titleField . ' AS char)) = LOWER(' . $this -> dbr -> addQuotes ( $link -> getDBkey () ) . '))' ;
2020-11-22 20:00:48 +00:00
} else {
2022-12-07 00:10:46 +00:00
$_or .= ' AND ' . $titleField . ' = ' . $this -> dbr -> addQuotes ( $link -> getDBkey () ) . ')' ;
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$ors [] = $_or ;
}
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$where .= implode ( ' OR ' , $ors ) . ')' ;
$this -> addWhere ( $where );
2020-11-22 20:00:48 +00:00
}
/**
* Set SQL for 'notuses' parameter .
*
2021-10-01 22:52:30 +00:00
* @ param mixed $option
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function _notuses ( $option ) {
if ( count ( $option ) > 0 ) {
2023-01-04 18:22:24 +00:00
$where = $this -> tableNames [ 'page' ] . '.page_id NOT IN (SELECT ' . $this -> tableNames [ 'templatelinks' ] . '.tl_from FROM ' . $this -> tableNames [ 'templatelinks' ] . ' INNER JOIN ' . $this -> tableNames [ 'linktarget' ] . ' ON ' . $this -> tableNames [ 'linktarget' ] . '.lt_id = ' . $this -> tableNames [ 'templatelinks' ] . '.tl_target_id WHERE (' ;
2020-11-22 20:00:48 +00:00
$ors = [];
2021-10-01 22:52:30 +00:00
2022-12-07 00:10:46 +00:00
$linksMigration = MediaWikiServices :: getInstance () -> getLinksMigration ();
2023-03-16 20:49:35 +00:00
[ $nsField , $titleField ] = $linksMigration -> getTitleFields ( 'templatelinks' );
2022-12-07 00:10:46 +00:00
2021-02-22 23:48:01 +00:00
foreach ( $option as $linkGroup ) {
foreach ( $linkGroup as $link ) {
2022-12-07 00:10:46 +00:00
$_or = '(' . $this -> tableNames [ 'linktarget' ] . '.' . $nsField . '=' . ( int ) $link -> getNamespace ();
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( $this -> parameters -> getParameter ( 'ignorecase' ) ) {
2022-12-07 00:10:46 +00:00
$_or .= ' AND LOWER(CAST(' . $this -> tableNames [ 'linktarget' ] . '.' . $titleField . ' AS char)) = LOWER(' . $this -> dbr -> addQuotes ( $link -> getDBkey () ) . '))' ;
2020-11-22 20:00:48 +00:00
} else {
2022-12-07 00:10:46 +00:00
$_or .= ' AND ' . $this -> tableNames [ 'linktarget' ] . '.' . $titleField . ' = ' . $this -> dbr -> addQuotes ( $link -> getDBkey () ) . ')' ;
2020-11-22 20:00:48 +00:00
}
$ors [] = $_or ;
}
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$where .= implode ( ' OR ' , $ors ) . '))' ;
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
$this -> addWhere ( $where ? ? '' );
2020-11-22 20:00:48 +00:00
}
}