X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FChangesList.php;h=8b8fd50f0c3e65526c729adb369cec0ddd4d9dc8;hb=a35b7d2a5e5e695d54ef6cacd9194a35e502c048;hp=39b94a1fe9c8021ab5d89e1ced6e073d6206d732;hpb=1ac6514e6d4a1f99ca2649a49addc4ca8bcb2099;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/ChangesList.php b/includes/ChangesList.php index 39b94a1fe9..8b8fd50f0c 100644 --- a/includes/ChangesList.php +++ b/includes/ChangesList.php @@ -27,7 +27,10 @@ class ChangesList { # Called by history lists and recent changes # - /** @todo document */ + /** + * Changeslist contructor + * @param Skin $skin + */ function __construct( &$skin ) { $this->skin =& $skin; $this->preCacheMessages(); @@ -54,12 +57,12 @@ class ChangesList { * As we use the same small set of messages in various methods and that * they are called often, we call them once and save them in $this->message */ - function preCacheMessages() { + private function preCacheMessages() { // Precache various messages if( !isset( $this->message ) ) { foreach( explode(' ', 'cur diff hist minoreditletter newpageletter last '. 'blocklink history boteditletter semicolon-separator' ) as $msg ) { - $this->message[$msg] = wfMsgExt( $msg, array( 'escape') ); + $this->message[$msg] = wfMsgExt( $msg, array( 'escapenoentities' ) ); } } } @@ -67,21 +70,49 @@ class ChangesList { /** * Returns the appropriate flags for new page, minor change and patrolling + * @param bool $new + * @param bool $minor + * @param bool $patrolled + * @param string $nothing, string to use for empty space + * @param bool $bot + * @param bool $newbie + * @return string */ - function recentChangesFlags( $new, $minor, $patrolled, $nothing = ' ', $bot = false ) { + protected function recentChangesFlags( $new, $minor, $patrolled, $nothing = ' ', $bot = false, $newbie = false ) { $f = $new ? '' . $this->message['newpageletter'] . '' : $nothing; $f .= $minor ? '' . $this->message['minoreditletter'] . '' : $nothing; $f .= $bot ? '' . $this->message['boteditletter'] . '' : $nothing; $f .= $patrolled ? '!' : $nothing; - return "$f"; + $f .= $newbie ? '*' : $nothing; + return $f; + } + + protected static function userIsNew( $attribs ) { + global $wgAutoConfirmCount, $wgAutoConfirmAge; + if( !array_key_exists('user_editcount',$attribs) || !array_key_exists('user_registration',$attribs) ) { + return false; // missing input! + } + static $time; + $time = time(); + $edits = $attribs['user_editcount']; + $age = $attribs['user_registration']; + if( $wgAutoConfirmCount && !$edits || $wgAutoConfirmAge && !$age ) { + return true; + } else if( $wgAutoConfirmCount && $edits < $wgAutoConfirmCount ) { + return true; + } else if( $wgAutoConfirmAge && ($time - wfTimestampOrNull(TS_UNIX,$age)) < $wgAutoConfirmAge ) { + return true; + } + return false; } /** * Returns text for the start of the tabular part of RC + * @return string */ - function beginRecentChangesList() { + public function beginRecentChangesList() { $this->rc_cache = array(); $this->rcMoveIndex = 0; $this->rcCacheIndex = 0; @@ -92,8 +123,9 @@ class ChangesList { /** * Returns text for the end of RC + * @return string */ - function endRecentChangesList() { + public function endRecentChangesList() { if( $this->rclistOpen ) { return "\n"; } else { @@ -101,34 +133,7 @@ class ChangesList { } } - /** - * int $field one of DELETED_* bitfield constants - * @return bool - */ - function isDeleted( $rc, $field ) { - return ($rc->mAttribs['rc_deleted'] & $field) == $field; - } - - /** - * Determine if the current user is allowed to view a particular - * field of this revision, if it's marked as deleted. - * @param int $field - * @return bool - */ - function userCan( $rc, $field ) { - if( ( $rc->mAttribs['rc_deleted'] & $field ) == $field ) { - global $wgUser; - $permission = ( $rc->mAttribs['rc_deleted'] & Revision::DELETED_RESTRICTED ) == Revision::DELETED_RESTRICTED - ? 'hiderevision' - : 'deleterevision'; - wfDebug( "Checking for $permission due to $field match on $rc->mAttribs['rc_deleted']\n" ); - return $wgUser->isAllowed( $permission ); - } else { - return true; - } - } - - function insertMove( &$s, $rc ) { + protected function insertMove( &$s, $rc ) { # Diff $s .= '(' . $this->message['diff'] . ') ('; # Hist @@ -141,12 +146,11 @@ class ChangesList { $this->skin->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) ); } - function insertDateHeader(&$s, $rc_timestamp) { + protected function insertDateHeader(&$s, $rc_timestamp) { global $wgLang; # Make date header if necessary $date = $wgLang->date( $rc_timestamp, true, true ); - $s = ''; if( $date != $this->lastdate ) { if( '' != $this->lastdate ) { $s .= "\n"; @@ -157,12 +161,12 @@ class ChangesList { } } - function insertLog(&$s, $title, $logtype) { + protected function insertLog(&$s, $title, $logtype) { $logname = LogPage::logName( $logtype ); $s .= '(' . $this->skin->makeKnownLinkObj($title, $logname ) . ')'; } - function insertDiffHist(&$s, &$rc, $unpatrolled) { + protected function insertDiffHist(&$s, &$rc, $unpatrolled) { # Diff link if( !$this->userCan($rc,Revision::DELETED_TEXT) ) { $diffLink = $this->message['diff']; @@ -190,7 +194,7 @@ class ChangesList { $s .= ') . . '; } - function insertArticleLink(&$s, &$rc, $unpatrolled, $watched) { + protected function insertArticleLink(&$s, &$rc, $unpatrolled, $watched) { # Article link # If it's a new article, there is no diff link, but if it hasn't been # patrolled yet, we need to give users a way to do so @@ -210,20 +214,20 @@ class ChangesList { wfRunHooks('ChangesListInsertArticleLink', array(&$this, &$articlelink, &$s, &$rc, $unpatrolled, $watched)); - + $s .= ' '.$articlelink; } - function insertTimestamp(&$s, $rc) { + protected function insertTimestamp(&$s, $rc) { global $wgLang; # Timestamp - $s .= $this->message['semicolon-separator'] . ' ' . $wgLang->time( $rc->mAttribs['rc_timestamp'], true, true ) . ' . . '; + $s .= $this->message['semicolon-separator'] . $wgLang->time( $rc->mAttribs['rc_timestamp'], true, true ) . ' . . '; } /** Insert links to user page, user talk page and eventually a blocking link */ - function insertUserRelatedLinks(&$s, &$rc) { + public function insertUserRelatedLinks(&$s, &$rc) { if ( $this->isDeleted($rc,Revision::DELETED_USER) ) { - $s .= ' ' . wfMsgHtml('rev-deleted-user') . ''; + $s .= ' ' . wfMsgHtml('rev-deleted-user') . ''; } else { $s .= $this->skin->userLink( $rc->mAttribs['rc_user'], $rc->mAttribs['rc_user_text'] ); $s .= $this->skin->userToolLinks( $rc->mAttribs['rc_user'], $rc->mAttribs['rc_user_text'] ); @@ -231,21 +235,21 @@ class ChangesList { } /** insert a formatted action */ - function insertAction(&$s, &$rc) { + protected function insertAction(&$s, &$rc) { # Add action if( $rc->mAttribs['rc_type'] == RC_LOG ) { // log action if ( $this->isDeleted($rc,LogPage::DELETED_ACTION) ) { $s .= ' ' . wfMsgHtml('rev-deleted-event') . ''; } else { - $s .= ' ' . LogPage::actionText( $rc->mAttribs['rc_log_type'], $rc->mAttribs['rc_log_action'], + $s .= ' ' . LogPage::actionText( $rc->mAttribs['rc_log_type'], $rc->mAttribs['rc_log_action'], $rc->getTitle(), $this->skin, LogPage::extractParams($rc->mAttribs['rc_params']), true, true ); } } } /** insert a formatted comment */ - function insertComment(&$s, &$rc) { + protected function insertComment(&$s, &$rc) { # Add comment if( $rc->mAttribs['rc_type'] != RC_MOVE && $rc->mAttribs['rc_type'] != RC_MOVE_OVER_REDIRECT ) { // log comment @@ -261,15 +265,15 @@ class ChangesList { * Check whether to enable recent changes patrol features * @return bool */ - function usePatrol() { - global $wgUseRCPatrol, $wgUser; - return( $wgUseRCPatrol && ($wgUser->isAllowed('patrol') || $wgUser->isAllowed('patrolmarks')) ); + public static function usePatrol() { + global $wgUser; + return $wgUser->useRCPatrol(); } /** * Returns the string which indicates the number of watching users */ - function numberofWatchingusers( $count ) { + protected function numberofWatchingusers( $count ) { global $wgLang; static $cache = array(); if ( $count > 0 ) { @@ -282,6 +286,36 @@ class ChangesList { return ''; } } + + /** + * Determine if said field of a revision is hidden + * @param RCCacheEntry $rc + * @param int $field one of DELETED_* bitfield constants + * @return bool + */ + public static function isDeleted( $rc, $field ) { + return ($rc->mAttribs['rc_deleted'] & $field) == $field; + } + + /** + * Determine if the current user is allowed to view a particular + * field of this revision, if it's marked as deleted. + * @param RCCacheEntry $rc + * @param int $field + * @return bool + */ + public static function userCan( $rc, $field ) { + if( ( $rc->mAttribs['rc_deleted'] & $field ) == $field ) { + global $wgUser; + $permission = ( $rc->mAttribs['rc_deleted'] & Revision::DELETED_RESTRICTED ) == Revision::DELETED_RESTRICTED + ? 'suppressrevision' + : 'deleterevision'; + wfDebug( "Checking for $permission due to $field match on $rc->mAttribs['rc_deleted']\n" ); + return $wgUser->isAllowed( $permission ); + } else { + return true; + } + } } @@ -292,8 +326,8 @@ class OldChangesList extends ChangesList { /** * Format a line using the old system (aka without any javascript). */ - function recentChangesLine( &$rc, $watched = false ) { - global $wgContLang, $wgRCShowChangedSize; + public function recentChangesLine( &$rc, $watched = false ) { + global $wgContLang, $wgRCShowChangedSize, $wgUser; $fname = 'ChangesList::recentChangesLineOld'; wfProfileIn( $fname ); @@ -303,17 +337,18 @@ class OldChangesList extends ChangesList { extract( $rc->mAttribs ); # Should patrol-related stuff be shown? - $unpatrolled = $this->usePatrol() && $rc_patrolled == 0; + $unpatrolled = $wgUser->useRCPatrol() && $rc_patrolled == 0; - $this->insertDateHeader($s,$rc_timestamp); + $dateheader = ""; // $s now contains only
  • ...
  • , for hooks' convenience. + $this->insertDateHeader($dateheader,$rc_timestamp); - $s .= '
  • '; + $s = '
  • '; // Moved pages if( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) { $this->insertMove( $s, $rc ); // Log entries - } elseif( $rc_log_type !='' ) { + } elseif( $rc_log_type ) { $logtitle = Title::newFromText( "Log/$rc_log_type", NS_SPECIAL ); $this->insertLog( $s, $logtitle, $rc_log_type ); // Log entries (old format) or log targets, and special pages @@ -324,14 +359,15 @@ class OldChangesList extends ChangesList { } else { wfDebug( "Unexpected special page in recentchanges\n" ); } - // Log entries + // Regular entries } else { wfProfileIn($fname.'-page'); $this->insertDiffHist($s, $rc, $unpatrolled); - # M, N, b and ! (minor, new, bot and unpatrolled) - $s .= ' ' . $this->recentChangesFlags( $rc_type == RC_NEW, $rc_minor, $unpatrolled, '', $rc_bot ); + $newbie = self::userIsNew( $rc->mAttribs ); + $s .= $this->recentChangesFlags( $rc_type == RC_NEW, $rc_minor, $unpatrolled, '', + $rc_bot, $newbie ); $this->insertArticleLink($s, $rc, $unpatrolled, $watched); wfProfileOut($fname.'-page'); @@ -344,12 +380,14 @@ class OldChangesList extends ChangesList { if( $wgRCShowChangedSize ) { $s .= ( $rc->getCharacterDifference() == '' ? '' : $rc->getCharacterDifference() . ' . . ' ); } - + # User tool links $this->insertUserRelatedLinks($s,$rc); + # Log action text (if any) $this->insertAction($s, $rc); + # Edit or log comment $this->insertComment($s, $rc); - - # Mark revision as deleted + + # Mark revision as deleted if so if ( !$rc_log_type && $this->isDeleted($rc,Revision::DELETED_TEXT) ) $s .= ' ' . wfMsgHtml( 'deletedrev' ) . ''; if($rc->numberofWatchingusers > 0) { @@ -358,10 +396,12 @@ class OldChangesList extends ChangesList { $s .= "
  • \n"; + wfRunHooks('OldChangesListRecentChangesLine', array(&$this, &$s, &$rc)); + wfProfileOut( $fname.'-rest' ); wfProfileOut( $fname ); - return $s; + return $dateheader . $s; } } @@ -373,8 +413,8 @@ class EnhancedChangesList extends ChangesList { /** * Format a line for enhanced recentchange (aka with javascript and block of lines). */ - function recentChangesLine( &$baseRC, $watched = false ) { - global $wgLang, $wgContLang; + public function recentChangesLine( &$baseRC, $watched = false ) { + global $wgLang, $wgContLang, $wgUser; # Create a specialised object $rc = RCCacheEntry::newFromParent( $baseRC ); @@ -396,7 +436,7 @@ class EnhancedChangesList extends ChangesList { } # Should patrol-related stuff be shown? - if( $this->usePatrol() ) { + if( $wgUser->useRCPatrol() ) { $rc->unpatrolled = !$rc_patrolled; } else { $rc->unpatrolled = false; @@ -420,18 +460,28 @@ class EnhancedChangesList extends ChangesList { wfDebug( "Unexpected special page in recentchanges\n" ); $clink = ''; } - // Page edits or log entries (group these page) - } else if( $this->isDeleted($rc,Revision::DELETED_TEXT) ) { - $clink = '' . $this->skin->makeKnownLinkObj( $rc->getTitle(), '' ) . ''; - if ( !ChangesList::userCan($rc,Revision::DELETED_TEXT) ) - $showdifflinks = false; + // New unpatrolled pages } else if( $rc->unpatrolled && $rc_type == RC_NEW ) { - # Unpatrolled new page, give rc_id in query $clink = $this->skin->makeKnownLinkObj( $rc->getTitle(), '', "rcid={$rc_id}" ); + // Log entries + } else if( $rc_type == RC_LOG ) { + if( $rc_log_type ) { + $logtitle = SpecialPage::getTitleFor( 'Log', $rc_log_type ); + $clink = '(' . $this->skin->makeKnownLinkObj( $logtitle, LogPage::logName($rc_log_type) ) . ')'; + } else { + $clink = $this->skin->makeLinkObj( $rc->getTitle(), '' ); + } + $watched = false; + // Edits } else { $clink = $this->skin->makeKnownLinkObj( $rc->getTitle(), '' ); } + # Don't show unusable diff links + if ( !ChangesList::userCan($rc,Revision::DELETED_TEXT) ) { + $showdifflinks = false; + } + $time = $wgContLang->time( $rc_timestamp, true, true ); $rc->watched = $watched; $rc->link = $clink; @@ -448,9 +498,9 @@ class EnhancedChangesList extends ChangesList { $querydiff = $curIdEq."&diff=$rc_this_oldid&oldid=$rc_last_oldid$rcIdQuery"; $aprops = ' tabindex="'.$baseRC->counter.'"'; $curLink = $this->skin->makeKnownLinkObj( $rc->getTitle(), $this->message['cur'], $querycur, '' ,'', $aprops ); - + # Make "diff" an "cur" links - if ( !$showdifflinks ) { + if( !$showdifflinks ) { $curLink = $this->message['cur']; $diffLink = $this->message['diff']; } else if( $rc_type == RC_NEW || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) { @@ -461,7 +511,7 @@ class EnhancedChangesList extends ChangesList { } else { $diffLink = $this->skin->makeKnownLinkObj( $rc->getTitle(), $this->message['diff'], $querydiff, '' ,'', $aprops ); } - + # Make "last" link if( !$showdifflinks ) { $lastLink = $this->message['last']; @@ -471,9 +521,9 @@ class EnhancedChangesList extends ChangesList { $lastLink = $this->skin->makeKnownLinkObj( $rc->getTitle(), $this->message['last'], $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid . $rcIdQuery ); } - + # Make user links - if ( $this->isDeleted($rc,Revision::DELETED_USER) ) { + if( $this->isDeleted($rc,Revision::DELETED_USER) ) { $rc->userlink = ' ' . wfMsgHtml('rev-deleted-user') . ''; } else { $rc->userlink = $this->skin->userLink( $rc_user, $rc_user_text ); @@ -492,7 +542,11 @@ class EnhancedChangesList extends ChangesList { # Use an @ character to prevent collision with page names $this->rc_cache['@@' . ($this->rcMoveIndex++)] = array($rc); } else { - if( !isset ( $this->rc_cache[$secureName] ) ) { + # Logs are grouped by type + if( $rc_type == RC_LOG ){ + $secureName = SpecialPage::getTitleFor( 'Log', $rc_log_type )->getPrefixedDBkey(); + } + if( !isset( $this->rc_cache[$secureName] ) ) { $this->rc_cache[$secureName] = array(); } array_push( $this->rc_cache[$secureName], $rc ); @@ -503,23 +557,26 @@ class EnhancedChangesList extends ChangesList { /** * Enhanced RC group */ - function recentChangesBlockGroup( $block ) { + protected function recentChangesBlockGroup( $block ) { global $wgLang, $wgContLang, $wgRCShowChangedSize; - $r = ''; + $r = '
    '; # Collate list of users - $isnew = false; - $namehidden = true; - $unpatrolled = false; $userlinks = array(); + # Other properties + $unpatrolled = $isnew = $newbie = false; + $curId = $currentRevision = 0; + # Some catalyst variables... + $namehidden = true; + $alllogs = true; foreach( $block as $rcObj ) { $oldid = $rcObj->mAttribs['rc_last_oldid']; - if( $rcObj->mAttribs['rc_new'] ) { + if( $rcObj->mAttribs['rc_type'] == RC_NEW ) { $isnew = true; } // If all log actions to this page were hidden, then don't // give the name of the affected page for this block! - if( !($rcObj->mAttribs['rc_deleted'] & LogPage::DELETED_ACTION) ) { + if( !$this->isDeleted( $rcObj, LogPage::DELETED_ACTION ) ) { $namehidden = false; } $u = $rcObj->userlink; @@ -529,6 +586,21 @@ class EnhancedChangesList extends ChangesList { if( $rcObj->unpatrolled ) { $unpatrolled = true; } + if( $rcObj->mAttribs['rc_type'] != RC_LOG ) { + $alllogs = false; + } + if( self::userIsNew( $rcObj->mAttribs ) ) { + $newbie = true; + } + # Get the latest entry with a page_id and oldid + # since logs may not have these. + if( !$curId && $rcObj->mAttribs['rc_cur_id'] ) { + $curId = $rcObj->mAttribs['rc_cur_id']; + } + if( !$currentRevision && $rcObj->mAttribs['rc_this_oldid'] ) { + $currentRevision = $rcObj->mAttribs['rc_this_oldid']; + } + $bot = $rcObj->mAttribs['rc_bot']; $userlinks[$u]++; } @@ -541,12 +613,12 @@ class EnhancedChangesList extends ChangesList { $text = $userlink; $text .= $wgContLang->getDirMark(); if( $count > 1 ) { - $text .= ' ('.$count.'×)'; + $text .= ' (' . $wgLang->formatNum( $count ) . '×)'; } array_push( $users, $text ); } - $users = ' [' . implode( $this->message['semicolon-separator'] . ' ', $users ) . ']'; + $users = ' [' . implode( $this->message['semicolon-separator'], $users ) . ']'; # Arrow $rci = 'RCI'.$this->rcCacheIndex; @@ -555,104 +627,121 @@ class EnhancedChangesList extends ChangesList { $toggleLink = "javascript:toggleVisibility('$rci','$rcm','$rcl')"; $tl = '' . $this->sideArrow() . ''; $tl .= ''; - $r .= '
    '.$tl; + $r .= ''.$tl.' '; # Main line - $r .= ' '.$this->recentChangesFlags( $isnew, false, $unpatrolled, ' ', $bot ); + $r .= $this->recentChangesFlags( $isnew, false, $unpatrolled, ' ', $bot, $newbie ); # Timestamp - $r .= ' '.$block[0]->timestamp.' '; + $r .= ' '.$block[0]->timestamp.' '; # Article link - if ( $namehidden ) + if( $namehidden ) { $r .= ' ' . wfMsgHtml('rev-deleted-event') . ''; - else + } else { $r .= $this->maybeWatchedLink( $block[0]->link, $block[0]->watched ); - $r .= $wgContLang->getDirMark(); - - $curIdEq = 'curid=' . $block[0]->mAttribs['rc_cur_id']; - $currentRevision = $block[0]->mAttribs['rc_this_oldid']; - if( $block[0]->mAttribs['rc_type'] != RC_LOG ) { - # Changes - $n = count($block); - static $nchanges = array(); - if ( !isset( $nchanges[$n] ) ) { - $nchanges[$n] = wfMsgExt( 'nchanges', array( 'parsemag', 'escape'), - $wgLang->formatNum( $n ) ); - } + } - $r .= ' ('; + $r .= $wgContLang->getDirMark(); + $curIdEq = 'curid=' . $curId; + # Changes message + $n = count($block); + static $nchanges = array(); + if ( !isset( $nchanges[$n] ) ) { + $nchanges[$n] = wfMsgExt( 'nchanges', array( 'parsemag', 'escape' ), $wgLang->formatNum( $n ) ); + } + # Total change link + $r .= ' '; + if( !$alllogs ) { + $r .= '('; if( !ChangesList::userCan($rcObj,Revision::DELETED_TEXT) ) { - $r .= $nchanges[$n]; + $r .= $nchanges[$n]; } else if( $isnew ) { $r .= $nchanges[$n]; } else { $r .= $this->skin->makeKnownLinkObj( $block[0]->getTitle(), $nchanges[$n], $curIdEq."&diff=$currentRevision&oldid=$oldid" ); } + $r .= ') . . '; + } - if( $wgRCShowChangedSize ) { - # Character difference - $chardiff = $rcObj->getCharacterDifference( $block[ count( $block ) - 1 ]->mAttribs['rc_old_len'], - $block[0]->mAttribs['rc_new_len'] ); - if( $chardiff == '' ) { - $r .= ') '; - } else { - $r .= ' ' . $chardiff. ' . . '; - } + # Character difference (does not apply if only log items) + if( $wgRCShowChangedSize && !$alllogs ) { + $last = 0; + $first = count($block) - 1; + # Some events (like logs) have an "empty" size, so we need to skip those... + while( $last < $first && $block[$last]->mAttribs['rc_new_len'] === NULL ) { + $last++; + } + while( $first > $last && $block[$first]->mAttribs['rc_old_len'] === NULL ) { + $first--; } + # Get net change + $chardiff = $rcObj->getCharacterDifference( $block[$first]->mAttribs['rc_old_len'], + $block[$last]->mAttribs['rc_new_len'] ); - # History + if( $chardiff == '' ) { + $r .= ' '; + } else { + $r .= ' ' . $chardiff. ' . . '; + } + } + + # History + if( $alllogs ) { + // don't show history link for logs + } else if( $namehidden || !$block[0]->getTitle()->exists() ) { + $r .= '(' . $this->message['history'] . ')'; + } else { $r .= '(' . $this->skin->makeKnownLinkObj( $block[0]->getTitle(), - $this->message['history'], $curIdEq.'&action=history' ); - $r .= ')'; + $this->message['history'], $curIdEq.'&action=history' ) . ')'; } $r .= $users; - $r .=$this->numberofWatchingusers($block[0]->numberofWatchingusers); - + $r .= $this->numberofWatchingusers($block[0]->numberofWatchingusers); + $r .= "
    \n"; # Sub-entries - $r .= '