55 private $linkRenderer;
75 $this->linkRenderer = $linkRenderer;
85 if ( $this->linkRenderer !==
null ) {
86 return $this->linkRenderer;
88 return MediaWikiServices::getInstance()->getLinkRenderer();
110 public function showOptions( $types = [], $user =
'', $page =
'', $pattern =
false, $year = 0,
111 $month = 0, $day = 0, $filter =
null, $tagFilter =
'', $action =
null, $extras = [],
115 $types = ( $types ===
'' ) ? [] : (array)$types;
117 $formDescriptor = [];
120 $formDescriptor[
'type'] = $this->getTypeMenuDesc( $types );
121 $formDescriptor[
'user'] = $this->getUserInputDesc( $user );
122 $formDescriptor[
'page'] = $this->getTitleInputDesc( $page );
125 if ( !$this->
getConfig()->
get( MainConfigNames::MiserMode ) ) {
126 $formDescriptor[
'pattern'] = $this->getTitlePatternDesc( $pattern );
133 $extraInputsDescriptor = $this->getExtraInputsDesc( $types, $extras );
135 is_array( $extraInputsDescriptor ) &&
136 !empty( $extraInputsDescriptor )
138 $formDescriptor[
'extra' ] = $extraInputsDescriptor;
140 is_string( $extraInputsDescriptor ) &&
141 $extraInputsDescriptor !==
''
144 $extraInputsString = $extraInputsDescriptor;
145 wfDeprecated(
'$input in LogEventsListGetExtraInputs hook',
'1.32' );
149 $formDescriptor[
'date'] = [
151 'label-message' =>
'date',
152 'default' => $year && $month && $day ? sprintf(
"%04d-%02d-%02d", $year, $month, $day ) :
'',
156 $formDescriptor[
'tagfilter'] = [
157 'type' =>
'tagfilter',
158 'name' =>
'tagfilter',
159 'label-message' =>
'tag-filter',
160 'default' => $tagFilter,
162 $formDescriptor[
'tagInvert'] = [
164 'name' =>
'tagInvert',
165 'label-message' =>
'invert',
166 'hide-if' => [
'===',
'tagfilter',
'' ],
167 'default' => $tagInvert,
172 $formDescriptor[
'filters'] = $this->getFiltersDesc( $filter );
178 $this->allowedActions !==
null &&
179 count( $this->allowedActions ) > 0
181 $formDescriptor[
'subtype'] = $this->getActionSelectorDesc( $types, $action );
188 ->setSubmitTextMsg(
'logeventslist-submit' )
190 ->setWrapperLegendMsg(
'log' )
192 ->setFormIdentifier(
'logeventslist' );
195 if ( isset( $extraInputsString ) ) {
203 $htmlForm->prepareForm()->displayForm(
false );
210 private function getFiltersDesc( $filter ) {
213 foreach ( $filter as
$type => $val ) {
214 $optionsMsg[
"logeventslist-{$type}-log"] =
$type;
216 if ( $val ===
false ) {
221 'class' => HTMLMultiSelectField::class,
222 'label-message' =>
'logeventslist-more-filters',
224 'options-messages' => $optionsMsg,
225 'default' => $default,
233 private function getTypeMenuDesc( $queryTypes ) {
234 $queryType = count( $queryTypes ) == 1 ? $queryTypes[0] :
'';
240 $restriction = $page->getRestriction();
241 if ( $this->
getAuthority()->isAllowed( $restriction ) ) {
242 $typesByName[
$type] = $page->getName()->text();
247 asort( $typesByName );
250 $public = $typesByName[
''];
251 unset( $typesByName[
''] );
252 $typesByName = [
'' => $public ] + $typesByName;
255 'class' => HTMLSelectField::class,
257 'options' => array_flip( $typesByName ),
258 'default' => $queryType,
266 private function getUserInputDesc( $user ) {
268 'class' => HTMLUserTextField::class,
269 'label-message' =>
'specialloguserlabel',
279 private function getTitleInputDesc( $page ) {
281 $titleFormatter = MediaWikiServices::getInstance()->getTitleFormatter();
282 $page = $titleFormatter->getPrefixedText( $page );
285 'class' => HTMLTitleTextField::class,
286 'label-message' =>
'speciallogtitlelabel',
297 private function getTitlePatternDesc( $pattern ) {
300 'label-message' =>
'log-title-wildcard',
302 'default' => $pattern,
311 private function getExtraInputsDesc( $types, $extras ) {
312 if ( count( $types ) == 1 ) {
313 if ( $types[0] ==
'suppress' ) {
316 'label-message' =>
'revdelete-offender',
317 'name' =>
'offender',
318 'default' => $extras[
'offender'] ??
'',
324 $formDescriptor = [];
325 $this->hookRunner->onLogEventsListGetExtraInputs( $types[0], $this, $input, $formDescriptor );
327 return empty( $formDescriptor ) ? $input : $formDescriptor;
340 private function getActionSelectorDesc( $types, $action ) {
342 $actionOptions[
'log-action-filter-all' ] =
'';
344 foreach ( $this->allowedActions as $value ) {
345 $msgKey =
'log-action-filter-' . $types[0] .
'-' . $value;
346 $actionOptions[ $msgKey ] = $value;
350 'class' => HTMLSelectField::class,
352 'options-messages' => $actionOptions,
353 'default' => $action,
354 'label' => $this->
msg(
'log-action-filter-' . $types[0] )->text(),
365 $this->allowedActions = $actions;
372 return "<ul class='mw-logevent-loglines'>\n";
389 $formatter->setContext( $this->
getContext() );
391 $formatter->setShowUserToolLinks( !( $this->flags & self::NO_EXTRA_USER_LINKS ) );
394 $entry->getTimestamp(),
402 [
'logid' => $entry->getId() ]
405 $action = $formatter->getActionText();
407 if ( $this->flags & self::NO_ACTION_LINK ) {
410 $revert = $formatter->getActionLinks();
411 if ( $revert !=
'' ) {
412 $revert =
'<span class="mw-logevent-actionlink">' . $revert .
'</span>';
416 $comment = $formatter->getComment();
419 $del = $this->getShowHideLinks( $row );
427 $classes = array_merge(
428 [
'mw-logline-' . $entry->getType() ],
432 'data-mw-logid' => $entry->getId(),
433 'data-mw-logaction' => $entry->getFullType(),
435 $ret =
"$del $timeLink $action $comment $revert $tagDisplay";
438 $this->hookRunner->onLogEventsListLineEnding( $this, $ret, $entry, $classes, $attribs );
439 $attribs = array_filter( $attribs,
440 [ Sanitizer::class,
'isReservedDataAttribute' ],
443 $attribs[
'class'] = $classes;
452 private function getShowHideLinks( $row ) {
454 if ( $this->flags == self::NO_ACTION_LINK ) {
459 if ( $this->flags & self::USE_CHECKBOXES && $this->showTagEditUI ) {
463 [
'name' =>
'ids[' . $row->log_id .
']' ]
468 if ( $row->log_type ==
'suppress' ) {
475 if ( $authority->isAllowed(
'deletedhistory' ) ) {
476 $canHide = $authority->isAllowed(
'deletelogentry' );
477 $canViewSuppressedOnly = $authority->isAllowed(
'viewsuppressed' ) &&
478 !$authority->isAllowed(
'suppressrevision' );
480 $canViewThisSuppressedEntry = $canViewSuppressedOnly && $entryIsSuppressed;
481 if ( $row->log_deleted || $canHide ) {
483 if ( $canHide && $this->flags & self::USE_CHECKBOXES && !$canViewThisSuppressedEntry ) {
486 $del =
Xml::check(
'deleterevisions',
false, [
'disabled' =>
'disabled' ] );
491 [
'name' =>
'ids[' . $row->log_id .
']' ]
497 $del = Linker::revDeleteLinkDisabled( $canHide );
502 'ids' => $row->log_id,
504 $del = Linker::revDeleteLink(
507 $canHide && !$canViewThisSuppressedEntry
524 $match = is_array(
$type ) ?
525 in_array( $row->log_type,
$type ) : $row->log_type ==
$type;
527 $match = is_array( $action ) ?
528 in_array( $row->log_action, $action ) : $row->log_action == $action;
558 if ( $bitfield & $field ) {
560 return $performer->
isAllowedAny(
'suppressrevision',
'viewsuppressed' );
562 return $performer->
isAllowed(
'deletedhistory' );
577 $logRestrictions = MediaWikiServices::getInstance()->getMainConfig()->get( MainConfigNames::LogRestrictions );
591 return ( $row->log_deleted & $field ) == $field;
620 &$out, $types = [], $page =
'', $user =
'', $param = []
622 $defaultParameters = [
625 'showIfEmpty' =>
true,
629 'useRequestParams' =>
false,
630 'useMaster' =>
false,
631 'extraUrlParams' =>
false,
633 # The + operator appends elements of remaining keys from the right
634 # handed array to the left handed, whereas duplicated keys are NOT overwritten.
635 $param += $defaultParameters;
636 # Convert $param array to individual variables
637 $lim = $param[
'lim'];
638 $conds = $param[
'conds'];
639 $showIfEmpty = $param[
'showIfEmpty'];
640 $msgKey = $param[
'msgKey'];
641 $wrap = $param[
'wrap'];
643 $extraUrlParams = $param[
'extraUrlParams'];
645 $useRequestParams = $param[
'useRequestParams'];
647 if ( !is_array( $msgKey ) ) {
648 $msgKey = [ $msgKey ];
652 $context = $out->getContext();
657 $services = MediaWikiServices::getInstance();
659 $linkRenderer = $services->getLinkRenderer();
661 # Insert list of top 50 (or top $lim) items
676 $services->getLinkBatchFactory(),
677 $services->getDBLoadBalancer(),
678 $services->getActorNormalization()
680 if ( !$useRequestParams ) {
681 # Reset vars that may have been taken from the request
683 $pager->mDefaultLimit = 50;
684 $pager->mOffset =
"";
685 $pager->mIsBackwards =
false;
688 if ( $param[
'useMaster'] ) {
692 if ( isset( $param[
'offset'] ) ) { # Tell pager to ignore
WebRequest offset
693 $pager->setOffset( $param[
'offset'] );
698 $pager->mLimit = $lim;
701 $logBody = $pager->getBody();
702 $numRows = $pager->getNumRows();
709 $msg = $context->msg( ...$msgKey );
713 $s .= $msg->parseAsBlock();
715 $s .= $loglist->beginLogEventsList() .
717 $loglist->endLogEventsList();
719 $context->getOutput()->addModuleStyles(
'mediawiki.interface.helpers.styles' );
720 } elseif ( $showIfEmpty ) {
722 $context->msg(
'logempty' )->parse() );
726 $titleFormatter = MediaWikiServices::getInstance()->getTitleFormatter();
727 $pageName = $titleFormatter->getPrefixedDBkey( $page );
728 } elseif ( $page !=
'' ) {
734 if ( $numRows > $pager->mLimit ) { # Show
"Full log" link
737 $urlParam[
'page'] = $pageName;
741 $urlParam[
'user'] = $user;
744 if ( !is_array( $types ) ) { # Make it an array,
if it isn
't
748 # If there is exactly one log type, we can link to Special:Log?type=foo
749 if ( count( $types ) == 1 ) {
750 $urlParam['type
'] = $types[0];
753 // @phan-suppress-next-line PhanSuspiciousValueComparison
754 if ( $extraUrlParams !== false ) {
755 $urlParam = array_merge( $urlParam, $extraUrlParams );
758 $s .= $linkRenderer->makeKnownLink(
759 SpecialPage::getTitleFor( 'Log
' ),
760 $context->msg( 'log-fulllog
' )->text(),
766 if ( $logBody && $msgKey[0] ) {
767 // TODO: The condition above is weird. Should this be done in any other cases?
768 // Or is it always true in practice?
770 // Mark as interface language (T60685)
771 $dir = $context->getLanguage()->getDir();
772 $lang = $context->getLanguage()->getHtmlCode();
773 $s = Html::rawElement( 'div
', [
774 'class' => "mw-content-$dir",
779 // Wrap in warning box
780 $s = Html::warningBox(
782 'mw-warning-with-logexcerpt
'
786 // @phan-suppress-next-line PhanSuspiciousValueComparison
787 if ( $wrap != '' ) { // Wrap message in html
788 $s = str_replace( '$1
', $s, $wrap );
791 /* hook can return false, if we don't want the message to be emitted (Wikia BugId:7093) */
792 if (
Hooks::runner()->onLogEventsListShowLogExtract(
$s, $types, $pageName, $user, $param ) ) {
814 $logRestrictions = MediaWikiServices::getInstance()->getMainConfig()->get( MainConfigNames::LogRestrictions );
816 if ( $audience !=
'public' && $performer ===
null ) {
817 throw new InvalidArgumentException(
818 'A User object must be given when checking for a user audience.'
826 foreach ( $logRestrictions as $logType => $right ) {
827 if ( $audience ==
'public' || !$performer->isAllowed( $right )
829 $hiddenLogs[] = $logType;
832 if ( count( $hiddenLogs ) == 1 ) {
833 return 'log_type != ' . $db->addQuotes( $hiddenLogs[0] );
834 } elseif ( $hiddenLogs ) {
835 return 'log_type NOT IN (' . $db->makeList( $hiddenLogs ) .
')';
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
The simplest way of implementing IContextSource is to hold a RequestContext as a member variable and ...
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
getContext()
Get the base IContextSource object.
setContext(IContextSource $context)
static newFromRow( $row)
Constructs new LogEntry from database result row.
An IContextSource implementation which will inherit context from another source but allow individual ...
static runner()
Get a HookRunner instance for calling hooks using the new interfaces.
static rawElement( $element, $attribs=[], $contents='')
Returns an HTML element in a string.
const NO_EXTRA_USER_LINKS
static typeAction( $row, $type, $action)
showOptions( $types=[], $user='', $page='', $pattern=false, $year=0, $month=0, $day=0, $filter=null, $tagFilter='', $action=null, $extras=[], $tagInvert=false)
Show options for the log list.
static showLogExtract(&$out, $types=[], $page='', $user='', $param=[])
Show log extract.
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 userCanBitfield( $bitfield, $field, Authority $performer)
Determine if the current user is allowed to view a particular field of this log row,...
__construct( $context, $linkRenderer=null, $flags=0)
setAllowedActions( $actions)
Sets the action types allowed for log filtering To one action type may correspond several log_actions...
static userCanViewLogType( $type, Authority $performer)
Determine if the current user is allowed to view a particular field of this log row,...
static isDeleted( $row, $field)
Class to simplify the use of log pages.
static validTypes()
Get the list of valid log types.
A class containing constants representing the names of configuration variables.
This is one of the Core classes and should be read at least once by any new developers.
static getMain()
Get the RequestContext object associated with the main request.
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
static getTitleValueFor( $name, $subpage=false, $fragment='')
Get a localised TitleValue object for a specified special page name.
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form stripping il...
static check( $name, $checked=false, $attribs=[])
Convenience function to build an HTML checkbox.
foreach( $mmfl['setupFiles'] as $fileName) if( $queue) if(empty( $mmfl['quiet'])) $s