Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like LogEventsList often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use LogEventsList, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 26 | class LogEventsList extends ContextSource { |
||
| 27 | const NO_ACTION_LINK = 1; |
||
| 28 | const NO_EXTRA_USER_LINKS = 2; |
||
| 29 | const USE_CHECKBOXES = 4; |
||
| 30 | |||
| 31 | public $flags; |
||
| 32 | |||
| 33 | /** |
||
| 34 | * @var array |
||
| 35 | */ |
||
| 36 | protected $mDefaultQuery; |
||
| 37 | |||
| 38 | /** |
||
| 39 | * @var bool |
||
| 40 | */ |
||
| 41 | protected $showTagEditUI; |
||
| 42 | |||
| 43 | /** |
||
| 44 | * @var array |
||
| 45 | */ |
||
| 46 | protected $allowedActions = null; |
||
| 47 | |||
| 48 | /** |
||
| 49 | * Constructor. |
||
| 50 | * The first two parameters used to be $skin and $out, but now only a context |
||
| 51 | * is needed, that's why there's a second unused parameter. |
||
| 52 | * |
||
| 53 | * @param IContextSource|Skin $context Context to use; formerly it was |
||
| 54 | * a Skin object. Use of Skin is deprecated. |
||
| 55 | * @param null $unused Unused; used to be an OutputPage object. |
||
| 56 | * @param int $flags Can be a combination of self::NO_ACTION_LINK, |
||
| 57 | * self::NO_EXTRA_USER_LINKS or self::USE_CHECKBOXES. |
||
| 58 | */ |
||
| 59 | public function __construct( $context, $unused = null, $flags = 0 ) { |
||
| 60 | if ( $context instanceof IContextSource ) { |
||
| 61 | $this->setContext( $context ); |
||
| 62 | } else { |
||
| 63 | // Old parameters, $context should be a Skin object |
||
| 64 | $this->setContext( $context->getContext() ); |
||
| 65 | } |
||
| 66 | |||
| 67 | $this->flags = $flags; |
||
| 68 | $this->showTagEditUI = ChangeTags::showTagEditingUI( $this->getUser() ); |
||
| 69 | } |
||
| 70 | |||
| 71 | /** |
||
| 72 | * Show options for the log list |
||
| 73 | * |
||
| 74 | * @param array|string $types |
||
| 75 | * @param string $user |
||
| 76 | * @param string $page |
||
| 77 | * @param string $pattern |
||
| 78 | * @param int $year Year |
||
| 79 | * @param int $month Month |
||
| 80 | * @param array $filter |
||
| 81 | * @param string $tagFilter Tag to select by default |
||
| 82 | * @param string $action |
||
| 83 | */ |
||
| 84 | public function showOptions( $types = [], $user = '', $page = '', $pattern = '', $year = 0, |
||
| 85 | $month = 0, $filter = null, $tagFilter = '', $action = null |
||
| 86 | ) { |
||
| 87 | global $wgScript, $wgMiserMode; |
||
| 88 | |||
| 89 | $title = SpecialPage::getTitleFor( 'Log' ); |
||
| 90 | |||
| 91 | // For B/C, we take strings, but make sure they are converted... |
||
| 92 | $types = ( $types === '' ) ? [] : (array)$types; |
||
| 93 | |||
| 94 | $tagSelector = ChangeTags::buildTagFilterSelector( $tagFilter ); |
||
| 95 | |||
| 96 | $html = Html::hidden( 'title', $title->getPrefixedDBkey() ); |
||
| 97 | |||
| 98 | // Basic selectors |
||
| 99 | $html .= $this->getTypeMenu( $types ) . "\n"; |
||
| 100 | $html .= $this->getUserInput( $user ) . "\n"; |
||
| 101 | $html .= $this->getTitleInput( $page ) . "\n"; |
||
| 102 | $html .= $this->getExtraInputs( $types ) . "\n"; |
||
| 103 | |||
| 104 | // Title pattern, if allowed |
||
| 105 | if ( !$wgMiserMode ) { |
||
| 106 | $html .= $this->getTitlePattern( $pattern ) . "\n"; |
||
| 107 | } |
||
| 108 | |||
| 109 | // date menu |
||
| 110 | $html .= Xml::tags( 'p', null, Xml::dateMenu( (int)$year, (int)$month ) ); |
||
| 111 | |||
| 112 | // Tag filter |
||
| 113 | if ( $tagSelector ) { |
||
| 114 | $html .= Xml::tags( 'p', null, implode( ' ', $tagSelector ) ); |
||
| 115 | } |
||
| 116 | |||
| 117 | // Filter links |
||
| 118 | if ( $filter ) { |
||
| 119 | $html .= Xml::tags( 'p', null, $this->getFilterLinks( $filter ) ); |
||
| 120 | } |
||
| 121 | |||
| 122 | // Action filter |
||
| 123 | if ( $action !== null ) { |
||
| 124 | $html .= Xml::tags( 'p', null, $this->getActionSelector( $types, $action ) ); |
||
| 125 | } |
||
| 126 | |||
| 127 | // Submit button |
||
| 128 | $html .= Xml::submitButton( $this->msg( 'logeventslist-submit' )->text() ); |
||
| 129 | |||
| 130 | // Fieldset |
||
| 131 | $html = Xml::fieldset( $this->msg( 'log' )->text(), $html ); |
||
| 132 | |||
| 133 | // Form wrapping |
||
| 134 | $html = Xml::tags( 'form', [ 'action' => $wgScript, 'method' => 'get' ], $html ); |
||
| 135 | |||
| 136 | $this->getOutput()->addHTML( $html ); |
||
| 137 | } |
||
| 138 | |||
| 139 | /** |
||
| 140 | * @param array $filter |
||
| 141 | * @return string Formatted HTML |
||
| 142 | */ |
||
| 143 | private function getFilterLinks( $filter ) { |
||
| 144 | // show/hide links |
||
| 145 | $messages = [ $this->msg( 'show' )->escaped(), $this->msg( 'hide' )->escaped() ]; |
||
| 146 | // Option value -> message mapping |
||
| 147 | $links = []; |
||
| 148 | $hiddens = ''; // keep track for "go" button |
||
| 149 | foreach ( $filter as $type => $val ) { |
||
| 150 | // Should the below assignment be outside the foreach? |
||
| 151 | // Then it would have to be copied. Not certain what is more expensive. |
||
| 152 | $query = $this->getDefaultQuery(); |
||
| 153 | $queryKey = "hide_{$type}_log"; |
||
| 154 | |||
| 155 | $hideVal = 1 - intval( $val ); |
||
| 156 | $query[$queryKey] = $hideVal; |
||
| 157 | |||
| 158 | $link = Linker::linkKnown( |
||
| 159 | $this->getTitle(), |
||
| 160 | $messages[$hideVal], |
||
| 161 | [], |
||
| 162 | $query |
||
| 163 | ); |
||
| 164 | |||
| 165 | // Message: log-show-hide-patrol |
||
| 166 | $links[$type] = $this->msg( "log-show-hide-{$type}" )->rawParams( $link )->escaped(); |
||
| 167 | $hiddens .= Html::hidden( "hide_{$type}_log", $val ) . "\n"; |
||
| 168 | } |
||
| 169 | |||
| 170 | // Build links |
||
| 171 | return '<small>' . $this->getLanguage()->pipeList( $links ) . '</small>' . $hiddens; |
||
| 172 | } |
||
| 173 | |||
| 174 | View Code Duplication | private function getDefaultQuery() { |
|
| 175 | if ( !isset( $this->mDefaultQuery ) ) { |
||
| 176 | $this->mDefaultQuery = $this->getRequest()->getQueryValues(); |
||
| 177 | unset( $this->mDefaultQuery['title'] ); |
||
| 178 | unset( $this->mDefaultQuery['dir'] ); |
||
| 179 | unset( $this->mDefaultQuery['offset'] ); |
||
| 180 | unset( $this->mDefaultQuery['limit'] ); |
||
| 181 | unset( $this->mDefaultQuery['order'] ); |
||
| 182 | unset( $this->mDefaultQuery['month'] ); |
||
| 183 | unset( $this->mDefaultQuery['year'] ); |
||
| 184 | } |
||
| 185 | |||
| 186 | return $this->mDefaultQuery; |
||
| 187 | } |
||
| 188 | |||
| 189 | /** |
||
| 190 | * @param array $queryTypes |
||
| 191 | * @return string Formatted HTML |
||
| 192 | */ |
||
| 193 | private function getTypeMenu( $queryTypes ) { |
||
| 194 | $queryType = count( $queryTypes ) == 1 ? $queryTypes[0] : ''; |
||
| 195 | $selector = $this->getTypeSelector(); |
||
| 196 | $selector->setDefault( $queryType ); |
||
| 197 | |||
| 198 | return $selector->getHTML(); |
||
| 199 | } |
||
| 200 | |||
| 201 | /** |
||
| 202 | * Returns log page selector. |
||
| 203 | * @return XmlSelect |
||
| 204 | * @since 1.19 |
||
| 205 | */ |
||
| 206 | public function getTypeSelector() { |
||
| 207 | $typesByName = []; // Temporary array |
||
| 208 | // First pass to load the log names |
||
| 209 | foreach ( LogPage::validTypes() as $type ) { |
||
| 210 | $page = new LogPage( $type ); |
||
| 211 | $restriction = $page->getRestriction(); |
||
| 212 | if ( $this->getUser()->isAllowed( $restriction ) ) { |
||
| 213 | $typesByName[$type] = $page->getName()->text(); |
||
| 214 | } |
||
| 215 | } |
||
| 216 | |||
| 217 | // Second pass to sort by name |
||
| 218 | asort( $typesByName ); |
||
| 219 | |||
| 220 | // Always put "All public logs" on top |
||
| 221 | $public = $typesByName['']; |
||
| 222 | unset( $typesByName[''] ); |
||
| 223 | $typesByName = [ '' => $public ] + $typesByName; |
||
| 224 | |||
| 225 | $select = new XmlSelect( 'type' ); |
||
| 226 | foreach ( $typesByName as $type => $name ) { |
||
| 227 | $select->addOption( $name, $type ); |
||
| 228 | } |
||
| 229 | |||
| 230 | return $select; |
||
| 231 | } |
||
| 232 | |||
| 233 | /** |
||
| 234 | * @param string $user |
||
| 235 | * @return string Formatted HTML |
||
| 236 | */ |
||
| 237 | private function getUserInput( $user ) { |
||
| 238 | $label = Xml::inputLabel( |
||
| 239 | $this->msg( 'specialloguserlabel' )->text(), |
||
| 240 | 'user', |
||
| 241 | 'mw-log-user', |
||
| 242 | 15, |
||
| 243 | $user, |
||
| 244 | [ 'class' => 'mw-autocomplete-user' ] |
||
| 245 | ); |
||
| 246 | |||
| 247 | return '<span class="mw-input-with-label">' . $label . '</span>'; |
||
| 248 | } |
||
| 249 | |||
| 250 | /** |
||
| 251 | * @param string $title |
||
| 252 | * @return string Formatted HTML |
||
| 253 | */ |
||
| 254 | private function getTitleInput( $title ) { |
||
| 255 | $label = Xml::inputLabel( |
||
| 256 | $this->msg( 'speciallogtitlelabel' )->text(), |
||
| 257 | 'page', |
||
| 258 | 'mw-log-page', |
||
| 259 | 20, |
||
| 260 | $title |
||
| 261 | ); |
||
| 262 | |||
| 263 | return '<span class="mw-input-with-label">' . $label . '</span>'; |
||
| 264 | } |
||
| 265 | |||
| 266 | /** |
||
| 267 | * @param string $pattern |
||
| 268 | * @return string Checkbox |
||
| 269 | */ |
||
| 270 | private function getTitlePattern( $pattern ) { |
||
| 271 | return '<span class="mw-input-with-label">' . |
||
| 272 | Xml::checkLabel( $this->msg( 'log-title-wildcard' )->text(), 'pattern', 'pattern', $pattern ) . |
||
| 273 | '</span>'; |
||
| 274 | } |
||
| 275 | |||
| 276 | /** |
||
| 277 | * @param array $types |
||
| 278 | * @return string |
||
| 279 | */ |
||
| 280 | private function getExtraInputs( $types ) { |
||
| 281 | if ( count( $types ) == 1 ) { |
||
| 282 | if ( $types[0] == 'suppress' ) { |
||
| 283 | $offender = $this->getRequest()->getVal( 'offender' ); |
||
| 284 | $user = User::newFromName( $offender, false ); |
||
| 285 | if ( !$user || ( $user->getId() == 0 && !IP::isIPAddress( $offender ) ) ) { |
||
| 286 | $offender = ''; // Blank field if invalid |
||
| 287 | } |
||
| 288 | return Xml::inputLabel( $this->msg( 'revdelete-offender' )->text(), 'offender', |
||
| 289 | 'mw-log-offender', 20, $offender ); |
||
| 290 | } else { |
||
| 291 | // Allow extensions to add their own extra inputs |
||
| 292 | $input = ''; |
||
| 293 | Hooks::run( 'LogEventsListGetExtraInputs', [ $types[0], $this, &$input ] ); |
||
| 294 | return $input; |
||
| 295 | } |
||
| 296 | } |
||
| 297 | |||
| 298 | return ''; |
||
| 299 | } |
||
| 300 | |||
| 301 | /** |
||
| 302 | * Drop down menu for selection of actions that can be used to filter the log |
||
| 303 | * @param array $types |
||
| 304 | * @param string $action |
||
| 305 | * @return string |
||
| 306 | * @since 1.27 |
||
| 307 | */ |
||
| 308 | private function getActionSelector( $types, $action ) { |
||
| 309 | if ( $this->allowedActions === null || !count( $this->allowedActions ) ) { |
||
| 310 | return ''; |
||
| 311 | } |
||
| 312 | $html = ''; |
||
| 313 | $html .= xml::label( wfMessage( 'log-action-filter-' . $types[0] )->text(), |
||
| 314 | 'action-filter-' .$types[0] ) . "\n"; |
||
| 315 | $select = new XmlSelect( 'subtype' ); |
||
| 316 | $select->addOption( wfMessage( 'log-action-filter-all' )->text(), '' ); |
||
| 317 | foreach ( $this->allowedActions as $value ) { |
||
| 318 | $msgKey = 'log-action-filter-' . $types[0] . '-' . $value; |
||
| 319 | $select->addOption( wfMessage( $msgKey )->text(), $value ); |
||
| 320 | } |
||
| 321 | $select->setDefault( $action ); |
||
| 322 | $html .= $select->getHtml(); |
||
| 323 | return $html; |
||
| 324 | } |
||
| 325 | |||
| 326 | /** |
||
| 327 | * Sets the action types allowed for log filtering |
||
| 328 | * To one action type may correspond several log_actions |
||
| 329 | * @param array $actions |
||
| 330 | * @since 1.27 |
||
| 331 | */ |
||
| 332 | public function setAllowedActions( $actions ) { |
||
| 333 | $this->allowedActions = $actions; |
||
| 334 | } |
||
| 335 | |||
| 336 | /** |
||
| 337 | * @return string |
||
| 338 | */ |
||
| 339 | public function beginLogEventsList() { |
||
| 340 | return "<ul>\n"; |
||
| 341 | } |
||
| 342 | |||
| 343 | /** |
||
| 344 | * @return string |
||
| 345 | */ |
||
| 346 | public function endLogEventsList() { |
||
| 347 | return "</ul>\n"; |
||
| 348 | } |
||
| 349 | |||
| 350 | /** |
||
| 351 | * @param stdClass $row A single row from the result set |
||
| 352 | * @return string Formatted HTML list item |
||
| 353 | */ |
||
| 354 | public function logLine( $row ) { |
||
| 355 | $entry = DatabaseLogEntry::newFromRow( $row ); |
||
| 356 | $formatter = LogFormatter::newFromEntry( $entry ); |
||
| 357 | $formatter->setContext( $this->getContext() ); |
||
| 358 | $formatter->setShowUserToolLinks( !( $this->flags & self::NO_EXTRA_USER_LINKS ) ); |
||
| 359 | |||
| 360 | $time = htmlspecialchars( $this->getLanguage()->userTimeAndDate( |
||
| 361 | $entry->getTimestamp(), $this->getUser() ) ); |
||
| 362 | |||
| 363 | $action = $formatter->getActionText(); |
||
| 364 | |||
| 365 | if ( $this->flags & self::NO_ACTION_LINK ) { |
||
| 366 | $revert = ''; |
||
| 367 | } else { |
||
| 368 | $revert = $formatter->getActionLinks(); |
||
| 369 | if ( $revert != '' ) { |
||
| 370 | $revert = '<span class="mw-logevent-actionlink">' . $revert . '</span>'; |
||
| 371 | } |
||
| 372 | } |
||
| 373 | |||
| 374 | $comment = $formatter->getComment(); |
||
| 375 | |||
| 376 | // Some user can hide log items and have review links |
||
| 377 | $del = $this->getShowHideLinks( $row ); |
||
| 378 | |||
| 379 | // Any tags... |
||
| 380 | list( $tagDisplay, $newClasses ) = ChangeTags::formatSummaryRow( |
||
| 381 | $row->ts_tags, |
||
| 382 | 'logevent', |
||
| 383 | $this->getContext() |
||
| 384 | ); |
||
| 385 | $classes = array_merge( |
||
| 386 | [ 'mw-logline-' . $entry->getType() ], |
||
| 387 | $newClasses |
||
| 388 | ); |
||
| 389 | |||
| 390 | return Html::rawElement( 'li', [ 'class' => $classes ], |
||
| 391 | "$del $time $action $comment $revert $tagDisplay" ) . "\n"; |
||
| 392 | } |
||
| 393 | |||
| 394 | /** |
||
| 395 | * @param stdClass $row Row |
||
| 396 | * @return string |
||
| 397 | */ |
||
| 398 | private function getShowHideLinks( $row ) { |
||
| 399 | // We don't want to see the links and |
||
| 400 | if ( $this->flags == self::NO_ACTION_LINK ) { |
||
| 401 | return ''; |
||
| 402 | } |
||
| 403 | |||
| 404 | $user = $this->getUser(); |
||
| 405 | |||
| 406 | // If change tag editing is available to this user, return the checkbox |
||
| 407 | if ( $this->flags & self::USE_CHECKBOXES && $this->showTagEditUI ) { |
||
| 408 | return Xml::check( |
||
| 409 | 'showhiderevisions', |
||
| 410 | false, |
||
| 411 | [ 'name' => 'ids[' . $row->log_id . ']' ] |
||
| 412 | ); |
||
| 413 | } |
||
| 414 | |||
| 415 | // no one can hide items from the suppress log. |
||
| 416 | if ( $row->log_type == 'suppress' ) { |
||
| 417 | return ''; |
||
| 418 | } |
||
| 419 | |||
| 420 | $del = ''; |
||
| 421 | // Don't show useless checkbox to people who cannot hide log entries |
||
| 422 | if ( $user->isAllowed( 'deletedhistory' ) ) { |
||
| 423 | $canHide = $user->isAllowed( 'deletelogentry' ); |
||
| 424 | $canViewSuppressedOnly = $user->isAllowed( 'viewsuppressed' ) && |
||
| 425 | !$user->isAllowed( 'suppressrevision' ); |
||
| 426 | $entryIsSuppressed = self::isDeleted( $row, LogPage::DELETED_RESTRICTED ); |
||
| 427 | $canViewThisSuppressedEntry = $canViewSuppressedOnly && $entryIsSuppressed; |
||
| 428 | if ( $row->log_deleted || $canHide ) { |
||
| 429 | // Show checkboxes instead of links. |
||
| 430 | if ( $canHide && $this->flags & self::USE_CHECKBOXES && !$canViewThisSuppressedEntry ) { |
||
| 431 | // If event was hidden from sysops |
||
| 432 | View Code Duplication | if ( !self::userCan( $row, LogPage::DELETED_RESTRICTED, $user ) ) { |
|
| 433 | $del = Xml::check( 'deleterevisions', false, [ 'disabled' => 'disabled' ] ); |
||
| 434 | } else { |
||
| 435 | $del = Xml::check( |
||
| 436 | 'showhiderevisions', |
||
| 437 | false, |
||
| 438 | [ 'name' => 'ids[' . $row->log_id . ']' ] |
||
| 439 | ); |
||
| 440 | } |
||
| 441 | } else { |
||
| 442 | // If event was hidden from sysops |
||
| 443 | if ( !self::userCan( $row, LogPage::DELETED_RESTRICTED, $user ) ) { |
||
| 444 | $del = Linker::revDeleteLinkDisabled( $canHide ); |
||
| 445 | } else { |
||
| 446 | $query = [ |
||
| 447 | 'target' => SpecialPage::getTitleFor( 'Log', $row->log_type )->getPrefixedDBkey(), |
||
| 448 | 'type' => 'logging', |
||
| 449 | 'ids' => $row->log_id, |
||
| 450 | ]; |
||
| 451 | $del = Linker::revDeleteLink( |
||
| 452 | $query, |
||
| 453 | $entryIsSuppressed, |
||
| 454 | $canHide && !$canViewThisSuppressedEntry |
||
| 455 | ); |
||
| 456 | } |
||
| 457 | } |
||
| 458 | } |
||
| 459 | } |
||
| 460 | |||
| 461 | return $del; |
||
| 462 | } |
||
| 463 | |||
| 464 | /** |
||
| 465 | * @param stdClass $row Row |
||
| 466 | * @param string|array $type |
||
| 467 | * @param string|array $action |
||
| 468 | * @param string $right |
||
| 469 | * @return bool |
||
| 470 | */ |
||
| 471 | public static function typeAction( $row, $type, $action, $right = '' ) { |
||
| 472 | $match = is_array( $type ) ? |
||
| 473 | in_array( $row->log_type, $type ) : $row->log_type == $type; |
||
| 474 | if ( $match ) { |
||
| 475 | $match = is_array( $action ) ? |
||
| 476 | in_array( $row->log_action, $action ) : $row->log_action == $action; |
||
| 477 | if ( $match && $right ) { |
||
| 478 | global $wgUser; |
||
| 479 | $match = $wgUser->isAllowed( $right ); |
||
| 480 | } |
||
| 481 | } |
||
| 482 | |||
| 483 | return $match; |
||
| 484 | } |
||
| 485 | |||
| 486 | /** |
||
| 487 | * Determine if the current user is allowed to view a particular |
||
| 488 | * field of this log row, if it's marked as deleted. |
||
| 489 | * |
||
| 490 | * @param stdClass $row Row |
||
| 491 | * @param int $field |
||
| 492 | * @param User $user User to check, or null to use $wgUser |
||
| 493 | * @return bool |
||
| 494 | */ |
||
| 495 | public static function userCan( $row, $field, User $user = null ) { |
||
| 496 | return self::userCanBitfield( $row->log_deleted, $field, $user ); |
||
| 497 | } |
||
| 498 | |||
| 499 | /** |
||
| 500 | * Determine if the current user is allowed to view a particular |
||
| 501 | * field of this log row, if it's marked as deleted. |
||
| 502 | * |
||
| 503 | * @param int $bitfield Current field |
||
| 504 | * @param int $field |
||
| 505 | * @param User $user User to check, or null to use $wgUser |
||
| 506 | * @return bool |
||
| 507 | */ |
||
| 508 | public static function userCanBitfield( $bitfield, $field, User $user = null ) { |
||
| 509 | if ( $bitfield & $field ) { |
||
| 510 | if ( $user === null ) { |
||
| 511 | global $wgUser; |
||
| 512 | $user = $wgUser; |
||
| 513 | } |
||
| 514 | if ( $bitfield & LogPage::DELETED_RESTRICTED ) { |
||
| 515 | $permissions = [ 'suppressrevision', 'viewsuppressed' ]; |
||
| 516 | } else { |
||
| 517 | $permissions = [ 'deletedhistory' ]; |
||
| 518 | } |
||
| 519 | $permissionlist = implode( ', ', $permissions ); |
||
| 520 | wfDebug( "Checking for $permissionlist due to $field match on $bitfield\n" ); |
||
| 521 | return call_user_func_array( [ $user, 'isAllowedAny' ], $permissions ); |
||
| 522 | } |
||
| 523 | return true; |
||
| 524 | } |
||
| 525 | |||
| 526 | /** |
||
| 527 | * @param stdClass $row Row |
||
| 528 | * @param int $field One of DELETED_* bitfield constants |
||
| 529 | * @return bool |
||
| 530 | */ |
||
| 531 | public static function isDeleted( $row, $field ) { |
||
| 532 | return ( $row->log_deleted & $field ) == $field; |
||
| 533 | } |
||
| 534 | |||
| 535 | /** |
||
| 536 | * Show log extract. Either with text and a box (set $msgKey) or without (don't set $msgKey) |
||
| 537 | * |
||
| 538 | * @param OutputPage|string $out By-reference |
||
| 539 | * @param string|array $types Log types to show |
||
| 540 | * @param string|Title $page The page title to show log entries for |
||
| 541 | * @param string $user The user who made the log entries |
||
| 542 | * @param array $param Associative Array with the following additional options: |
||
| 543 | * - lim Integer Limit of items to show, default is 50 |
||
| 544 | * - conds Array Extra conditions for the query (e.g. "log_action != 'revision'") |
||
| 545 | * - showIfEmpty boolean Set to false if you don't want any output in case the loglist is empty |
||
| 546 | * if set to true (default), "No matching items in log" is displayed if loglist is empty |
||
| 547 | * - msgKey Array If you want a nice box with a message, set this to the key of the message. |
||
| 548 | * First element is the message key, additional optional elements are parameters for the key |
||
| 549 | * that are processed with wfMessage |
||
| 550 | * - offset Set to overwrite offset parameter in WebRequest |
||
| 551 | * set to '' to unset offset |
||
| 552 | * - wrap String Wrap the message in html (usually something like "<div ...>$1</div>"). |
||
| 553 | * - flags Integer display flags (NO_ACTION_LINK,NO_EXTRA_USER_LINKS) |
||
| 554 | * - useRequestParams boolean Set true to use Pager-related parameters in the WebRequest |
||
| 555 | * - useMaster boolean Use master DB |
||
| 556 | * - extraUrlParams array|bool Additional url parameters for "full log" link (if it is shown) |
||
| 557 | * @return int Number of total log items (not limited by $lim) |
||
| 558 | */ |
||
| 559 | public static function showLogExtract( |
||
| 703 | |||
| 704 | /** |
||
| 705 | * SQL clause to skip forbidden log types for this user |
||
| 706 | * |
||
| 707 | * @param IDatabase $db |
||
| 708 | * @param string $audience Public/user |
||
| 709 | * @param User $user User to check, or null to use $wgUser |
||
| 710 | * @return string|bool String on success, false on failure. |
||
| 711 | */ |
||
| 712 | public static function getExcludeClause( $db, $audience = 'public', User $user = null ) { |
||
| 713 | global $wgLogRestrictions; |
||
| 714 | |||
| 715 | if ( $audience != 'public' && $user === null ) { |
||
| 716 | global $wgUser; |
||
| 717 | $user = $wgUser; |
||
| 718 | } |
||
| 719 | |||
| 720 | // Reset the array, clears extra "where" clauses when $par is used |
||
| 721 | $hiddenLogs = []; |
||
| 722 | |||
| 723 | // Don't show private logs to unprivileged users |
||
| 737 | } |
||
| 738 |