r96441 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r96440‎ | r96441 | r96442 >
Date:15:32, 7 September 2011
Author:nikerabbit
Status:resolved (Comments)
Tags:scaptrap 
Comment:
Committing my new logging classes for review. Will later commit changes that use these classes.
Modified paths:
  • /trunk/phase3/includes/AutoLoader.php (modified) (history)
  • /trunk/phase3/includes/LogPage.php (modified) (history)
  • /trunk/phase3/includes/logging (added) (history)
  • /trunk/phase3/includes/logging/LogEntry.php (added) (history)
  • /trunk/phase3/includes/logging/LogFormatter.php (added) (history)

Diff [purge]

Index: trunk/phase3/includes/logging/LogEntry.php
@@ -0,0 +1,465 @@
 2+<?php
 3+/**
 4+ * Contain classes for dealing with individual log entries
 5+ *
 6+ * This is how I see the log system history:
 7+ * - appending to plain wiki pages
 8+ * - formatting log entries based on database fields
 9+ * - user is now part of the action message
 10+ *
 11+ * @file
 12+ * @author Niklas Laxström
 13+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
 14+ * @since 1.19
 15+ */
 16+
 17+/**
 18+ * Interface for log entries. Every log entry has these methods.
 19+ * @since 1.19
 20+ */
 21+interface LogEntry {
 22+
 23+ /**
 24+ * The main log type.
 25+ * @return string
 26+ */
 27+ public function getType();
 28+
 29+ /**
 30+ * The log subtype.
 31+ * @return string
 32+ */
 33+ public function getSubtype();
 34+
 35+ /**
 36+ * The full logtype in format maintype/subtype.
 37+ * @return string
 38+ */
 39+ public function getFullType();
 40+
 41+ /**
 42+ * Get the extra parameters stored for this message.
 43+ * @return array
 44+ */
 45+ public function getParameters();
 46+
 47+ /**
 48+ * Get the user for performed this action.
 49+ * @return User
 50+ */
 51+ public function getPerformer();
 52+
 53+ /**
 54+ * Get the target page of this action.
 55+ * @return Title
 56+ */
 57+ public function getTarget();
 58+
 59+ /**
 60+ * Get the timestamp when the action was executed.
 61+ * @return string
 62+ */
 63+ public function getTimestamp();
 64+
 65+ /**
 66+ * Get the user provided comment.
 67+ * @return string
 68+ */
 69+ public function getComment();
 70+
 71+ /**
 72+ * Get the access restriction.
 73+ * @return string
 74+ */
 75+ public function getDeleted();
 76+
 77+ /**
 78+ * @param $field Integer: one of LogPage::DELETED_* bitfield constants
 79+ * @return Boolean
 80+ */
 81+ public function isDeleted( $field );
 82+}
 83+
 84+/**
 85+ * Extends the LogEntryInterface with some basic functionality
 86+ * @since 1.19
 87+ */
 88+abstract class LogEntryBase implements LogEntry {
 89+
 90+ public function getFullType() {
 91+ return $this->getType() . '/' . $this->getSubtype();
 92+ }
 93+
 94+ public function isDeleted( $field ) {
 95+ return ( $this->getDeleted() & $field ) === $field;
 96+ }
 97+
 98+ /**
 99+ * Whether the parameters for this log are stored in new or
 100+ * old format.
 101+ */
 102+ public function isLegacy() {
 103+ return false;
 104+ }
 105+
 106+}
 107+
 108+/**
 109+ * This class wraps around database result row.
 110+ * @since 1.19
 111+ */
 112+class DatabaseLogEntry extends LogEntryBase {
 113+ // Static->
 114+
 115+ /**
 116+ * Returns array of information that is needed for querying
 117+ * log entries. Array contains the following keys:
 118+ * tables, fields, conds, options and join_conds
 119+ * @return array
 120+ */
 121+ public static function getSelectQueryData() {
 122+ $tables = array( 'logging', 'user' );
 123+ $fields = array(
 124+ 'log_id', 'log_type', 'log_action', 'log_timestamp',
 125+ 'log_user', 'log_user_text',
 126+ 'log_namespace', 'log_title', //unused log_page
 127+ 'log_comment', 'log_params', 'log_deleted',
 128+ 'user_id', 'user_name', 'user_editcount',
 129+ );
 130+
 131+ $conds = array();
 132+
 133+ $joins = array(
 134+ // IP's don't have an entry in user table
 135+ 'user' => array( 'LEFT JOIN', 'log_user=user_id' ),
 136+ );
 137+
 138+ return array(
 139+ 'tables' => $tables,
 140+ 'fields' => $fields,
 141+ 'conds' => array(),
 142+ 'options' => array(),
 143+ 'join_conds' => $joins,
 144+ );
 145+ }
 146+
 147+ /**
 148+ * Constructs new LogEntry from database result row.
 149+ * Supports rows from both logging and recentchanges table.
 150+ * @param $row
 151+ * @return DatabaseLogEntry
 152+ */
 153+ public static function newFromRow( $row ) {
 154+ if ( is_array( $row ) && isset( $row['rc_logid'] ) ) {
 155+ return new RCDatabaseLogEntry( (object) $row );
 156+ } else {
 157+ return new self( $row );
 158+ }
 159+ }
 160+
 161+ // Non-static->
 162+
 163+ /// Database result row.
 164+ protected $row;
 165+
 166+ protected function __construct( $row ) {
 167+ $this->row = $row;
 168+ }
 169+
 170+ /**
 171+ * Returns the unique database id.
 172+ * @return int
 173+ */
 174+ public function getId() {
 175+ return (int)$this->row->log_id;
 176+ }
 177+
 178+ /**
 179+ * Returns whatever is stored in the database field.
 180+ * @return string
 181+ */
 182+ protected function getRawParameters() {
 183+ return $this->row->log_params;
 184+ }
 185+
 186+ // LogEntryBase->
 187+
 188+ public function isLegacy() {
 189+ // This does the check
 190+ $this->getParameters();
 191+ return $this->legacy;
 192+ }
 193+
 194+ // LogEntry->
 195+
 196+ public function getType() {
 197+ return $this->row->log_type;
 198+ }
 199+
 200+ public function getSubtype() {
 201+ return $this->row->log_action;
 202+ }
 203+
 204+ public function getParameters() {
 205+ if ( !isset( $this->params ) ) {
 206+ $blob = $this->getRawParameters();
 207+ $params = FormatJson::decode( $blob, true /* array */ );
 208+ if ( $params !== null ) {
 209+ $this->params = $params;
 210+ $this->legacy = false;
 211+ } else {
 212+ $this->params = explode( "\n", $blob );
 213+ $this->legacy = true;
 214+ }
 215+ }
 216+ return $this->params;
 217+ }
 218+
 219+ public function getPerformer() {
 220+ $userId = (int) $this->row->log_user;
 221+ if ( $userId !== 0 ) {
 222+ return User::newFromRow( $this->row );
 223+ } else {
 224+ $userText = $this->row->log_user_text;
 225+ return User::newFromName( $userText, false );
 226+ }
 227+ }
 228+
 229+ public function getTarget() {
 230+ $namespace = $this->row->log_namespace;
 231+ $page = $this->row->log_title;
 232+ $title = Title::makeTitle( $namespace, $page );
 233+ return $title;
 234+ }
 235+
 236+ public function getTimestamp() {
 237+ return wfTimestamp( TS_MW, $this->row->log_timestamp );
 238+ }
 239+
 240+ public function getComment() {
 241+ return $this->row->log_comment;
 242+ }
 243+
 244+ public function getDeleted() {
 245+ return $this->row->log_deleted;
 246+ }
 247+
 248+}
 249+
 250+class RCDatabaseLogEntry extends DatabaseLogEntry {
 251+
 252+ public function getId() {
 253+ return $this->row->rc_logid;
 254+ }
 255+
 256+ protected function getRawParameters() {
 257+ return $this->row->rc_params;
 258+ }
 259+
 260+ // LogEntry->
 261+
 262+ public function getType() {
 263+ return $this->row->rc_log_type;
 264+ }
 265+
 266+ public function getSubtype() {
 267+ return $this->row->rc_log_action;
 268+ }
 269+
 270+ public function getPerformer() {
 271+ $userId = (int) $this->row->rc_user;
 272+ if ( $userId !== 0 ) {
 273+ return User::newFromId( $userId );
 274+ } else {
 275+ $userText = $this->row->rc_user_text;
 276+ // Might be an IP, don't validate the username
 277+ return User::newFromName( $userText, false );
 278+ }
 279+ }
 280+
 281+ public function getTarget() {
 282+ $namespace = $this->row->rc_namespace;
 283+ $page = $this->row->rc_title;
 284+ $title = Title::makeTitle( $namespace, $page );
 285+ return $title;
 286+ }
 287+
 288+ public function getTimestamp() {
 289+ return wfTimestamp( TS_MW, $this->row->rc_timestamp );
 290+ }
 291+
 292+ public function getComment() {
 293+ return $this->row->rc_comment;
 294+ }
 295+
 296+ public function getDeleted() {
 297+ return $this->row->rc_deleted;
 298+ }
 299+
 300+}
 301+
 302+/**
 303+ * Class for creating log entries manually, for
 304+ * example to inject them into the database.
 305+ * @since 1.19
 306+ */
 307+class ManualLogEntry extends LogEntryBase {
 308+ protected $type; ///!< @var string
 309+ protected $subtype; ///!< @var string
 310+ protected $parameters = array(); ///!< @var array
 311+ protected $performer; ///!< @var User
 312+ protected $target; ///!< @var Title
 313+ protected $timestamp; ///!< @var string
 314+ protected $comment; ///!< @var string
 315+ protected $deleted; ///!< @var int
 316+
 317+ public function __construct( $type, $subtype ) {
 318+ $this->type = $type;
 319+ $this->subtype = $subtype;
 320+ }
 321+
 322+ /**
 323+ * Set extra log parameters.
 324+ * You can pass params to the log action message
 325+ * by prefixing the keys with a number and colon.
 326+ * The numbering should start with number 4, the
 327+ * first three parameters are hardcoded for every
 328+ * message. Example:
 329+ * $entry->setParameters(
 330+ * '4:color' => 'blue',
 331+ * 'animal' => 'dog'
 332+ * );
 333+ * @param $parameters Associative array
 334+ */
 335+ public function setParameters( $parameters ) {
 336+ $this->parameters = $parameters;
 337+ }
 338+
 339+ public function setPerformer( User $performer ) {
 340+ $this->performer = $performer;
 341+ }
 342+
 343+ public function setTarget( Title $target ) {
 344+ $this->target = $target;
 345+ }
 346+
 347+ public function setTimestamp( $timestamp ) {
 348+ $this->timestamp = $timestamp;
 349+ }
 350+
 351+ public function setComment( $comment ) {
 352+ $this->comment = $comment;
 353+ }
 354+
 355+ public function setDeleted( $deleted ) {
 356+ $this->deleted = $deleted;
 357+ }
 358+
 359+ /**
 360+ * Inserts the entry into the logging table.
 361+ * @return int If of the log entry
 362+ */
 363+ public function insert() {
 364+ global $wgLogRestrictions;
 365+
 366+ $dbw = wfGetDB( DB_MASTER );
 367+ $id = $dbw->nextSequenceValue( 'logging_log_id_seq' );
 368+
 369+ if ( $this->timestamp === null ) {
 370+ $this->timestamp = wfTimestampNow();
 371+ }
 372+
 373+ $data = array(
 374+ 'log_id' => $id,
 375+ 'log_type' => $this->getType(),
 376+ 'log_action' => $this->getSubtype(),
 377+ 'log_timestamp' => $dbw->timestamp( $this->getTimestamp() ),
 378+ 'log_user' => $this->getPerformer()->getId(),
 379+ 'log_user_text' => $this->getPerformer()->getName(),
 380+ 'log_namespace' => $this->getTarget()->getNamespace(),
 381+ 'log_title' => $this->getTarget()->getDBkey(),
 382+ 'log_page' => $this->getTarget()->getArticleId(),
 383+ 'log_comment' => $this->getComment(),
 384+ 'log_params' => FormatJson::encode( (array) $this->getParameters() ),
 385+ );
 386+ $dbw->insert( 'logging', $data, __METHOD__ );
 387+ $this->id = !is_null( $id ) ? $id : $dbw->insertId();
 388+ return $this->id;
 389+ }
 390+
 391+ /**
 392+ * Publishes the log entry.
 393+ * @param $newId int id of the log entry.
 394+ * @param $to string: rcandudp (default), rc, udp
 395+ */
 396+ public function publish( $newId, $to = 'rcandudp' ) {
 397+ $log = new LogPage( $this->getType() );
 398+ if ( $log->isRestricted() ) {
 399+ return;
 400+ }
 401+
 402+ $formatter = LogFormatter::newFromEntry( $this );
 403+ $context = RequestContext::newExtraneousContext( $this->getTarget() );
 404+ $formatter->setContext( $context );
 405+
 406+ $logpage = SpecialPage::getTitleFor( 'Log', $this->getType() );
 407+ $user = $this->getPerformer();
 408+ $rc = RecentChange::newLogEntry(
 409+ $this->getTimestamp(),
 410+ $logpage,
 411+ $user,
 412+ $formatter->getPlainActionText(), // Used for IRC feeds
 413+ $user->isAnon() ? $user->getName() : '',
 414+ $this->getType(),
 415+ $this->getSubtype(),
 416+ $this->getTarget(),
 417+ $this->getComment(),
 418+ FormatJson::encode( (array) $this->getParameters() ),
 419+ $newId
 420+ );
 421+
 422+ if ( $to === 'rc' || $to === 'rcandudp' ) {
 423+ $rc->save();
 424+ }
 425+
 426+ if ( $to === 'udp' || $to === 'rcandudp' ) {
 427+ $rc->notifyRC2UDP();
 428+ }
 429+ }
 430+
 431+ // LogEntry->
 432+
 433+ public function getType() {
 434+ return $this->type;
 435+ }
 436+
 437+ public function getSubtype() {
 438+ return $this->subtype;
 439+ }
 440+
 441+ public function getParameters() {
 442+ return $this->parameters;
 443+ }
 444+
 445+ public function getPerformer() {
 446+ return $this->performer;
 447+ }
 448+
 449+ public function getTarget() {
 450+ return $this->target;
 451+ }
 452+
 453+ public function getTimestamp() {
 454+ $ts = $this->timestamp !== null ? $this->timestamp : wfTimestampNow();
 455+ return wfTimestamp( TS_MW, $ts );
 456+ }
 457+
 458+ public function getComment() {
 459+ return $this->comment;
 460+ }
 461+
 462+ public function getDeleted() {
 463+ return (int) $this->deleted;
 464+ }
 465+
 466+}
\ No newline at end of file
Property changes on: trunk/phase3/includes/logging/LogEntry.php
___________________________________________________________________
Added: svn:eol-style
1467 + native
Index: trunk/phase3/includes/logging/LogFormatter.php
@@ -0,0 +1,342 @@
 2+<?php
 3+/**
 4+ * Contains classes for formatting log entries
 5+ *
 6+ * @file
 7+ * @author Niklas Laxström
 8+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
 9+ * @since 1.19
 10+ */
 11+
 12+/**
 13+ * Implements the default log formatting.
 14+ * Can be overridden by subclassing and setting
 15+ * $wgLogActionsHandlers['type/subtype'] = 'class'; or
 16+ * $wgLogActionsHandlers['type/*'] = 'class';
 17+ * @since 1.19
 18+ */
 19+class LogFormatter {
 20+
 21+ // Static->
 22+
 23+ /**
 24+ * Constructs a new formatter suitable for given entry.
 25+ * @param $entry LogEntry
 26+ * @return LogFormatter
 27+ */
 28+ public static function newFromEntry( LogEntry $entry ) {
 29+ global $wgLogActionsHandlers;
 30+ $fulltype = $entry->getFullType();
 31+ $wildcard = $entry->getType() . '/*';
 32+ $handler = '';
 33+
 34+ if ( isset( $wgLogActionsHandlers[$fulltype] ) ) {
 35+ $handler = $wgLogActionsHandlers[$fulltype];
 36+ } elseif ( isset( $wgLogActionsHandlers[$wildcard] ) ) {
 37+ $handler = $wgLogActionsHandlers[$wildcard];
 38+ }
 39+
 40+ if ( $handler !== '' && class_exists( $handler ) ) {
 41+ return new $handler( $entry );
 42+ }
 43+
 44+ return new LegacyLogFormatter( $entry );
 45+ }
 46+
 47+ /**
 48+ * Handy shortcut for constructing a formatter directly from
 49+ * database row.
 50+ * @param $row
 51+ * @see DatabaseLogEntry::getSelectQueryData
 52+ * @return LogFormatter
 53+ */
 54+ public static function newFromRow( $row ) {
 55+ return self::newFromEntry( DatabaseLogEntry::newFromRow( $row ) );
 56+ }
 57+
 58+ // Nonstatic->
 59+
 60+ /// @var LogEntry
 61+ protected $entry;
 62+
 63+ /// Whether to output user tool links
 64+ protected $linkFlood = false;
 65+
 66+ /**
 67+ * Set to true if we are constructing a message text that is going to
 68+ * be included in page history or send to IRC feed. Links are replaced
 69+ * with plaintext or with [[pagename]] kind of syntax, that is parsed
 70+ * by page histories and IRC feeds.
 71+ * @var boolean
 72+ */
 73+ protected $plaintext = false;
 74+
 75+ protected function __construct( LogEntry $entry ) {
 76+ $this->entry = $entry;
 77+ $this->context = RequestContext::getMain();
 78+ }
 79+
 80+ /**
 81+ * Replace the default context
 82+ * @param $context RequestContext
 83+ */
 84+ public function setContext( RequestContext $context ) {
 85+ $this->context = $context;
 86+ }
 87+
 88+ /**
 89+ * If set to true, will produce user tool links after
 90+ * the user name. This should be replaced with generic
 91+ * CSS/JS solution.
 92+ * @param $value boolean
 93+ */
 94+ public function setShowUserToolLinks( $value ) {
 95+ $this->linkFlood = $value;
 96+ }
 97+
 98+ /**
 99+ * Ugly hack to produce plaintext version of the message.
 100+ * Usually you also want to set extraneous request context
 101+ * to avoid formatting for any particular user.
 102+ * @see getActionText()
 103+ * @return string text
 104+ */
 105+ public function getPlainActionText() {
 106+ $this->plaintext = true;
 107+ $text = $this->getActionText();
 108+ $this->plaintext = false;
 109+ return $text;
 110+ }
 111+
 112+ /**
 113+ * Gets the log action, including username.
 114+ * @return string HTML
 115+ */
 116+ public function getActionText() {
 117+ $element = $this->getActionMessage();
 118+ if ( $element instanceof Message ) {
 119+ $element = $this->plaintext ? $element->text() : $element->escaped();
 120+ }
 121+
 122+ if ( $this->entry->isDeleted( LogPage::DELETED_ACTION ) ) {
 123+ $performer = $this->getPerformerElement() . $this->msg( 'word-separator' )->text();
 124+ $element = $performer . self::getRestrictedElement( 'rev-deleted-event' );
 125+ }
 126+
 127+ return $element;
 128+ }
 129+
 130+ /**
 131+ * Returns a sentence describing the log action. Usually
 132+ * a Message object is returned, but old style log types
 133+ * and entries might return pre-escaped html string.
 134+ * @return Message|pre-escaped html
 135+ */
 136+ protected function getActionMessage() {
 137+ $message = $this->msg( $this->getMessageKey() );
 138+ $message->params( $this->getMessageParameters() );
 139+ return $message;
 140+ }
 141+
 142+ /**
 143+ * Returns a key to be used for formatting the action sentence.
 144+ * Default is logentry-TYPE-SUBTYPE for modern logs. Legacy log
 145+ * types will use custom keys, and subclasses can also alter the
 146+ * key depending on the entry itself.
 147+ * @return string message key
 148+ */
 149+ protected function getMessageKey() {
 150+ $type = $this->entry->getType();
 151+ $subtype = $this->entry->getSubtype();
 152+ $key = "logentry-$type-$subtype";
 153+ return $key;
 154+ }
 155+
 156+ /**
 157+ * Extract parameters intented for action message from
 158+ * array of all parameters. The are three hardcoded
 159+ * parameters (array zero-indexed, this list not):
 160+ * - 1: user name with premade link
 161+ * - 2: usable for gender magic function
 162+ * - 3: target page with premade link
 163+ * @return array
 164+ */
 165+ protected function getMessageParameters() {
 166+ $entry = $this->entry;
 167+
 168+ $params = array();
 169+ $params[0] = Message::rawParam( $this->getPerformerElement() );
 170+ $params[1] = $entry->getPerformer()->getName();
 171+ $params[2] = Message::rawParam( $this->makePageLink( $entry->getTarget() ) );
 172+
 173+ if ( $entry->isLegacy() ) {
 174+ foreach ( $entry->getParameters() as $index => $value ) {
 175+ $params[$index+3] = $value;
 176+ }
 177+ }
 178+
 179+ // Filter out parameters which are not in format #:foo
 180+ foreach ( $entry->getParameters() as $key => $value ) {
 181+ if ( strpos( $key, ':' ) === false ) continue;
 182+ list( $index, $type, $name ) = explode( ':', $key, 3 );
 183+ $params[$index-1] = $value;
 184+ }
 185+
 186+ /* Message class doesn't like non consecutive numbering.
 187+ * Fill in missing indexes with empty strings to avoid
 188+ * incorrect renumbering.
 189+ */
 190+ $max = max( array_keys( $params ) );
 191+ for ( $i = 4; $i < $max; $i++ ) {
 192+ if ( !isset( $params[$i] ) ) {
 193+ $params[$i] = '';
 194+ }
 195+ }
 196+
 197+ return $params;
 198+ }
 199+
 200+ /**
 201+ * Helper to make a link to the page, taking the plaintext
 202+ * value in consideration.
 203+ * @param $title Title the page
 204+ * @param $parameters array query parameters
 205+ * @return String
 206+ */
 207+ protected function makePageLink( Title $title, $parameters = array() ) {
 208+ if ( !$this->plaintext ) {
 209+ $link = Linker::link( $title, null, array(), $parameters );
 210+ } else {
 211+ $link = '[[' . $title->getPrefixedText() . ']]';
 212+ }
 213+ return $link;
 214+ }
 215+
 216+ /**
 217+ * Provides the name of the user who performed the log action.
 218+ * Used as part of log action message or standalone, depending
 219+ * which parts of the log entry has been hidden.
 220+ */
 221+ public function getPerformerElement() {
 222+ $performer = $this->entry->getPerformer();
 223+
 224+ if ( $this->plaintext ) {
 225+ $element = $performer->getName();
 226+ } else {
 227+ $element = Linker::userLink(
 228+ $performer->getId(),
 229+ $performer->getName()
 230+ );
 231+
 232+ if ( $this->linkFlood ) {
 233+ $element .= Linker::userToolLinks(
 234+ $performer->getId(),
 235+ $performer->getName(),
 236+ true, // Red if no edits
 237+ 0, // Flags
 238+ $performer->getEditCount()
 239+ );
 240+ }
 241+ }
 242+
 243+ if ( $this->entry->isDeleted( LogPage::DELETED_USER ) ) {
 244+ $element = self::getRestrictedElement( 'rev-deleted-user' );
 245+ }
 246+
 247+ return $element;
 248+ }
 249+
 250+ /**
 251+ * Gets the luser provided comment
 252+ * @return string HTML
 253+ */
 254+ public function getComment() {
 255+ $lang = $this->context->getLang();
 256+ $element = $lang->getDirMark() . Linker::commentBlock( $this->entry->getComment() );
 257+
 258+ if ( $this->entry->isDeleted( LogPage::DELETED_COMMENT ) ) {
 259+ $element = self::getRestrictedElement( 'rev-deleted-comment' );
 260+ }
 261+
 262+ return $element;
 263+ }
 264+
 265+ /**
 266+ * Helper method for displaying restricted element.
 267+ * @param $message string
 268+ * @return string HTML
 269+ */
 270+ protected function getRestrictedElement( $message ) {
 271+ if ( $this->plaintext ) {
 272+ return $this->msg( $message )->text();
 273+ }
 274+
 275+ $content = $this->msg( $message )->escaped();
 276+ $attribs = array( 'class' => 'history-deleted' );
 277+ return Html::rawElement( 'span', $attribs, $content );
 278+ }
 279+
 280+ /**
 281+ * Shortcut for wfMessage which honors local context.
 282+ * @todo Would it be better to require replacing the global context instead?
 283+ * @param $key string
 284+ * @return Message
 285+ */
 286+ protected function msg( $key ) {
 287+ return wfMessage( $key )
 288+ ->inLanguage( $this->context->getLang() )
 289+ ->title( $this->context->getTitle() );
 290+ }
 291+
 292+}
 293+
 294+/**
 295+ * This class formats all log entries for log types
 296+ * which have not been converted to the new system.
 297+ * This is not about old log entries which store
 298+ * parameters in a different format - the new
 299+ * LogFormatter classes have code to support formatting
 300+ * those too.
 301+ * @since 1.19
 302+ */
 303+class LegacyLogFormatter extends LogFormatter {
 304+ protected function getActionMessage() {
 305+ $entry = $this->entry;
 306+ $action = LogPage::actionText(
 307+ $entry->getType(),
 308+ $entry->getSubtype(),
 309+ $entry->getTarget(),
 310+ $this->context->getUser()->getSkin(),
 311+ (array)$entry->getParameters(),
 312+ true
 313+ );
 314+
 315+ $performer = $this->getPerformerElement();
 316+ return $performer . $this->msg( 'word-separator' )->text() . $action;
 317+ }
 318+
 319+}
 320+
 321+/**
 322+ * This class formats Block log entries.
 323+ * @since 1.19
 324+ */
 325+class BlockLogFormatter extends LogFormatter {
 326+ protected function getMessageKey() {
 327+ $key = parent::getMessageKey();
 328+ $params = $this->getMessageParameters();
 329+ if ( isset( $params[4] ) && $params[4] === '1' ) {
 330+ $key .= '-noredirect';
 331+ }
 332+ return $key;
 333+ }
 334+
 335+ protected function getMessageParameters() {
 336+ $params = parent::getMessageParameters();
 337+ $oldname = $this->makePageLink( $this->entry->getTarget(), array( 'redirect' => 'no' ) );
 338+ $newname = $this->makePageLink( Title::newFromText( $params[3] ) );
 339+ $params[2] = Message::rawParam( $oldname );
 340+ $params[3] = Message::rawParam( $newname );
 341+ return $params;
 342+ }
 343+}
\ No newline at end of file
Property changes on: trunk/phase3/includes/logging/LogFormatter.php
___________________________________________________________________
Added: svn:eol-style
1344 + native
Index: trunk/phase3/includes/AutoLoader.php
@@ -531,6 +531,16 @@
532532 'JSMinPlus' => 'includes/libs/jsminplus.php',
533533 'JSParser' => 'includes/libs/jsminplus.php',
534534
 535+ # includes/logging
 536+ 'LogEntry' => 'includes/logging/LogEntry.php',
 537+ 'LogEntryBase' => 'includes/logging/LogEntry.php',
 538+ 'DatabaseLogEntry' => 'includes/logging/LogEntry.php',
 539+ 'RCDatabaseLogEntry' => 'includes/logging/LogEntry.php',
 540+ 'ManualLogEntry' => 'includes/logging/LogEntry.php',
 541+ 'LogFormatter' => 'includes/logging/LogFormatter.php',
 542+ 'LegacyLogFormatter' => 'includes/logging/LogFormatter.php',
 543+ 'BlockLogFormatter' => 'includes/logging/LogFormatter.php',
 544+
535545 # includes/media
536546 'BitmapHandler' => 'includes/media/Bitmap.php',
537547 'BitmapHandler_ClientOnly' => 'includes/media/Bitmap_ClientOnly.php',
@@ -866,6 +876,7 @@
867877 # tests/parser
868878 'ParserTest' => 'tests/parser/parserTest.inc',
869879 'ParserTestParserHook' => 'tests/parser/parserTestsParserHook.php',
 880+ 'ParserTestStaticParserHook' => 'tests/parser/parserTestsStaticParserHook.php',
870881
871882 # tests/selenium
872883 'Selenium' => 'tests/selenium/Selenium.php',
Index: trunk/phase3/includes/LogPage.php
@@ -172,6 +172,7 @@
173173 *
174174 * @param $type String: logtype
175175 * @return String: log name
 176+ * @deprecated in 1.19, warnings in 1.21. Use getName()
176177 */
177178 public static function logName( $type ) {
178179 global $wgLogNames;
@@ -190,6 +191,7 @@
191192 * @todo handle missing log types
192193 * @param $type String: logtype
193194 * @return String: headertext of this logtype
 195+ * @deprecated in 1.19, warnings in 1.21. Use getDescription()
194196 */
195197 public static function logHeader( $type ) {
196198 global $wgLogHeaders;
@@ -576,4 +578,66 @@
577579
578580 return $messages[$flag];
579581 }
 582+
 583+
 584+ /**
 585+ * Name of the log.
 586+ * @return Message
 587+ * @since 1.19
 588+ */
 589+ public function getName() {
 590+ global $wgLogNames;
 591+
 592+ // BC
 593+ if ( isset( $wgLogNames[$this->type] ) ) {
 594+ $key = $wgLogNames[$this->type];
 595+ } else {
 596+ $key = 'log-name-' . $this->type;
 597+ }
 598+
 599+ return wfMessage( $key );
 600+ }
 601+
 602+ /**
 603+ * Description of this log type.
 604+ * @return Message
 605+ * @since 1.19
 606+ */
 607+ public function getDescription() {
 608+ global $wgLogHeaders;
 609+ // BC
 610+ if ( isset( $wgLogHeaders[$this->type] ) ) {
 611+ $key = $wgLogHeaders[$this->type];
 612+ } else {
 613+ $key = 'log-description-' . $this->type;
 614+ }
 615+ return wfMessage( $key );
 616+ }
 617+
 618+ /**
 619+ * Returns the right needed to read this log type.
 620+ * @return string
 621+ * @since 1.19
 622+ */
 623+ public function getRestriction() {
 624+ global $wgLogRestrictions;
 625+ if ( isset( $wgLogRestrictions[$this->type] ) ) {
 626+ $restriction = $wgLogRestrictions[$this->type];
 627+ } else {
 628+ // '' always returns true with $user->isAllowed()
 629+ $restriction = '';
 630+ }
 631+ return $restriction;
 632+ }
 633+
 634+ /**
 635+ * Tells if this log is not viewable by all.
 636+ * @return bool
 637+ * @since 1.19
 638+ */
 639+ public function isRestricted() {
 640+ $restriction = $this->getRestriction();
 641+ return $restriction !== '' && $restriction !== '*';
 642+ }
 643+
580644 }

Follow-up revisions

RevisionCommit summaryAuthorDate
r96444Ffixes to r96443 and r96441nikerabbit16:11, 7 September 2011
r96546Enabled MoveLogFormatter...nikerabbit09:09, 8 September 2011
r100396Bugfix to r96441, class_exists throws warnings when arrays are passed to itjohnduhart00:09, 21 October 2011
r110955(bug 33374) - 'Deletion log summary not properly truncated'aaron19:53, 8 February 2012
r113888Unbreak maintenance/deleteDefaultMessages.php for PostgreSQL...saper01:52, 15 March 2012

Comments

#Comment by Aaron Schulz (talk | contribs)   03:12, 22 September 2011

Wikis will break if upgraded to this and downgraded to 1.18.

#Comment by Aaron Schulz (talk | contribs)   03:17, 27 September 2011

Can you work on a quick & dirty patch that can be merged into 1.18wmf1 sometime that formats the serialized log_params/rc_params into something halfway pretty? Like taking: a:2:{s:9:"4::target";s:22:"Fichier:P8180347 7.JPG";s:10:"5::noredir";s:1:"1";} ...and outputting: [target=Fichier:P8180347 7.JPG, noredir=1]

We want to minimize the breakage a little if we have to rollback from 1.19 to 1.18.

#Comment by Umherirrender (talk | contribs)   19:14, 3 February 2012

See bug 33374, maybe truncate it right now inside the setter or later in the insert method, but than you have to check also RecentChange::newLogEntry.

class ManualLogEntry extends LogEntryBase {
...
	public function setComment( $comment ) {
		# Truncate whole multibyte characters
		$this->comment = $wgContLang->truncate( $comment, 255 );
	}
...
}

Status & tagging log