47 private $formattedComments;
63 parent::__construct( $query, $moduleName,
'le' );
64 $this->commentStore = $commentStore;
65 $this->commentFormatter = $commentFormatter;
66 $this->changeTagDefStore = $changeTagDefStore;
79 $prop = array_fill_keys( $params[
'prop'],
true );
81 $this->fld_ids = isset( $prop[
'ids'] );
82 $this->fld_title = isset( $prop[
'title'] );
83 $this->fld_type = isset( $prop[
'type'] );
84 $this->fld_user = isset( $prop[
'user'] );
85 $this->fld_userid = isset( $prop[
'userid'] );
86 $this->fld_timestamp = isset( $prop[
'timestamp'] );
87 $this->fld_comment = isset( $prop[
'comment'] );
88 $this->fld_parsedcomment = isset( $prop[
'parsedcomment'] );
89 $this->fld_details = isset( $prop[
'details'] );
90 $this->fld_tags = isset( $prop[
'tags'] );
93 if ( $hideLogs !==
false ) {
97 $this->
addTables( [
'logging',
'actor' ] );
99 'actor' => [
'JOIN',
'actor_id=log_actor' ],
110 if ( $this->fld_ids ) {
113 'page' => [
'LEFT JOIN',
114 [
'log_namespace=page_namespace',
115 'log_title=page_title' ] ]
120 $this->
addFields( [
'page_id',
'log_page' ] );
122 $this->
addFieldsIf( [
'actor_name',
'actor_user' ], $this->fld_user );
123 $this->
addFieldsIf(
'actor_user', $this->fld_userid );
125 [
'log_namespace',
'log_title' ],
126 $this->fld_title || $this->fld_parsedcomment
128 $this->
addFieldsIf(
'log_params', $this->fld_details || $this->fld_ids );
130 if ( $this->fld_comment || $this->fld_parsedcomment ) {
131 $commentQuery = $this->commentStore->getJoin(
'log_comment' );
132 $this->
addTables( $commentQuery[
'tables'] );
133 $this->
addFields( $commentQuery[
'fields'] );
137 if ( $this->fld_tags ) {
141 if ( $params[
'tag'] !==
null ) {
144 [
'log_id=ct_log_id' ] ] ] );
146 $this->
addWhereFld(
'ct_tag_id', $this->changeTagDefStore->getId( $params[
'tag'] ) );
153 if ( $params[
'action'] !==
null ) {
156 $logAction = $params[
'action'];
157 if ( !str_contains( $logAction,
'/' ) ) {
161 $logActions = array_fill_keys( $this->getAllowedLogActions(),
true );
162 [ $type, $action ] = explode(
'/', $logAction, 2 );
163 $valid = isset( $logActions[$logAction] ) || isset( $logActions[$type .
'/*'] );
169 [
'apierror-unrecognizedvalue', $encParamName,
wfEscapeWikiText( $logAction ) ],
170 "unknown_$encParamName"
178 } elseif ( $params[
'type'] !==
null ) {
189 $this->
addWhereRange(
'log_id', $params[
'dir'],
null,
null );
191 if ( $params[
'continue'] !==
null ) {
193 $op = ( $params[
'dir'] ===
'newer' ?
'>=' :
'<=' );
194 $this->
addWhere( $db->buildComparison( $op, [
195 'log_timestamp' => $db->timestamp( $cont[0] ),
196 'log_id' => $cont[1],
200 $limit = $params[
'limit'];
203 $user = $params[
'user'];
204 if ( $user !==
null ) {
208 $title = $params[
'title'];
209 if ( $title !==
null ) {
210 $titleObj = Title::newFromText( $title );
211 if ( $titleObj ===
null || $titleObj->isExternal() ) {
214 $this->
addWhereFld(
'log_namespace', $titleObj->getNamespace() );
215 $this->
addWhereFld(
'log_title', $titleObj->getDBkey() );
218 if ( $params[
'namespace'] !==
null ) {
219 $this->
addWhereFld(
'log_namespace', $params[
'namespace'] );
222 $prefix = $params[
'prefix'];
224 if ( $prefix !==
null ) {
225 if ( $this->
getConfig()->
get( MainConfigNames::MiserMode ) ) {
229 $title = Title::newFromText( $prefix );
230 if ( $title ===
null || $title->isExternal() ) {
233 $this->
addWhereFld(
'log_namespace', $title->getNamespace() );
234 $this->
addWhere(
'log_title ' . $db->buildLike( $title->getDBkey(), $db->anyString() ) );
238 if ( $params[
'namespace'] !==
null || $title !==
null || $user !==
null ) {
239 if ( !$this->
getAuthority()->isAllowed(
'deletedhistory' ) ) {
242 } elseif ( !$this->
getAuthority()->isAllowedAny(
'suppressrevision',
'viewsuppressed' ) ) {
249 if ( ( $params[
'namespace'] !==
null || $title !==
null ) && $titleBits ) {
250 $this->
addWhere( $db->bitAnd(
'log_deleted', $titleBits ) .
" != $titleBits" );
252 if ( $user !==
null && $userBits ) {
253 $this->
addWhere( $db->bitAnd(
'log_deleted', $userBits ) .
" != $userBits" );
262 if ( $params[
'tag'] ===
null && $user ===
null ) {
267 'MAX_EXECUTION_TIME',
268 $this->
getConfig()->
get( MainConfigNames::MaxExecutionTimeForExpensiveQueries )
272 $res = $this->
select( __METHOD__ );
274 if ( $this->fld_title ) {
277 if ( $this->fld_parsedcomment ) {
278 $this->formattedComments = $this->commentFormatter->formatItems(
279 $this->commentFormatter->rows( $res )
280 ->commentKey(
'log_comment' )
281 ->indexField(
'log_id' )
282 ->namespaceField(
'log_namespace' )
283 ->titleField(
'log_title' )
288 foreach ( $res as $row ) {
289 if ( ++$count > $limit ) {
296 $vals = $this->extractRowInfo( $row );
297 $fit = $result->addValue( [
'query', $this->
getModuleName() ],
null, $vals );
303 $result->addIndexedTagName( [
'query', $this->
getModuleName() ],
'item' );
306 private function extractRowInfo( $row ) {
313 if ( $this->fld_ids ) {
314 $vals[
'logid'] = (int)$row->log_id;
317 if ( $this->fld_title ) {
318 $title = Title::makeTitle( $row->log_namespace, $row->log_title );
322 if ( $this->fld_title || $this->fld_ids || $this->fld_details && $row->log_params !==
'' ) {
324 $vals[
'actionhidden'] =
true;
328 if ( $this->fld_title ) {
333 if ( $this->fld_ids ) {
334 $vals[
'pageid'] = (int)$row->page_id;
335 $vals[
'logpage'] = (
int)$row->log_page;
336 $revId = $logEntry->getAssociatedRevId();
338 $vals[
'revid'] = (int)$revId;
341 if ( $this->fld_details ) {
347 if ( $this->fld_type ) {
348 $vals[
'type'] = $row->log_type;
349 $vals[
'action'] = $row->log_action;
352 if ( $this->fld_user || $this->fld_userid ) {
354 $vals[
'userhidden'] =
true;
358 if ( $this->fld_user ) {
359 $vals[
'user'] = $row->actor_name;
361 if ( $this->fld_userid ) {
362 $vals[
'userid'] = (int)$row->actor_user;
365 if ( !$row->actor_user ) {
366 $vals[
'anon'] =
true;
370 if ( $this->fld_timestamp ) {
371 $vals[
'timestamp'] =
wfTimestamp( TS_ISO_8601, $row->log_timestamp );
374 if ( $this->fld_comment || $this->fld_parsedcomment ) {
376 $vals[
'commenthidden'] =
true;
380 if ( $this->fld_comment ) {
381 $vals[
'comment'] = $this->commentStore->getComment(
'log_comment', $row )->text;
384 if ( $this->fld_parsedcomment ) {
386 $vals[
'parsedcomment'] = $this->formattedComments[$row->log_id];
391 if ( $this->fld_tags ) {
392 if ( $row->ts_tags ) {
393 $tags = explode(
',', $row->ts_tags );
395 $vals[
'tags'] = $tags;
402 $vals[
'suppressed'] =
true;
411 private function getAllowedLogActions() {
413 return array_keys( array_merge(
414 $config->get( MainConfigNames::LogActions ),
415 $config->get( MainConfigNames::LogActionsHandlers )
423 if ( $params[
'prop'] !==
null && in_array(
'parsedcomment', $params[
'prop'] ) ) {
425 return 'anon-public-user-private';
431 return 'anon-public-user-private';
438 $logActions = $this->getAllowedLogActions();
445 ParamValidator::PARAM_ISMULTI =>
true,
446 ParamValidator::PARAM_DEFAULT =>
'ids|title|type|user|timestamp|comment|details',
447 ParamValidator::PARAM_TYPE => [
466 ParamValidator::PARAM_TYPE => $logActions
469 ParamValidator::PARAM_TYPE =>
'timestamp'
472 ParamValidator::PARAM_TYPE =>
'timestamp'
475 ParamValidator::PARAM_DEFAULT =>
'older',
476 ParamValidator::PARAM_TYPE => [
482 'newer' =>
'api-help-paramvalue-direction-newer',
483 'older' =>
'api-help-paramvalue-direction-older',
487 ParamValidator::PARAM_TYPE =>
'user',
488 UserDef::PARAM_ALLOWED_USER_TYPES => [
'name',
'ip',
'id',
'interwiki' ],
492 ParamValidator::PARAM_TYPE =>
'namespace',
498 ParamValidator::PARAM_DEFAULT => 10,
499 ParamValidator::PARAM_TYPE =>
'limit',
500 IntegerDef::PARAM_MIN => 1,
509 if ( $config->get( MainConfigNames::MiserMode ) ) {
518 'action=query&list=logevents'
519 =>
'apihelp-query+logevents-example-simple',
524 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)
Dies if more than one parameter from a certain set of parameters are 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 this is set, the result could take longer to generate,...
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.