File: HideAbuseLog.php

package info (click to toggle)
mediawiki 1%3A1.43.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 417,464 kB
  • sloc: php: 1,062,949; javascript: 664,290; sql: 9,714; python: 5,458; xml: 3,489; sh: 1,131; makefile: 64
file content (204 lines) | stat: -rw-r--r-- 6,684 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
<?php

namespace MediaWiki\Extension\AbuseFilter\View;

use LogEventsList;
use LogPage;
use ManualLogEntry;
use MediaWiki\Context\IContextSource;
use MediaWiki\Deferred\DeferredUpdates;
use MediaWiki\Extension\AbuseFilter\AbuseFilterPermissionManager;
use MediaWiki\Extension\AbuseFilter\Pager\AbuseLogPager;
use MediaWiki\Html\Html;
use MediaWiki\HTMLForm\HTMLForm;
use MediaWiki\Linker\LinkRenderer;
use MediaWiki\MediaWikiServices;
use Wikimedia\Rdbms\LBFactory;

class HideAbuseLog extends AbuseFilterView {

	/** @var LBFactory */
	private $lbFactory;

	/** @var int[] */
	private $hideIDs;

	/**
	 * @param LBFactory $lbFactory
	 * @param AbuseFilterPermissionManager $afPermManager
	 * @param IContextSource $context
	 * @param LinkRenderer $linkRenderer
	 * @param string $basePageName
	 */
	public function __construct(
		LBFactory $lbFactory,
		AbuseFilterPermissionManager $afPermManager,
		IContextSource $context,
		LinkRenderer $linkRenderer,
		string $basePageName
	) {
		parent::__construct( $afPermManager, $context, $linkRenderer, $basePageName, [] );
		$this->lbFactory = $lbFactory;
		$this->hideIDs = array_keys( $this->getRequest()->getArray( 'hideids', [] ) );
	}

	/**
	 * Shows the page
	 */
	public function show(): void {
		$output = $this->getOutput();
		$output->enableOOUI();

		if ( !$this->afPermManager->canHideAbuseLog( $this->getAuthority() ) ) {
			$output->addWikiMsg( 'abusefilter-log-hide-forbidden' );
			return;
		}

		if ( !$this->hideIDs ) {
			$output->addWikiMsg( 'abusefilter-log-hide-no-selected' );
			return;
		}

		// TODO DI
		$pager = new AbuseLogPager(
			$this->getContext(),
			MediaWikiServices::getInstance()->getLinkRenderer(),
			[ 'afl_id' => $this->hideIDs ],
			MediaWikiServices::getInstance()->getLinkBatchFactory(),
			MediaWikiServices::getInstance()->getPermissionManager(),
			$this->afPermManager,
			$this->basePageName,
			array_fill_keys( $this->hideIDs, $this->getRequest()->getVal( 'wpshoworhide' ) )
		);
		$pager->doQuery();
		if ( $pager->getResult()->numRows() === 0 ) {
			$output->addWikiMsg( 'abusefilter-log-hide-no-selected' );
			return;
		}

		$output->addModuleStyles( 'mediawiki.interface.helpers.styles' );
		$output->wrapWikiMsg(
			"<strong>$1</strong>",
			[
				'abusefilter-log-hide-selected',
				$this->getLanguage()->formatNum( count( $this->hideIDs ) )
			]
		);
		$output->addHTML( Html::rawElement( 'ul', [ 'class' => 'plainlinks' ], $pager->getBody() ) );

		$hideReasonsOther = $this->msg( 'revdelete-reasonotherlist' )->text();
		$hideReasons = $this->msg( 'revdelete-reason-dropdown-suppress' )->inContentLanguage()->text();
		$hideReasons = Html::listDropdownOptions( $hideReasons, [ 'other' => $hideReasonsOther ] );

		$formInfo = [
			'showorhide' => [
				'type' => 'radio',
				'label-message' => 'abusefilter-log-hide-set-visibility',
				'options-messages' => [
					'abusefilter-log-hide-show' => 'show',
					'abusefilter-log-hide-hide' => 'hide'
				],
				'default' => 'hide',
				'flatlist' => true
			],
			'dropdownreason' => [
				'type' => 'select',
				'options' => $hideReasons,
				'label-message' => 'abusefilter-log-hide-reason'
			],
			'reason' => [
				'type' => 'text',
				'label-message' => 'abusefilter-log-hide-reason-other',
			],
		];

		$actionURL = $this->getTitle( 'hide' )->getLocalURL( [ 'hideids' => array_fill_keys( $this->hideIDs, 1 ) ] );
		HTMLForm::factory( 'ooui', $formInfo, $this->getContext() )
			->setAction( $actionURL )
			->setWrapperLegend( $this->msg( 'abusefilter-log-hide-legend' )->text() )
			->setSubmitCallback( [ $this, 'saveHideForm' ] )
			->showAlways();

		// Show suppress log for this entry. Hack: since every suppression is performed on a
		// totally different page (i.e. Special:AbuseLog/xxx), we use showLogExtract without
		// specifying a title and then adding it in conds.
		// This isn't shown if the request was posted because we update visibility in a DeferredUpdate, so it would
		// display outdated info that might confuse the user.
		// TODO Can we improve this somehow?
		if ( !$this->getRequest()->wasPosted() ) {
			$suppressLogPage = new LogPage( 'suppress' );
			$output->addHTML( "<h2>" . $suppressLogPage->getName()->escaped() . "</h2>\n" );
			$searchTitles = [];
			foreach ( $this->hideIDs as $id ) {
				$searchTitles[] = $this->getTitle( (string)$id )->getDBkey();
			}
			$conds = [ 'log_namespace' => NS_SPECIAL, 'log_title' => $searchTitles ];
			LogEventsList::showLogExtract( $output, 'suppress', '', '', [ 'conds' => $conds ] );
		}
	}

	/**
	 * Process the hide form after submission. This performs the actual visibility update. Used as callback by HTMLForm
	 *
	 * @param array $fields
	 * @return bool|array True on success, array of error message keys otherwise
	 */
	public function saveHideForm( array $fields ) {
		// Determine which rows actually have to be changed
		$dbw = $this->lbFactory->getPrimaryDatabase();
		$newValue = $fields['showorhide'] === 'hide' ? 1 : 0;
		$actualIDs = $dbw->newSelectQueryBuilder()
			->select( 'afl_id' )
			->from( 'abuse_filter_log' )
			->where( [
				'afl_id' => $this->hideIDs,
				$dbw->expr( 'afl_deleted', '!=', $newValue ),
			] )
			->caller( __METHOD__ )
			->fetchFieldValues();
		if ( !count( $actualIDs ) ) {
			return [ 'abusefilter-log-hide-no-change' ];
		}

		$dbw->newUpdateQueryBuilder()
			->update( 'abuse_filter_log' )
			->set( [ 'afl_deleted' => $newValue ] )
			->where( [ 'afl_id' => $actualIDs ] )
			->caller( __METHOD__ )
			->execute();

		// Log in a DeferredUpdates to avoid potential flood
		DeferredUpdates::addCallableUpdate( function () use ( $fields, $actualIDs ) {
			$reason = $fields['dropdownreason'];
			if ( $reason === 'other' ) {
				$reason = $fields['reason'];
			} elseif ( $fields['reason'] !== '' ) {
				$reason .=
					$this->msg( 'colon-separator' )->inContentLanguage()->text() . $fields['reason'];
			}

			$action = $fields['showorhide'] === 'hide' ? 'hide-afl' : 'unhide-afl';
			foreach ( $actualIDs as $logid ) {
				$logEntry = new ManualLogEntry( 'suppress', $action );
				$logEntry->setPerformer( $this->getUser() );
				$logEntry->setTarget( $this->getTitle( $logid ) );
				$logEntry->setComment( $reason );
				$logEntry->insert();
			}
		} );

		$count = count( $actualIDs );
		$this->getOutput()->prependHTML(
			Html::successBox(
				$this->msg( 'abusefilter-log-hide-done' )->params(
					$this->getLanguage()->formatNum( $count ),
					// Messages used: abusefilter-log-hide-done-hide, abusefilter-log-hide-done-show
					$this->msg( 'abusefilter-log-hide-done-' . $fields['showorhide'] )->numParams( $count )->text()
				)->escaped()
			)
		);

		return true;
	}

}