43 private $commentStore;
46 private $commentFormatter;
49 private $changeTagDefStore;
52 private $formattedComments;
68 parent::__construct( $query, $moduleName,
'le' );
69 $this->commentStore = $commentStore;
70 $this->commentFormatter = $commentFormatter;
71 $this->changeTagDefStore = $changeTagDefStore;
84 $prop = array_fill_keys( $params[
'prop'],
true );
86 $this->fld_ids = isset( $prop[
'ids'] );
87 $this->fld_title = isset( $prop[
'title'] );
88 $this->fld_type = isset( $prop[
'type'] );
89 $this->fld_user = isset( $prop[
'user'] );
90 $this->fld_userid = isset( $prop[
'userid'] );
91 $this->fld_timestamp = isset( $prop[
'timestamp'] );
92 $this->fld_comment = isset( $prop[
'comment'] );
93 $this->fld_parsedcomment = isset( $prop[
'parsedcomment'] );
94 $this->fld_details = isset( $prop[
'details'] );
95 $this->fld_tags = isset( $prop[
'tags'] );
98 if ( $hideLogs !==
false ) {
102 $this->
addTables( [
'logging',
'actor' ] );
104 'actor' => [
'JOIN',
'actor_id=log_actor' ],
115 if ( $this->fld_ids ) {
118 'page' => [
'LEFT JOIN',
119 [
'log_namespace=page_namespace',
120 'log_title=page_title' ] ]
125 $this->
addFields( [
'page_id',
'log_page' ] );
127 $this->
addFieldsIf( [
'actor_name',
'actor_user' ], $this->fld_user );
128 $this->
addFieldsIf(
'actor_user', $this->fld_userid );
130 [
'log_namespace',
'log_title' ],
131 $this->fld_title || $this->fld_parsedcomment
133 $this->
addFieldsIf(
'log_params', $this->fld_details || $this->fld_ids );
135 if ( $this->fld_comment || $this->fld_parsedcomment ) {
136 $commentQuery = $this->commentStore->getJoin(
'log_comment' );
137 $this->
addTables( $commentQuery[
'tables'] );
138 $this->
addFields( $commentQuery[
'fields'] );
142 if ( $this->fld_tags ) {
146 if ( $params[
'tag'] !==
null ) {
149 [
'log_id=ct_log_id' ] ] ] );
151 $this->
addWhereFld(
'ct_tag_id', $this->changeTagDefStore->getId( $params[
'tag'] ) );
158 if ( $params[
'action'] !==
null ) {
161 $logAction = $params[
'action'];
162 if ( !str_contains( $logAction,
'/' ) ) {
166 $logActions = array_fill_keys( $this->getAllowedLogActions(),
true );
167 [
$type, $action ] = explode(
'/', $logAction, 2 );
168 $valid = isset( $logActions[$logAction] ) || isset( $logActions[
$type .
'/*'] );
174 [
'apierror-unrecognizedvalue', $encParamName,
wfEscapeWikiText( $logAction ) ],
175 "unknown_$encParamName"
183 } elseif ( $params[
'type'] !==
null ) {
194 $this->
addWhereRange(
'log_id', $params[
'dir'],
null,
null );
196 if ( $params[
'continue'] !==
null ) {
198 $op = ( $params[
'dir'] ===
'newer' ?
'>=' :
'<=' );
199 $this->
addWhere( $db->buildComparison( $op, [
200 'log_timestamp' => $db->timestamp( $cont[0] ),
201 'log_id' => $cont[1],
205 $limit = $params[
'limit'];
208 $user = $params[
'user'];
209 if ( $user !==
null ) {
213 $title = $params[
'title'];
215 $titleObj = Title::newFromText(
$title );
216 if ( $titleObj ===
null || $titleObj->isExternal() ) {
219 $this->
addWhereFld(
'log_namespace', $titleObj->getNamespace() );
220 $this->
addWhereFld(
'log_title', $titleObj->getDBkey() );
223 if ( $params[
'namespace'] !==
null ) {
224 $this->
addWhereFld(
'log_namespace', $params[
'namespace'] );
227 $prefix = $params[
'prefix'];
229 if ( $prefix !==
null ) {
230 if ( $this->
getConfig()->
get( MainConfigNames::MiserMode ) ) {
234 $title = Title::newFromText( $prefix );
239 $this->
addWhere(
'log_title ' . $db->buildLike(
$title->getDBkey(), $db->anyString() ) );
243 if ( $params[
'namespace'] !==
null ||
$title !==
null || $user !==
null ) {
244 if ( !$this->
getAuthority()->isAllowed(
'deletedhistory' ) ) {
247 } elseif ( !$this->
getAuthority()->isAllowedAny(
'suppressrevision',
'viewsuppressed' ) ) {
254 if ( ( $params[
'namespace'] !==
null ||
$title !==
null ) && $titleBits ) {
255 $this->
addWhere( $db->bitAnd(
'log_deleted', $titleBits ) .
" != $titleBits" );
257 if ( $user !==
null && $userBits ) {
258 $this->
addWhere( $db->bitAnd(
'log_deleted', $userBits ) .
" != $userBits" );
267 if ( $params[
'tag'] ===
null && $user ===
null ) {
272 'MAX_EXECUTION_TIME',
273 $this->
getConfig()->
get( MainConfigNames::MaxExecutionTimeForExpensiveQueries )
279 if ( $this->fld_title ) {
282 if ( $this->fld_parsedcomment ) {
283 $this->formattedComments = $this->commentFormatter->formatItems(
284 $this->commentFormatter->rows(
$res )
285 ->commentKey(
'log_comment' )
286 ->indexField(
'log_id' )
287 ->namespaceField(
'log_namespace' )
288 ->titleField(
'log_title' )
293 foreach (
$res as $row ) {
294 if ( ++$count > $limit ) {
301 $vals = $this->extractRowInfo( $row );
302 $fit = $result->addValue( [
'query', $this->
getModuleName() ],
null, $vals );
308 $result->addIndexedTagName( [
'query', $this->
getModuleName() ],
'item' );
311 private function extractRowInfo( $row ) {
318 if ( $this->fld_ids ) {
319 $vals[
'logid'] = (int)$row->log_id;
322 if ( $this->fld_title ) {
323 $title = Title::makeTitle( $row->log_namespace, $row->log_title );
327 if ( $this->fld_title || $this->fld_ids || $this->fld_details && $row->log_params !==
'' ) {
329 $vals[
'actionhidden'] =
true;
333 if ( $this->fld_title ) {
338 if ( $this->fld_ids ) {
339 $vals[
'pageid'] = (int)$row->page_id;
340 $vals[
'logpage'] = (
int)$row->log_page;
341 $revId = $logEntry->getAssociatedRevId();
343 $vals[
'revid'] = (int)$revId;
346 if ( $this->fld_details ) {
352 if ( $this->fld_type ) {
353 $vals[
'type'] = $row->log_type;
354 $vals[
'action'] = $row->log_action;
357 if ( $this->fld_user || $this->fld_userid ) {
359 $vals[
'userhidden'] =
true;
363 if ( $this->fld_user ) {
364 $vals[
'user'] = $row->actor_name;
366 if ( $this->fld_userid ) {
367 $vals[
'userid'] = (int)$row->actor_user;
370 if ( !$row->actor_user ) {
371 $vals[
'anon'] =
true;
375 if ( $this->fld_timestamp ) {
376 $vals[
'timestamp'] =
wfTimestamp( TS_ISO_8601, $row->log_timestamp );
379 if ( $this->fld_comment || $this->fld_parsedcomment ) {
381 $vals[
'commenthidden'] =
true;
385 if ( $this->fld_comment ) {
386 $vals[
'comment'] = $this->commentStore->getComment(
'log_comment', $row )->text;
389 if ( $this->fld_parsedcomment ) {
391 $vals[
'parsedcomment'] = $this->formattedComments[$row->log_id];
396 if ( $this->fld_tags ) {
397 if ( $row->ts_tags ) {
398 $tags = explode(
',', $row->ts_tags );
400 $vals[
'tags'] = $tags;
407 $vals[
'suppressed'] =
true;
416 private function getAllowedLogActions() {
418 return array_keys( array_merge(
419 $config->get( MainConfigNames::LogActions ),
420 $config->get( MainConfigNames::LogActionsHandlers )
428 if ( $params[
'prop'] !==
null && in_array(
'parsedcomment', $params[
'prop'] ) ) {
430 return 'anon-public-user-private';
436 return 'anon-public-user-private';
443 $logActions = $this->getAllowedLogActions();
450 ParamValidator::PARAM_ISMULTI =>
true,
451 ParamValidator::PARAM_DEFAULT =>
'ids|title|type|user|timestamp|comment|details',
452 ParamValidator::PARAM_TYPE => [
471 ParamValidator::PARAM_TYPE => $logActions
474 ParamValidator::PARAM_TYPE =>
'timestamp'
477 ParamValidator::PARAM_TYPE =>
'timestamp'
480 ParamValidator::PARAM_DEFAULT =>
'older',
481 ParamValidator::PARAM_TYPE => [
488 ParamValidator::PARAM_TYPE =>
'user',
489 UserDef::PARAM_ALLOWED_USER_TYPES => [
'name',
'ip',
'id',
'interwiki' ],
493 ParamValidator::PARAM_TYPE =>
'namespace',
499 ParamValidator::PARAM_DEFAULT => 10,
500 ParamValidator::PARAM_TYPE =>
'limit',
501 IntegerDef::PARAM_MIN => 1,
510 if ( $config->get( MainConfigNames::MiserMode ) ) {
519 'action=query&list=logevents'
520 =>
'apihelp-query+logevents-example-simple',
525 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Logevents';
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
dieWithError( $msg, $code=null, $data=null, $httpCode=0)
Abort execution with an error.
encodeParamName( $paramName)
This method mangles parameter name based on the prefix supplied to the constructor.
parseContinueParamOrDie(string $continue, array $types)
Parse the 'continue' parameter in the usual format and validate the types of each part,...
const PARAM_HELP_MSG_PER_VALUE
((string|array|Message)[]) When PARAM_TYPE is an array, or 'string' with PARAM_ISMULTI,...
const LIMIT_BIG1
Fast query, standard limit.
requireMaxOneParameter( $params,... $required)
Die if more than one of a certain set of parameters is set and not false.
getResult()
Get the result object.
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
const GET_VALUES_FOR_HELP
getAllowedParams() flag: When set, the result could take longer to generate, but should be more thoro...
const LIMIT_BIG2
Fast query, apihighlimits limit.
getModuleName()
Get the name of the module being executed by this instance.
This is a base class for all Query modules.
static addTitleInfo(&$arr, $title, $prefix='')
Add information (title and namespace) about a Title object to a result array.
setContinueEnumParameter( $paramName, $paramValue)
Set a query-continue value.
addWhereRange( $field, $dir, $start, $end, $sort=true)
Add a WHERE clause corresponding to a range, and an ORDER BY clause to sort in the right direction.
addFields( $value)
Add a set of fields to select to the internal array.
addOption( $name, $value=null)
Add an option such as LIMIT or USE INDEX.
addTables( $tables, $alias=null)
Add a set of tables to the internal array.
addTimestampWhereRange( $field, $dir, $start, $end, $sort=true)
Add a WHERE clause corresponding to a range, similar to addWhereRange, but converts $start and $end t...
getDB()
Get the Query database connection (read-only)
executeGenderCacheFromResultWrapper(IResultWrapper $res, $fname=__METHOD__, $fieldPrefix='page')
Preprocess the result set to fill the GenderCache with the necessary information before using self::a...
select( $method, $extraQuery=[], array &$hookData=null)
Execute a SELECT query based on the values in the internal arrays.
addFieldsIf( $value, $condition)
Same as addFields(), but add the fields only if a condition is met.
addJoinConds( $join_conds)
Add a set of JOIN conditions to the internal array.
addWhereFld( $field, $value)
Equivalent to addWhere( [ $field => $value ] )
addWhere( $value)
Add a set of WHERE clauses to the internal array.
userCanSeeRevDel()
Check whether the current user has permission to view revision-deleted fields.
Query action to List the log events, with optional filtering by various parameters.
getExamplesMessages()
Returns usage examples for this module.
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
getAllowedParams( $flags=0)
__construct(ApiQuery $query, $moduleName, CommentStore $commentStore, RowCommentFormatter $commentFormatter, NameTableStore $changeTagDefStore)
getCacheMode( $params)
Get the cache mode for the data generated by this module.
getHelpUrls()
Return links to more detailed help pages about the module.
This is the main query class.
const META_TYPE
Key for the 'type' metadata item.
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
static newFromRow( $row)
Constructs new LogEntry from database result row.
static getExcludeClause( $db, $audience='public', Authority $performer=null)
SQL clause to skip forbidden log types for this user.
static userCan( $row, $field, Authority $performer)
Determine if the current user is allowed to view a particular field of this log row,...
static isDeleted( $row, $field)
static validTypes()
Get the list of valid log types.
A class containing constants representing the names of configuration variables.