Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 388 |
|
0.00% |
0 / 17 |
CRAP | |
0.00% |
0 / 1 |
| CentralNoticeCampaignLogPager | |
0.00% |
0 / 388 |
|
0.00% |
0 / 17 |
3906 | |
0.00% |
0 / 1 |
| __construct | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
2 | |||
| getIndexField | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| getQueryInfo | |
0.00% |
0 / 33 |
|
0.00% |
0 / 1 |
90 | |||
| formatRow | |
0.00% |
0 / 71 |
|
0.00% |
0 / 1 |
56 | |||
| showInitialSettings | |
0.00% |
0 / 63 |
|
0.00% |
0 / 1 |
90 | |||
| showChanges | |
0.00% |
0 / 59 |
|
0.00% |
0 / 1 |
42 | |||
| getBannerStats | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
12 | |||
| testBooleanChange | |
0.00% |
0 / 18 |
|
0.00% |
0 / 1 |
20 | |||
| testSetChange | |
0.00% |
0 / 28 |
|
0.00% |
0 / 1 |
56 | |||
| testPriorityChange | |
0.00% |
0 / 16 |
|
0.00% |
0 / 1 |
6 | |||
| getPriorityMessage | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
2 | |||
| testPercentageChange | |
0.00% |
0 / 16 |
|
0.00% |
0 / 1 |
6 | |||
| testTextChange | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
6 | |||
| testTypeChange | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
6 | |||
| getTypeText | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
20 | |||
| getStartBody | |
0.00% |
0 / 23 |
|
0.00% |
0 / 1 |
2 | |||
| getEndBody | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| 1 | <?php |
| 2 | |
| 3 | use MediaWiki\Html\Html; |
| 4 | use MediaWiki\MainConfigNames; |
| 5 | use MediaWiki\Pager\ReverseChronologicalPager; |
| 6 | use MediaWiki\Title\Title; |
| 7 | use MediaWiki\User\User; |
| 8 | use Wikimedia\Rdbms\IExpression; |
| 9 | use Wikimedia\Rdbms\LikeValue; |
| 10 | |
| 11 | class CentralNoticeCampaignLogPager extends ReverseChronologicalPager { |
| 12 | /** @var Title */ |
| 13 | public $viewPage; |
| 14 | |
| 15 | public function __construct( |
| 16 | protected readonly SpecialCentralNoticeLogs $special, |
| 17 | ) { |
| 18 | parent::__construct(); |
| 19 | |
| 20 | // Override paging defaults |
| 21 | [ $this->mLimit, ] = $this->mRequest->getLimitOffsetForUser( |
| 22 | $this->getUser(), |
| 23 | 20, |
| 24 | '' |
| 25 | ); |
| 26 | $this->mLimitsShown = [ 20, 50, 100 ]; |
| 27 | |
| 28 | $this->viewPage = Campaign::getTitleForURL(); |
| 29 | } |
| 30 | |
| 31 | /** |
| 32 | * Sort the log list by timestamp |
| 33 | * @return string |
| 34 | */ |
| 35 | public function getIndexField() { |
| 36 | return 'notlog_timestamp'; |
| 37 | } |
| 38 | |
| 39 | /** |
| 40 | * Pull log entries from the database |
| 41 | * @inheritDoc |
| 42 | */ |
| 43 | public function getQueryInfo() { |
| 44 | $request = $this->getRequest(); |
| 45 | |
| 46 | $filterStartDate = 0; |
| 47 | $filterEndDate = 0; |
| 48 | $start = $this->special->getDateValue( 'start' ); |
| 49 | $end = $this->special->getDateValue( 'end' ); |
| 50 | |
| 51 | if ( $start ) { |
| 52 | $filterStartDate = substr( $start, 0, 8 ); |
| 53 | } |
| 54 | if ( $end ) { |
| 55 | $filterEndDate = substr( $end, 0, 8 ); |
| 56 | } |
| 57 | $filterCampaign = $request->getVal( 'campaign' ); |
| 58 | $filterUser = $request->getVal( 'user' ); |
| 59 | $reset = $request->getVal( 'centralnoticelogreset' ); |
| 60 | |
| 61 | $info = [ |
| 62 | 'tables' => [ 'notice_log' => 'cn_notice_log' ], |
| 63 | 'fields' => '*', |
| 64 | 'conds' => [] |
| 65 | ]; |
| 66 | |
| 67 | if ( !$reset ) { |
| 68 | $dbr = $this->getDatabase(); |
| 69 | if ( $filterStartDate > 0 ) { |
| 70 | $filterStartDate = intval( $filterStartDate . '000000' ); |
| 71 | $info['conds'][] = $dbr->expr( 'notlog_timestamp', '>=', $filterStartDate ); |
| 72 | } |
| 73 | if ( $filterEndDate > 0 ) { |
| 74 | $filterEndDate = intval( $filterEndDate . '000000' ); |
| 75 | $info['conds'][] = $dbr->expr( 'notlog_timestamp', '<', $filterEndDate ); |
| 76 | } |
| 77 | if ( $filterCampaign ) { |
| 78 | $info['conds'][] = $dbr->expr( 'notlog_not_name', IExpression::LIKE, new LikeValue( |
| 79 | $dbr->anyString(), $filterCampaign, $dbr->anyString() ) ); |
| 80 | } |
| 81 | if ( $filterUser ) { |
| 82 | $user = User::newFromName( $filterUser ); |
| 83 | if ( $user ) { |
| 84 | $info['conds']['notlog_user_id'] = $user->getId(); |
| 85 | } |
| 86 | } |
| 87 | } |
| 88 | |
| 89 | return $info; |
| 90 | } |
| 91 | |
| 92 | /** |
| 93 | * Generate the content of each table row (1 row = 1 log entry) |
| 94 | * @param stdClass $row |
| 95 | * @return string HTML |
| 96 | */ |
| 97 | public function formatRow( $row ) { |
| 98 | $lang = $this->getLanguage(); |
| 99 | |
| 100 | // Create a user object so we can pull the name, user page, etc. |
| 101 | $loggedUser = User::newFromId( $row->notlog_user_id ); |
| 102 | // Create the user page link |
| 103 | $userLink = $this->special->getLinkRenderer()->makeKnownLink( |
| 104 | $loggedUser->getUserPage(), |
| 105 | $loggedUser->getName() |
| 106 | ); |
| 107 | $userTalkLink = $this->special->getLinkRenderer()->makeKnownLink( |
| 108 | $loggedUser->getTalkPage(), |
| 109 | $this->msg( 'centralnotice-talk-link' )->text() |
| 110 | ); |
| 111 | |
| 112 | // Create the campaign link |
| 113 | $campaignLink = $this->special->getLinkRenderer()->makeKnownLink( |
| 114 | $this->viewPage, |
| 115 | $row->notlog_not_name, |
| 116 | [], |
| 117 | Campaign::getQueryForURL( $row->notlog_not_name ) |
| 118 | ); |
| 119 | |
| 120 | // Begin log entry primary row |
| 121 | $htmlOut = Html::openElement( 'tr' ); |
| 122 | |
| 123 | $htmlOut .= Html::openElement( 'td', [ 'valign' => 'top' ] ); |
| 124 | $notlogId = (int)$row->notlog_id; |
| 125 | if ( $row->notlog_action !== 'removed' ) { |
| 126 | $collapsedImg = $this->getLanguage()->isRtl() ? |
| 127 | 'collapsed-rtl.png' : |
| 128 | 'collapsed-ltr.png'; |
| 129 | |
| 130 | $extensionAssetsPath = $this->getConfig()->get( MainConfigNames::ExtensionAssetsPath ); |
| 131 | $htmlOut .= '<a href="javascript:toggleLogDisplay(\'' . $notlogId . '\')">' . |
| 132 | '<img src="' . $extensionAssetsPath . '/CentralNotice/resources/images/' . $collapsedImg . '" ' . |
| 133 | 'id="cn-collapsed-' . $notlogId . '" style="display:block;"/>' . |
| 134 | '<img src="' . $extensionAssetsPath . '/CentralNotice/resources/images/uncollapsed.png" ' . |
| 135 | 'id="cn-uncollapsed-' . $notlogId . '" style="display:none;"/>' . |
| 136 | '</a>'; |
| 137 | } |
| 138 | $htmlOut .= Html::closeElement( 'td' ); |
| 139 | $htmlOut .= Html::element( 'td', [ 'valign' => 'top', 'class' => 'primary' ], |
| 140 | $lang->date( $row->notlog_timestamp ) . $this->msg( 'word-separator' )->plain() . |
| 141 | $lang->time( $row->notlog_timestamp ) |
| 142 | ); |
| 143 | $htmlOut .= Html::rawElement( 'td', [ 'valign' => 'top', 'class' => 'primary' ], |
| 144 | $this->msg( 'centralnotice-user-links' ) |
| 145 | ->rawParams( $userLink, $userTalkLink ) |
| 146 | ->escaped() |
| 147 | ); |
| 148 | // The following messages are generated here: |
| 149 | // * centralnotice-action-created |
| 150 | // * centralnotice-action-modified |
| 151 | // * centralnotice-action-removed |
| 152 | $htmlOut .= Html::element( 'td', [ 'valign' => 'top', 'class' => 'primary' ], |
| 153 | $this->msg( 'centralnotice-action-' . $row->notlog_action )->text() |
| 154 | ); |
| 155 | $htmlOut .= Html::rawElement( 'td', [ 'valign' => 'top', 'class' => 'primary' ], |
| 156 | $campaignLink |
| 157 | ); |
| 158 | |
| 159 | $summary = $row->notlog_comment === null |
| 160 | ? ' ' |
| 161 | : htmlspecialchars( $row->notlog_comment ); |
| 162 | |
| 163 | $htmlOut .= Html::rawElement( 'td', |
| 164 | [ 'valign' => 'top', 'class' => 'primary-summary' ], |
| 165 | $summary |
| 166 | ); |
| 167 | |
| 168 | $htmlOut .= Html::rawElement( 'td', [], |
| 169 | ' ' |
| 170 | ); |
| 171 | |
| 172 | // End log entry primary row |
| 173 | $htmlOut .= Html::closeElement( 'tr' ); |
| 174 | |
| 175 | if ( $row->notlog_action !== 'removed' ) { |
| 176 | // Begin log entry secondary row |
| 177 | $htmlOut .= Html::openElement( 'tr', |
| 178 | [ 'id' => 'cn-log-details-' . $notlogId, 'style' => 'display:none;' ] ); |
| 179 | |
| 180 | $htmlOut .= Html::rawElement( 'td', [ 'valign' => 'top' ], |
| 181 | // force a table cell in older browsers |
| 182 | ' ' |
| 183 | ); |
| 184 | $htmlOut .= Html::openElement( 'td', [ 'valign' => 'top', 'colspan' => '6' ] ); |
| 185 | if ( $row->notlog_action === 'created' ) { |
| 186 | $htmlOut .= $this->showInitialSettings( $row ); |
| 187 | } elseif ( $row->notlog_action === 'modified' ) { |
| 188 | $htmlOut .= $this->showChanges( $row ); |
| 189 | } |
| 190 | $htmlOut .= Html::closeElement( 'td' ); |
| 191 | |
| 192 | // End log entry secondary row |
| 193 | $htmlOut .= Html::closeElement( 'tr' ); |
| 194 | } |
| 195 | |
| 196 | return $htmlOut; |
| 197 | } |
| 198 | |
| 199 | /** |
| 200 | * @param stdClass $row |
| 201 | * @return string |
| 202 | */ |
| 203 | public function showInitialSettings( $row ) { |
| 204 | $lang = $this->getLanguage(); |
| 205 | $details = ''; |
| 206 | $wordSeparator = $this->msg( 'word-separator' )->plain(); |
| 207 | $details .= $this->msg( |
| 208 | 'centralnotice-log-label', |
| 209 | $this->msg( 'centralnotice-start-timestamp' )->text(), |
| 210 | $lang->date( $row->notlog_end_start ) . $wordSeparator . |
| 211 | $lang->time( $row->notlog_end_start ) |
| 212 | )->parse() . "<br />"; |
| 213 | $details .= $this->msg( |
| 214 | 'centralnotice-log-label', |
| 215 | $this->msg( 'centralnotice-end-timestamp' )->text(), |
| 216 | $lang->date( $row->notlog_end_end ) . $wordSeparator . |
| 217 | $lang->time( $row->notlog_end_end ) |
| 218 | )->parse() . "<br />"; |
| 219 | $details .= $this->msg( |
| 220 | 'centralnotice-log-label', |
| 221 | $this->msg( 'centralnotice-projects' )->text(), |
| 222 | wfEscapeWikiText( $row->notlog_end_projects ) |
| 223 | )->parse() . "<br />"; |
| 224 | $language_count = count( explode( ', ', $row->notlog_end_languages ) ); |
| 225 | $languageList = ''; |
| 226 | if ( $language_count > 15 ) { |
| 227 | $languageList = $this->msg( 'centralnotice-multiple-languages' ) |
| 228 | ->numParams( $language_count )->text(); |
| 229 | } elseif ( $language_count > 0 ) { |
| 230 | $languageList = $row->notlog_end_languages; |
| 231 | } |
| 232 | $details .= $this->msg( |
| 233 | 'centralnotice-log-label', |
| 234 | $this->msg( 'centralnotice-languages' )->text(), |
| 235 | wfEscapeWikiText( $languageList ) |
| 236 | )->parse() . "<br />"; |
| 237 | $details .= $this->msg( |
| 238 | 'centralnotice-log-label', |
| 239 | $this->msg( 'centralnotice-geo' )->text(), |
| 240 | ( $row->notlog_end_geo ? 'on' : 'off' ) |
| 241 | )->parse() . "<br />"; |
| 242 | if ( $row->notlog_end_geo ) { |
| 243 | $country_count = count( explode( ', ', $row->notlog_end_countries ?? '' ) ); |
| 244 | $countryList = ''; |
| 245 | if ( $country_count > 20 ) { |
| 246 | $countryList = $this->msg( 'centralnotice-multiple-countries' ) |
| 247 | ->numParams( $country_count )->text(); |
| 248 | } elseif ( $country_count > 0 ) { |
| 249 | $countryList = $row->notlog_end_countries; |
| 250 | } |
| 251 | $details .= $this->msg( |
| 252 | 'centralnotice-log-label', |
| 253 | $this->msg( 'centralnotice-countries' )->text(), |
| 254 | wfEscapeWikiText( $countryList ) |
| 255 | )->parse() . "<br />"; |
| 256 | |
| 257 | $regions_count = count( explode( ', ', $row->notlog_end_regions ?? '' ) ); |
| 258 | $regionsList = ''; |
| 259 | if ( $regions_count > 20 ) { |
| 260 | $regionsList = $this->msg( 'centralnotice-multiple-regions' ) |
| 261 | ->numParams( $regions_count )->text(); |
| 262 | } elseif ( $regions_count > 0 ) { |
| 263 | $regionsList = $row->notlog_end_regions; |
| 264 | } |
| 265 | $details .= $this->msg( |
| 266 | 'centralnotice-log-label', |
| 267 | $this->msg( 'centralnotice-regions' )->text(), |
| 268 | wfEscapeWikiText( $regionsList ) |
| 269 | )->parse() . "<br />"; |
| 270 | |
| 271 | } |
| 272 | return $details; |
| 273 | } |
| 274 | |
| 275 | /** |
| 276 | * @param stdClass $row |
| 277 | * @return string |
| 278 | */ |
| 279 | public function showChanges( $row ) { |
| 280 | $lang = $this->getLanguage(); |
| 281 | $details = ''; |
| 282 | $wordSeparator = $this->msg( 'word-separator' )->plain(); |
| 283 | if ( $row->notlog_begin_start !== $row->notlog_end_start ) { |
| 284 | $details .= $this->msg( |
| 285 | 'centralnotice-log-label', |
| 286 | $this->msg( 'centralnotice-start-timestamp' )->text(), |
| 287 | $this->msg( |
| 288 | 'centralnotice-changed', |
| 289 | $lang->date( $row->notlog_begin_start ) . $wordSeparator . |
| 290 | $lang->time( $row->notlog_begin_start ), |
| 291 | $lang->date( $row->notlog_end_start ) . $wordSeparator . |
| 292 | $lang->time( $row->notlog_end_start ) |
| 293 | )->text() |
| 294 | )->parse() . "<br />"; |
| 295 | } |
| 296 | if ( $row->notlog_begin_end !== $row->notlog_end_end ) { |
| 297 | $details .= $this->msg( |
| 298 | 'centralnotice-log-label', |
| 299 | $this->msg( 'centralnotice-end-timestamp' )->text(), |
| 300 | $this->msg( |
| 301 | 'centralnotice-changed', |
| 302 | $lang->date( $row->notlog_begin_end ) . $wordSeparator . |
| 303 | $lang->time( $row->notlog_begin_end ), |
| 304 | $lang->date( $row->notlog_end_end ) . $wordSeparator . |
| 305 | $lang->time( $row->notlog_end_end ) |
| 306 | )->text() |
| 307 | )->parse() . "<br />"; |
| 308 | } |
| 309 | // When adding new params, update the possibly generated |
| 310 | // i18n keys in the respective functions. |
| 311 | $details .= $this->testBooleanChange( 'enabled', $row ); |
| 312 | $details .= $this->testPriorityChange( 'preferred', $row ); |
| 313 | $details .= $this->testBooleanChange( 'locked', $row ); |
| 314 | $details .= $this->testBooleanChange( 'geo', $row ); |
| 315 | $details .= $this->testBooleanChange( 'buckets', $row ); |
| 316 | $details .= $this->testPercentageChange( 'throttle', $row ); |
| 317 | $details .= $this->testSetChange( 'projects', $row ); |
| 318 | $details .= $this->testSetChange( 'languages', $row ); |
| 319 | $details .= $this->testSetChange( 'countries', $row ); |
| 320 | $details .= $this->testSetChange( 'regions', $row ); |
| 321 | $details .= $this->testBooleanChange( 'archived', $row ); |
| 322 | $details .= $this->testTypeChange( $row ); |
| 323 | |
| 324 | $details .= $this->testTextChange( |
| 325 | 'campaign-mixins', |
| 326 | $row->notlog_end_mixins, |
| 327 | $row->notlog_begin_mixins |
| 328 | ); |
| 329 | |
| 330 | if ( $row->notlog_begin_banners !== $row->notlog_end_banners ) { |
| 331 | // Show changes to banner weights and assignment |
| 332 | $beginBanners = $this->getBannerStats( json_decode( $row->notlog_begin_banners, true ) ); |
| 333 | $endBanners = $this->getBannerStats( json_decode( $row->notlog_end_banners, true ) ); |
| 334 | if ( $beginBanners ) { |
| 335 | $before = $lang->commaList( $beginBanners ); |
| 336 | } else { |
| 337 | $before = $this->msg( 'centralnotice-no-assignments' )->text(); |
| 338 | } |
| 339 | if ( $endBanners ) { |
| 340 | $after = $lang->commaList( $endBanners ); |
| 341 | } else { |
| 342 | $after = $this->msg( 'centralnotice-no-assignments' )->text(); |
| 343 | } |
| 344 | $details .= $this->msg( |
| 345 | 'centralnotice-log-label', |
| 346 | $this->msg( 'centralnotice-templates' )->text(), |
| 347 | $this->msg( 'centralnotice-changed', $before, $after )->text() |
| 348 | )->parse() . "<br />"; |
| 349 | } |
| 350 | return $details; |
| 351 | } |
| 352 | |
| 353 | private function getBannerStats( array $array ): array { |
| 354 | $ret = []; |
| 355 | foreach ( $array as $key => $params ) { |
| 356 | if ( is_array( $params ) ) { |
| 357 | $weight = $params['weight']; |
| 358 | $bucket = chr( 65 + $params['bucket'] ); |
| 359 | } else { |
| 360 | // Legacy, we used to only store the weight |
| 361 | $weight = $params; |
| 362 | $bucket = 0; |
| 363 | } |
| 364 | $ret[$key] = "$key ($bucket, $weight)"; |
| 365 | } |
| 366 | |
| 367 | return $ret; |
| 368 | } |
| 369 | |
| 370 | /** |
| 371 | * @param string $param |
| 372 | * @param stdClass $row |
| 373 | * @return string |
| 374 | */ |
| 375 | private function testBooleanChange( $param, $row ) { |
| 376 | $result = ''; |
| 377 | $beginField = 'notlog_begin_' . $param; |
| 378 | $endField = 'notlog_end_' . $param; |
| 379 | if ( $row->$beginField !== $row->$endField ) { |
| 380 | // The following messages are generated here: |
| 381 | // * centralnotice-enabled |
| 382 | // * centralnotice-locked |
| 383 | // * centralnotice-geo |
| 384 | // * centralnotice-buckets |
| 385 | // * centralnotice-archived |
| 386 | $result .= $this->msg( |
| 387 | 'centralnotice-log-label', |
| 388 | $this->msg( 'centralnotice-' . $param )->text(), |
| 389 | $this->msg( |
| 390 | 'centralnotice-changed', |
| 391 | ( $row->$beginField |
| 392 | ? $this->msg( 'centralnotice-on' )->text() |
| 393 | : $this->msg( 'centralnotice-off' )->text() ), |
| 394 | ( $row->$endField |
| 395 | ? $this->msg( 'centralnotice-on' )->text() |
| 396 | : $this->msg( 'centralnotice-off' )->text() ) |
| 397 | )->text() |
| 398 | )->parse() . "<br />"; |
| 399 | } |
| 400 | return $result; |
| 401 | } |
| 402 | |
| 403 | /** |
| 404 | * @param string $param |
| 405 | * @param stdClass $row |
| 406 | * @return string |
| 407 | */ |
| 408 | private function testSetChange( $param, $row ) { |
| 409 | $result = ''; |
| 410 | $beginField = 'notlog_begin_' . $param; |
| 411 | $endField = 'notlog_end_' . $param; |
| 412 | |
| 413 | if ( $row->$beginField !== $row->$endField ) { |
| 414 | $lang = $this->getLanguage(); |
| 415 | $beginSet = []; |
| 416 | $endSet = []; |
| 417 | if ( $row->$beginField ) { |
| 418 | $beginSet = explode( ', ', $row->$beginField ); |
| 419 | } |
| 420 | if ( $row->$endField ) { |
| 421 | $endSet = explode( ', ', $row->$endField ); |
| 422 | } |
| 423 | $added = array_diff( $endSet, $beginSet ); |
| 424 | $removed = array_diff( $beginSet, $endSet ); |
| 425 | $differences = ''; |
| 426 | if ( $added ) { |
| 427 | $differences .= $this->msg( |
| 428 | 'centralnotice-added', $lang->commaList( $added ) )->text(); |
| 429 | if ( $removed ) { |
| 430 | $differences .= '; '; |
| 431 | } |
| 432 | } |
| 433 | if ( $removed ) { |
| 434 | $differences .= $this->msg( |
| 435 | 'centralnotice-removed', $lang->commaList( $removed ) )->text(); |
| 436 | } |
| 437 | // The following messages are generated here: |
| 438 | // * centralnotice-projects |
| 439 | // * centralnotice-languages |
| 440 | // * centralnotice-countries |
| 441 | // * centralnotice-regions |
| 442 | $result .= $this->msg( |
| 443 | 'centralnotice-log-label', |
| 444 | $this->msg( 'centralnotice-' . $param )->text(), |
| 445 | $differences |
| 446 | )->parse() . "<br />"; |
| 447 | } |
| 448 | return $result; |
| 449 | } |
| 450 | |
| 451 | /** |
| 452 | * Test for changes to campaign priority |
| 453 | * @param string $param |
| 454 | * @param stdClass $row |
| 455 | * @return string |
| 456 | */ |
| 457 | private function testPriorityChange( $param, $row ) { |
| 458 | $result = ''; |
| 459 | $beginField = 'notlog_begin_' . $param; |
| 460 | $endField = 'notlog_end_' . $param; |
| 461 | if ( $row->$beginField !== $row->$endField ) { |
| 462 | $beginMessage = $this->getPriorityMessage( $row->$beginField ); |
| 463 | $endMessage = $this->getPriorityMessage( $row->$endField ); |
| 464 | |
| 465 | // The following messages are generated here: |
| 466 | // * centralnotice-preferred |
| 467 | $result .= $this->msg( |
| 468 | 'centralnotice-log-label', |
| 469 | $this->msg( 'centralnotice-' . $param )->text(), |
| 470 | $this->msg( |
| 471 | 'centralnotice-changed', |
| 472 | $beginMessage, |
| 473 | $endMessage |
| 474 | )->text() |
| 475 | )->parse() . "<br />"; |
| 476 | } |
| 477 | return $result; |
| 478 | } |
| 479 | |
| 480 | private function getPriorityMessage( int $value ): string { |
| 481 | return match ( $value ) { |
| 482 | CentralNotice::LOW_PRIORITY => $this->msg( 'centralnotice-priority-low' )->text(), |
| 483 | CentralNotice::NORMAL_PRIORITY => $this->msg( 'centralnotice-priority-normal' )->text(), |
| 484 | CentralNotice::HIGH_PRIORITY => $this->msg( 'centralnotice-priority-high' )->text(), |
| 485 | CentralNotice::EMERGENCY_PRIORITY => $this->msg( 'centralnotice-priority-emergency' )->text(), |
| 486 | default => '', |
| 487 | }; |
| 488 | } |
| 489 | |
| 490 | /** |
| 491 | * Test for changes to a property interpreted as a percentage |
| 492 | * @param string $param name |
| 493 | * @param stdClass $row settings |
| 494 | * @return string |
| 495 | */ |
| 496 | private function testPercentageChange( $param, $row ) { |
| 497 | $beginField = 'notlog_begin_' . $param; |
| 498 | $endField = 'notlog_end_' . $param; |
| 499 | $result = ''; |
| 500 | if ( $row->$beginField !== $row->$endField ) { |
| 501 | $beginMessage = strval( $row->$beginField ) . '%'; |
| 502 | $endMessage = strval( $row->$endField ) . '%'; |
| 503 | // The following messages are generated here: |
| 504 | // * centralnotice-throttle |
| 505 | $result .= $this->msg( |
| 506 | 'centralnotice-log-label', |
| 507 | $this->msg( 'centralnotice-' . $param )->text(), |
| 508 | $this->msg( |
| 509 | 'centralnotice-changed', |
| 510 | $beginMessage, |
| 511 | $endMessage |
| 512 | )->text() |
| 513 | )->parse() . "<br />"; |
| 514 | } |
| 515 | return $result; |
| 516 | } |
| 517 | |
| 518 | /** |
| 519 | * @param string $param |
| 520 | * @param string $newval |
| 521 | * @param string $oldval |
| 522 | * @return string |
| 523 | */ |
| 524 | protected function testTextChange( $param, $newval, $oldval ) { |
| 525 | $result = ''; |
| 526 | if ( $oldval !== $newval ) { |
| 527 | // The following messages are generated here: |
| 528 | // * centralnotice-campaign-mixins |
| 529 | // * centralnotice-category |
| 530 | // * centralnotice-landingpages |
| 531 | // * centralnotice-controller_mixin |
| 532 | // * centralnotice-prioritylangs |
| 533 | // * centralnotice-devices |
| 534 | $result .= $this->msg( |
| 535 | 'centralnotice-log-label', |
| 536 | $this->msg( 'centralnotice-' . $param )->text(), |
| 537 | $this->msg( |
| 538 | 'centralnotice-changed', |
| 539 | wfEscapeWikiText( $oldval ), |
| 540 | wfEscapeWikiText( $newval ) |
| 541 | )->text() |
| 542 | )->parse() . "<br/>"; |
| 543 | } |
| 544 | return $result; |
| 545 | } |
| 546 | |
| 547 | /** |
| 548 | * @param stdClass $row |
| 549 | * @return string |
| 550 | */ |
| 551 | private function testTypeChange( $row ) { |
| 552 | $result = ''; |
| 553 | |
| 554 | $oldval = $row->notlog_begin_type; |
| 555 | $newval = $row->notlog_end_type; |
| 556 | |
| 557 | if ( $oldval !== $newval ) { |
| 558 | $result .= $this->msg( |
| 559 | 'centralnotice-log-label', |
| 560 | $this->msg( 'centralnotice-campaign-type' )->text(), |
| 561 | $this->msg( |
| 562 | 'centralnotice-changed', |
| 563 | $this->getTypeText( $oldval ), |
| 564 | $this->getTypeText( $newval ) |
| 565 | )->text() |
| 566 | )->parse() . "<br/>"; |
| 567 | } |
| 568 | |
| 569 | return $result; |
| 570 | } |
| 571 | |
| 572 | private function getTypeText( ?string $typeId ): string { |
| 573 | // This is the case for no type set; $typeId should be null. |
| 574 | if ( !$typeId ) { |
| 575 | return $this->msg( 'centralnotice-empty-campaign-type-option' )->plain(); |
| 576 | } |
| 577 | |
| 578 | $type = CampaignType::getById( $typeId ); |
| 579 | |
| 580 | // This is the case for a type that exists in the logs but not in the config |
| 581 | if ( !$type ) { |
| 582 | return $typeId; |
| 583 | } |
| 584 | |
| 585 | $message = $this->msg( $type->getMessageKey() ); |
| 586 | |
| 587 | // This is the case for a type that exists in the logs and the config but has no |
| 588 | // associated i18n message |
| 589 | if ( !$message->exists() ) { |
| 590 | return $typeId; |
| 591 | } |
| 592 | |
| 593 | return $message->plain(); |
| 594 | } |
| 595 | |
| 596 | /** |
| 597 | * Specify table headers |
| 598 | * @return string HTML |
| 599 | */ |
| 600 | public function getStartBody() { |
| 601 | $htmlOut = Html::openElement( 'table', [ 'id' => 'cn-campaign-logs', 'cellpadding' => 3 ] ); |
| 602 | $htmlOut .= Html::openElement( 'tr' ); |
| 603 | $htmlOut .= Html::element( 'th', [ 'style' => 'width: 20px;' ] ); |
| 604 | $htmlOut .= Html::element( 'th', [ 'align' => 'left', 'style' => 'width: 130px;' ], |
| 605 | $this->msg( 'centralnotice-timestamp' )->text() |
| 606 | ); |
| 607 | $htmlOut .= Html::element( 'th', [ 'align' => 'left', 'style' => 'width: 160px;' ], |
| 608 | $this->msg( 'centralnotice-user' )->text() |
| 609 | ); |
| 610 | $htmlOut .= Html::element( 'th', [ 'align' => 'left', 'style' => 'width: 100px;' ], |
| 611 | $this->msg( 'centralnotice-action' )->text() |
| 612 | ); |
| 613 | $htmlOut .= Html::element( 'th', [ 'align' => 'left', 'style' => 'width: 160px;' ], |
| 614 | $this->msg( 'centralnotice-notice' )->text() |
| 615 | ); |
| 616 | $htmlOut .= Html::element( 'th', [ 'align' => 'left', 'style' => 'width: 250px;' ], |
| 617 | $this->msg( 'centralnotice-change-summary-heading' )->text() |
| 618 | ); |
| 619 | $htmlOut .= Html::rawElement( 'td', [], |
| 620 | ' ' |
| 621 | ); |
| 622 | $htmlOut .= Html::closeElement( 'tr' ); |
| 623 | return $htmlOut; |
| 624 | } |
| 625 | |
| 626 | /** |
| 627 | * Close table |
| 628 | * @return string HTML |
| 629 | */ |
| 630 | public function getEndBody() { |
| 631 | return Html::closeElement( 'table' ); |
| 632 | } |
| 633 | } |