49 protected $allowedActions =
null;
54 private $linkRenderer;
69 public function __construct( $context, $linkRenderer =
null, $flags = 0 ) {
74 $this->linkRenderer = $linkRenderer;
76 $this->hookRunner = Hooks::runner();
84 if ( $this->linkRenderer !==
null ) {
85 return $this->linkRenderer;
87 return MediaWikiServices::getInstance()->getLinkRenderer();
107 public function showOptions( $types = [], $user =
'', $page =
'', $pattern =
false, $year = 0,
108 $month = 0, $day = 0, $filter =
null, $tagFilter =
'', $action =
null
111 $types = ( $types ===
'' ) ? [] : (array)$types;
113 $formDescriptor = [];
116 $formDescriptor[
'type'] = $this->getTypeMenuDesc( $types );
117 $formDescriptor[
'user'] = $this->getUserInputDesc( $user );
118 $formDescriptor[
'page'] = $this->getTitleInputDesc( $page );
124 $extraInputsDescriptor = $this->getExtraInputsDesc( $types );
126 is_array( $extraInputsDescriptor ) &&
127 !empty( $extraInputsDescriptor )
129 $formDescriptor[
'extra' ] = $extraInputsDescriptor;
131 is_string( $extraInputsDescriptor ) &&
132 $extraInputsDescriptor !==
''
135 $extraInputsString = $extraInputsDescriptor;
136 wfDeprecated(
'$input in LogEventsListGetExtraInputs hook',
'1.32' );
140 if ( !$this->
getConfig()->
get( MainConfigNames::MiserMode ) ) {
141 $formDescriptor[
'pattern'] = $this->getTitlePatternDesc( $pattern );
145 $formDescriptor[
'date'] = [
147 'label-message' =>
'date',
148 'default' => $year && $month && $day ? sprintf(
"%04d-%02d-%02d", $year, $month, $day ) :
'',
152 $formDescriptor[
'tagfilter'] = [
153 'type' =>
'tagfilter',
154 'name' =>
'tagfilter',
155 'label-message' =>
'tag-filter',
160 $formDescriptor[
'filters'] = $this->getFiltersDesc( $filter );
166 $this->allowedActions !==
null &&
167 count( $this->allowedActions ) > 0
169 $formDescriptor[
'subtype'] = $this->getActionSelectorDesc( $types, $action );
174 $htmlForm = HTMLForm::factory(
'ooui', $formDescriptor, $context );
176 ->setSubmitTextMsg(
'logeventslist-submit' )
178 ->setWrapperLegendMsg(
'log' )
180 ->setFormIdentifier(
'logeventslist' );
183 if ( isset( $extraInputsString ) ) {
184 $htmlForm->addFooterText( Html::rawElement(
191 $htmlForm->prepareForm()->displayForm(
false );
198 private function getFiltersDesc( $filter ) {
201 foreach ( $filter as
$type => $val ) {
202 $optionsMsg[
"logeventslist-{$type}-log"] =
$type;
204 if ( $val ===
false ) {
209 'class' => HTMLMultiSelectField::class,
210 'label-message' =>
'logeventslist-more-filters',
212 'options-messages' => $optionsMsg,
213 'default' => $default,
221 private function getTypeMenuDesc( $queryTypes ) {
222 $queryType = count( $queryTypes ) == 1 ? $queryTypes[0] :
'';
228 $restriction = $page->getRestriction();
229 if ( $this->
getAuthority()->isAllowed( $restriction ) ) {
230 $typesByName[
$type] = $page->getName()->text();
235 asort( $typesByName );
238 $public = $typesByName[
''];
239 unset( $typesByName[
''] );
240 $typesByName = [
'' => $public ] + $typesByName;
243 'class' => HTMLSelectField::class,
245 'options' => array_flip( $typesByName ),
246 'default' => $queryType,
254 private function getUserInputDesc( $user ) {
256 'class' => HTMLUserTextField::class,
257 'label-message' =>
'specialloguserlabel',
267 private function getTitleInputDesc( $page ) {
269 'class' => HTMLTitleTextField::class,
270 'label-message' =>
'speciallogtitlelabel',
280 private function getTitlePatternDesc( $pattern ) {
283 'label-message' =>
'log-title-wildcard',
292 private function getExtraInputsDesc( $types ) {
293 if ( count( $types ) == 1 ) {
294 if ( $types[0] ==
'suppress' ) {
297 'label-message' =>
'revdelete-offender',
298 'name' =>
'offender',
304 $formDescriptor = [];
305 $this->hookRunner->onLogEventsListGetExtraInputs( $types[0], $this, $input, $formDescriptor );
307 return empty( $formDescriptor ) ? $input : $formDescriptor;
320 private function getActionSelectorDesc( $types, $action ) {
322 $actionOptions[
'log-action-filter-all' ] =
'';
324 foreach ( $this->allowedActions as $value ) {
325 $msgKey =
'log-action-filter-' . $types[0] .
'-' . $value;
326 $actionOptions[ $msgKey ] = $value;
330 'class' => HTMLSelectField::class,
332 'options-messages' => $actionOptions,
333 'default' => $action,
334 'label' => $this->
msg(
'log-action-filter-' . $types[0] )->text(),
345 $this->allowedActions = $actions;
352 return "<ul class='mw-logevent-loglines'>\n";
367 $entry = DatabaseLogEntry::newFromRow( $row );
368 $formatter = LogFormatter::newFromEntry( $entry );
369 $formatter->setContext( $this->
getContext() );
371 $formatter->setShowUserToolLinks( !( $this->flags & self::NO_EXTRA_USER_LINKS ) );
374 $entry->getTimestamp(),
382 [
'logid' => $entry->getId() ]
385 $action = $formatter->getActionText();
387 if ( $this->flags & self::NO_ACTION_LINK ) {
390 $revert = $formatter->getActionLinks();
391 if ( $revert !=
'' ) {
392 $revert =
'<span class="mw-logevent-actionlink">' . $revert .
'</span>';
396 $comment = $formatter->getComment();
399 $del = $this->getShowHideLinks( $row );
407 $classes = array_merge(
408 [
'mw-logline-' . $entry->getType() ],
412 'data-mw-logid' => $entry->getId(),
413 'data-mw-logaction' => $entry->getFullType(),
415 $ret =
"$del $timeLink $action $comment $revert $tagDisplay";
418 $this->hookRunner->onLogEventsListLineEnding( $this, $ret, $entry, $classes, $attribs );
419 $attribs = array_filter( $attribs,
420 [ Sanitizer::class,
'isReservedDataAttribute' ],
423 $attribs[
'class'] = $classes;
425 return Html::rawElement(
'li', $attribs, $ret ) .
"\n";
432 private function getShowHideLinks( $row ) {
434 if ( $this->flags == self::NO_ACTION_LINK ) {
439 if ( $this->flags & self::USE_CHECKBOXES && $this->showTagEditUI ) {
443 [
'name' =>
'ids[' . $row->log_id .
']' ]
448 if ( $row->log_type ==
'suppress' ) {
455 if ( $authority->isAllowed(
'deletedhistory' ) ) {
456 $canHide = $authority->isAllowed(
'deletelogentry' );
457 $canViewSuppressedOnly = $authority->isAllowed(
'viewsuppressed' ) &&
458 !$authority->isAllowed(
'suppressrevision' );
460 $canViewThisSuppressedEntry = $canViewSuppressedOnly && $entryIsSuppressed;
461 if ( $row->log_deleted || $canHide ) {
463 if ( $canHide && $this->flags & self::USE_CHECKBOXES && !$canViewThisSuppressedEntry ) {
466 $del =
Xml::check(
'deleterevisions',
false, [
'disabled' =>
'disabled' ] );
471 [
'name' =>
'ids[' . $row->log_id .
']' ]
482 'ids' => $row->log_id,
487 $canHide && !$canViewThisSuppressedEntry
504 $match = is_array(
$type ) ?
505 in_array( $row->log_type,
$type ) : $row->log_type ==
$type;
507 $match = is_array( $action ) ?
508 in_array( $row->log_action, $action ) : $row->log_action == $action;
524 return self::userCanBitfield( $row->log_deleted, $field, $performer ) &&
525 self::userCanViewLogType( $row->log_type, $performer );
538 if ( $bitfield & $field ) {
540 return $performer->
isAllowedAny(
'suppressrevision',
'viewsuppressed' );
542 return $performer->
isAllowed(
'deletedhistory' );
557 $logRestrictions = MediaWikiServices::getInstance()->getMainConfig()->get( MainConfigNames::LogRestrictions );
571 return ( $row->log_deleted & $field ) == $field;
600 &$out, $types = [], $page =
'', $user =
'', $param = []
602 $defaultParameters = [
605 'showIfEmpty' =>
true,
609 'useRequestParams' =>
false,
610 'useMaster' =>
false,
611 'extraUrlParams' =>
false,
613 # The + operator appends elements of remaining keys from the right
614 # handed array to the left handed, whereas duplicated keys are NOT overwritten.
615 $param += $defaultParameters;
616 # Convert $param array to individual variables
617 $lim = $param[
'lim'];
618 $conds = $param[
'conds'];
619 $showIfEmpty = $param[
'showIfEmpty'];
620 $msgKey = $param[
'msgKey'];
621 $wrap = $param[
'wrap'];
623 $extraUrlParams = $param[
'extraUrlParams'];
625 $useRequestParams = $param[
'useRequestParams'];
627 if ( !is_array( $msgKey ) ) {
628 $msgKey = [ $msgKey ];
632 $context = $out->getContext();
634 $context = RequestContext::getMain();
637 $services = MediaWikiServices::getInstance();
639 $linkRenderer = $services->getLinkRenderer();
641 # Insert list of top 50 (or top $lim) items
656 $services->getLinkBatchFactory(),
657 $services->getDBLoadBalancer(),
658 $services->getActorNormalization()
660 if ( !$useRequestParams ) {
661 # Reset vars that may have been taken from the request
663 $pager->mDefaultLimit = 50;
664 $pager->mOffset =
"";
665 $pager->mIsBackwards =
false;
668 if ( $param[
'useMaster'] ) {
672 if ( isset( $param[
'offset'] ) ) { # Tell pager to ignore
WebRequest offset
673 $pager->setOffset( $param[
'offset'] );
678 $pager->mLimit = $lim;
681 $logBody = $pager->getBody();
682 $numRows = $pager->getNumRows();
689 $msg = $context->msg( ...$msgKey );
693 $s .= $msg->parseAsBlock();
695 $s .= $loglist->beginLogEventsList() .
697 $loglist->endLogEventsList();
699 $context->getOutput()->addModuleStyles(
'mediawiki.interface.helpers.styles' );
700 } elseif ( $showIfEmpty ) {
701 $s = Html::rawElement(
'div', [
'class' =>
'mw-warning-logempty' ],
702 $context->msg(
'logempty' )->parse() );
706 $titleFormatter = MediaWikiServices::getInstance()->getTitleFormatter();
707 $pageName = $titleFormatter->getPrefixedDBkey( $page );
708 } elseif ( $page !=
'' ) {
714 if ( $numRows > $pager->mLimit ) { # Show
"Full log" link
717 $urlParam[
'page'] = $pageName;
721 $urlParam[
'user'] = $user;
724 if ( !is_array( $types ) ) { # Make it an array,
if it isn
't
728 # If there is exactly one log type, we can link to Special:Log?type=foo
729 if ( count( $types ) == 1 ) {
730 $urlParam['type
'] = $types[0];
733 // @phan-suppress-next-line PhanSuspiciousValueComparison
734 if ( $extraUrlParams !== false ) {
735 $urlParam = array_merge( $urlParam, $extraUrlParams );
738 $s .= $linkRenderer->makeKnownLink(
739 SpecialPage::getTitleFor( 'Log
' ),
740 $context->msg( 'log-fulllog
' )->text(),
746 if ( $logBody && $msgKey[0] ) {
747 // TODO: The condition above is weird. Should this be done in any other cases?
748 // Or is it always true in practice?
750 // Mark as interface language (T60685)
751 $dir = $context->getLanguage()->getDir();
752 $lang = $context->getLanguage()->getHtmlCode();
753 $s = Html::rawElement( 'div
', [
754 'class' => "mw-content-$dir",
759 // Wrap in warning box
760 $s = Html::warningBox(
762 'mw-warning-with-logexcerpt
'
766 // @phan-suppress-next-line PhanSuspiciousValueComparison
767 if ( $wrap != '' ) { // Wrap message in html
768 $s = str_replace( '$1
', $s, $wrap );
771 /* hook can return false, if we don't want the message to be emitted (Wikia BugId:7093) */
772 if ( Hooks::runner()->onLogEventsListShowLogExtract(
$s, $types, $pageName, $user, $param ) ) {
794 $logRestrictions = MediaWikiServices::getInstance()->getMainConfig()->get( MainConfigNames::LogRestrictions );
796 if ( $audience !=
'public' && $performer ===
null ) {
797 throw new InvalidArgumentException(
798 'A User object must be given when checking for a user audience.'
806 foreach ( $logRestrictions as $logType => $right ) {
807 if ( $audience ==
'public' || !$performer->isAllowed( $right )
809 $hiddenLogs[] = $logType;
812 if ( count( $hiddenLogs ) == 1 ) {
813 return 'log_type != ' . $db->addQuotes( $hiddenLogs[0] );
814 } elseif ( $hiddenLogs ) {
815 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()
setContext(IContextSource $context)
An IContextSource implementation which will inherit context from another source but allow individual ...
static revDeleteLinkDisabled( $delete=true)
Creates a dead (show/hide) link for deleting revisions/log entries.
static revDeleteLink( $query=[], $restricted=false, $delete=true)
Creates a (show/hide) link for deleting revisions/log entries.
const NO_EXTRA_USER_LINKS
static typeAction( $row, $type, $action)
static showLogExtract(&$out, $types=[], $page='', $user='', $param=[])
Show log extract.
showOptions( $types=[], $user='', $page='', $pattern=false, $year=0, $month=0, $day=0, $filter=null, $tagFilter='', $action=null)
Show options for the log list.
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 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