Merge "Perform a permission check on the title when changing the page language"
[lhc/web/wiklou.git] / includes / changes / ChangesList.php
index bc7d721..cac4769 100644 (file)
  */
 use MediaWiki\Linker\LinkRenderer;
 use MediaWiki\MediaWikiServices;
+use Wikimedia\Rdbms\ResultWrapper;
 
 class ChangesList extends ContextSource {
+       const CSS_CLASS_PREFIX = 'mw-changeslist-';
+
        /**
         * @var Skin
         */
@@ -38,6 +41,9 @@ class ChangesList extends ContextSource {
        protected $rclistOpen;
        protected $rcMoveIndex;
 
+       /** @var callable */
+       protected $changeLinePrefixer;
+
        /** @var BagOStuff */
        protected $watchMsgCache;
 
@@ -46,12 +52,18 @@ class ChangesList extends ContextSource {
         */
        protected $linkRenderer;
 
+       /**
+        * @var array
+        */
+       protected $filterGroups;
+
        /**
         * Changeslist constructor
         *
         * @param Skin|IContextSource $obj
+        * @param array $filterGroups Array of ChangesListFilterGroup objects (currently optional)
         */
-       public function __construct( $obj ) {
+       public function __construct( $obj, array $filterGroups = [] ) {
                if ( $obj instanceof IContextSource ) {
                        $this->setContext( $obj );
                        $this->skin = $obj->getSkin();
@@ -62,6 +74,7 @@ class ChangesList extends ContextSource {
                $this->preCacheMessages();
                $this->watchMsgCache = new HashBagOStuff( [ 'maxKeys' => 50 ] );
                $this->linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
+               $this->filterGroups = $filterGroups;
        }
 
        /**
@@ -69,16 +82,19 @@ class ChangesList extends ContextSource {
         * Some users might want to use an enhanced list format, for instance
         *
         * @param IContextSource $context
+        * @param array $groups Array of ChangesListFilterGroup objects (currently optional)
         * @return ChangesList
         */
-       public static function newFromContext( IContextSource $context ) {
+       public static function newFromContext( IContextSource $context, array $groups = [] ) {
                $user = $context->getUser();
                $sk = $context->getSkin();
                $list = null;
                if ( Hooks::run( 'FetchChangesList', [ $user, &$sk, &$list ] ) ) {
                        $new = $context->getRequest()->getBool( 'enhanced', $user->getOption( 'usenewrc' ) );
 
-                       return $new ? new EnhancedChangesList( $context ) : new OldChangesList( $context );
+                       return $new ?
+                               new EnhancedChangesList( $context, $groups ) :
+                               new OldChangesList( $context, $groups );
                } else {
                        return $list;
                }
@@ -89,7 +105,7 @@ class ChangesList extends ContextSource {
         *
         * @since 1.27
         *
-        * @param RecentChange $rc Passed by reference
+        * @param RecentChange &$rc Passed by reference
         * @param bool $watched (default false)
         * @param int $linenumber (default null)
         *
@@ -156,44 +172,46 @@ class ChangesList extends ContextSource {
         * @return array of classes
         */
        protected function getHTMLClasses( $rc, $watched ) {
-               $classes = [];
+               $classes = [ self::CSS_CLASS_PREFIX . 'line' ];
                $logType = $rc->mAttribs['rc_log_type'];
-               $prefix = 'mw-changeslist-';
 
                if ( $logType ) {
-                       $classes[] = Sanitizer::escapeClass( $prefix . 'log-' . $logType );
+                       $classes[] = self::CSS_CLASS_PREFIX . 'log';
+                       $classes[] = Sanitizer::escapeClass( self::CSS_CLASS_PREFIX . 'log-' . $logType );
                } else {
-                       $classes[] = Sanitizer::escapeClass( $prefix . 'ns' .
+                       $classes[] = self::CSS_CLASS_PREFIX . 'edit';
+                       $classes[] = Sanitizer::escapeClass( self::CSS_CLASS_PREFIX . 'ns' .
                                $rc->mAttribs['rc_namespace'] . '-' . $rc->mAttribs['rc_title'] );
+                       $classes[] = Sanitizer::escapeClass( self::CSS_CLASS_PREFIX . 'ns-' .
+                               $rc->mAttribs['rc_namespace'] );
                }
 
                // Indicate watched status on the line to allow for more
                // comprehensive styling.
                $classes[] = $watched && $rc->mAttribs['rc_timestamp'] >= $watched
-                       ? $prefix . 'line-watched'
-                       : $prefix . 'line-not-watched';
+                       ? self::CSS_CLASS_PREFIX . 'line-watched'
+                       : self::CSS_CLASS_PREFIX . 'line-not-watched';
 
                $classes = array_merge( $classes, $this->getHTMLClassesForFilters( $rc ) );
 
                return $classes;
        }
 
+       /**
+        * Get an array of CSS classes attributed to filters for this row
+        *
+        * @param RecentChange $rc
+        * @return array Array of CSS classes
+        */
        protected function getHTMLClassesForFilters( $rc ) {
                $classes = [];
-               $prefix = 'mw-changeslist-';
-
-               $classes[] = $prefix . ( $rc->getAttribute( 'rc_bot' ) ? 'bot' : 'human' );
-               $classes[] = $prefix . ( $rc->getAttribute( 'rc_user' ) ? 'liu' : 'anon' );
-               $classes[] = $prefix . ( $rc->getAttribute( 'rc_minor' ) ? 'minor' : 'major' );
-               $classes[] = $prefix .
-                       ( $rc->getAttribute( 'rc_patrolled' ) ? 'patrolled' : 'unpatrolled' );
-               $classes[] = $prefix .
-                       ( $this->getUser()->equals( $rc->getPerformer() ) ? 'self' : 'others' );
-               $classes[] = $prefix . 'src-' . str_replace( '.', '-', $rc->getAttribute( 'rc_source' ) );
-
-               $performer = $rc->getPerformer();
-               if ( $performer && $performer->isLoggedIn() ) {
-                       $classes[] = $prefix . 'user-' . $performer->getExperienceLevel();
+
+               if ( $this->filterGroups !== null ) {
+                       foreach ( $this->filterGroups as $filterGroup ) {
+                               foreach ( $filterGroup->getFilters() as $filter ) {
+                                       $filter->applyCssClassIfNeeded( $this, $rc, $classes );
+                               }
+                       }
                }
 
                return $classes;
@@ -349,7 +367,7 @@ class ChangesList extends ContextSource {
        }
 
        /**
-        * @param string $s HTML to update
+        * @param string &$s HTML to update
         * @param mixed $rc_timestamp
         */
        public function insertDateHeader( &$s, $rc_timestamp ) {
@@ -366,7 +384,7 @@ class ChangesList extends ContextSource {
        }
 
        /**
-        * @param string $s HTML to update
+        * @param string &$s HTML to update
         * @param Title $title
         * @param string $logtype
         */
@@ -379,8 +397,8 @@ class ChangesList extends ContextSource {
        }
 
        /**
-        * @param string $s HTML to update
-        * @param RecentChange $rc
+        * @param string &$s HTML to update
+        * @param RecentChange &$rc
         * @param bool|null $unpatrolled Unused variable, since 1.27.
         */
        public function insertDiffHist( &$s, &$rc, $unpatrolled = null ) {
@@ -429,7 +447,7 @@ class ChangesList extends ContextSource {
        }
 
        /**
-        * @param string $s Article link will be appended to this string, in place.
+        * @param string &$s Article link will be appended to this string, in place.
         * @param RecentChange $rc
         * @param bool $unpatrolled
         * @param bool $watched
@@ -440,7 +458,7 @@ class ChangesList extends ContextSource {
        }
 
        /**
-        * @param RecentChange $rc
+        * @param RecentChange &$rc
         * @param bool $unpatrolled
         * @param bool $watched
         * @return string HTML
@@ -495,7 +513,7 @@ class ChangesList extends ContextSource {
        /**
         * Insert time timestamp string from $rc into $s
         *
-        * @param string $s HTML to update
+        * @param string &$s HTML to update
         * @param RecentChange $rc
         */
        public function insertTimestamp( &$s, $rc ) {
@@ -607,8 +625,8 @@ class ChangesList extends ContextSource {
 
        /** Inserts a rollback link
         *
-        * @param string $s
-        * @param RecentChange $rc
+        * @param string &$s
+        * @param RecentChange &$rc
         */
        public function insertRollback( &$s, &$rc ) {
                if ( $rc->mAttribs['rc_type'] == RC_EDIT
@@ -645,9 +663,9 @@ class ChangesList extends ContextSource {
        }
 
        /**
-        * @param string $s
-        * @param RecentChange $rc
-        * @param array $classes
+        * @param string &$s
+        * @param RecentChange &$rc
+        * @param array &$classes
         */
        public function insertTags( &$s, &$rc, &$classes ) {
                if ( empty( $rc->mAttribs['ts_tags'] ) ) {
@@ -665,7 +683,7 @@ class ChangesList extends ContextSource {
 
        /**
         * @param RecentChange $rc
-        * @param array $classes
+        * @param array &$classes
         * @return string
         * @since 1.26
         */
@@ -728,4 +746,40 @@ class ChangesList extends ContextSource {
                        && intval( $rcObj->getAttribute( 'rc_this_oldid' ) ) === 0;
        }
 
+       /**
+        * Get recommended data attributes for a change line.
+        * @param RecentChange $rc
+        * @return string[] attribute name => value
+        */
+       protected function getDataAttributes( RecentChange $rc ) {
+               $attrs = [];
+
+               $type = $rc->getAttribute( 'rc_source' );
+               switch ( $type ) {
+                       case RecentChange::SRC_EDIT:
+                       case RecentChange::SRC_NEW:
+                               $attrs['data-mw-revid'] = $rc->mAttribs['rc_this_oldid'];
+                               break;
+                       case RecentChange::SRC_LOG:
+                               $attrs['data-mw-logid'] = $rc->mAttribs['rc_logid'];
+                               $attrs['data-mw-logaction'] =
+                                       $rc->mAttribs['rc_log_type'] . '/' . $rc->mAttribs['rc_log_action'];
+                               break;
+               }
+
+               $attrs[ 'data-mw-ts' ] = $rc->getAttribute( 'rc_timestamp' );
+
+               return $attrs;
+       }
+
+       /**
+        * Sets the callable that generates a change line prefix added to the beginning of each line.
+        *
+        * @param callable $prefixer Callable to run that generates the change line prefix.
+        *     Takes three parameters: a RecentChange object, a ChangesList object,
+        *     and whether the current entry is a grouped entry.
+        */
+       public function setChangeLinePrefixer( callable $prefixer ) {
+               $this->changeLinePrefixer = $prefixer;
+       }
 }