MediaWiki  REL1_24
LogEntry.php
Go to the documentation of this file.
00001 <?php
00035 interface LogEntry {
00040     public function getType();
00041 
00046     public function getSubtype();
00047 
00052     public function getFullType();
00053 
00058     public function getParameters();
00059 
00064     public function getPerformer();
00065 
00070     public function getTarget();
00071 
00076     public function getTimestamp();
00077 
00082     public function getComment();
00083 
00088     public function getDeleted();
00089 
00094     public function isDeleted( $field );
00095 }
00096 
00101 abstract class LogEntryBase implements LogEntry {
00102     public function getFullType() {
00103         return $this->getType() . '/' . $this->getSubtype();
00104     }
00105 
00106     public function isDeleted( $field ) {
00107         return ( $this->getDeleted() & $field ) === $field;
00108     }
00109 
00115     public function isLegacy() {
00116         return false;
00117     }
00118 }
00119 
00124 class DatabaseLogEntry extends LogEntryBase {
00125     // Static->
00126 
00133     public static function getSelectQueryData() {
00134         $tables = array( 'logging', 'user' );
00135         $fields = array(
00136             'log_id', 'log_type', 'log_action', 'log_timestamp',
00137             'log_user', 'log_user_text',
00138             'log_namespace', 'log_title', // unused log_page
00139             'log_comment', 'log_params', 'log_deleted',
00140             'user_id', 'user_name', 'user_editcount',
00141         );
00142 
00143         $joins = array(
00144             // IP's don't have an entry in user table
00145             'user' => array( 'LEFT JOIN', 'log_user=user_id' ),
00146         );
00147 
00148         return array(
00149             'tables' => $tables,
00150             'fields' => $fields,
00151             'conds' => array(),
00152             'options' => array(),
00153             'join_conds' => $joins,
00154         );
00155     }
00156 
00163     public static function newFromRow( $row ) {
00164         $row = (object)$row;
00165         if ( isset( $row->rc_logid ) ) {
00166             return new RCDatabaseLogEntry( $row );
00167         } else {
00168             return new self( $row );
00169         }
00170     }
00171 
00172     // Non-static->
00173 
00175     protected $row;
00176 
00178     protected $performer;
00179 
00183     protected $legacy;
00184 
00185     protected function __construct( $row ) {
00186         $this->row = $row;
00187     }
00188 
00193     public function getId() {
00194         return (int)$this->row->log_id;
00195     }
00196 
00201     protected function getRawParameters() {
00202         return $this->row->log_params;
00203     }
00204 
00205     // LogEntryBase->
00206 
00207     public function isLegacy() {
00208         // This does the check
00209         $this->getParameters();
00210 
00211         return $this->legacy;
00212     }
00213 
00214     // LogEntry->
00215 
00216     public function getType() {
00217         return $this->row->log_type;
00218     }
00219 
00220     public function getSubtype() {
00221         return $this->row->log_action;
00222     }
00223 
00224     public function getParameters() {
00225         if ( !isset( $this->params ) ) {
00226             $blob = $this->getRawParameters();
00227             wfSuppressWarnings();
00228             $params = unserialize( $blob );
00229             wfRestoreWarnings();
00230             if ( $params !== false ) {
00231                 $this->params = $params;
00232                 $this->legacy = false;
00233             } else {
00234                 $this->params = $blob === '' ? array() : explode( "\n", $blob );
00235                 $this->legacy = true;
00236             }
00237         }
00238 
00239         return $this->params;
00240     }
00241 
00242     public function getPerformer() {
00243         if ( !$this->performer ) {
00244             $userId = (int)$this->row->log_user;
00245             if ( $userId !== 0 ) { // logged-in users
00246                 if ( isset( $this->row->user_name ) ) {
00247                     $this->performer = User::newFromRow( $this->row );
00248                 } else {
00249                     $this->performer = User::newFromId( $userId );
00250                 }
00251             } else { // IP users
00252                 $userText = $this->row->log_user_text;
00253                 $this->performer = User::newFromName( $userText, false );
00254             }
00255         }
00256 
00257         return $this->performer;
00258     }
00259 
00260     public function getTarget() {
00261         $namespace = $this->row->log_namespace;
00262         $page = $this->row->log_title;
00263         $title = Title::makeTitle( $namespace, $page );
00264 
00265         return $title;
00266     }
00267 
00268     public function getTimestamp() {
00269         return wfTimestamp( TS_MW, $this->row->log_timestamp );
00270     }
00271 
00272     public function getComment() {
00273         return $this->row->log_comment;
00274     }
00275 
00276     public function getDeleted() {
00277         return $this->row->log_deleted;
00278     }
00279 }
00280 
00281 class RCDatabaseLogEntry extends DatabaseLogEntry {
00282 
00283     public function getId() {
00284         return $this->row->rc_logid;
00285     }
00286 
00287     protected function getRawParameters() {
00288         return $this->row->rc_params;
00289     }
00290 
00291     // LogEntry->
00292 
00293     public function getType() {
00294         return $this->row->rc_log_type;
00295     }
00296 
00297     public function getSubtype() {
00298         return $this->row->rc_log_action;
00299     }
00300 
00301     public function getPerformer() {
00302         if ( !$this->performer ) {
00303             $userId = (int)$this->row->rc_user;
00304             if ( $userId !== 0 ) {
00305                 $this->performer = User::newFromId( $userId );
00306             } else {
00307                 $userText = $this->row->rc_user_text;
00308                 // Might be an IP, don't validate the username
00309                 $this->performer = User::newFromName( $userText, false );
00310             }
00311         }
00312 
00313         return $this->performer;
00314     }
00315 
00316     public function getTarget() {
00317         $namespace = $this->row->rc_namespace;
00318         $page = $this->row->rc_title;
00319         $title = Title::makeTitle( $namespace, $page );
00320 
00321         return $title;
00322     }
00323 
00324     public function getTimestamp() {
00325         return wfTimestamp( TS_MW, $this->row->rc_timestamp );
00326     }
00327 
00328     public function getComment() {
00329         return $this->row->rc_comment;
00330     }
00331 
00332     public function getDeleted() {
00333         return $this->row->rc_deleted;
00334     }
00335 }
00336 
00342 class ManualLogEntry extends LogEntryBase {
00344     protected $type;
00345 
00347     protected $subtype;
00348 
00350     protected $parameters = array();
00351 
00353     protected $relations = array();
00354 
00356     protected $performer;
00357 
00359     protected $target;
00360 
00362     protected $timestamp;
00363 
00365     protected $comment = '';
00366 
00368     protected $deleted;
00369 
00371     protected $id;
00372 
00381     public function __construct( $type, $subtype ) {
00382         $this->type = $type;
00383         $this->subtype = $subtype;
00384     }
00385 
00402     public function setParameters( $parameters ) {
00403         $this->parameters = $parameters;
00404     }
00405 
00413     public function setRelations( array $relations ) {
00414         $this->relations = $relations;
00415     }
00416 
00424     public function setPerformer( User $performer ) {
00425         $this->performer = $performer;
00426     }
00427 
00435     public function setTarget( Title $target ) {
00436         $this->target = $target;
00437     }
00438 
00446     public function setTimestamp( $timestamp ) {
00447         $this->timestamp = $timestamp;
00448     }
00449 
00457     public function setComment( $comment ) {
00458         $this->comment = $comment;
00459     }
00460 
00468     public function setDeleted( $deleted ) {
00469         $this->deleted = $deleted;
00470     }
00471 
00478     public function insert( IDatabase $dbw = null ) {
00479         global $wgContLang;
00480 
00481         $dbw = $dbw ?: wfGetDB( DB_MASTER );
00482         $id = $dbw->nextSequenceValue( 'logging_log_id_seq' );
00483 
00484         if ( $this->timestamp === null ) {
00485             $this->timestamp = wfTimestampNow();
00486         }
00487 
00488         # Trim spaces on user supplied text
00489         $comment = trim( $this->getComment() );
00490 
00491         # Truncate for whole multibyte characters.
00492         $comment = $wgContLang->truncate( $comment, 255 );
00493 
00494         $data = array(
00495             'log_id' => $id,
00496             'log_type' => $this->getType(),
00497             'log_action' => $this->getSubtype(),
00498             'log_timestamp' => $dbw->timestamp( $this->getTimestamp() ),
00499             'log_user' => $this->getPerformer()->getId(),
00500             'log_user_text' => $this->getPerformer()->getName(),
00501             'log_namespace' => $this->getTarget()->getNamespace(),
00502             'log_title' => $this->getTarget()->getDBkey(),
00503             'log_page' => $this->getTarget()->getArticleID(),
00504             'log_comment' => $comment,
00505             'log_params' => serialize( (array)$this->getParameters() ),
00506         );
00507         if ( isset( $this->deleted ) ) {
00508             $data['log_deleted'] = $this->deleted;
00509         }
00510 
00511         $dbw->insert( 'logging', $data, __METHOD__ );
00512         $this->id = !is_null( $id ) ? $id : $dbw->insertId();
00513 
00514         $rows = array();
00515         foreach ( $this->relations as $tag => $values ) {
00516             if ( !strlen( $tag ) ) {
00517                 throw new MWException( "Got empty log search tag." );
00518             }
00519 
00520             if ( !is_array( $values ) ) {
00521                 $values = array( $values );
00522             }
00523 
00524             foreach ( $values as $value ) {
00525                 $rows[] = array(
00526                     'ls_field' => $tag,
00527                     'ls_value' => $value,
00528                     'ls_log_id' => $this->id
00529                 );
00530             }
00531         }
00532         if ( count( $rows ) ) {
00533             $dbw->insert( 'log_search', $rows, __METHOD__, 'IGNORE' );
00534         }
00535 
00536         // Update any bloom filter cache
00537         $member = $this->getTarget()->getNamespace() . ':' . $this->getTarget()->getDBkey();
00538         BloomCache::get( 'main' )->insert( wfWikiId(), 'TitleHasLogs', $member );
00539 
00540         return $this->id;
00541     }
00542 
00549     public function getRecentChange( $newId = 0 ) {
00550         $formatter = LogFormatter::newFromEntry( $this );
00551         $context = RequestContext::newExtraneousContext( $this->getTarget() );
00552         $formatter->setContext( $context );
00553 
00554         $logpage = SpecialPage::getTitleFor( 'Log', $this->getType() );
00555         $user = $this->getPerformer();
00556         $ip = "";
00557         if ( $user->isAnon() ) {
00558             /*
00559              * "MediaWiki default" and friends may have
00560              * no IP address in their name
00561              */
00562             if ( IP::isIPAddress( $user->getName() ) ) {
00563                 $ip = $user->getName();
00564             }
00565         }
00566 
00567         return RecentChange::newLogEntry(
00568             $this->getTimestamp(),
00569             $logpage,
00570             $user,
00571             $formatter->getPlainActionText(),
00572             $ip,
00573             $this->getType(),
00574             $this->getSubtype(),
00575             $this->getTarget(),
00576             $this->getComment(),
00577             serialize( (array)$this->getParameters() ),
00578             $newId,
00579             $formatter->getIRCActionComment() // Used for IRC feeds
00580         );
00581     }
00582 
00588     public function publish( $newId, $to = 'rcandudp' ) {
00589         $log = new LogPage( $this->getType() );
00590         if ( $log->isRestricted() ) {
00591             return;
00592         }
00593 
00594         $rc = $this->getRecentChange( $newId );
00595 
00596         if ( $to === 'rc' || $to === 'rcandudp' ) {
00597             $rc->save( 'pleasedontudp' );
00598         }
00599 
00600         if ( $to === 'udp' || $to === 'rcandudp' ) {
00601             $rc->notifyRCFeeds();
00602         }
00603     }
00604 
00605     // LogEntry->
00606 
00607     public function getType() {
00608         return $this->type;
00609     }
00610 
00611     public function getSubtype() {
00612         return $this->subtype;
00613     }
00614 
00615     public function getParameters() {
00616         return $this->parameters;
00617     }
00618 
00622     public function getPerformer() {
00623         return $this->performer;
00624     }
00625 
00629     public function getTarget() {
00630         return $this->target;
00631     }
00632 
00633     public function getTimestamp() {
00634         $ts = $this->timestamp !== null ? $this->timestamp : wfTimestampNow();
00635 
00636         return wfTimestamp( TS_MW, $ts );
00637     }
00638 
00639     public function getComment() {
00640         return $this->comment;
00641     }
00642 
00643     public function getDeleted() {
00644         return (int)$this->deleted;
00645     }
00646 }