[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/includes/logging/ -> LogEntry.php (source)

   1  <?php
   2  /**
   3   * Contain classes for dealing with individual log entries
   4   *
   5   * This is how I see the log system history:
   6   * - appending to plain wiki pages
   7   * - formatting log entries based on database fields
   8   * - user is now part of the action message
   9   *
  10   * This program is free software; you can redistribute it and/or modify
  11   * it under the terms of the GNU General Public License as published by
  12   * the Free Software Foundation; either version 2 of the License, or
  13   * (at your option) any later version.
  14   *
  15   * This program is distributed in the hope that it will be useful,
  16   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18   * GNU General Public License for more details.
  19   *
  20   * You should have received a copy of the GNU General Public License along
  21   * with this program; if not, write to the Free Software Foundation, Inc.,
  22   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  23   * http://www.gnu.org/copyleft/gpl.html
  24   *
  25   * @file
  26   * @author Niklas Laxström
  27   * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
  28   * @since 1.19
  29   */
  30  
  31  /**
  32   * Interface for log entries. Every log entry has these methods.
  33   * @since 1.19
  34   */
  35  interface LogEntry {
  36      /**
  37       * The main log type.
  38       * @return string
  39       */
  40  	public function getType();
  41  
  42      /**
  43       * The log subtype.
  44       * @return string
  45       */
  46  	public function getSubtype();
  47  
  48      /**
  49       * The full logtype in format maintype/subtype.
  50       * @return string
  51       */
  52  	public function getFullType();
  53  
  54      /**
  55       * Get the extra parameters stored for this message.
  56       * @return array
  57       */
  58  	public function getParameters();
  59  
  60      /**
  61       * Get the user for performed this action.
  62       * @return User
  63       */
  64  	public function getPerformer();
  65  
  66      /**
  67       * Get the target page of this action.
  68       * @return Title
  69       */
  70  	public function getTarget();
  71  
  72      /**
  73       * Get the timestamp when the action was executed.
  74       * @return string
  75       */
  76  	public function getTimestamp();
  77  
  78      /**
  79       * Get the user provided comment.
  80       * @return string
  81       */
  82  	public function getComment();
  83  
  84      /**
  85       * Get the access restriction.
  86       * @return string
  87       */
  88  	public function getDeleted();
  89  
  90      /**
  91       * @param int $field One of LogPage::DELETED_* bitfield constants
  92       * @return bool
  93       */
  94  	public function isDeleted( $field );
  95  }
  96  
  97  /**
  98   * Extends the LogEntryInterface with some basic functionality
  99   * @since 1.19
 100   */
 101  abstract class LogEntryBase implements LogEntry {
 102  	public function getFullType() {
 103          return $this->getType() . '/' . $this->getSubtype();
 104      }
 105  
 106  	public function isDeleted( $field ) {
 107          return ( $this->getDeleted() & $field ) === $field;
 108      }
 109  
 110      /**
 111       * Whether the parameters for this log are stored in new or
 112       * old format.
 113       * @return bool
 114       */
 115  	public function isLegacy() {
 116          return false;
 117      }
 118  }
 119  
 120  /**
 121   * This class wraps around database result row.
 122   * @since 1.19
 123   */
 124  class DatabaseLogEntry extends LogEntryBase {
 125      // Static->
 126  
 127      /**
 128       * Returns array of information that is needed for querying
 129       * log entries. Array contains the following keys:
 130       * tables, fields, conds, options and join_conds
 131       * @return array
 132       */
 133  	public static function getSelectQueryData() {
 134          $tables = array( 'logging', 'user' );
 135          $fields = array(
 136              'log_id', 'log_type', 'log_action', 'log_timestamp',
 137              'log_user', 'log_user_text',
 138              'log_namespace', 'log_title', // unused log_page
 139              'log_comment', 'log_params', 'log_deleted',
 140              'user_id', 'user_name', 'user_editcount',
 141          );
 142  
 143          $joins = array(
 144              // IP's don't have an entry in user table
 145              'user' => array( 'LEFT JOIN', 'log_user=user_id' ),
 146          );
 147  
 148          return array(
 149              'tables' => $tables,
 150              'fields' => $fields,
 151              'conds' => array(),
 152              'options' => array(),
 153              'join_conds' => $joins,
 154          );
 155      }
 156  
 157      /**
 158       * Constructs new LogEntry from database result row.
 159       * Supports rows from both logging and recentchanges table.
 160       * @param stdClass|array $row
 161       * @return DatabaseLogEntry
 162       */
 163  	public static function newFromRow( $row ) {
 164          $row = (object)$row;
 165          if ( isset( $row->rc_logid ) ) {
 166              return new RCDatabaseLogEntry( $row );
 167          } else {
 168              return new self( $row );
 169          }
 170      }
 171  
 172      // Non-static->
 173  
 174      /** @var stdClass Database result row. */
 175      protected $row;
 176  
 177      /** @var User */
 178      protected $performer;
 179  
 180      /** @var bool Whether the parameters for this log entry are stored in new
 181       *    or old format.
 182       */
 183      protected $legacy;
 184  
 185  	protected function __construct( $row ) {
 186          $this->row = $row;
 187      }
 188  
 189      /**
 190       * Returns the unique database id.
 191       * @return int
 192       */
 193  	public function getId() {
 194          return (int)$this->row->log_id;
 195      }
 196  
 197      /**
 198       * Returns whatever is stored in the database field.
 199       * @return string
 200       */
 201  	protected function getRawParameters() {
 202          return $this->row->log_params;
 203      }
 204  
 205      // LogEntryBase->
 206  
 207  	public function isLegacy() {
 208          // This does the check
 209          $this->getParameters();
 210  
 211          return $this->legacy;
 212      }
 213  
 214      // LogEntry->
 215  
 216  	public function getType() {
 217          return $this->row->log_type;
 218      }
 219  
 220  	public function getSubtype() {
 221          return $this->row->log_action;
 222      }
 223  
 224  	public function getParameters() {
 225          if ( !isset( $this->params ) ) {
 226              $blob = $this->getRawParameters();
 227              wfSuppressWarnings();
 228              $params = unserialize( $blob );
 229              wfRestoreWarnings();
 230              if ( $params !== false ) {
 231                  $this->params = $params;
 232                  $this->legacy = false;
 233              } else {
 234                  $this->params = $blob === '' ? array() : explode( "\n", $blob );
 235                  $this->legacy = true;
 236              }
 237          }
 238  
 239          return $this->params;
 240      }
 241  
 242  	public function getPerformer() {
 243          if ( !$this->performer ) {
 244              $userId = (int)$this->row->log_user;
 245              if ( $userId !== 0 ) { // logged-in users
 246                  if ( isset( $this->row->user_name ) ) {
 247                      $this->performer = User::newFromRow( $this->row );
 248                  } else {
 249                      $this->performer = User::newFromId( $userId );
 250                  }
 251              } else { // IP users
 252                  $userText = $this->row->log_user_text;
 253                  $this->performer = User::newFromName( $userText, false );
 254              }
 255          }
 256  
 257          return $this->performer;
 258      }
 259  
 260  	public function getTarget() {
 261          $namespace = $this->row->log_namespace;
 262          $page = $this->row->log_title;
 263          $title = Title::makeTitle( $namespace, $page );
 264  
 265          return $title;
 266      }
 267  
 268  	public function getTimestamp() {
 269          return wfTimestamp( TS_MW, $this->row->log_timestamp );
 270      }
 271  
 272  	public function getComment() {
 273          return $this->row->log_comment;
 274      }
 275  
 276  	public function getDeleted() {
 277          return $this->row->log_deleted;
 278      }
 279  }
 280  
 281  class RCDatabaseLogEntry extends DatabaseLogEntry {
 282  
 283  	public function getId() {
 284          return $this->row->rc_logid;
 285      }
 286  
 287  	protected function getRawParameters() {
 288          return $this->row->rc_params;
 289      }
 290  
 291      // LogEntry->
 292  
 293  	public function getType() {
 294          return $this->row->rc_log_type;
 295      }
 296  
 297  	public function getSubtype() {
 298          return $this->row->rc_log_action;
 299      }
 300  
 301  	public function getPerformer() {
 302          if ( !$this->performer ) {
 303              $userId = (int)$this->row->rc_user;
 304              if ( $userId !== 0 ) {
 305                  $this->performer = User::newFromId( $userId );
 306              } else {
 307                  $userText = $this->row->rc_user_text;
 308                  // Might be an IP, don't validate the username
 309                  $this->performer = User::newFromName( $userText, false );
 310              }
 311          }
 312  
 313          return $this->performer;
 314      }
 315  
 316  	public function getTarget() {
 317          $namespace = $this->row->rc_namespace;
 318          $page = $this->row->rc_title;
 319          $title = Title::makeTitle( $namespace, $page );
 320  
 321          return $title;
 322      }
 323  
 324  	public function getTimestamp() {
 325          return wfTimestamp( TS_MW, $this->row->rc_timestamp );
 326      }
 327  
 328  	public function getComment() {
 329          return $this->row->rc_comment;
 330      }
 331  
 332  	public function getDeleted() {
 333          return $this->row->rc_deleted;
 334      }
 335  }
 336  
 337  /**
 338   * Class for creating log entries manually, for
 339   * example to inject them into the database.
 340   * @since 1.19
 341   */
 342  class ManualLogEntry extends LogEntryBase {
 343      /** @var string Type of log entry */
 344      protected $type;
 345  
 346      /** @var string Sub type of log entry */
 347      protected $subtype;
 348  
 349      /** @var array Parameters for log entry */
 350      protected $parameters = array();
 351  
 352      /** @var array */
 353      protected $relations = array();
 354  
 355      /** @var User Performer of the action for the log entry */
 356      protected $performer;
 357  
 358      /** @var Title Target title for the log entry */
 359      protected $target;
 360  
 361      /** @var string Timestamp of creation of the log entry */
 362      protected $timestamp;
 363  
 364      /** @var string Comment for the log entry */
 365      protected $comment = '';
 366  
 367      /** @var int Deletion state of the log entry */
 368      protected $deleted;
 369  
 370      /** @var int ID of the log entry */
 371      protected $id;
 372  
 373      /**
 374       * Constructor.
 375       *
 376       * @since 1.19
 377       *
 378       * @param string $type
 379       * @param string $subtype
 380       */
 381  	public function __construct( $type, $subtype ) {
 382          $this->type = $type;
 383          $this->subtype = $subtype;
 384      }
 385  
 386      /**
 387       * Set extra log parameters.
 388       * You can pass params to the log action message
 389       * by prefixing the keys with a number and colon.
 390       * The numbering should start with number 4, the
 391       * first three parameters are hardcoded for every
 392       * message. Example:
 393       * $entry->setParameters(
 394       *   '4:color' => 'blue',
 395       *   'animal' => 'dog'
 396       * );
 397       *
 398       * @since 1.19
 399       *
 400       * @param array $parameters Associative array
 401       */
 402  	public function setParameters( $parameters ) {
 403          $this->parameters = $parameters;
 404      }
 405  
 406      /**
 407       * Declare arbitrary tag/value relations to this log entry.
 408       * These can be used to filter log entries later on.
 409       *
 410       * @param array $relations Map of (tag => (list of values|value))
 411       * @since 1.22
 412       */
 413  	public function setRelations( array $relations ) {
 414          $this->relations = $relations;
 415      }
 416  
 417      /**
 418       * Set the user that performed the action being logged.
 419       *
 420       * @since 1.19
 421       *
 422       * @param User $performer
 423       */
 424  	public function setPerformer( User $performer ) {
 425          $this->performer = $performer;
 426      }
 427  
 428      /**
 429       * Set the title of the object changed.
 430       *
 431       * @since 1.19
 432       *
 433       * @param Title $target
 434       */
 435  	public function setTarget( Title $target ) {
 436          $this->target = $target;
 437      }
 438  
 439      /**
 440       * Set the timestamp of when the logged action took place.
 441       *
 442       * @since 1.19
 443       *
 444       * @param string $timestamp
 445       */
 446  	public function setTimestamp( $timestamp ) {
 447          $this->timestamp = $timestamp;
 448      }
 449  
 450      /**
 451       * Set a comment associated with the action being logged.
 452       *
 453       * @since 1.19
 454       *
 455       * @param string $comment
 456       */
 457  	public function setComment( $comment ) {
 458          $this->comment = $comment;
 459      }
 460  
 461      /**
 462       * TODO: document
 463       *
 464       * @since 1.19
 465       *
 466       * @param int $deleted
 467       */
 468  	public function setDeleted( $deleted ) {
 469          $this->deleted = $deleted;
 470      }
 471  
 472      /**
 473       * Inserts the entry into the logging table.
 474       * @param IDatabase $dbw
 475       * @return int ID of the log entry
 476       * @throws MWException
 477       */
 478  	public function insert( IDatabase $dbw = null ) {
 479          global $wgContLang;
 480  
 481          $dbw = $dbw ?: wfGetDB( DB_MASTER );
 482          $id = $dbw->nextSequenceValue( 'logging_log_id_seq' );
 483  
 484          if ( $this->timestamp === null ) {
 485              $this->timestamp = wfTimestampNow();
 486          }
 487  
 488          # Trim spaces on user supplied text
 489          $comment = trim( $this->getComment() );
 490  
 491          # Truncate for whole multibyte characters.
 492          $comment = $wgContLang->truncate( $comment, 255 );
 493  
 494          $data = array(
 495              'log_id' => $id,
 496              'log_type' => $this->getType(),
 497              'log_action' => $this->getSubtype(),
 498              'log_timestamp' => $dbw->timestamp( $this->getTimestamp() ),
 499              'log_user' => $this->getPerformer()->getId(),
 500              'log_user_text' => $this->getPerformer()->getName(),
 501              'log_namespace' => $this->getTarget()->getNamespace(),
 502              'log_title' => $this->getTarget()->getDBkey(),
 503              'log_page' => $this->getTarget()->getArticleID(),
 504              'log_comment' => $comment,
 505              'log_params' => serialize( (array)$this->getParameters() ),
 506          );
 507          if ( isset( $this->deleted ) ) {
 508              $data['log_deleted'] = $this->deleted;
 509          }
 510  
 511          $dbw->insert( 'logging', $data, __METHOD__ );
 512          $this->id = !is_null( $id ) ? $id : $dbw->insertId();
 513  
 514          $rows = array();
 515          foreach ( $this->relations as $tag => $values ) {
 516              if ( !strlen( $tag ) ) {
 517                  throw new MWException( "Got empty log search tag." );
 518              }
 519  
 520              if ( !is_array( $values ) ) {
 521                  $values = array( $values );
 522              }
 523  
 524              foreach ( $values as $value ) {
 525                  $rows[] = array(
 526                      'ls_field' => $tag,
 527                      'ls_value' => $value,
 528                      'ls_log_id' => $this->id
 529                  );
 530              }
 531          }
 532          if ( count( $rows ) ) {
 533              $dbw->insert( 'log_search', $rows, __METHOD__, 'IGNORE' );
 534          }
 535  
 536          // Update any bloom filter cache
 537          $member = $this->getTarget()->getNamespace() . ':' . $this->getTarget()->getDBkey();
 538          BloomCache::get( 'main' )->insert( wfWikiId(), 'TitleHasLogs', $member );
 539  
 540          return $this->id;
 541      }
 542  
 543      /**
 544       * Get a RecentChanges object for the log entry
 545       * @param int $newId
 546       * @return RecentChange
 547       * @since 1.23
 548       */
 549  	public function getRecentChange( $newId = 0 ) {
 550          $formatter = LogFormatter::newFromEntry( $this );
 551          $context = RequestContext::newExtraneousContext( $this->getTarget() );
 552          $formatter->setContext( $context );
 553  
 554          $logpage = SpecialPage::getTitleFor( 'Log', $this->getType() );
 555          $user = $this->getPerformer();
 556          $ip = "";
 557          if ( $user->isAnon() ) {
 558              /*
 559               * "MediaWiki default" and friends may have
 560               * no IP address in their name
 561               */
 562              if ( IP::isIPAddress( $user->getName() ) ) {
 563                  $ip = $user->getName();
 564              }
 565          }
 566  
 567          return RecentChange::newLogEntry(
 568              $this->getTimestamp(),
 569              $logpage,
 570              $user,
 571              $formatter->getPlainActionText(),
 572              $ip,
 573              $this->getType(),
 574              $this->getSubtype(),
 575              $this->getTarget(),
 576              $this->getComment(),
 577              serialize( (array)$this->getParameters() ),
 578              $newId,
 579              $formatter->getIRCActionComment() // Used for IRC feeds
 580          );
 581      }
 582  
 583      /**
 584       * Publishes the log entry.
 585       * @param int $newId Id of the log entry.
 586       * @param string $to One of: rcandudp (default), rc, udp
 587       */
 588  	public function publish( $newId, $to = 'rcandudp' ) {
 589          $log = new LogPage( $this->getType() );
 590          if ( $log->isRestricted() ) {
 591              return;
 592          }
 593  
 594          $rc = $this->getRecentChange( $newId );
 595  
 596          if ( $to === 'rc' || $to === 'rcandudp' ) {
 597              $rc->save( 'pleasedontudp' );
 598          }
 599  
 600          if ( $to === 'udp' || $to === 'rcandudp' ) {
 601              $rc->notifyRCFeeds();
 602          }
 603      }
 604  
 605      // LogEntry->
 606  
 607  	public function getType() {
 608          return $this->type;
 609      }
 610  
 611  	public function getSubtype() {
 612          return $this->subtype;
 613      }
 614  
 615  	public function getParameters() {
 616          return $this->parameters;
 617      }
 618  
 619      /**
 620       * @return User
 621       */
 622  	public function getPerformer() {
 623          return $this->performer;
 624      }
 625  
 626      /**
 627       * @return Title
 628       */
 629  	public function getTarget() {
 630          return $this->target;
 631      }
 632  
 633  	public function getTimestamp() {
 634          $ts = $this->timestamp !== null ? $this->timestamp : wfTimestampNow();
 635  
 636          return wfTimestamp( TS_MW, $ts );
 637      }
 638  
 639  	public function getComment() {
 640          return $this->comment;
 641      }
 642  
 643  	public function getDeleted() {
 644          return (int)$this->deleted;
 645      }
 646  }


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1