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 |
1 | 467 | + 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 |
1 | 344 | + native |
Index: trunk/phase3/includes/AutoLoader.php |
— | — | @@ -531,6 +531,16 @@ |
532 | 532 | 'JSMinPlus' => 'includes/libs/jsminplus.php', |
533 | 533 | 'JSParser' => 'includes/libs/jsminplus.php', |
534 | 534 | |
| 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 | + |
535 | 545 | # includes/media |
536 | 546 | 'BitmapHandler' => 'includes/media/Bitmap.php', |
537 | 547 | 'BitmapHandler_ClientOnly' => 'includes/media/Bitmap_ClientOnly.php', |
— | — | @@ -866,6 +876,7 @@ |
867 | 877 | # tests/parser |
868 | 878 | 'ParserTest' => 'tests/parser/parserTest.inc', |
869 | 879 | 'ParserTestParserHook' => 'tests/parser/parserTestsParserHook.php', |
| 880 | + 'ParserTestStaticParserHook' => 'tests/parser/parserTestsStaticParserHook.php', |
870 | 881 | |
871 | 882 | # tests/selenium |
872 | 883 | 'Selenium' => 'tests/selenium/Selenium.php', |
Index: trunk/phase3/includes/LogPage.php |
— | — | @@ -172,6 +172,7 @@ |
173 | 173 | * |
174 | 174 | * @param $type String: logtype |
175 | 175 | * @return String: log name |
| 176 | + * @deprecated in 1.19, warnings in 1.21. Use getName() |
176 | 177 | */ |
177 | 178 | public static function logName( $type ) { |
178 | 179 | global $wgLogNames; |
— | — | @@ -190,6 +191,7 @@ |
191 | 192 | * @todo handle missing log types |
192 | 193 | * @param $type String: logtype |
193 | 194 | * @return String: headertext of this logtype |
| 195 | + * @deprecated in 1.19, warnings in 1.21. Use getDescription() |
194 | 196 | */ |
195 | 197 | public static function logHeader( $type ) { |
196 | 198 | global $wgLogHeaders; |
— | — | @@ -576,4 +578,66 @@ |
577 | 579 | |
578 | 580 | return $messages[$flag]; |
579 | 581 | } |
| 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 | + |
580 | 644 | } |