[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/includes/changes/ -> RecentChange.php (source)

   1  <?php
   2  /**
   3   * Utility class for creating and accessing recent change 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   */
  22  
  23  /**
  24   * Utility class for creating new RC entries
  25   *
  26   * mAttribs:
  27   *  rc_id           id of the row in the recentchanges table
  28   *  rc_timestamp    time the entry was made
  29   *  rc_namespace    namespace #
  30   *  rc_title        non-prefixed db key
  31   *  rc_type         is new entry, used to determine whether updating is necessary
  32   *  rc_source       string representation of change source
  33   *  rc_minor        is minor
  34   *  rc_cur_id       page_id of associated page entry
  35   *  rc_user         user id who made the entry
  36   *  rc_user_text    user name who made the entry
  37   *  rc_comment      edit summary
  38   *  rc_this_oldid   rev_id associated with this entry (or zero)
  39   *  rc_last_oldid   rev_id associated with the entry before this one (or zero)
  40   *  rc_bot          is bot, hidden
  41   *  rc_ip           IP address of the user in dotted quad notation
  42   *  rc_new          obsolete, use rc_type==RC_NEW
  43   *  rc_patrolled    boolean whether or not someone has marked this edit as patrolled
  44   *  rc_old_len      integer byte length of the text before the edit
  45   *  rc_new_len      the same after the edit
  46   *  rc_deleted      partial deletion
  47   *  rc_logid        the log_id value for this log entry (or zero)
  48   *  rc_log_type     the log type (or null)
  49   *  rc_log_action   the log action (or null)
  50   *  rc_params       log params
  51   *
  52   * mExtra:
  53   *  prefixedDBkey   prefixed db key, used by external app via msg queue
  54   *  lastTimestamp   timestamp of previous entry, used in WHERE clause during update
  55   *  oldSize         text size before the change
  56   *  newSize         text size after the change
  57   *  pageStatus      status of the page: created, deleted, moved, restored, changed
  58   *
  59   * temporary:       not stored in the database
  60   *      notificationtimestamp
  61   *      numberofWatchingusers
  62   */
  63  class RecentChange {
  64      // Constants for the rc_source field.  Extensions may also have
  65      // their own source constants.
  66      const SRC_EDIT = 'mw.edit';
  67      const SRC_NEW = 'mw.new';
  68      const SRC_LOG = 'mw.log';
  69      const SRC_EXTERNAL = 'mw.external'; // obsolete
  70  
  71      public $mAttribs = array();
  72      public $mExtra = array();
  73  
  74      /**
  75       * @var Title
  76       */
  77      public $mTitle = false;
  78  
  79      /**
  80       * @var User
  81       */
  82      private $mPerformer = false;
  83  
  84      public $numberofWatchingusers = 0; # Dummy to prevent error message in SpecialRecentChangesLinked
  85      public $notificationtimestamp;
  86  
  87      /**
  88       * @var int Line number of recent change. Default -1.
  89       */
  90      public $counter = -1;
  91  
  92      # Factory methods
  93  
  94      /**
  95       * @param mixed $row
  96       * @return RecentChange
  97       */
  98  	public static function newFromRow( $row ) {
  99          $rc = new RecentChange;
 100          $rc->loadFromRow( $row );
 101  
 102          return $rc;
 103      }
 104  
 105      /**
 106       * Parsing text to RC_* constants
 107       * @since 1.24
 108       * @param string|array $type
 109       * @throws MWException
 110       * @return int|array RC_TYPE
 111       */
 112  	public static function parseToRCType( $type ) {
 113          if ( is_array( $type ) ) {
 114              $retval = array();
 115              foreach ( $type as $t ) {
 116                  $retval[] = RecentChange::parseToRCType( $t );
 117              }
 118  
 119              return $retval;
 120          }
 121  
 122          switch ( $type ) {
 123              case 'edit':
 124                  return RC_EDIT;
 125              case 'new':
 126                  return RC_NEW;
 127              case 'log':
 128                  return RC_LOG;
 129              case 'external':
 130                  return RC_EXTERNAL;
 131              default:
 132                  throw new MWException( "Unknown type '$type'" );
 133          }
 134      }
 135  
 136      /**
 137       * Parsing RC_* constants to human-readable test
 138       * @since 1.24
 139       * @param int $rcType
 140       * @return string $type
 141       */
 142  	public static function parseFromRCType( $rcType ) {
 143          switch ( $rcType ) {
 144              case RC_EDIT:
 145                  $type = 'edit';
 146                  break;
 147              case RC_NEW:
 148                  $type = 'new';
 149                  break;
 150              case RC_LOG:
 151                  $type = 'log';
 152                  break;
 153              case RC_EXTERNAL:
 154                  $type = 'external';
 155                  break;
 156              default:
 157                  $type = "$rcType";
 158          }
 159  
 160          return $type;
 161      }
 162  
 163      /**
 164       * Obtain the recent change with a given rc_id value
 165       *
 166       * @param int $rcid The rc_id value to retrieve
 167       * @return RecentChange
 168       */
 169  	public static function newFromId( $rcid ) {
 170          return self::newFromConds( array( 'rc_id' => $rcid ), __METHOD__ );
 171      }
 172  
 173      /**
 174       * Find the first recent change matching some specific conditions
 175       *
 176       * @param array $conds Array of conditions
 177       * @param mixed $fname Override the method name in profiling/logs
 178       * @param array $options Query options
 179       * @return RecentChange
 180       */
 181  	public static function newFromConds( $conds, $fname = __METHOD__, $options = array() ) {
 182          $dbr = wfGetDB( DB_SLAVE );
 183          $row = $dbr->selectRow( 'recentchanges', self::selectFields(), $conds, $fname, $options );
 184          if ( $row !== false ) {
 185              return self::newFromRow( $row );
 186          } else {
 187              return null;
 188          }
 189      }
 190  
 191      /**
 192       * Return the list of recentchanges fields that should be selected to create
 193       * a new recentchanges object.
 194       * @return array
 195       */
 196  	public static function selectFields() {
 197          return array(
 198              'rc_id',
 199              'rc_timestamp',
 200              'rc_user',
 201              'rc_user_text',
 202              'rc_namespace',
 203              'rc_title',
 204              'rc_comment',
 205              'rc_minor',
 206              'rc_bot',
 207              'rc_new',
 208              'rc_cur_id',
 209              'rc_this_oldid',
 210              'rc_last_oldid',
 211              'rc_type',
 212              'rc_source',
 213              'rc_patrolled',
 214              'rc_ip',
 215              'rc_old_len',
 216              'rc_new_len',
 217              'rc_deleted',
 218              'rc_logid',
 219              'rc_log_type',
 220              'rc_log_action',
 221              'rc_params',
 222          );
 223      }
 224  
 225      # Accessors
 226  
 227      /**
 228       * @param array $attribs
 229       */
 230  	public function setAttribs( $attribs ) {
 231          $this->mAttribs = $attribs;
 232      }
 233  
 234      /**
 235       * @param array $extra
 236       */
 237  	public function setExtra( $extra ) {
 238          $this->mExtra = $extra;
 239      }
 240  
 241      /**
 242       * @return Title
 243       */
 244      public function &getTitle() {
 245          if ( $this->mTitle === false ) {
 246              $this->mTitle = Title::makeTitle( $this->mAttribs['rc_namespace'], $this->mAttribs['rc_title'] );
 247          }
 248  
 249          return $this->mTitle;
 250      }
 251  
 252      /**
 253       * Get the User object of the person who performed this change.
 254       *
 255       * @return User
 256       */
 257  	public function getPerformer() {
 258          if ( $this->mPerformer === false ) {
 259              if ( $this->mAttribs['rc_user'] ) {
 260                  $this->mPerformer = User::newFromID( $this->mAttribs['rc_user'] );
 261              } else {
 262                  $this->mPerformer = User::newFromName( $this->mAttribs['rc_user_text'], false );
 263              }
 264          }
 265  
 266          return $this->mPerformer;
 267      }
 268  
 269      /**
 270       * Writes the data in this object to the database
 271       * @param bool $noudp
 272       */
 273  	public function save( $noudp = false ) {
 274          global $wgPutIPinRC, $wgUseEnotif, $wgShowUpdatedMarker, $wgContLang;
 275  
 276          $dbw = wfGetDB( DB_MASTER );
 277          if ( !is_array( $this->mExtra ) ) {
 278              $this->mExtra = array();
 279          }
 280  
 281          if ( !$wgPutIPinRC ) {
 282              $this->mAttribs['rc_ip'] = '';
 283          }
 284  
 285          # If our database is strict about IP addresses, use NULL instead of an empty string
 286          if ( $dbw->strictIPs() and $this->mAttribs['rc_ip'] == '' ) {
 287              unset( $this->mAttribs['rc_ip'] );
 288          }
 289  
 290          # Trim spaces on user supplied text
 291          $this->mAttribs['rc_comment'] = trim( $this->mAttribs['rc_comment'] );
 292  
 293          # Make sure summary is truncated (whole multibyte characters)
 294          $this->mAttribs['rc_comment'] = $wgContLang->truncate( $this->mAttribs['rc_comment'], 255 );
 295  
 296          # Fixup database timestamps
 297          $this->mAttribs['rc_timestamp'] = $dbw->timestamp( $this->mAttribs['rc_timestamp'] );
 298          $this->mAttribs['rc_id'] = $dbw->nextSequenceValue( 'recentchanges_rc_id_seq' );
 299  
 300          ## If we are using foreign keys, an entry of 0 for the page_id will fail, so use NULL
 301          if ( $dbw->cascadingDeletes() and $this->mAttribs['rc_cur_id'] == 0 ) {
 302              unset( $this->mAttribs['rc_cur_id'] );
 303          }
 304  
 305          # Insert new row
 306          $dbw->insert( 'recentchanges', $this->mAttribs, __METHOD__ );
 307  
 308          # Set the ID
 309          $this->mAttribs['rc_id'] = $dbw->insertId();
 310  
 311          # Notify extensions
 312          wfRunHooks( 'RecentChange_save', array( &$this ) );
 313  
 314          # Notify external application via UDP
 315          if ( !$noudp ) {
 316              $this->notifyRCFeeds();
 317          }
 318  
 319          # E-mail notifications
 320          if ( $wgUseEnotif || $wgShowUpdatedMarker ) {
 321              $editor = $this->getPerformer();
 322              $title = $this->getTitle();
 323  
 324              if ( wfRunHooks( 'AbortEmailNotification', array( $editor, $title, $this ) ) ) {
 325                  # @todo FIXME: This would be better as an extension hook
 326                  $enotif = new EmailNotification();
 327                  $enotif->notifyOnPageChange( $editor, $title,
 328                      $this->mAttribs['rc_timestamp'],
 329                      $this->mAttribs['rc_comment'],
 330                      $this->mAttribs['rc_minor'],
 331                      $this->mAttribs['rc_last_oldid'],
 332                      $this->mExtra['pageStatus'] );
 333              }
 334          }
 335      }
 336  
 337      /**
 338       * Notify all the feeds about the change.
 339       * @param array $feeds Optional feeds to send to, defaults to $wgRCFeeds
 340       */
 341  	public function notifyRCFeeds( array $feeds = null ) {
 342          global $wgRCFeeds;
 343          if ( $feeds === null ) {
 344              $feeds = $wgRCFeeds;
 345          }
 346  
 347          $performer = $this->getPerformer();
 348  
 349          foreach ( $feeds as $feed ) {
 350              $feed += array(
 351                  'omit_bots' => false,
 352                  'omit_anon' => false,
 353                  'omit_user' => false,
 354                  'omit_minor' => false,
 355                  'omit_patrolled' => false,
 356              );
 357  
 358              if (
 359                  ( $feed['omit_bots'] && $this->mAttribs['rc_bot'] ) ||
 360                  ( $feed['omit_anon'] && $performer->isAnon() ) ||
 361                  ( $feed['omit_user'] && !$performer->isAnon() ) ||
 362                  ( $feed['omit_minor'] && $this->mAttribs['rc_minor'] ) ||
 363                  ( $feed['omit_patrolled'] && $this->mAttribs['rc_patrolled'] ) ||
 364                  $this->mAttribs['rc_type'] == RC_EXTERNAL
 365              ) {
 366                  continue;
 367              }
 368  
 369              $engine = self::getEngine( $feed['uri'] );
 370  
 371              if ( isset( $this->mExtra['actionCommentIRC'] ) ) {
 372                  $actionComment = $this->mExtra['actionCommentIRC'];
 373              } else {
 374                  $actionComment = null;
 375              }
 376  
 377              /** @var $formatter RCFeedFormatter */
 378              $formatter = is_object( $feed['formatter'] ) ? $feed['formatter'] : new $feed['formatter']();
 379              $line = $formatter->getLine( $feed, $this, $actionComment );
 380  
 381              $engine->send( $feed, $line );
 382          }
 383      }
 384  
 385      /**
 386       * Gets the stream engine object for a given URI from $wgRCEngines
 387       *
 388       * @param string $uri URI to get the engine object for
 389       * @throws MWException
 390       * @return RCFeedEngine The engine object
 391       */
 392  	public static function getEngine( $uri ) {
 393          global $wgRCEngines;
 394  
 395          $scheme = parse_url( $uri, PHP_URL_SCHEME );
 396          if ( !$scheme ) {
 397              throw new MWException( __FUNCTION__ . ": Invalid stream logger URI: '$uri'" );
 398          }
 399  
 400          if ( !isset( $wgRCEngines[$scheme] ) ) {
 401              throw new MWException( __FUNCTION__ . ": Unknown stream logger URI scheme: $scheme" );
 402          }
 403  
 404          return new $wgRCEngines[$scheme];
 405      }
 406  
 407      /**
 408       * Mark a given change as patrolled
 409       *
 410       * @param RecentChange|int $change RecentChange or corresponding rc_id
 411       * @param bool $auto For automatic patrol
 412       * @return array See doMarkPatrolled(), or null if $change is not an existing rc_id
 413       */
 414  	public static function markPatrolled( $change, $auto = false ) {
 415          global $wgUser;
 416  
 417          $change = $change instanceof RecentChange
 418              ? $change
 419              : RecentChange::newFromId( $change );
 420  
 421          if ( !$change instanceof RecentChange ) {
 422              return null;
 423          }
 424  
 425          return $change->doMarkPatrolled( $wgUser, $auto );
 426      }
 427  
 428      /**
 429       * Mark this RecentChange as patrolled
 430       *
 431       * NOTE: Can also return 'rcpatroldisabled', 'hookaborted' and
 432       * 'markedaspatrollederror-noautopatrol' as errors
 433       * @param User $user User object doing the action
 434       * @param bool $auto For automatic patrol
 435       * @return array Array of permissions errors, see Title::getUserPermissionsErrors()
 436       */
 437  	public function doMarkPatrolled( User $user, $auto = false ) {
 438          global $wgUseRCPatrol, $wgUseNPPatrol;
 439          $errors = array();
 440          // If recentchanges patrol is disabled, only new pages
 441          // can be patrolled
 442          if ( !$wgUseRCPatrol && ( !$wgUseNPPatrol || $this->getAttribute( 'rc_type' ) != RC_NEW ) ) {
 443              $errors[] = array( 'rcpatroldisabled' );
 444          }
 445          // Automatic patrol needs "autopatrol", ordinary patrol needs "patrol"
 446          $right = $auto ? 'autopatrol' : 'patrol';
 447          $errors = array_merge( $errors, $this->getTitle()->getUserPermissionsErrors( $right, $user ) );
 448          if ( !wfRunHooks( 'MarkPatrolled', array( $this->getAttribute( 'rc_id' ), &$user, false ) ) ) {
 449              $errors[] = array( 'hookaborted' );
 450          }
 451          // Users without the 'autopatrol' right can't patrol their
 452          // own revisions
 453          if ( $user->getName() == $this->getAttribute( 'rc_user_text' )
 454              && !$user->isAllowed( 'autopatrol' )
 455          ) {
 456              $errors[] = array( 'markedaspatrollederror-noautopatrol' );
 457          }
 458          if ( $errors ) {
 459              return $errors;
 460          }
 461          // If the change was patrolled already, do nothing
 462          if ( $this->getAttribute( 'rc_patrolled' ) ) {
 463              return array();
 464          }
 465          // Actually set the 'patrolled' flag in RC
 466          $this->reallyMarkPatrolled();
 467          // Log this patrol event
 468          PatrolLog::record( $this, $auto, $user );
 469          wfRunHooks( 'MarkPatrolledComplete', array( $this->getAttribute( 'rc_id' ), &$user, false ) );
 470  
 471          return array();
 472      }
 473  
 474      /**
 475       * Mark this RecentChange patrolled, without error checking
 476       * @return int Number of affected rows
 477       */
 478  	public function reallyMarkPatrolled() {
 479          $dbw = wfGetDB( DB_MASTER );
 480          $dbw->update(
 481              'recentchanges',
 482              array(
 483                  'rc_patrolled' => 1
 484              ),
 485              array(
 486                  'rc_id' => $this->getAttribute( 'rc_id' )
 487              ),
 488              __METHOD__
 489          );
 490          // Invalidate the page cache after the page has been patrolled
 491          // to make sure that the Patrol link isn't visible any longer!
 492          $this->getTitle()->invalidateCache();
 493  
 494          return $dbw->affectedRows();
 495      }
 496  
 497      /**
 498       * Makes an entry in the database corresponding to an edit
 499       *
 500       * @param string $timestamp
 501       * @param Title $title
 502       * @param bool $minor
 503       * @param User $user
 504       * @param string $comment
 505       * @param int $oldId
 506       * @param string $lastTimestamp
 507       * @param bool $bot
 508       * @param string $ip
 509       * @param int $oldSize
 510       * @param int $newSize
 511       * @param int $newId
 512       * @param int $patrol
 513       * @return RecentChange
 514       */
 515  	public static function notifyEdit( $timestamp, &$title, $minor, &$user, $comment, $oldId,
 516          $lastTimestamp, $bot, $ip = '', $oldSize = 0, $newSize = 0, $newId = 0, $patrol = 0 ) {
 517          $rc = new RecentChange;
 518          $rc->mTitle = $title;
 519          $rc->mPerformer = $user;
 520          $rc->mAttribs = array(
 521              'rc_timestamp' => $timestamp,
 522              'rc_namespace' => $title->getNamespace(),
 523              'rc_title' => $title->getDBkey(),
 524              'rc_type' => RC_EDIT,
 525              'rc_source' => self::SRC_EDIT,
 526              'rc_minor' => $minor ? 1 : 0,
 527              'rc_cur_id' => $title->getArticleID(),
 528              'rc_user' => $user->getId(),
 529              'rc_user_text' => $user->getName(),
 530              'rc_comment' => $comment,
 531              'rc_this_oldid' => $newId,
 532              'rc_last_oldid' => $oldId,
 533              'rc_bot' => $bot ? 1 : 0,
 534              'rc_ip' => self::checkIPAddress( $ip ),
 535              'rc_patrolled' => intval( $patrol ),
 536              'rc_new' => 0, # obsolete
 537              'rc_old_len' => $oldSize,
 538              'rc_new_len' => $newSize,
 539              'rc_deleted' => 0,
 540              'rc_logid' => 0,
 541              'rc_log_type' => null,
 542              'rc_log_action' => '',
 543              'rc_params' => ''
 544          );
 545  
 546          $rc->mExtra = array(
 547              'prefixedDBkey' => $title->getPrefixedDBkey(),
 548              'lastTimestamp' => $lastTimestamp,
 549              'oldSize' => $oldSize,
 550              'newSize' => $newSize,
 551              'pageStatus' => 'changed'
 552          );
 553          $rc->save();
 554  
 555          return $rc;
 556      }
 557  
 558      /**
 559       * Makes an entry in the database corresponding to page creation
 560       * Note: the title object must be loaded with the new id using resetArticleID()
 561       *
 562       * @param string $timestamp
 563       * @param Title $title
 564       * @param bool $minor
 565       * @param User $user
 566       * @param string $comment
 567       * @param bool $bot
 568       * @param string $ip
 569       * @param int $size
 570       * @param int $newId
 571       * @param int $patrol
 572       * @return RecentChange
 573       */
 574  	public static function notifyNew( $timestamp, &$title, $minor, &$user, $comment, $bot,
 575          $ip = '', $size = 0, $newId = 0, $patrol = 0 ) {
 576          $rc = new RecentChange;
 577          $rc->mTitle = $title;
 578          $rc->mPerformer = $user;
 579          $rc->mAttribs = array(
 580              'rc_timestamp' => $timestamp,
 581              'rc_namespace' => $title->getNamespace(),
 582              'rc_title' => $title->getDBkey(),
 583              'rc_type' => RC_NEW,
 584              'rc_source' => self::SRC_NEW,
 585              'rc_minor' => $minor ? 1 : 0,
 586              'rc_cur_id' => $title->getArticleID(),
 587              'rc_user' => $user->getId(),
 588              'rc_user_text' => $user->getName(),
 589              'rc_comment' => $comment,
 590              'rc_this_oldid' => $newId,
 591              'rc_last_oldid' => 0,
 592              'rc_bot' => $bot ? 1 : 0,
 593              'rc_ip' => self::checkIPAddress( $ip ),
 594              'rc_patrolled' => intval( $patrol ),
 595              'rc_new' => 1, # obsolete
 596              'rc_old_len' => 0,
 597              'rc_new_len' => $size,
 598              'rc_deleted' => 0,
 599              'rc_logid' => 0,
 600              'rc_log_type' => null,
 601              'rc_log_action' => '',
 602              'rc_params' => ''
 603          );
 604  
 605          $rc->mExtra = array(
 606              'prefixedDBkey' => $title->getPrefixedDBkey(),
 607              'lastTimestamp' => 0,
 608              'oldSize' => 0,
 609              'newSize' => $size,
 610              'pageStatus' => 'created'
 611          );
 612          $rc->save();
 613  
 614          return $rc;
 615      }
 616  
 617      /**
 618       * @param string $timestamp
 619       * @param Title $title
 620       * @param User $user
 621       * @param string $actionComment
 622       * @param string $ip
 623       * @param string $type
 624       * @param string $action
 625       * @param Title $target
 626       * @param string $logComment
 627       * @param string $params
 628       * @param int $newId
 629       * @param string $actionCommentIRC
 630       * @return bool
 631       */
 632  	public static function notifyLog( $timestamp, &$title, &$user, $actionComment, $ip, $type,
 633          $action, $target, $logComment, $params, $newId = 0, $actionCommentIRC = ''
 634      ) {
 635          global $wgLogRestrictions;
 636  
 637          # Don't add private logs to RC!
 638          if ( isset( $wgLogRestrictions[$type] ) && $wgLogRestrictions[$type] != '*' ) {
 639              return false;
 640          }
 641          $rc = self::newLogEntry( $timestamp, $title, $user, $actionComment, $ip, $type, $action,
 642              $target, $logComment, $params, $newId, $actionCommentIRC );
 643          $rc->save();
 644  
 645          return true;
 646      }
 647  
 648      /**
 649       * @param string $timestamp
 650       * @param Title $title
 651       * @param User $user
 652       * @param string $actionComment
 653       * @param string $ip
 654       * @param string $type
 655       * @param string $action
 656       * @param Title $target
 657       * @param string $logComment
 658       * @param string $params
 659       * @param int $newId
 660       * @param string $actionCommentIRC
 661       * @return RecentChange
 662       */
 663  	public static function newLogEntry( $timestamp, &$title, &$user, $actionComment, $ip,
 664          $type, $action, $target, $logComment, $params, $newId = 0, $actionCommentIRC = '' ) {
 665          global $wgRequest;
 666  
 667          ## Get pageStatus for email notification
 668          switch ( $type . '-' . $action ) {
 669              case 'delete-delete':
 670                  $pageStatus = 'deleted';
 671                  break;
 672              case 'move-move':
 673              case 'move-move_redir':
 674                  $pageStatus = 'moved';
 675                  break;
 676              case 'delete-restore':
 677                  $pageStatus = 'restored';
 678                  break;
 679              case 'upload-upload':
 680                  $pageStatus = 'created';
 681                  break;
 682              case 'upload-overwrite':
 683              default:
 684                  $pageStatus = 'changed';
 685                  break;
 686          }
 687  
 688          $rc = new RecentChange;
 689          $rc->mTitle = $target;
 690          $rc->mPerformer = $user;
 691          $rc->mAttribs = array(
 692              'rc_timestamp' => $timestamp,
 693              'rc_namespace' => $target->getNamespace(),
 694              'rc_title' => $target->getDBkey(),
 695              'rc_type' => RC_LOG,
 696              'rc_source' => self::SRC_LOG,
 697              'rc_minor' => 0,
 698              'rc_cur_id' => $target->getArticleID(),
 699              'rc_user' => $user->getId(),
 700              'rc_user_text' => $user->getName(),
 701              'rc_comment' => $logComment,
 702              'rc_this_oldid' => 0,
 703              'rc_last_oldid' => 0,
 704              'rc_bot' => $user->isAllowed( 'bot' ) ? $wgRequest->getBool( 'bot', true ) : 0,
 705              'rc_ip' => self::checkIPAddress( $ip ),
 706              'rc_patrolled' => 1,
 707              'rc_new' => 0, # obsolete
 708              'rc_old_len' => null,
 709              'rc_new_len' => null,
 710              'rc_deleted' => 0,
 711              'rc_logid' => $newId,
 712              'rc_log_type' => $type,
 713              'rc_log_action' => $action,
 714              'rc_params' => $params
 715          );
 716  
 717          $rc->mExtra = array(
 718              'prefixedDBkey' => $title->getPrefixedDBkey(),
 719              'lastTimestamp' => 0,
 720              'actionComment' => $actionComment, // the comment appended to the action, passed from LogPage
 721              'pageStatus' => $pageStatus,
 722              'actionCommentIRC' => $actionCommentIRC
 723          );
 724  
 725          return $rc;
 726      }
 727  
 728      /**
 729       * Initialises the members of this object from a mysql row object
 730       *
 731       * @param mixed $row
 732       */
 733  	public function loadFromRow( $row ) {
 734          $this->mAttribs = get_object_vars( $row );
 735          $this->mAttribs['rc_timestamp'] = wfTimestamp( TS_MW, $this->mAttribs['rc_timestamp'] );
 736          $this->mAttribs['rc_deleted'] = $row->rc_deleted; // MUST be set
 737      }
 738  
 739      /**
 740       * Get an attribute value
 741       *
 742       * @param string $name Attribute name
 743       * @return mixed
 744       */
 745  	public function getAttribute( $name ) {
 746          return isset( $this->mAttribs[$name] ) ? $this->mAttribs[$name] : null;
 747      }
 748  
 749      /**
 750       * @return array
 751       */
 752  	public function getAttributes() {
 753          return $this->mAttribs;
 754      }
 755  
 756      /**
 757       * Gets the end part of the diff URL associated with this object
 758       * Blank if no diff link should be displayed
 759       * @param bool $forceCur
 760       * @return string
 761       */
 762  	public function diffLinkTrail( $forceCur ) {
 763          if ( $this->mAttribs['rc_type'] == RC_EDIT ) {
 764              $trail = "curid=" . (int)( $this->mAttribs['rc_cur_id'] ) .
 765                  "&oldid=" . (int)( $this->mAttribs['rc_last_oldid'] );
 766              if ( $forceCur ) {
 767                  $trail .= '&diff=0';
 768              } else {
 769                  $trail .= '&diff=' . (int)( $this->mAttribs['rc_this_oldid'] );
 770              }
 771          } else {
 772              $trail = '';
 773          }
 774  
 775          return $trail;
 776      }
 777  
 778      /**
 779       * Returns the change size (HTML).
 780       * The lengths can be given optionally.
 781       * @param int $old
 782       * @param int $new
 783       * @return string
 784       */
 785  	public function getCharacterDifference( $old = 0, $new = 0 ) {
 786          if ( $old === 0 ) {
 787              $old = $this->mAttribs['rc_old_len'];
 788          }
 789          if ( $new === 0 ) {
 790              $new = $this->mAttribs['rc_new_len'];
 791          }
 792          if ( $old === null || $new === null ) {
 793              return '';
 794          }
 795  
 796          return ChangesList::showCharacterDifference( $old, $new );
 797      }
 798  
 799      /**
 800       * Purge expired changes from the recentchanges table
 801       * @since 1.22
 802       */
 803  	public static function purgeExpiredChanges() {
 804          if ( wfReadOnly() ) {
 805              return;
 806          }
 807  
 808          $method = __METHOD__;
 809          $dbw = wfGetDB( DB_MASTER );
 810          $dbw->onTransactionIdle( function () use ( $dbw, $method ) {
 811              global $wgRCMaxAge;
 812  
 813              $cutoff = $dbw->timestamp( time() - $wgRCMaxAge );
 814              $dbw->delete(
 815                  'recentchanges',
 816                  array( 'rc_timestamp < ' . $dbw->addQuotes( $cutoff ) ),
 817                  $method
 818              );
 819          } );
 820      }
 821  
 822  	private static function checkIPAddress( $ip ) {
 823          global $wgRequest;
 824          if ( $ip ) {
 825              if ( !IP::isIPAddress( $ip ) ) {
 826                  throw new MWException( "Attempt to write \"" . $ip .
 827                      "\" as an IP address into recent changes" );
 828              }
 829          } else {
 830              $ip = $wgRequest->getIP();
 831              if ( !$ip ) {
 832                  $ip = '';
 833              }
 834          }
 835  
 836          return $ip;
 837      }
 838  
 839      /**
 840       * Check whether the given timestamp is new enough to have a RC row with a given tolerance
 841       * as the recentchanges table might not be cleared out regularly (so older entries might exist)
 842       * or rows which will be deleted soon shouldn't be included.
 843       *
 844       * @param mixed $timestamp MWTimestamp compatible timestamp
 845       * @param int $tolerance Tolerance in seconds
 846       * @return bool
 847       */
 848  	public static function isInRCLifespan( $timestamp, $tolerance = 0 ) {
 849          global $wgRCMaxAge;
 850  
 851          return wfTimestamp( TS_UNIX, $timestamp ) > time() - $tolerance - $wgRCMaxAge;
 852      }
 853  }


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