[ Index ] |
PHP Cross Reference of MediaWiki-1.24.0 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Contains classes for formatting log entries 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 * http://www.gnu.org/copyleft/gpl.html 19 * 20 * @file 21 * @author Niklas Laxström 22 * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later 23 * @since 1.19 24 */ 25 26 /** 27 * Implements the default log formatting. 28 * Can be overridden by subclassing and setting 29 * $wgLogActionsHandlers['type/subtype'] = 'class'; or 30 * $wgLogActionsHandlers['type/*'] = 'class'; 31 * @since 1.19 32 */ 33 class LogFormatter { 34 // Audience options for viewing usernames, comments, and actions 35 const FOR_PUBLIC = 1; 36 const FOR_THIS_USER = 2; 37 38 // Static-> 39 40 /** 41 * Constructs a new formatter suitable for given entry. 42 * @param LogEntry $entry 43 * @return LogFormatter 44 */ 45 public static function newFromEntry( LogEntry $entry ) { 46 global $wgLogActionsHandlers; 47 $fulltype = $entry->getFullType(); 48 $wildcard = $entry->getType() . '/*'; 49 $handler = ''; 50 51 if ( isset( $wgLogActionsHandlers[$fulltype] ) ) { 52 $handler = $wgLogActionsHandlers[$fulltype]; 53 } elseif ( isset( $wgLogActionsHandlers[$wildcard] ) ) { 54 $handler = $wgLogActionsHandlers[$wildcard]; 55 } 56 57 if ( $handler !== '' && is_string( $handler ) && class_exists( $handler ) ) { 58 return new $handler( $entry ); 59 } 60 61 return new LegacyLogFormatter( $entry ); 62 } 63 64 /** 65 * Handy shortcut for constructing a formatter directly from 66 * database row. 67 * @param object $row 68 * @see DatabaseLogEntry::getSelectQueryData 69 * @return LogFormatter 70 */ 71 public static function newFromRow( $row ) { 72 return self::newFromEntry( DatabaseLogEntry::newFromRow( $row ) ); 73 } 74 75 // Nonstatic-> 76 77 /** @var LogEntryBase */ 78 protected $entry; 79 80 /** @var int Constant for handling log_deleted */ 81 protected $audience = self::FOR_PUBLIC; 82 83 /** @var bool Whether to output user tool links */ 84 protected $linkFlood = false; 85 86 /** 87 * Set to true if we are constructing a message text that is going to 88 * be included in page history or send to IRC feed. Links are replaced 89 * with plaintext or with [[pagename]] kind of syntax, that is parsed 90 * by page histories and IRC feeds. 91 * @var string 92 */ 93 protected $plaintext = false; 94 95 /** @var string */ 96 protected $irctext = false; 97 98 protected function __construct( LogEntry $entry ) { 99 $this->entry = $entry; 100 $this->context = RequestContext::getMain(); 101 } 102 103 /** 104 * Replace the default context 105 * @param IContextSource $context 106 */ 107 public function setContext( IContextSource $context ) { 108 $this->context = $context; 109 } 110 111 /** 112 * Set the visibility restrictions for displaying content. 113 * If set to public, and an item is deleted, then it will be replaced 114 * with a placeholder even if the context user is allowed to view it. 115 * @param int $audience Const self::FOR_THIS_USER or self::FOR_PUBLIC 116 */ 117 public function setAudience( $audience ) { 118 $this->audience = ( $audience == self::FOR_THIS_USER ) 119 ? self::FOR_THIS_USER 120 : self::FOR_PUBLIC; 121 } 122 123 /** 124 * Check if a log item can be displayed 125 * @param int $field LogPage::DELETED_* constant 126 * @return bool 127 */ 128 protected function canView( $field ) { 129 if ( $this->audience == self::FOR_THIS_USER ) { 130 return LogEventsList::userCanBitfield( 131 $this->entry->getDeleted(), $field, $this->context->getUser() ); 132 } else { 133 return !$this->entry->isDeleted( $field ); 134 } 135 } 136 137 /** 138 * If set to true, will produce user tool links after 139 * the user name. This should be replaced with generic 140 * CSS/JS solution. 141 * @param bool $value 142 */ 143 public function setShowUserToolLinks( $value ) { 144 $this->linkFlood = $value; 145 } 146 147 /** 148 * Ugly hack to produce plaintext version of the message. 149 * Usually you also want to set extraneous request context 150 * to avoid formatting for any particular user. 151 * @see getActionText() 152 * @return string Plain text 153 */ 154 public function getPlainActionText() { 155 $this->plaintext = true; 156 $text = $this->getActionText(); 157 $this->plaintext = false; 158 159 return $text; 160 } 161 162 /** 163 * Even uglier hack to maintain backwards compatibilty with IRC bots 164 * (bug 34508). 165 * @see getActionText() 166 * @return string Text 167 */ 168 public function getIRCActionComment() { 169 $actionComment = $this->getIRCActionText(); 170 $comment = $this->entry->getComment(); 171 172 if ( $comment != '' ) { 173 if ( $actionComment == '' ) { 174 $actionComment = $comment; 175 } else { 176 $actionComment .= wfMessage( 'colon-separator' )->inContentLanguage()->text() . $comment; 177 } 178 } 179 180 return $actionComment; 181 } 182 183 /** 184 * Even uglier hack to maintain backwards compatibilty with IRC bots 185 * (bug 34508). 186 * @see getActionText() 187 * @return string Text 188 */ 189 public function getIRCActionText() { 190 $this->plaintext = true; 191 $this->irctext = true; 192 193 $entry = $this->entry; 194 $parameters = $entry->getParameters(); 195 // @see LogPage::actionText() 196 // Text of title the action is aimed at. 197 $target = $entry->getTarget()->getPrefixedText(); 198 $text = null; 199 switch ( $entry->getType() ) { 200 case 'move': 201 switch ( $entry->getSubtype() ) { 202 case 'move': 203 $movesource = $parameters['4::target']; 204 $text = wfMessage( '1movedto2' ) 205 ->rawParams( $target, $movesource )->inContentLanguage()->escaped(); 206 break; 207 case 'move_redir': 208 $movesource = $parameters['4::target']; 209 $text = wfMessage( '1movedto2_redir' ) 210 ->rawParams( $target, $movesource )->inContentLanguage()->escaped(); 211 break; 212 case 'move-noredirect': 213 break; 214 case 'move_redir-noredirect': 215 break; 216 } 217 break; 218 219 case 'delete': 220 switch ( $entry->getSubtype() ) { 221 case 'delete': 222 $text = wfMessage( 'deletedarticle' ) 223 ->rawParams( $target )->inContentLanguage()->escaped(); 224 break; 225 case 'restore': 226 $text = wfMessage( 'undeletedarticle' ) 227 ->rawParams( $target )->inContentLanguage()->escaped(); 228 break; 229 // @codingStandardsIgnoreStart Long line 230 //case 'revision': // Revision deletion 231 //case 'event': // Log deletion 232 // see https://svn.wikimedia.org/viewvc/mediawiki/trunk/phase3/includes/LogPage.php?&pathrev=97044&r1=97043&r2=97044 233 //default: 234 // @codingStandardsIgnoreEnd 235 } 236 break; 237 238 case 'patrol': 239 // @codingStandardsIgnoreStart Long line 240 // https://svn.wikimedia.org/viewvc/mediawiki/trunk/phase3/includes/PatrolLog.php?&pathrev=97495&r1=97494&r2=97495 241 // @codingStandardsIgnoreEnd 242 // Create a diff link to the patrolled revision 243 if ( $entry->getSubtype() === 'patrol' ) { 244 $diffLink = htmlspecialchars( 245 wfMessage( 'patrol-log-diff', $parameters['4::curid'] ) 246 ->inContentLanguage()->text() ); 247 $text = wfMessage( 'patrol-log-line', $diffLink, "[[$target]]", "" ) 248 ->inContentLanguage()->text(); 249 } else { 250 // broken?? 251 } 252 break; 253 254 case 'protect': 255 switch ( $entry->getSubtype() ) { 256 case 'protect': 257 $text = wfMessage( 'protectedarticle' ) 258 ->rawParams( $target . ' ' . $parameters[0] )->inContentLanguage()->escaped(); 259 break; 260 case 'unprotect': 261 $text = wfMessage( 'unprotectedarticle' ) 262 ->rawParams( $target )->inContentLanguage()->escaped(); 263 break; 264 case 'modify': 265 $text = wfMessage( 'modifiedarticleprotection' ) 266 ->rawParams( $target . ' ' . $parameters[0] )->inContentLanguage()->escaped(); 267 break; 268 } 269 break; 270 271 case 'newusers': 272 switch ( $entry->getSubtype() ) { 273 case 'newusers': 274 case 'create': 275 $text = wfMessage( 'newuserlog-create-entry' ) 276 ->inContentLanguage()->escaped(); 277 break; 278 case 'create2': 279 case 'byemail': 280 $text = wfMessage( 'newuserlog-create2-entry' ) 281 ->rawParams( $target )->inContentLanguage()->escaped(); 282 break; 283 case 'autocreate': 284 $text = wfMessage( 'newuserlog-autocreate-entry' ) 285 ->inContentLanguage()->escaped(); 286 break; 287 } 288 break; 289 290 case 'upload': 291 switch ( $entry->getSubtype() ) { 292 case 'upload': 293 $text = wfMessage( 'uploadedimage' ) 294 ->rawParams( $target )->inContentLanguage()->escaped(); 295 break; 296 case 'overwrite': 297 $text = wfMessage( 'overwroteimage' ) 298 ->rawParams( $target )->inContentLanguage()->escaped(); 299 break; 300 } 301 break; 302 303 case 'rights': 304 if ( count( $parameters['4::oldgroups'] ) ) { 305 $oldgroups = implode( ', ', $parameters['4::oldgroups'] ); 306 } else { 307 $oldgroups = wfMessage( 'rightsnone' )->inContentLanguage()->escaped(); 308 } 309 if ( count( $parameters['5::newgroups'] ) ) { 310 $newgroups = implode( ', ', $parameters['5::newgroups'] ); 311 } else { 312 $newgroups = wfMessage( 'rightsnone' )->inContentLanguage()->escaped(); 313 } 314 switch ( $entry->getSubtype() ) { 315 case 'rights': 316 $text = wfMessage( 'rightslogentry' ) 317 ->rawParams( $target, $oldgroups, $newgroups )->inContentLanguage()->escaped(); 318 break; 319 case 'autopromote': 320 $text = wfMessage( 'rightslogentry-autopromote' ) 321 ->rawParams( $target, $oldgroups, $newgroups )->inContentLanguage()->escaped(); 322 break; 323 } 324 break; 325 // case 'suppress' --private log -- aaron (so we know who to blame in a few years :-D) 326 // default: 327 } 328 if ( is_null( $text ) ) { 329 $text = $this->getPlainActionText(); 330 } 331 332 $this->plaintext = false; 333 $this->irctext = false; 334 335 return $text; 336 } 337 338 /** 339 * Gets the log action, including username. 340 * @return string HTML 341 */ 342 public function getActionText() { 343 if ( $this->canView( LogPage::DELETED_ACTION ) ) { 344 $element = $this->getActionMessage(); 345 if ( $element instanceof Message ) { 346 $element = $this->plaintext ? $element->text() : $element->escaped(); 347 } 348 if ( $this->entry->isDeleted( LogPage::DELETED_ACTION ) ) { 349 $element = $this->styleRestricedElement( $element ); 350 } 351 } else { 352 $performer = $this->getPerformerElement() . $this->msg( 'word-separator' )->text(); 353 $element = $performer . $this->getRestrictedElement( 'rev-deleted-event' ); 354 } 355 356 return $element; 357 } 358 359 /** 360 * Returns a sentence describing the log action. Usually 361 * a Message object is returned, but old style log types 362 * and entries might return pre-escaped HTML string. 363 * @return Message|string Pre-escaped HTML 364 */ 365 protected function getActionMessage() { 366 $message = $this->msg( $this->getMessageKey() ); 367 $message->params( $this->getMessageParameters() ); 368 369 return $message; 370 } 371 372 /** 373 * Returns a key to be used for formatting the action sentence. 374 * Default is logentry-TYPE-SUBTYPE for modern logs. Legacy log 375 * types will use custom keys, and subclasses can also alter the 376 * key depending on the entry itself. 377 * @return string Message key 378 */ 379 protected function getMessageKey() { 380 $type = $this->entry->getType(); 381 $subtype = $this->entry->getSubtype(); 382 383 return "logentry-$type-$subtype"; 384 } 385 386 /** 387 * Returns extra links that comes after the action text, like "revert", etc. 388 * 389 * @return string 390 */ 391 public function getActionLinks() { 392 return ''; 393 } 394 395 /** 396 * Extracts the optional extra parameters for use in action messages. 397 * The array indexes start from number 3. 398 * @return array 399 */ 400 protected function extractParameters() { 401 $entry = $this->entry; 402 $params = array(); 403 404 if ( $entry->isLegacy() ) { 405 foreach ( $entry->getParameters() as $index => $value ) { 406 $params[$index + 3] = $value; 407 } 408 } 409 410 // Filter out parameters which are not in format #:foo 411 foreach ( $entry->getParameters() as $key => $value ) { 412 if ( strpos( $key, ':' ) === false ) { 413 continue; 414 } 415 list( $index, $type, ) = explode( ':', $key, 3 ); 416 $params[$index - 1] = $this->formatParameterValue( $type, $value ); 417 } 418 419 /* Message class doesn't like non consecutive numbering. 420 * Fill in missing indexes with empty strings to avoid 421 * incorrect renumbering. 422 */ 423 if ( count( $params ) ) { 424 $max = max( array_keys( $params ) ); 425 for ( $i = 4; $i < $max; $i++ ) { 426 if ( !isset( $params[$i] ) ) { 427 $params[$i] = ''; 428 } 429 } 430 } 431 432 return $params; 433 } 434 435 /** 436 * Formats parameters intented for action message from 437 * array of all parameters. There are three hardcoded 438 * parameters (array is zero-indexed, this list not): 439 * - 1: user name with premade link 440 * - 2: usable for gender magic function 441 * - 3: target page with premade link 442 * @return array 443 */ 444 protected function getMessageParameters() { 445 if ( isset( $this->parsedParameters ) ) { 446 return $this->parsedParameters; 447 } 448 449 $entry = $this->entry; 450 $params = $this->extractParameters(); 451 $params[0] = Message::rawParam( $this->getPerformerElement() ); 452 $params[1] = $this->canView( LogPage::DELETED_USER ) ? $entry->getPerformer()->getName() : ''; 453 $params[2] = Message::rawParam( $this->makePageLink( $entry->getTarget() ) ); 454 455 // Bad things happens if the numbers are not in correct order 456 ksort( $params ); 457 458 $this->parsedParameters = $params; 459 return $this->parsedParameters; 460 } 461 462 /** 463 * Formats parameters values dependent to their type 464 * @param string $type The type of the value. 465 * Valid are currently: 466 * * - (empty) or plain: The value is returned as-is 467 * * raw: The value will be added to the log message 468 * as raw parameter (e.g. no escaping) 469 * Use this only if there is no other working 470 * type like user-link or title-link 471 * * msg: The value is a message-key, the output is 472 * the message in user language 473 * * msg-content: The value is a message-key, the output 474 * is the message in content language 475 * * user: The value is a user name, e.g. for GENDER 476 * * user-link: The value is a user name, returns a 477 * link for the user 478 * * title: The value is a page title, 479 * returns name of page 480 * * title-link: The value is a page title, 481 * returns link to this page 482 * * number: Format value as number 483 * @param string $value The parameter value that should 484 * be formated 485 * @return string|array Formated value 486 * @since 1.21 487 */ 488 protected function formatParameterValue( $type, $value ) { 489 $saveLinkFlood = $this->linkFlood; 490 491 switch ( strtolower( trim( $type ) ) ) { 492 case 'raw': 493 $value = Message::rawParam( $value ); 494 break; 495 case 'msg': 496 $value = $this->msg( $value )->text(); 497 break; 498 case 'msg-content': 499 $value = $this->msg( $value )->inContentLanguage()->text(); 500 break; 501 case 'number': 502 $value = Message::numParam( $value ); 503 break; 504 case 'user': 505 $user = User::newFromName( $value ); 506 $value = $user->getName(); 507 break; 508 case 'user-link': 509 $this->setShowUserToolLinks( false ); 510 511 $user = User::newFromName( $value ); 512 $value = Message::rawParam( $this->makeUserLink( $user ) ); 513 514 $this->setShowUserToolLinks( $saveLinkFlood ); 515 break; 516 case 'title': 517 $title = Title::newFromText( $value ); 518 $value = $title->getPrefixedText(); 519 break; 520 case 'title-link': 521 $title = Title::newFromText( $value ); 522 $value = Message::rawParam( $this->makePageLink( $title ) ); 523 break; 524 case 'plain': 525 // Plain text, nothing to do 526 default: 527 // Catch other types and use the old behavior (return as-is) 528 } 529 530 return $value; 531 } 532 533 /** 534 * Helper to make a link to the page, taking the plaintext 535 * value in consideration. 536 * @param Title $title The page 537 * @param array $parameters Query parameters 538 * @throws MWException 539 * @return string 540 */ 541 protected function makePageLink( Title $title = null, $parameters = array() ) { 542 if ( !$this->plaintext ) { 543 $link = Linker::link( $title, null, array(), $parameters ); 544 } else { 545 if ( !$title instanceof Title ) { 546 throw new MWException( "Expected title, got null" ); 547 } 548 $link = '[[' . $title->getPrefixedText() . ']]'; 549 } 550 551 return $link; 552 } 553 554 /** 555 * Provides the name of the user who performed the log action. 556 * Used as part of log action message or standalone, depending 557 * which parts of the log entry has been hidden. 558 * @return string 559 */ 560 public function getPerformerElement() { 561 if ( $this->canView( LogPage::DELETED_USER ) ) { 562 $performer = $this->entry->getPerformer(); 563 $element = $this->makeUserLink( $performer ); 564 if ( $this->entry->isDeleted( LogPage::DELETED_USER ) ) { 565 $element = $this->styleRestricedElement( $element ); 566 } 567 } else { 568 $element = $this->getRestrictedElement( 'rev-deleted-user' ); 569 } 570 571 return $element; 572 } 573 574 /** 575 * Gets the user provided comment 576 * @return string HTML 577 */ 578 public function getComment() { 579 if ( $this->canView( LogPage::DELETED_COMMENT ) ) { 580 $comment = Linker::commentBlock( $this->entry->getComment() ); 581 // No hard coded spaces thanx 582 $element = ltrim( $comment ); 583 if ( $this->entry->isDeleted( LogPage::DELETED_COMMENT ) ) { 584 $element = $this->styleRestricedElement( $element ); 585 } 586 } else { 587 $element = $this->getRestrictedElement( 'rev-deleted-comment' ); 588 } 589 590 return $element; 591 } 592 593 /** 594 * Helper method for displaying restricted element. 595 * @param string $message 596 * @return string HTML or wiki text 597 */ 598 protected function getRestrictedElement( $message ) { 599 if ( $this->plaintext ) { 600 return $this->msg( $message )->text(); 601 } 602 603 $content = $this->msg( $message )->escaped(); 604 $attribs = array( 'class' => 'history-deleted' ); 605 606 return Html::rawElement( 'span', $attribs, $content ); 607 } 608 609 /** 610 * Helper method for styling restricted element. 611 * @param string $content 612 * @return string HTML or wiki text 613 */ 614 protected function styleRestricedElement( $content ) { 615 if ( $this->plaintext ) { 616 return $content; 617 } 618 $attribs = array( 'class' => 'history-deleted' ); 619 620 return Html::rawElement( 'span', $attribs, $content ); 621 } 622 623 /** 624 * Shortcut for wfMessage which honors local context. 625 * @param string $key 626 * @return Message 627 */ 628 protected function msg( $key ) { 629 return $this->context->msg( $key ); 630 } 631 632 protected function makeUserLink( User $user ) { 633 if ( $this->plaintext ) { 634 $element = $user->getName(); 635 } else { 636 $element = Linker::userLink( 637 $user->getId(), 638 $user->getName() 639 ); 640 641 if ( $this->linkFlood ) { 642 $element .= Linker::userToolLinksRedContribs( 643 $user->getId(), 644 $user->getName(), 645 $user->getEditCount() 646 ); 647 } 648 } 649 650 return $element; 651 } 652 653 /** 654 * @return array Array of titles that should be preloaded with LinkBatch 655 */ 656 public function getPreloadTitles() { 657 return array(); 658 } 659 660 /** 661 * @return array Output of getMessageParameters() for testing 662 */ 663 public function getMessageParametersForTesting() { 664 // This function was added because getMessageParameters() is 665 // protected and a change from protected to public caused 666 // problems with extensions 667 return $this->getMessageParameters(); 668 } 669 } 670 671 /** 672 * This class formats all log entries for log types 673 * which have not been converted to the new system. 674 * This is not about old log entries which store 675 * parameters in a different format - the new 676 * LogFormatter classes have code to support formatting 677 * those too. 678 * @since 1.19 679 */ 680 class LegacyLogFormatter extends LogFormatter { 681 /** 682 * Backward compatibility for extension changing the comment from 683 * the LogLine hook. This will be set by the first call on getComment(), 684 * then it might be modified by the hook when calling getActionLinks(), 685 * so that the modified value will be returned when calling getComment() 686 * a second time. 687 * 688 * @var string|null 689 */ 690 private $comment = null; 691 692 /** 693 * Cache for the result of getActionLinks() so that it does not need to 694 * run multiple times depending on the order that getComment() and 695 * getActionLinks() are called. 696 * 697 * @var string|null 698 */ 699 private $revert = null; 700 701 public function getComment() { 702 if ( $this->comment === null ) { 703 $this->comment = parent::getComment(); 704 } 705 706 // Make sure we execute the LogLine hook so that we immediately return 707 // the correct value. 708 if ( $this->revert === null ) { 709 $this->getActionLinks(); 710 } 711 712 return $this->comment; 713 } 714 715 protected function getActionMessage() { 716 $entry = $this->entry; 717 $action = LogPage::actionText( 718 $entry->getType(), 719 $entry->getSubtype(), 720 $entry->getTarget(), 721 $this->plaintext ? null : $this->context->getSkin(), 722 (array)$entry->getParameters(), 723 !$this->plaintext // whether to filter [[]] links 724 ); 725 726 $performer = $this->getPerformerElement(); 727 if ( !$this->irctext ) { 728 $action = $performer . $this->msg( 'word-separator' )->text() . $action; 729 } 730 731 return $action; 732 } 733 734 public function getActionLinks() { 735 if ( $this->revert !== null ) { 736 return $this->revert; 737 } 738 739 if ( $this->entry->isDeleted( LogPage::DELETED_ACTION ) ) { 740 $this->revert = ''; 741 return $this->revert; 742 } 743 744 $title = $this->entry->getTarget(); 745 $type = $this->entry->getType(); 746 $subtype = $this->entry->getSubtype(); 747 748 // Show unblock/change block link 749 if ( ( $type == 'block' || $type == 'suppress' ) 750 && ( $subtype == 'block' || $subtype == 'reblock' ) 751 ) { 752 if ( !$this->context->getUser()->isAllowed( 'block' ) ) { 753 return ''; 754 } 755 756 $links = array( 757 Linker::linkKnown( 758 SpecialPage::getTitleFor( 'Unblock', $title->getDBkey() ), 759 $this->msg( 'unblocklink' )->escaped() 760 ), 761 Linker::linkKnown( 762 SpecialPage::getTitleFor( 'Block', $title->getDBkey() ), 763 $this->msg( 'change-blocklink' )->escaped() 764 ) 765 ); 766 767 return $this->msg( 'parentheses' )->rawParams( 768 $this->context->getLanguage()->pipeList( $links ) )->escaped(); 769 // Show change protection link 770 } elseif ( $type == 'protect' 771 && ( $subtype == 'protect' || $subtype == 'modify' || $subtype == 'unprotect' ) 772 ) { 773 $links = array( 774 Linker::link( $title, 775 $this->msg( 'hist' )->escaped(), 776 array(), 777 array( 778 'action' => 'history', 779 'offset' => $this->entry->getTimestamp() 780 ) 781 ) 782 ); 783 if ( $this->context->getUser()->isAllowed( 'protect' ) ) { 784 $links[] = Linker::linkKnown( 785 $title, 786 $this->msg( 'protect_change' )->escaped(), 787 array(), 788 array( 'action' => 'protect' ) 789 ); 790 } 791 792 return $this->msg( 'parentheses' )->rawParams( 793 $this->context->getLanguage()->pipeList( $links ) )->escaped(); 794 // Show unmerge link 795 } elseif ( $type == 'merge' && $subtype == 'merge' ) { 796 if ( !$this->context->getUser()->isAllowed( 'mergehistory' ) ) { 797 return ''; 798 } 799 800 $params = $this->extractParameters(); 801 $revert = Linker::linkKnown( 802 SpecialPage::getTitleFor( 'MergeHistory' ), 803 $this->msg( 'revertmerge' )->escaped(), 804 array(), 805 array( 806 'target' => $params[3], 807 'dest' => $title->getPrefixedDBkey(), 808 'mergepoint' => $params[4], 809 'submitted' => 1 // show the revisions immediately 810 ) 811 ); 812 813 return $this->msg( 'parentheses' )->rawParams( $revert )->escaped(); 814 } 815 816 // Do nothing. The implementation is handled by the hook modifiying the 817 // passed-by-ref parameters. This also changes the default value so that 818 // getComment() and getActionLinks() do not call them indefinitely. 819 $this->revert = ''; 820 821 // This is to populate the $comment member of this instance so that it 822 // can be modified when calling the hook just below. 823 if ( $this->comment === null ) { 824 $this->getComment(); 825 } 826 827 $params = $this->entry->getParameters(); 828 829 wfRunHooks( 'LogLine', array( $type, $subtype, $title, $params, 830 &$this->comment, &$this->revert, $this->entry->getTimestamp() ) ); 831 832 return $this->revert; 833 } 834 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 14:03:12 2014 | Cross-referenced by PHPXref 0.7.1 |