Completed
Branch master (d58858)
by
unknown
28:23
created

SpecialLog::getGroupName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 3
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
/**
3
 * Implements Special:Log
4
 *
5
 * Copyright © 2008 Aaron Schulz
6
 *
7
 * This program is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 2 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License along
18
 * with this program; if not, write to the Free Software Foundation, Inc.,
19
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
 * http://www.gnu.org/copyleft/gpl.html
21
 *
22
 * @file
23
 * @ingroup SpecialPage
24
 */
25
26
/**
27
 * A special page that lists log entries
28
 *
29
 * @ingroup SpecialPage
30
 */
31
class SpecialLog extends SpecialPage {
32
	public function __construct() {
33
		parent::__construct( 'Log' );
34
	}
35
36
	public function execute( $par ) {
37
		$this->setHeaders();
38
		$this->outputHeader();
39
		$this->getOutput()->addModules( 'mediawiki.userSuggest' );
40
41
		$opts = new FormOptions;
42
		$opts->add( 'type', '' );
43
		$opts->add( 'user', '' );
44
		$opts->add( 'page', '' );
45
		$opts->add( 'pattern', false );
46
		$opts->add( 'year', null, FormOptions::INTNULL );
47
		$opts->add( 'month', null, FormOptions::INTNULL );
48
		$opts->add( 'tagfilter', '' );
49
		$opts->add( 'offset', '' );
50
		$opts->add( 'dir', '' );
51
		$opts->add( 'offender', '' );
52
		$opts->add( 'subtype', '' );
53
54
		// Set values
55
		$opts->fetchValuesFromRequest( $this->getRequest() );
56
		if ( $par !== null ) {
57
			$this->parseParams( $opts, (string)$par );
58
		}
59
60
		# Don't let the user get stuck with a certain date
61
		if ( $opts->getValue( 'offset' ) || $opts->getValue( 'dir' ) == 'prev' ) {
62
			$opts->setValue( 'year', '' );
63
			$opts->setValue( 'month', '' );
64
		}
65
66
		// If the user doesn't have the right permission to view the specific
67
		// log type, throw a PermissionsError
68
		// If the log type is invalid, just show all public logs
69
		$logRestrictions = $this->getConfig()->get( 'LogRestrictions' );
70
		$type = $opts->getValue( 'type' );
71
		if ( !LogPage::isLogType( $type ) ) {
72
			$opts->setValue( 'type', '' );
73
		} elseif ( isset( $logRestrictions[$type] )
74
			&& !$this->getUser()->isAllowed( $logRestrictions[$type] )
75
		) {
76
			throw new PermissionsError( $logRestrictions[$type] );
77
		}
78
79
		# Handle type-specific inputs
80
		$qc = [];
81
		if ( $opts->getValue( 'type' ) == 'suppress' ) {
82
			$offender = User::newFromName( $opts->getValue( 'offender' ), false );
83
			if ( $offender && $offender->getId() > 0 ) {
84
				$qc = [ 'ls_field' => 'target_author_id', 'ls_value' => $offender->getId() ];
85
			} elseif ( $offender && IP::isIPAddress( $offender->getName() ) ) {
86
				$qc = [ 'ls_field' => 'target_author_ip', 'ls_value' => $offender->getName() ];
87
			}
88
		} else {
89
			// Allow extensions to add relations to their search types
90
			Hooks::run(
91
				'SpecialLogAddLogSearchRelations',
92
				[ $opts->getValue( 'type' ), $this->getRequest(), &$qc ]
93
			);
94
		}
95
96
		# Some log types are only for a 'User:' title but we might have been given
97
		# only the username instead of the full title 'User:username'. This part try
98
		# to lookup for a user by that name and eventually fix user input. See bug 1697.
99
		if ( in_array( $opts->getValue( 'type' ), self::getLogTypesOnUser() ) ) {
100
			# ok we have a type of log which expect a user title.
101
			$target = Title::newFromText( $opts->getValue( 'page' ) );
102
			if ( $target && $target->getNamespace() === NS_MAIN ) {
103
				# User forgot to add 'User:', we are adding it for him
104
				$opts->setValue( 'page',
105
					Title::makeTitleSafe( NS_USER, $opts->getValue( 'page' ) )
106
				);
107
			}
108
		}
109
110
		$this->show( $opts, $qc );
111
	}
112
113
	/**
114
	 * List log type for which the target is a user
115
	 * Thus if the given target is in NS_MAIN we can alter it to be an NS_USER
116
	 * Title user instead.
117
	 *
118
	 * @since 1.25
119
	 * @return array
120
	 */
121
	public static function getLogTypesOnUser() {
122
		static $types = null;
123
		if ( $types !== null ) {
124
			return $types;
125
		}
126
		$types = [
127
			'block',
128
			'newusers',
129
			'rights',
130
		];
131
132
		Hooks::run( 'GetLogTypesOnUser', [ &$types ] );
133
		return $types;
134
	}
135
136
	/**
137
	 * Return an array of subpages that this special page will accept.
138
	 *
139
	 * @return string[] subpages
140
	 */
141
	public function getSubpagesForPrefixSearch() {
142
		$subpages = $this->getConfig()->get( 'LogTypes' );
143
		$subpages[] = 'all';
144
		sort( $subpages );
145
		return $subpages;
146
	}
147
148
	private function parseParams( FormOptions $opts, $par ) {
149
		# Get parameters
150
		$parms = explode( '/', ( $par = ( $par !== null ) ? $par : '' ) );
151
		$symsForAll = [ '*', 'all' ];
152
		if ( $parms[0] != '' &&
153
			( in_array( $par, $this->getConfig()->get( 'LogTypes' ) ) || in_array( $par, $symsForAll ) )
154
		) {
155
			$opts->setValue( 'type', $par );
156
		} elseif ( count( $parms ) == 2 ) {
157
			$opts->setValue( 'type', $parms[0] );
158
			$opts->setValue( 'user', $parms[1] );
159
		} elseif ( $par != '' ) {
160
			$opts->setValue( 'user', $par );
161
		}
162
	}
163
164
	private function show( FormOptions $opts, array $extraConds ) {
165
		# Create a LogPager item to get the results and a LogEventsList item to format them...
166
		$loglist = new LogEventsList(
167
			$this->getContext(),
168
			null,
169
			LogEventsList::USE_CHECKBOXES
170
		);
171
172
		$pager = new LogPager(
173
			$loglist,
174
			$opts->getValue( 'type' ),
175
			$opts->getValue( 'user' ),
176
			$opts->getValue( 'page' ),
177
			$opts->getValue( 'pattern' ),
178
			$extraConds,
179
			$opts->getValue( 'year' ),
180
			$opts->getValue( 'month' ),
181
			$opts->getValue( 'tagfilter' ),
182
			$opts->getValue( 'subtype' )
183
		);
184
185
		$this->addHeader( $opts->getValue( 'type' ) );
186
187
		# Set relevant user
188
		if ( $pager->getPerformer() ) {
189
			$this->getSkin()->setRelevantUser( User::newFromName( $pager->getPerformer() ) );
0 ignored issues
show
Security Bug introduced by
It seems like \User::newFromName($pager->getPerformer()) targeting User::newFromName() can also be of type false; however, Skin::setRelevantUser() does only seem to accept object<User>, did you maybe forget to handle an error condition?
Loading history...
190
		}
191
192
		# Show form options
193
		$loglist->showOptions(
194
			$pager->getType(),
195
			$pager->getPerformer(),
196
			$pager->getPage(),
0 ignored issues
show
Bug introduced by
It seems like $pager->getPage() targeting LogPager::getPage() can also be of type object<Title>; however, LogEventsList::showOptions() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
197
			$pager->getPattern(),
198
			$pager->getYear(),
0 ignored issues
show
Security Bug introduced by
It seems like $pager->getYear() targeting LogPager::getYear() can also be of type false; however, LogEventsList::showOptions() does only seem to accept integer, did you maybe forget to handle an error condition?
Loading history...
199
			$pager->getMonth(),
0 ignored issues
show
Security Bug introduced by
It seems like $pager->getMonth() targeting LogPager::getMonth() can also be of type false; however, LogEventsList::showOptions() does only seem to accept integer, did you maybe forget to handle an error condition?
Loading history...
200
			$pager->getFilterParams(),
201
			$pager->getTagFilter(),
202
			$pager->getAction()
203
		);
204
205
		# Insert list
206
		$logBody = $pager->getBody();
207
		if ( $logBody ) {
208
			$this->getOutput()->addHTML(
209
				$pager->getNavigationBar() .
210
					$this->getActionButtons(
211
						$loglist->beginLogEventsList() .
212
							$logBody .
213
							$loglist->endLogEventsList()
214
					) .
215
					$pager->getNavigationBar()
216
			);
217
		} else {
218
			$this->getOutput()->addWikiMsg( 'logempty' );
219
		}
220
	}
221
222
	private function getActionButtons( $formcontents ) {
223
		$user = $this->getUser();
224
		$canRevDelete = $user->isAllowedAll( 'deletedhistory', 'deletelogentry' );
225
		$showTagEditUI = ChangeTags::showTagEditingUI( $user );
226
		# If the user doesn't have the ability to delete log entries nor edit tags,
227
		# don't bother showing them the button(s).
228
		if ( !$canRevDelete && !$showTagEditUI ) {
229
			return $formcontents;
230
		}
231
232
		# Show button to hide log entries and/or edit change tags
233
		$s = Html::openElement(
234
			'form',
235
			[ 'action' => wfScript(), 'id' => 'mw-log-deleterevision-submit' ]
236
		) . "\n";
237
		$s .= Html::hidden( 'action', 'historysubmit' ) . "\n";
238
		$s .= Html::hidden( 'type', 'logging' ) . "\n";
239
240
		$buttons = '';
241 View Code Duplication
		if ( $canRevDelete ) {
242
			$buttons .= Html::element(
243
				'button',
244
				[
245
					'type' => 'submit',
246
					'name' => 'revisiondelete',
247
					'value' => '1',
248
					'class' => "deleterevision-log-submit mw-log-deleterevision-button"
249
				],
250
				$this->msg( 'showhideselectedlogentries' )->text()
251
			) . "\n";
252
		}
253 View Code Duplication
		if ( $showTagEditUI ) {
254
			$buttons .= Html::element(
255
				'button',
256
				[
257
					'type' => 'submit',
258
					'name' => 'editchangetags',
259
					'value' => '1',
260
					'class' => "editchangetags-log-submit mw-log-editchangetags-button"
261
				],
262
				$this->msg( 'log-edit-tags' )->text()
263
			) . "\n";
264
		}
265
266
		$buttons .= ( new ListToggle( $this->getOutput() ) )->getHTML();
267
268
		$s .= $buttons . $formcontents . $buttons;
269
		$s .= Html::closeElement( 'form' );
270
271
		return $s;
272
	}
273
274
	/**
275
	 * Set page title and show header for this log type
276
	 * @param string $type
277
	 * @since 1.19
278
	 */
279
	protected function addHeader( $type ) {
280
		$page = new LogPage( $type );
281
		$this->getOutput()->setPageTitle( $page->getName() );
282
		$this->getOutput()->addHTML( $page->getDescription()
283
			->setContext( $this->getContext() )->parseAsBlock() );
284
	}
285
286
	protected function getGroupName() {
287
		return 'changes';
288
	}
289
}
290