44use Wikimedia\Timestamp\TimestampException;
81 parent::__construct(
'Log' );
82 $this->linkBatchFactory = $linkBatchFactory;
83 $this->dbProvider = $dbProvider;
84 $this->actorNormalization = $actorNormalization;
85 $this->userIdentityLookup = $userIdentityLookup;
86 $this->userNameUtils = $userNameUtils;
87 $this->logFormatterFactory = $logFormatterFactory;
94 $out->addModuleStyles(
'mediawiki.interface.helpers.styles' );
98 $opts->
add(
'type',
'' );
99 $opts->add(
'user',
'' );
100 $opts->add(
'page',
'' );
101 $opts->add(
'pattern',
false );
102 $opts->add(
'year',
null, FormOptions::INTNULL );
103 $opts->add(
'month',
null, FormOptions::INTNULL );
104 $opts->add(
'day',
null, FormOptions::INTNULL );
105 $opts->add(
'tagfilter',
'' );
106 $opts->add(
'tagInvert',
false );
107 $opts->add(
'offset',
'' );
108 $opts->add(
'dir',
'' );
109 $opts->add(
'offender',
'' );
110 $opts->add(
'subtype',
'' );
111 $opts->add(
'logid',
'' );
114 if ( $par !==
null ) {
115 $this->parseParams( (
string)$par );
117 $opts->fetchValuesFromRequest( $this->
getRequest() );
120 $dateString = $this->
getRequest()->getVal(
'wpdate' );
123 $dateStamp = MWTimestamp::getInstance( $dateString .
' 00:00:00' );
124 }
catch ( TimestampException $e ) {
130 $opts->setValue(
'year', (
int)$dateStamp->format(
'Y' ) );
131 $opts->setValue(
'month', (
int)$dateStamp->format(
'm' ) );
132 $opts->setValue(
'day', (
int)$dateStamp->format(
'd' ) );
139 $type = $opts->getValue(
'type' );
140 if ( isset( $logRestrictions[$type] )
141 && !$this->
getAuthority()->isAllowed( $logRestrictions[$type] )
146 # TODO: Move this into LogPager like other query conditions.
147 # Handle type-specific inputs
149 $offenderName = $opts->getValue(
'offender' );
150 if ( $opts->getValue(
'type' ) ==
'suppress' && $offenderName !==
'' ) {
151 $dbr = $this->dbProvider->getReplicaDatabase();
152 $offenderId = $this->actorNormalization->findActorIdByName( $offenderName, $dbr );
154 $qc = [
'ls_field' =>
'target_author_actor',
'ls_value' => strval( $offenderId ) ];
162 $opts->getValue(
'type' ), $this->getRequest(), $qc );
165 # TODO: Move this into LogEventList and use it as filter-callback in the field descriptor.
166 # Some log types are only for a 'User:' title but we might have been given
167 # only the username instead of the full title 'User:username'. This part try
168 # to lookup for a user by that name and eventually fix user input. See T3697.
169 if ( in_array( $opts->getValue(
'type' ), self::getLogTypesOnUser( $this->getHookRunner() ) ) ) {
170 # ok we have a type of log which expect a user title.
171 $page = $opts->getValue(
'page' );
172 $target = Title::newFromText( $page );
173 if ( $target && $target->getNamespace() ===
NS_MAIN ) {
174 if ( IPUtils::isValidRange( $target->getText() ) ) {
175 $page = IPUtils::sanitizeRange( $target->getText() );
177 # User forgot to add 'User:', we are adding it for him
178 $target = Title::makeTitleSafe(
NS_USER, $page );
179 } elseif ( $target && $target->getNamespace() ===
NS_USER
180 && IPUtils::isValidRange( $target->getText() )
182 $ipOrRange = IPUtils::sanitizeRange( $target->getText() );
183 if ( $ipOrRange !== $target->getText() ) {
184 $target = Title::makeTitleSafe(
NS_USER, $ipOrRange );
187 if ( $target !==
null ) {
188 $page = $target->getPrefixedText();
189 $opts->setValue(
'page', $page );
194 $this->show( $opts, $qc );
209 static $types =
null;
210 if ( $types !==
null ) {
221 ->onGetLogTypesOnUser( $types );
231 $subpages = LogPage::validTypes();
245 private function parseParams(
string $par ) {
247 $parms = explode(
'/', $par, 2 );
248 $symsForAll = [
'*',
'all' ];
249 if ( $parms[0] !==
'' &&
250 ( in_array( $parms[0], LogPage::validTypes() ) || in_array( $parms[0], $symsForAll ) )
252 $this->
getRequest()->setVal(
'type', $parms[0] );
253 if ( count( $parms ) === 2 ) {
254 $this->
getRequest()->setVal(
'user', $parms[1] );
256 } elseif ( $par !==
'' ) {
261 private function show( FormOptions $opts, array $extraConds ) {
262 # Create a LogPager item to get the results and a LogEventsList item to format them...
266 LogEventsList::USE_CHECKBOXES
268 $pager =
new LogPager(
270 $opts->getValue(
'type' ),
271 $opts->getValue(
'user' ),
272 $opts->getValue(
'page' ),
273 $opts->getValue(
'pattern' ),
275 $opts->getValue(
'year' ),
276 $opts->getValue(
'month' ),
277 $opts->getValue(
'day' ),
278 $opts->getValue(
'tagfilter' ),
279 $opts->getValue(
'subtype' ),
280 $opts->getValue(
'logid' ),
281 $this->linkBatchFactory,
282 $this->actorNormalization,
283 $this->logFormatterFactory,
284 $opts->getValue(
'tagInvert' )
288 $performer = $pager->getPerformer();
290 $performerUser = $this->userIdentityLookup->getUserIdentityByName( $performer );
293 if ( $performerUser && !IPUtils::isValidRange( $performer ) &&
294 ( $this->userNameUtils->isIP( $performer ) || $performerUser->isRegistered() )
296 $this->
getSkin()->setRelevantUser( $performerUser );
301 $succeed = $loglist->showOptions(
302 $opts->getValue(
'type' ),
303 $opts->getValue(
'year' ),
304 $opts->getValue(
'month' ),
305 $opts->getValue(
'day' )
312 (
new LogPage( $opts->getValue(
'type' ) ) )->getName()
316 $logBody = $pager->getBody();
319 $pager->getNavigationBar() .
320 $this->getActionButtons(
321 $loglist->beginLogEventsList() .
323 $loglist->endLogEventsList()
325 $pager->getNavigationBar()
328 $this->
getOutput()->addWikiMsg(
'logempty' );
332 private function getActionButtons( $formcontents ) {
334 ->isAllowedAll(
'deletedhistory',
'deletelogentry' );
336 # If the user doesn't have the ability to delete log entries nor edit tags,
337 # don't bother showing them the button(s).
338 if ( !$canRevDelete && !$showTagEditUI ) {
339 return $formcontents;
342 # Show button to hide log entries and/or edit change tags
343 $s = Html::openElement(
345 [
'action' =>
wfScript(),
'id' =>
'mw-log-deleterevision-submit' ]
347 $s .= Html::hidden(
'type',
'logging' ) .
"\n";
350 if ( $canRevDelete ) {
357 'class' =>
"deleterevision-log-submit mw-log-deleterevision-button mw-ui-button"
359 $this->
msg(
'showhideselectedlogentries' )->text()
362 if ( $showTagEditUI ) {
369 'class' =>
"editchangetags-log-submit mw-log-editchangetags-button mw-ui-button"
371 $this->
msg(
'log-edit-tags' )->text()
375 $buttons .= (
new ListToggle( $this->
getOutput() ) )->getHTML();
377 $s .= $buttons . $formcontents . $buttons;
378 $s .= Html::closeElement(
'form' );
389class_alias( SpecialLog::class,
'SpecialLog' );
wfScript( $script='index')
Get the URL path to a MediaWiki entry point.
Class to simplify the use of log pages.
A class containing constants representing the names of configuration variables.
const LogRestrictions
Name constant for the LogRestrictions setting, for use with Config::get()
Parent class for all special pages.
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
getSkin()
Shortcut to get the skin being used for this instance.
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,...
getConfig()
Shortcut to get main config object.
getContext()
Gets the context this SpecialPage is executed in.
getRequest()
Get the WebRequest being used for this instance.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getOutput()
Get the OutputPage being used for this instance.
getAuthority()
Shortcut to get the Authority executing this instance.
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages By default the message key is the canonical name of...
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Show an error when a user tries to do something they do not have the necessary permissions for.