Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
23.97% |
29 / 121 |
|
33.33% |
1 / 3 |
CRAP | |
0.00% |
0 / 1 |
HideAbuseLog | |
23.97% |
29 / 121 |
|
33.33% |
1 / 3 |
100.15 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 | |||
show | |
32.86% |
23 / 70 |
|
0.00% |
0 / 1 |
16.90 | |||
saveHideForm | |
0.00% |
0 / 45 |
|
0.00% |
0 / 1 |
56 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Extension\AbuseFilter\View; |
4 | |
5 | use MediaWiki\Cache\LinkBatchFactory; |
6 | use MediaWiki\Context\IContextSource; |
7 | use MediaWiki\Deferred\DeferredUpdates; |
8 | use MediaWiki\Extension\AbuseFilter\AbuseFilterPermissionManager; |
9 | use MediaWiki\Extension\AbuseFilter\Pager\AbuseLogPager; |
10 | use MediaWiki\Extension\AbuseFilter\Variables\VariablesBlobStore; |
11 | use MediaWiki\Html\Html; |
12 | use MediaWiki\HTMLForm\HTMLForm; |
13 | use MediaWiki\Linker\LinkRenderer; |
14 | use MediaWiki\Logging\LogEventsList; |
15 | use MediaWiki\Logging\LogPage; |
16 | use MediaWiki\Logging\ManualLogEntry; |
17 | use MediaWiki\Permissions\PermissionManager; |
18 | use Wikimedia\Rdbms\LBFactory; |
19 | |
20 | class HideAbuseLog extends AbuseFilterView { |
21 | |
22 | private LBFactory $lbFactory; |
23 | private LinkBatchFactory $linkBatchFactory; |
24 | private PermissionManager $permissionManager; |
25 | private VariablesBlobStore $variablesBlobStore; |
26 | |
27 | /** @var int[] */ |
28 | private $hideIDs; |
29 | |
30 | public function __construct( |
31 | LBFactory $lbFactory, |
32 | AbuseFilterPermissionManager $afPermManager, |
33 | IContextSource $context, |
34 | LinkRenderer $linkRenderer, |
35 | LinkBatchFactory $linkBatchFactory, |
36 | PermissionManager $permissionManager, |
37 | VariablesBlobStore $variablesBlobStore, |
38 | string $basePageName |
39 | ) { |
40 | parent::__construct( $afPermManager, $context, $linkRenderer, $basePageName, [] ); |
41 | $this->lbFactory = $lbFactory; |
42 | $this->linkBatchFactory = $linkBatchFactory; |
43 | $this->permissionManager = $permissionManager; |
44 | $this->variablesBlobStore = $variablesBlobStore; |
45 | |
46 | $this->hideIDs = array_keys( $this->getRequest()->getArray( 'hideids', [] ) ); |
47 | } |
48 | |
49 | /** |
50 | * Shows the page |
51 | */ |
52 | public function show(): void { |
53 | $output = $this->getOutput(); |
54 | $output->enableOOUI(); |
55 | |
56 | if ( !$this->afPermManager->canHideAbuseLog( $this->getAuthority() ) ) { |
57 | $output->addWikiMsg( 'abusefilter-log-hide-forbidden' ); |
58 | return; |
59 | } |
60 | |
61 | if ( !$this->hideIDs ) { |
62 | $output->addWikiMsg( 'abusefilter-log-hide-no-selected' ); |
63 | return; |
64 | } |
65 | |
66 | $pager = new AbuseLogPager( |
67 | $this->getContext(), |
68 | $this->linkRenderer, |
69 | [ 'afl_id' => $this->hideIDs ], |
70 | $this->linkBatchFactory, |
71 | $this->permissionManager, |
72 | $this->afPermManager, |
73 | $this->variablesBlobStore, |
74 | $this->basePageName, |
75 | array_fill_keys( $this->hideIDs, $this->getRequest()->getVal( 'wpshoworhide' ) ) |
76 | ); |
77 | $pager->doQuery(); |
78 | if ( $pager->getResult()->numRows() === 0 ) { |
79 | $output->addWikiMsg( 'abusefilter-log-hide-no-selected' ); |
80 | return; |
81 | } |
82 | |
83 | $output->addModuleStyles( 'mediawiki.interface.helpers.styles' ); |
84 | $output->wrapWikiMsg( |
85 | "<strong>$1</strong>", |
86 | [ |
87 | 'abusefilter-log-hide-selected', |
88 | $this->getLanguage()->formatNum( count( $this->hideIDs ) ) |
89 | ] |
90 | ); |
91 | $output->addHTML( Html::rawElement( 'ul', [ 'class' => 'plainlinks' ], $pager->getBody() ) ); |
92 | |
93 | $hideReasonsOther = $this->msg( 'revdelete-reasonotherlist' )->text(); |
94 | $hideReasons = $this->msg( 'revdelete-reason-dropdown-suppress' )->inContentLanguage()->text(); |
95 | $hideReasons = Html::listDropdownOptions( $hideReasons, [ 'other' => $hideReasonsOther ] ); |
96 | |
97 | $formInfo = [ |
98 | 'showorhide' => [ |
99 | 'type' => 'radio', |
100 | 'label-message' => 'abusefilter-log-hide-set-visibility', |
101 | 'options-messages' => [ |
102 | 'abusefilter-log-hide-show' => 'show', |
103 | 'abusefilter-log-hide-hide' => 'hide' |
104 | ], |
105 | 'default' => 'hide', |
106 | 'flatlist' => true |
107 | ], |
108 | 'dropdownreason' => [ |
109 | 'type' => 'select', |
110 | 'options' => $hideReasons, |
111 | 'label-message' => 'abusefilter-log-hide-reason' |
112 | ], |
113 | 'reason' => [ |
114 | 'type' => 'text', |
115 | 'label-message' => 'abusefilter-log-hide-reason-other', |
116 | ], |
117 | ]; |
118 | |
119 | $actionURL = $this->getTitle( 'hide' )->getLocalURL( [ 'hideids' => array_fill_keys( $this->hideIDs, 1 ) ] ); |
120 | HTMLForm::factory( 'ooui', $formInfo, $this->getContext() ) |
121 | ->setAction( $actionURL ) |
122 | ->setWrapperLegend( $this->msg( 'abusefilter-log-hide-legend' )->text() ) |
123 | ->setSubmitCallback( [ $this, 'saveHideForm' ] ) |
124 | ->showAlways(); |
125 | |
126 | // Show suppress log for this entry. Hack: since every suppression is performed on a |
127 | // totally different page (i.e. Special:AbuseLog/xxx), we use showLogExtract without |
128 | // specifying a title and then adding it in conds. |
129 | // This isn't shown if the request was posted because we update visibility in a DeferredUpdate, so it would |
130 | // display outdated info that might confuse the user. |
131 | // TODO Can we improve this somehow? |
132 | if ( !$this->getRequest()->wasPosted() ) { |
133 | $suppressLogPage = new LogPage( 'suppress' ); |
134 | $output->addHTML( "<h2>" . $suppressLogPage->getName()->escaped() . "</h2>\n" ); |
135 | $searchTitles = []; |
136 | foreach ( $this->hideIDs as $id ) { |
137 | $searchTitles[] = $this->getTitle( (string)$id )->getDBkey(); |
138 | } |
139 | $conds = [ 'log_namespace' => NS_SPECIAL, 'log_title' => $searchTitles ]; |
140 | LogEventsList::showLogExtract( $output, 'suppress', '', '', [ 'conds' => $conds ] ); |
141 | } |
142 | } |
143 | |
144 | /** |
145 | * Process the hide form after submission. This performs the actual visibility update. Used as callback by HTMLForm |
146 | * |
147 | * @param array $fields |
148 | * @return bool|array True on success, array of error message keys otherwise |
149 | */ |
150 | public function saveHideForm( array $fields ) { |
151 | // Determine which rows actually have to be changed |
152 | $dbw = $this->lbFactory->getPrimaryDatabase(); |
153 | $newValue = $fields['showorhide'] === 'hide' ? 1 : 0; |
154 | $actualIDs = $dbw->newSelectQueryBuilder() |
155 | ->select( 'afl_id' ) |
156 | ->from( 'abuse_filter_log' ) |
157 | ->where( [ |
158 | 'afl_id' => $this->hideIDs, |
159 | $dbw->expr( 'afl_deleted', '!=', $newValue ), |
160 | ] ) |
161 | ->caller( __METHOD__ ) |
162 | ->fetchFieldValues(); |
163 | if ( !count( $actualIDs ) ) { |
164 | return [ 'abusefilter-log-hide-no-change' ]; |
165 | } |
166 | |
167 | $dbw->newUpdateQueryBuilder() |
168 | ->update( 'abuse_filter_log' ) |
169 | ->set( [ 'afl_deleted' => $newValue ] ) |
170 | ->where( [ 'afl_id' => $actualIDs ] ) |
171 | ->caller( __METHOD__ ) |
172 | ->execute(); |
173 | |
174 | // Log in a DeferredUpdates to avoid potential flood |
175 | DeferredUpdates::addCallableUpdate( function () use ( $fields, $actualIDs ) { |
176 | $reason = $fields['dropdownreason']; |
177 | if ( $reason === 'other' ) { |
178 | $reason = $fields['reason']; |
179 | } elseif ( $fields['reason'] !== '' ) { |
180 | $reason .= |
181 | $this->msg( 'colon-separator' )->inContentLanguage()->text() . $fields['reason']; |
182 | } |
183 | |
184 | $action = $fields['showorhide'] === 'hide' ? 'hide-afl' : 'unhide-afl'; |
185 | foreach ( $actualIDs as $logid ) { |
186 | $logEntry = new ManualLogEntry( 'suppress', $action ); |
187 | $logEntry->setPerformer( $this->getUser() ); |
188 | $logEntry->setTarget( $this->getTitle( $logid ) ); |
189 | $logEntry->setComment( $reason ); |
190 | $logEntry->insert(); |
191 | } |
192 | } ); |
193 | |
194 | $count = count( $actualIDs ); |
195 | $this->getOutput()->addModuleStyles( 'mediawiki.codex.messagebox.styles' ); |
196 | $this->getOutput()->prependHTML( |
197 | Html::successBox( |
198 | $this->msg( 'abusefilter-log-hide-done' )->params( |
199 | $this->getLanguage()->formatNum( $count ), |
200 | // Messages used: abusefilter-log-hide-done-hide, abusefilter-log-hide-done-show |
201 | $this->msg( 'abusefilter-log-hide-done-' . $fields['showorhide'] )->numParams( $count )->text() |
202 | )->escaped() |
203 | ) |
204 | ); |
205 | |
206 | return true; |
207 | } |
208 | |
209 | } |