43use Wikimedia\Timestamp\TimestampException;
76 parent::__construct(
'Log' );
77 $this->linkBatchFactory = $linkBatchFactory;
78 $this->dbProvider = $dbProvider;
79 $this->actorNormalization = $actorNormalization;
80 $this->userIdentityLookup = $userIdentityLookup;
81 $this->userNameUtils = $userNameUtils;
88 $out->addModules(
'mediawiki.userSuggest' );
89 $out->addModuleStyles(
'mediawiki.interface.helpers.styles' );
93 $opts->
add(
'type',
'' );
94 $opts->add(
'user',
'' );
95 $opts->add(
'page',
'' );
96 $opts->add(
'pattern',
false );
97 $opts->add(
'year',
null, FormOptions::INTNULL );
98 $opts->add(
'month',
null, FormOptions::INTNULL );
99 $opts->add(
'day',
null, FormOptions::INTNULL );
100 $opts->add(
'tagfilter',
'' );
101 $opts->add(
'tagInvert',
false );
102 $opts->add(
'offset',
'' );
103 $opts->add(
'dir',
'' );
104 $opts->add(
'offender',
'' );
105 $opts->add(
'subtype',
'' );
106 $opts->add(
'logid',
'' );
109 if ( $par !==
null ) {
110 $this->parseParams( (
string)$par );
112 $opts->fetchValuesFromRequest( $this->
getRequest() );
115 $dateString = $this->
getRequest()->getVal(
'wpdate' );
118 $dateStamp = MWTimestamp::getInstance( $dateString .
' 00:00:00' );
119 }
catch ( TimestampException $e ) {
125 $opts->setValue(
'year', (
int)$dateStamp->format(
'Y' ) );
126 $opts->setValue(
'month', (
int)$dateStamp->format(
'm' ) );
127 $opts->setValue(
'day', (
int)$dateStamp->format(
'd' ) );
134 $type = $opts->getValue(
'type' );
135 if ( isset( $logRestrictions[$type] )
136 && !$this->
getAuthority()->isAllowed( $logRestrictions[$type] )
141 # TODO: Move this into LogPager like other query conditions.
142 # Handle type-specific inputs
144 $offenderName = $opts->getValue(
'offender' );
145 if ( $opts->getValue(
'type' ) ==
'suppress' && $offenderName !==
'' ) {
146 $dbr = $this->dbProvider->getReplicaDatabase();
147 $offenderId = $this->actorNormalization->findActorIdByName( $offenderName, $dbr );
149 $qc = [
'ls_field' =>
'target_author_actor',
'ls_value' => strval( $offenderId ) ];
157 $opts->getValue(
'type' ), $this->getRequest(), $qc );
160 # TODO: Move this into LogEventList and use it as filter-callback in the field descriptor.
161 # Some log types are only for a 'User:' title but we might have been given
162 # only the username instead of the full title 'User:username'. This part try
163 # to lookup for a user by that name and eventually fix user input. See T3697.
164 if ( in_array( $opts->getValue(
'type' ), self::getLogTypesOnUser( $this->getHookRunner() ) ) ) {
165 # ok we have a type of log which expect a user title.
166 $page = $opts->getValue(
'page' );
167 $target = Title::newFromText( $page );
168 if ( $target && $target->getNamespace() ===
NS_MAIN ) {
169 if ( IPUtils::isValidRange( $target->getText() ) ) {
170 $page = IPUtils::sanitizeRange( $target->getText() );
172 # User forgot to add 'User:', we are adding it for him
173 $target = Title::makeTitleSafe(
NS_USER, $page );
174 } elseif ( $target && $target->getNamespace() ===
NS_USER
175 && IPUtils::isValidRange( $target->getText() )
177 $ipOrRange = IPUtils::sanitizeRange( $target->getText() );
178 if ( $ipOrRange !== $target->getText() ) {
179 $target = Title::makeTitleSafe(
NS_USER, $ipOrRange );
182 if ( $target !==
null ) {
183 $page = $target->getPrefixedText();
184 $opts->setValue(
'page', $page );
189 $this->show( $opts, $qc );
204 static $types =
null;
205 if ( $types !==
null ) {
216 ->onGetLogTypesOnUser( $types );
226 $subpages = LogPage::validTypes();
240 private function parseParams(
string $par ) {
242 $parms = explode(
'/', $par, 2 );
243 $symsForAll = [
'*',
'all' ];
244 if ( $parms[0] !==
'' &&
245 ( in_array( $parms[0], LogPage::validTypes() ) || in_array( $parms[0], $symsForAll ) )
247 $this->
getRequest()->setVal(
'type', $parms[0] );
248 if ( count( $parms ) === 2 ) {
249 $this->
getRequest()->setVal(
'user', $parms[1] );
251 } elseif ( $par !==
'' ) {
256 private function show( FormOptions $opts, array $extraConds ) {
257 # Create a LogPager item to get the results and a LogEventsList item to format them...
261 LogEventsList::USE_CHECKBOXES
263 $pager =
new LogPager(
265 $opts->getValue(
'type' ),
266 $opts->getValue(
'user' ),
267 $opts->getValue(
'page' ),
268 $opts->getValue(
'pattern' ),
270 $opts->getValue(
'year' ),
271 $opts->getValue(
'month' ),
272 $opts->getValue(
'day' ),
273 $opts->getValue(
'tagfilter' ),
274 $opts->getValue(
'subtype' ),
275 $opts->getValue(
'logid' ),
276 $this->linkBatchFactory,
277 $this->actorNormalization,
278 $opts->getValue(
'tagInvert' )
282 $performer = $pager->getPerformer();
284 $performerUser = $this->userIdentityLookup->getUserIdentityByName( $performer );
287 if ( $performerUser && !IPUtils::isValidRange( $performer ) &&
288 ( $this->userNameUtils->isIP( $performer ) || $performerUser->isRegistered() )
290 $this->
getSkin()->setRelevantUser( $performerUser );
295 $succeed = $loglist->showOptions(
296 $opts->getValue(
'type' ),
297 $opts->getValue(
'year' ),
298 $opts->getValue(
'month' ),
299 $opts->getValue(
'day' )
306 (
new LogPage( $opts->getValue(
'type' ) ) )->getName()
310 $logBody = $pager->getBody();
313 $pager->getNavigationBar() .
314 $this->getActionButtons(
315 $loglist->beginLogEventsList() .
317 $loglist->endLogEventsList()
319 $pager->getNavigationBar()
322 $this->
getOutput()->addWikiMsg(
'logempty' );
326 private function getActionButtons( $formcontents ) {
328 ->isAllowedAll(
'deletedhistory',
'deletelogentry' );
330 # If the user doesn't have the ability to delete log entries nor edit tags,
331 # don't bother showing them the button(s).
332 if ( !$canRevDelete && !$showTagEditUI ) {
333 return $formcontents;
336 # Show button to hide log entries and/or edit change tags
337 $s = Html::openElement(
339 [
'action' =>
wfScript(),
'id' =>
'mw-log-deleterevision-submit' ]
341 $s .= Html::hidden(
'type',
'logging' ) .
"\n";
344 if ( $canRevDelete ) {
351 'class' =>
"deleterevision-log-submit mw-log-deleterevision-button mw-ui-button"
353 $this->
msg(
'showhideselectedlogentries' )->text()
356 if ( $showTagEditUI ) {
363 'class' =>
"editchangetags-log-submit mw-log-editchangetags-button mw-ui-button"
365 $this->
msg(
'log-edit-tags' )->text()
369 $buttons .= (
new ListToggle( $this->
getOutput() ) )->getHTML();
371 $s .= $buttons . $formcontents . $buttons;
372 $s .= Html::closeElement(
'form' );
383class_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.