MediaWiki  REL1_19
RecentChange.php
Go to the documentation of this file.
00001 <?php
00002 
00045 class RecentChange {
00046         var $mAttribs = array(), $mExtra = array();
00047 
00051         var $mTitle = false;
00052 
00056         var $mMovedToTitle = false;
00057         var $numberofWatchingusers = 0 ; # Dummy to prevent error message in SpecialRecentchangeslinked
00058         var $notificationtimestamp;
00059 
00060         # Factory methods
00061 
00066         public static function newFromRow( $row ) {
00067                 $rc = new RecentChange;
00068                 $rc->loadFromRow( $row );
00069                 return $rc;
00070         }
00071 
00076         public static function newFromCurRow( $row ) {
00077                 $rc = new RecentChange;
00078                 $rc->loadFromCurRow( $row );
00079                 $rc->notificationtimestamp = false;
00080                 $rc->numberofWatchingusers = false;
00081                 return $rc;
00082         }
00083 
00090         public static function newFromId( $rcid ) {
00091                 $dbr = wfGetDB( DB_SLAVE );
00092                 $res = $dbr->select( 'recentchanges', '*', array( 'rc_id' => $rcid ), __METHOD__ );
00093                 if( $res && $dbr->numRows( $res ) > 0 ) {
00094                         $row = $dbr->fetchObject( $res );
00095                         return self::newFromRow( $row );
00096                 } else {
00097                         return null;
00098                 }
00099         }
00100 
00108         public static function newFromConds( $conds, $fname = __METHOD__ ) {
00109                 $dbr = wfGetDB( DB_SLAVE );
00110                 $res = $dbr->select(
00111                         'recentchanges',
00112                         '*',
00113                         $conds,
00114                         $fname
00115                 );
00116                 if( $res instanceof ResultWrapper && $res->numRows() > 0 ) {
00117                         $row = $res->fetchObject();
00118                         $res->free();
00119                         return self::newFromRow( $row );
00120                 }
00121                 return null;
00122         }
00123 
00124         # Accessors
00125 
00129         public function setAttribs( $attribs ) {
00130                 $this->mAttribs = $attribs;
00131         }
00132 
00136         public function setExtra( $extra ) {
00137                 $this->mExtra = $extra;
00138         }
00139 
00144         public function &getTitle() {
00145                 if( $this->mTitle === false ) {
00146                         $this->mTitle = Title::makeTitle( $this->mAttribs['rc_namespace'], $this->mAttribs['rc_title'] );
00147                         # Make sure the correct page ID is process cached
00148                         $this->mTitle->resetArticleID( $this->mAttribs['rc_cur_id'] );
00149                 }
00150                 return $this->mTitle;
00151         }
00152 
00156         public function getMovedToTitle() {
00157                 if( $this->mMovedToTitle === false ) {
00158                         $this->mMovedToTitle = Title::makeTitle( $this->mAttribs['rc_moved_to_ns'],
00159                                 $this->mAttribs['rc_moved_to_title'] );
00160                 }
00161                 return $this->mMovedToTitle;
00162         }
00163 
00168         public function save( $noudp = false ) {
00169                 global $wgLocalInterwiki, $wgPutIPinRC, $wgContLang;
00170 
00171                 $dbw = wfGetDB( DB_MASTER );
00172                 if( !is_array($this->mExtra) ) {
00173                         $this->mExtra = array();
00174                 }
00175                 $this->mExtra['lang'] = $wgLocalInterwiki;
00176 
00177                 if( !$wgPutIPinRC ) {
00178                         $this->mAttribs['rc_ip'] = '';
00179                 }
00180 
00181                 # If our database is strict about IP addresses, use NULL instead of an empty string
00182                 if( $dbw->strictIPs() and $this->mAttribs['rc_ip'] == '' ) {
00183                         unset( $this->mAttribs['rc_ip'] );
00184                 }
00185 
00186                 # Make sure summary is truncated (whole multibyte characters)
00187                 $this->mAttribs['rc_comment'] = $wgContLang->truncate( $this->mAttribs['rc_comment'], 255 );
00188 
00189                 # Fixup database timestamps
00190                 $this->mAttribs['rc_timestamp'] = $dbw->timestamp($this->mAttribs['rc_timestamp']);
00191                 $this->mAttribs['rc_cur_time'] = $dbw->timestamp($this->mAttribs['rc_cur_time']);
00192                 $this->mAttribs['rc_id'] = $dbw->nextSequenceValue( 'recentchanges_rc_id_seq' );
00193 
00194                 ## If we are using foreign keys, an entry of 0 for the page_id will fail, so use NULL
00195                 if( $dbw->cascadingDeletes() and $this->mAttribs['rc_cur_id']==0 ) {
00196                         unset( $this->mAttribs['rc_cur_id'] );
00197                 }
00198 
00199                 # Insert new row
00200                 $dbw->insert( 'recentchanges', $this->mAttribs, __METHOD__ );
00201 
00202                 # Set the ID
00203                 $this->mAttribs['rc_id'] = $dbw->insertId();
00204 
00205                 # Notify extensions
00206                 wfRunHooks( 'RecentChange_save', array( &$this ) );
00207 
00208                 # Notify external application via UDP
00209                 if ( !$noudp ) {
00210                         $this->notifyRC2UDP();
00211                 }
00212 
00213                 # E-mail notifications
00214                 global $wgUseEnotif, $wgShowUpdatedMarker, $wgUser;
00215                 if( $wgUseEnotif || $wgShowUpdatedMarker ) {
00216                         // Users
00217                         if( $this->mAttribs['rc_user'] ) {
00218                                 $editor = ($wgUser->getId() == $this->mAttribs['rc_user']) ?
00219                                         $wgUser : User::newFromID( $this->mAttribs['rc_user'] );
00220                         // Anons
00221                         } else {
00222                                 $editor = ($wgUser->getName() == $this->mAttribs['rc_user_text']) ?
00223                                         $wgUser : User::newFromName( $this->mAttribs['rc_user_text'], false );
00224                         }
00225                         $title = Title::makeTitle( $this->mAttribs['rc_namespace'], $this->mAttribs['rc_title'] );
00226 
00227                         # @todo FIXME: This would be better as an extension hook
00228                         $enotif = new EmailNotification();
00229                         $status = $enotif->notifyOnPageChange( $editor, $title,
00230                                 $this->mAttribs['rc_timestamp'],
00231                                 $this->mAttribs['rc_comment'],
00232                                 $this->mAttribs['rc_minor'],
00233                                 $this->mAttribs['rc_last_oldid'] );
00234                 }
00235         }
00236 
00237         public function notifyRC2UDP() {
00238                 global $wgRC2UDPAddress, $wgRC2UDPOmitBots;
00239                 # Notify external application via UDP
00240                 if( $wgRC2UDPAddress && ( !$this->mAttribs['rc_bot'] || !$wgRC2UDPOmitBots ) ) {
00241                         self::sendToUDP( $this->getIRCLine() );
00242                 }
00243         }
00244 
00254         public static function sendToUDP( $line, $address = '', $prefix = '', $port = '' ) {
00255                 global $wgRC2UDPAddress, $wgRC2UDPPrefix, $wgRC2UDPPort;
00256                 # Assume default for standard RC case
00257                 $address = $address ? $address : $wgRC2UDPAddress;
00258                 $prefix = $prefix ? $prefix : $wgRC2UDPPrefix;
00259                 $port = $port ? $port : $wgRC2UDPPort;
00260                 # Notify external application via UDP
00261                 if( $address ) {
00262                         $conn = socket_create( AF_INET, SOCK_DGRAM, SOL_UDP );
00263                         if( $conn ) {
00264                                 $line = $prefix . $line;
00265                                 wfDebug( __METHOD__ . ": sending UDP line: $line\n" );
00266                                 socket_sendto( $conn, $line, strlen($line), 0, $address, $port );
00267                                 socket_close( $conn );
00268                                 return true;
00269                         } else {
00270                                 wfDebug( __METHOD__ . ": failed to create UDP socket\n" );
00271                         }
00272                 }
00273                 return false;
00274         }
00275 
00281         public static function cleanupForIRC( $text ) {
00282                 return Sanitizer::decodeCharReferences( str_replace( array( "\n", "\r" ), array( "", "" ), $text ) );
00283         }
00284 
00292         public static function markPatrolled( $change, $auto = false ) {
00293                 global $wgUser;
00294 
00295                 $change = $change instanceof RecentChange
00296                         ? $change
00297                         : RecentChange::newFromId($change);
00298 
00299                 if( !$change instanceof RecentChange ) {
00300                         return null;
00301                 }
00302                 return $change->doMarkPatrolled( $wgUser, $auto );
00303         }
00304 
00313         public function doMarkPatrolled( User $user, $auto = false ) {
00314                 global $wgUseRCPatrol, $wgUseNPPatrol;
00315                 $errors = array();
00316                 // If recentchanges patrol is disabled, only new pages
00317                 // can be patrolled
00318                 if( !$wgUseRCPatrol && ( !$wgUseNPPatrol || $this->getAttribute('rc_type') != RC_NEW ) ) {
00319                         $errors[] = array('rcpatroldisabled');
00320                 }
00321                 // Automatic patrol needs "autopatrol", ordinary patrol needs "patrol"
00322                 $right = $auto ? 'autopatrol' : 'patrol';
00323                 $errors = array_merge( $errors, $this->getTitle()->getUserPermissionsErrors( $right, $user ) );
00324                 if( !wfRunHooks('MarkPatrolled', array($this->getAttribute('rc_id'), &$user, false)) ) {
00325                         $errors[] = array('hookaborted');
00326                 }
00327                 // Users without the 'autopatrol' right can't patrol their
00328                 // own revisions
00329                 if( $user->getName() == $this->getAttribute('rc_user_text') && !$user->isAllowed('autopatrol') ) {
00330                         $errors[] = array('markedaspatrollederror-noautopatrol');
00331                 }
00332                 if( $errors ) {
00333                         return $errors;
00334                 }
00335                 // If the change was patrolled already, do nothing
00336                 if( $this->getAttribute('rc_patrolled') ) {
00337                         return array();
00338                 }
00339                 // Actually set the 'patrolled' flag in RC
00340                 $this->reallyMarkPatrolled();
00341                 // Log this patrol event
00342                 PatrolLog::record( $this, $auto );
00343                 wfRunHooks( 'MarkPatrolledComplete', array($this->getAttribute('rc_id'), &$user, false) );
00344                 return array();
00345         }
00346 
00351         public function reallyMarkPatrolled() {
00352                 $dbw = wfGetDB( DB_MASTER );
00353                 $dbw->update(
00354                         'recentchanges',
00355                         array(
00356                                 'rc_patrolled' => 1
00357                         ),
00358                         array(
00359                                 'rc_id' => $this->getAttribute('rc_id')
00360                         ),
00361                         __METHOD__
00362                 );
00363                 return $dbw->affectedRows();
00364         }
00365 
00384         public static function notifyEdit( $timestamp, &$title, $minor, &$user, $comment, $oldId,
00385                 $lastTimestamp, $bot, $ip='', $oldSize=0, $newSize=0, $newId=0, $patrol=0 ) {
00386                 global $wgRequest;
00387                 if( !$ip ) {
00388                         $ip = $wgRequest->getIP();
00389                         if( !$ip ) $ip = '';
00390                 }
00391 
00392                 $rc = new RecentChange;
00393                 $rc->mAttribs = array(
00394                         'rc_timestamp'  => $timestamp,
00395                         'rc_cur_time'   => $timestamp,
00396                         'rc_namespace'  => $title->getNamespace(),
00397                         'rc_title'      => $title->getDBkey(),
00398                         'rc_type'       => RC_EDIT,
00399                         'rc_minor'      => $minor ? 1 : 0,
00400                         'rc_cur_id'     => $title->getArticleID(),
00401                         'rc_user'       => $user->getId(),
00402                         'rc_user_text'  => $user->getName(),
00403                         'rc_comment'    => $comment,
00404                         'rc_this_oldid' => $newId,
00405                         'rc_last_oldid' => $oldId,
00406                         'rc_bot'        => $bot ? 1 : 0,
00407                         'rc_moved_to_ns' => 0,
00408                         'rc_moved_to_title' => '',
00409                         'rc_ip'         => $ip,
00410                         'rc_patrolled'  => intval($patrol),
00411                         'rc_new'        => 0,  # obsolete
00412                         'rc_old_len'    => $oldSize,
00413                         'rc_new_len'    => $newSize,
00414                         'rc_deleted'    => 0,
00415                         'rc_logid'      => 0,
00416                         'rc_log_type'   => null,
00417                         'rc_log_action' => '',
00418                         'rc_params'     => ''
00419                 );
00420 
00421                 $rc->mExtra =  array(
00422                         'prefixedDBkey' => $title->getPrefixedDBkey(),
00423                         'lastTimestamp' => $lastTimestamp,
00424                         'oldSize'       => $oldSize,
00425                         'newSize'       => $newSize,
00426                 );
00427                 $rc->save();
00428                 return $rc;
00429         }
00430 
00448         public static function notifyNew( $timestamp, &$title, $minor, &$user, $comment, $bot,
00449                 $ip='', $size=0, $newId=0, $patrol=0 ) {
00450                 global $wgRequest;
00451                 if( !$ip ) {
00452                         $ip = $wgRequest->getIP();
00453                         if( !$ip ) {
00454                                 $ip = '';
00455                         }
00456                 }
00457 
00458                 $rc = new RecentChange;
00459                 $rc->mAttribs = array(
00460                         'rc_timestamp'      => $timestamp,
00461                         'rc_cur_time'       => $timestamp,
00462                         'rc_namespace'      => $title->getNamespace(),
00463                         'rc_title'          => $title->getDBkey(),
00464                         'rc_type'           => RC_NEW,
00465                         'rc_minor'          => $minor ? 1 : 0,
00466                         'rc_cur_id'         => $title->getArticleID(),
00467                         'rc_user'           => $user->getId(),
00468                         'rc_user_text'      => $user->getName(),
00469                         'rc_comment'        => $comment,
00470                         'rc_this_oldid'     => $newId,
00471                         'rc_last_oldid'     => 0,
00472                         'rc_bot'            => $bot ? 1 : 0,
00473                         'rc_moved_to_ns'    => 0,
00474                         'rc_moved_to_title' => '',
00475                         'rc_ip'             => $ip,
00476                         'rc_patrolled'      => intval($patrol),
00477                         'rc_new'            => 1, # obsolete
00478                         'rc_old_len'        => 0,
00479                         'rc_new_len'        => $size,
00480                         'rc_deleted'        => 0,
00481                         'rc_logid'          => 0,
00482                         'rc_log_type'       => null,
00483                         'rc_log_action'     => '',
00484                         'rc_params'         => ''
00485                 );
00486 
00487                 $rc->mExtra =  array(
00488                         'prefixedDBkey' => $title->getPrefixedDBkey(),
00489                         'lastTimestamp' => 0,
00490                         'oldSize' => 0,
00491                         'newSize' => $size
00492                 );
00493                 $rc->save();
00494                 return $rc;
00495         }
00496 
00511         public static function notifyLog( $timestamp, &$title, &$user, $actionComment, $ip='', $type,
00512                 $action, $target, $logComment, $params, $newId=0 )
00513         {
00514                 global $wgLogRestrictions;
00515                 # Don't add private logs to RC!
00516                 if( isset($wgLogRestrictions[$type]) && $wgLogRestrictions[$type] != '*' ) {
00517                         return false;
00518                 }
00519                 $rc = self::newLogEntry( $timestamp, $title, $user, $actionComment, $ip, $type, $action,
00520                         $target, $logComment, $params, $newId );
00521                 $rc->save();
00522                 return true;
00523         }
00524 
00539         public static function newLogEntry( $timestamp, &$title, &$user, $actionComment, $ip='',
00540                 $type, $action, $target, $logComment, $params, $newId=0 ) {
00541                 global $wgRequest;
00542                 if( !$ip ) {
00543                         $ip = $wgRequest->getIP();
00544                         if( !$ip ) {
00545                                 $ip = '';
00546                         }
00547                 }
00548 
00549                 $rc = new RecentChange;
00550                 $rc->mAttribs = array(
00551                         'rc_timestamp'  => $timestamp,
00552                         'rc_cur_time'   => $timestamp,
00553                         'rc_namespace'  => $target->getNamespace(),
00554                         'rc_title'      => $target->getDBkey(),
00555                         'rc_type'       => RC_LOG,
00556                         'rc_minor'      => 0,
00557                         'rc_cur_id'     => $target->getArticleID(),
00558                         'rc_user'       => $user->getId(),
00559                         'rc_user_text'  => $user->getName(),
00560                         'rc_comment'    => $logComment,
00561                         'rc_this_oldid' => 0,
00562                         'rc_last_oldid' => 0,
00563                         'rc_bot'        => $user->isAllowed( 'bot' ) ? $wgRequest->getBool( 'bot', true ) : 0,
00564                         'rc_moved_to_ns' => 0,
00565                         'rc_moved_to_title' => '',
00566                         'rc_ip'         => $ip,
00567                         'rc_patrolled'  => 1,
00568                         'rc_new'        => 0, # obsolete
00569                         'rc_old_len'    => null,
00570                         'rc_new_len'    => null,
00571                         'rc_deleted'    => 0,
00572                         'rc_logid'      => $newId,
00573                         'rc_log_type'   => $type,
00574                         'rc_log_action' => $action,
00575                         'rc_params'     => $params
00576                 );
00577                 $rc->mExtra =  array(
00578                         'prefixedDBkey' => $title->getPrefixedDBkey(),
00579                         'lastTimestamp' => 0,
00580                         'actionComment' => $actionComment, // the comment appended to the action, passed from LogPage
00581                 );
00582                 return $rc;
00583         }
00584 
00590         public function loadFromRow( $row ) {
00591                 $this->mAttribs = get_object_vars( $row );
00592                 $this->mAttribs['rc_timestamp'] = wfTimestamp(TS_MW, $this->mAttribs['rc_timestamp']);
00593                 $this->mAttribs['rc_deleted'] = $row->rc_deleted; // MUST be set
00594         }
00595 
00601         public function loadFromCurRow( $row ) {
00602                 $this->mAttribs = array(
00603                         'rc_timestamp' => wfTimestamp(TS_MW, $row->rev_timestamp),
00604                         'rc_cur_time' => $row->rev_timestamp,
00605                         'rc_user' => $row->rev_user,
00606                         'rc_user_text' => $row->rev_user_text,
00607                         'rc_namespace' => $row->page_namespace,
00608                         'rc_title' => $row->page_title,
00609                         'rc_comment' => $row->rev_comment,
00610                         'rc_minor' => $row->rev_minor_edit ? 1 : 0,
00611                         'rc_type' => $row->page_is_new ? RC_NEW : RC_EDIT,
00612                         'rc_cur_id' => $row->page_id,
00613                         'rc_this_oldid' => $row->rev_id,
00614                         'rc_last_oldid' => isset($row->rc_last_oldid) ? $row->rc_last_oldid : 0,
00615                         'rc_bot'        => 0,
00616                         'rc_moved_to_ns'        => 0,
00617                         'rc_moved_to_title'     => '',
00618                         'rc_ip' => '',
00619                         'rc_id' => $row->rc_id,
00620                         'rc_patrolled' => $row->rc_patrolled,
00621                         'rc_new' => $row->page_is_new, # obsolete
00622                         'rc_old_len' => $row->rc_old_len,
00623                         'rc_new_len' => $row->rc_new_len,
00624                         'rc_params' => isset($row->rc_params) ? $row->rc_params : '',
00625                         'rc_log_type' => isset($row->rc_log_type) ? $row->rc_log_type : null,
00626                         'rc_log_action' => isset($row->rc_log_action) ? $row->rc_log_action : null,
00627                         'rc_log_id' => isset($row->rc_log_id) ? $row->rc_log_id: 0,
00628                         'rc_deleted' => $row->rc_deleted // MUST be set
00629                 );
00630         }
00631 
00638         public function getAttribute( $name ) {
00639                 return isset( $this->mAttribs[$name] ) ? $this->mAttribs[$name] : null;
00640         }
00641 
00645         public function getAttributes() {
00646                 return $this->mAttribs;
00647         }
00648 
00655         public function diffLinkTrail( $forceCur ) {
00656                 if( $this->mAttribs['rc_type'] == RC_EDIT ) {
00657                         $trail = "curid=" . (int)($this->mAttribs['rc_cur_id']) .
00658                                 "&oldid=" . (int)($this->mAttribs['rc_last_oldid']);
00659                         if( $forceCur ) {
00660                                 $trail .= '&diff=0' ;
00661                         } else {
00662                                 $trail .= '&diff=' . (int)($this->mAttribs['rc_this_oldid']);
00663                         }
00664                 } else {
00665                         $trail = '';
00666                 }
00667                 return $trail;
00668         }
00669 
00673         public function getIRCLine() {
00674                 global $wgUseRCPatrol, $wgUseNPPatrol, $wgRC2UDPInterwikiPrefix, $wgLocalInterwiki,
00675                         $wgCanonicalServer, $wgScript;
00676 
00677                 if( $this->mAttribs['rc_type'] == RC_LOG ) {
00678                         $titleObj = Title::newFromText( 'Log/' . $this->mAttribs['rc_log_type'], NS_SPECIAL );
00679                 } else {
00680                         $titleObj =& $this->getTitle();
00681                 }
00682                 $title = $titleObj->getPrefixedText();
00683                 $title = self::cleanupForIRC( $title );
00684 
00685                 if( $this->mAttribs['rc_type'] == RC_LOG ) {
00686                         $url = '';
00687                 } else {
00688                         $url = $wgCanonicalServer . $wgScript;
00689                         if( $this->mAttribs['rc_type'] == RC_NEW ) {
00690                                 $query = '?oldid=' . $this->mAttribs['rc_this_oldid'];
00691                         } else {
00692                                 $query = '?diff=' . $this->mAttribs['rc_this_oldid'] . '&oldid=' . $this->mAttribs['rc_last_oldid'];
00693                         }
00694                         if ( $wgUseRCPatrol || ( $this->mAttribs['rc_type'] == RC_NEW && $wgUseNPPatrol ) ) {
00695                                 $query .= '&rcid=' . $this->mAttribs['rc_id'];
00696                         }
00697                         // HACK: We need this hook for WMF's secure server setup
00698                         wfRunHooks( 'IRCLineURL', array( &$url, &$query ) );
00699                         $url .= $query;
00700                 }
00701 
00702                 if( $this->mAttribs['rc_old_len'] !== null && $this->mAttribs['rc_new_len'] !== null ) {
00703                         $szdiff = $this->mAttribs['rc_new_len'] - $this->mAttribs['rc_old_len'];
00704                         if($szdiff < -500) {
00705                                 $szdiff = "\002$szdiff\002";
00706                         } elseif($szdiff >= 0) {
00707                                 $szdiff = '+' . $szdiff ;
00708                         }
00709                         $szdiff = '(' . $szdiff . ')' ;
00710                 } else {
00711                         $szdiff = '';
00712                 }
00713 
00714                 $user = self::cleanupForIRC( $this->mAttribs['rc_user_text'] );
00715 
00716                 if ( $this->mAttribs['rc_type'] == RC_LOG ) {
00717                         $targetText = $this->getTitle()->getPrefixedText();
00718                         $comment = self::cleanupForIRC( str_replace( "[[$targetText]]", "[[\00302$targetText\00310]]", $this->mExtra['actionComment'] ) );
00719                         $flag = $this->mAttribs['rc_log_action'];
00720                 } else {
00721                         $comment = self::cleanupForIRC( $this->mAttribs['rc_comment'] );
00722                         $flag = '';
00723                         if ( !$this->mAttribs['rc_patrolled'] && ( $wgUseRCPatrol || $this->mAttribs['rc_new'] && $wgUseNPPatrol ) ) {
00724                                 $flag .= '!';
00725                         }
00726                         $flag .= ( $this->mAttribs['rc_new'] ? "N" : "" ) . ( $this->mAttribs['rc_minor'] ? "M" : "" ) . ( $this->mAttribs['rc_bot'] ? "B" : "" );
00727                 }
00728 
00729                 if ( $wgRC2UDPInterwikiPrefix === true && $wgLocalInterwiki !== false ) {
00730                         $prefix = $wgLocalInterwiki;
00731                 } elseif ( $wgRC2UDPInterwikiPrefix ) {
00732                         $prefix = $wgRC2UDPInterwikiPrefix;
00733                 } else {
00734                         $prefix = false;
00735                 }
00736                 if ( $prefix !== false ) {
00737                         $titleString = "\00314[[\00303$prefix:\00307$title\00314]]";
00738                 } else {
00739                         $titleString = "\00314[[\00307$title\00314]]";
00740                 }
00741 
00742                 # see http://www.irssi.org/documentation/formats for some colour codes. prefix is \003,
00743                 # no colour (\003) switches back to the term default
00744                 $fullString = "$titleString\0034 $flag\00310 " .
00745                                           "\00302$url\003 \0035*\003 \00303$user\003 \0035*\003 $szdiff \00310$comment\003\n";
00746 
00747                 return $fullString;
00748         }
00749 
00757         public function getCharacterDifference( $old = 0, $new = 0 ) {
00758                 if( $old === 0 ) {
00759                         $old = $this->mAttribs['rc_old_len'];
00760                 }
00761                 if( $new === 0 ) {
00762                         $new = $this->mAttribs['rc_new_len'];
00763                 }
00764                 if( $old === null || $new === null ) {
00765                         return '';
00766                 }
00767                 return ChangesList::showCharacterDifference( $old, $new );
00768         }
00769 }