Merge "+Test for Status->CleanParams with a callback"
[lhc/web/wiklou.git] / includes / specials / SpecialRecentchanges.php
index f866158..4f89c00 100644 (file)
  *
  * @ingroup SpecialPage
  */
-class SpecialRecentChanges extends IncludableSpecialPage {
-       var $rcOptions, $rcSubpage;
-       protected $customFilters;
-
+class SpecialRecentChanges extends ChangesListSpecialPage {
        /**
         * The feed format to output as (either 'rss' or 'atom'), or null if no
         * feed output was requested
@@ -38,91 +35,8 @@ class SpecialRecentChanges extends IncludableSpecialPage {
         */
        protected $feedFormat;
 
-       public function __construct( $name = 'Recentchanges' ) {
-               parent::__construct( $name );
-       }
-
-       /**
-        * Get a FormOptions object containing the default options
-        *
-        * @return FormOptions
-        */
-       public function getDefaultOptions() {
-               $opts = new FormOptions();
-               $user = $this->getUser();
-
-               $opts->add( 'days', $user->getIntOption( 'rcdays' ) );
-               $opts->add( 'limit', $user->getIntOption( 'rclimit' ) );
-               $opts->add( 'from', '' );
-
-               $opts->add( 'hideminor', $user->getBoolOption( 'hideminor' ) );
-               $opts->add( 'hidebots', true );
-               $opts->add( 'hideanons', false );
-               $opts->add( 'hideliu', false );
-               $opts->add( 'hidepatrolled', $user->getBoolOption( 'hidepatrolled' ) );
-               $opts->add( 'hidemyself', false );
-
-               $opts->add( 'namespace', '', FormOptions::INTNULL );
-               $opts->add( 'invert', false );
-               $opts->add( 'associated', false );
-
-               $opts->add( 'categories', '' );
-               $opts->add( 'categories_any', false );
-               $opts->add( 'tagfilter', '' );
-
-               return $opts;
-       }
-
-       /**
-        * Create a FormOptions object with options as specified by the user
-        *
-        * @param array $parameters
-        * @return FormOptions
-        */
-       public function setup( $parameters ) {
-               global $wgFeedLimit;
-
-               $opts = $this->getDefaultOptions();
-
-               foreach ( $this->getCustomFilters() as $key => $params ) {
-                       $opts->add( $key, $params['default'] );
-               }
-
-               $opts->fetchValuesFromRequest( $this->getRequest() );
-
-               // Give precedence to subpage syntax
-               if ( $parameters !== null ) {
-                       $this->parseParameters( $parameters, $opts );
-               }
-
-               $opts->validateIntBounds( 'limit', 0, $this->feedFormat ? $wgFeedLimit : 5000 );
-
-               return $opts;
-       }
-
-       /**
-        * Get custom show/hide filters
-        *
-        * @return array Map of filter URL param names to properties (msg/default)
-        */
-       protected function getCustomFilters() {
-               if ( $this->customFilters === null ) {
-                       $this->customFilters = array();
-                       wfRunHooks( 'SpecialRecentChangesFilters', array( $this, &$this->customFilters ) );
-               }
-
-               return $this->customFilters;
-       }
-
-       /**
-        * Get the current FormOptions for this request
-        */
-       public function getOptions() {
-               if ( $this->rcOptions === null ) {
-                       $this->rcOptions = $this->setup( $this->rcSubpage );
-               }
-
-               return $this->rcOptions;
+       public function __construct( $name = 'Recentchanges', $restriction = '' ) {
+               parent::__construct( $name, $restriction );
        }
 
        /**
@@ -179,25 +93,48 @@ class SpecialRecentChanges extends IncludableSpecialPage {
        }
 
        /**
-        * Return an array with a ChangesFeed object and ChannelFeed object
+        * Get a FormOptions object containing the default options
         *
-        * @param string $feedFormat Feed's format (either 'rss' or 'atom')
-        * @return array
+        * @return FormOptions
         */
-       public function getFeedObject( $feedFormat ) {
-               $changesFeed = new ChangesFeed( $feedFormat, 'rcfeed' );
-               $formatter = $changesFeed->getFeedObject(
-                       $this->msg( 'recentchanges' )->inContentLanguage()->text(),
-                       $this->msg( 'recentchanges-feed-description' )->inContentLanguage()->text(),
-                       $this->getTitle()->getFullURL()
-               );
+       public function getDefaultOptions() {
+               $opts = parent::getDefaultOptions();
+               $user = $this->getUser();
 
-               return array( $changesFeed, $formatter );
+               $opts->add( 'days', $user->getIntOption( 'rcdays' ) );
+               $opts->add( 'limit', $user->getIntOption( 'rclimit' ) );
+               $opts->add( 'from', '' );
+
+               $opts->add( 'hideminor', $user->getBoolOption( 'hideminor' ) );
+               $opts->add( 'hidebots', true );
+               $opts->add( 'hideanons', false );
+               $opts->add( 'hideliu', false );
+               $opts->add( 'hidepatrolled', $user->getBoolOption( 'hidepatrolled' ) );
+               $opts->add( 'hidemyself', false );
+
+               $opts->add( 'categories', '' );
+               $opts->add( 'categories_any', false );
+               $opts->add( 'tagfilter', '' );
+
+               return $opts;
        }
 
        /**
-        * Process $par and put options found if $opts
-        * Mainly used when including the page
+        * Get custom show/hide filters
+        *
+        * @return array Map of filter URL param names to properties (msg/default)
+        */
+       protected function getCustomFilters() {
+               if ( $this->customFilters === null ) {
+                       $this->customFilters = array();
+                       wfRunHooks( 'SpecialRecentChangesFilters', array( $this, &$this->customFilters ) );
+               }
+
+               return $this->customFilters;
+       }
+
+       /**
+        * Process $par and put options found in $opts. Used when including the page.
         *
         * @param string $par
         * @param FormOptions $opts
@@ -247,25 +184,9 @@ class SpecialRecentChanges extends IncludableSpecialPage {
                }
        }
 
-       /**
-        * Get last modified date, for client caching
-        * Don't use this if we are using the patrol feature, patrol changes don't
-        * update the timestamp
-        *
-        * @param string $feedFormat
-        * @return string|bool
-        */
-       public function checkLastModified( $feedFormat ) {
-               $dbr = wfGetDB( DB_SLAVE );
-               $lastmod = $dbr->selectField( 'recentchanges', 'MAX(rc_timestamp)', false, __METHOD__ );
-               if ( $feedFormat || !$this->getUser()->useRCPatrol() ) {
-                       if ( $lastmod && $this->getOutput()->checkLastModified( $lastmod ) ) {
-                               # Client cache fresh and headers sent, nothing more to do.
-                               return false;
-                       }
-               }
-
-               return $lastmod;
+       public function validateOptions( FormOptions $opts ) {
+               global $wgFeedLimit;
+               $opts->validateIntBounds( 'limit', 0, $this->feedFormat ? $wgFeedLimit : 5000 );
        }
 
        /**
@@ -513,28 +434,6 @@ class SpecialRecentChanges extends IncludableSpecialPage {
                }
        }
 
-       /**
-        * Get the query string to append to feed link URLs.
-        *
-        * @return string
-        */
-       public function getFeedQuery() {
-               global $wgFeedLimit;
-
-               $this->getOptions()->validateIntBounds( 'limit', 0, $wgFeedLimit );
-               $options = $this->getOptions()->getChangedValues();
-
-               // wfArrayToCgi() omits options set to null or false
-               foreach ( $options as &$value ) {
-                       if ( $value === false ) {
-                               $value = '0';
-                       }
-               }
-               unset( $value );
-
-               return wfArrayToCgi( $options );
-       }
-
        /**
         * Return the text to be displayed above the changes
         *
@@ -593,7 +492,7 @@ class SpecialRecentChanges extends IncludableSpecialPage {
                        $out .= Html::hidden( $key, $value );
                }
 
-               $t = $this->getTitle();
+               $t = $this->getPageTitle();
                $out .= Html::hidden( 'title', $t->getPrefixedText() );
                $form = Xml::tags( 'form', array( 'action' => $wgScript ), $out );
                $panel[] = $form;
@@ -610,6 +509,27 @@ class SpecialRecentChanges extends IncludableSpecialPage {
                $this->setBottomText( $opts );
        }
 
+       /**
+        * Send the text to be displayed above the options
+        *
+        * @param FormOptions $opts Unused
+        */
+       function setTopText( FormOptions $opts ) {
+               global $wgContLang;
+
+               $message = $this->msg( 'recentchangestext' )->inContentLanguage();
+               if ( !$message->isDisabled() ) {
+                       $this->getOutput()->addWikiText(
+                               Html::rawElement( 'p',
+                                       array( 'lang' => $wgContLang->getCode(), 'dir' => $wgContLang->getDir() ),
+                                       "\n" . $message->plain() . "\n"
+                               ),
+                               /* $lineStart */ false,
+                               /* $interface */ false
+                       );
+               }
+       }
+
        /**
         * Get options to be displayed in a form
         *
@@ -643,91 +563,72 @@ class SpecialRecentChanges extends IncludableSpecialPage {
        }
 
        /**
-        * Return the legend displayed within the fieldset.
-        *
-        * This method is also called from SpecialWatchlist.
+        * Add page-specific modules.
+        */
+       protected function addModules() {
+               parent::addModules();
+               $out = $this->getOutput();
+               $out->addModules( 'mediawiki.special.recentchanges' );
+       }
+
+       /**
+        * Get last modified date, for client caching
+        * Don't use this if we are using the patrol feature, patrol changes don't
+        * update the timestamp
         *
-        * @param $context the object available as $this in non-static functions
-        * @return string
+        * @param string $feedFormat
+        * @return string|bool
         */
-       public static function makeLegend( IContextSource $context ) {
-               global $wgRecentChangesFlags;
-               $user = $context->getUser();
-               # The legend showing what the letters and stuff mean
-               $legend = Xml::openElement( 'dl' ) . "\n";
-               # Iterates through them and gets the messages for both letter and tooltip
-               $legendItems = $wgRecentChangesFlags;
-               if ( !$user->useRCPatrol() ) {
-                       unset( $legendItems['unpatrolled'] );
-               }
-               foreach ( $legendItems as $key => $legendInfo ) { # generate items of the legend
-                       $label = $legendInfo['title'];
-                       $letter = $legendInfo['letter'];
-                       $cssClass = isset( $legendInfo['class'] ) ? $legendInfo['class'] : $key;
-
-                       $legend .= Xml::element( 'dt',
-                               array( 'class' => $cssClass ), $context->msg( $letter )->text()
-                       ) . "\n";
-                       if ( $key === 'newpage' ) {
-                               $legend .= Xml::openElement( 'dd' );
-                               $legend .= $context->msg( $label )->escaped();
-                               $legend .= ' ' . $context->msg( 'recentchanges-legend-newpage' )->parse();
-                               $legend .= Xml::closeElement( 'dd' ) . "\n";
-                       } else {
-                               $legend .= Xml::element( 'dd', array(),
-                                       $context->msg( $label )->text()
-                               ) . "\n";
+       public function checkLastModified( $feedFormat ) {
+               $dbr = wfGetDB( DB_SLAVE );
+               $lastmod = $dbr->selectField( 'recentchanges', 'MAX(rc_timestamp)', false, __METHOD__ );
+               if ( $feedFormat || !$this->getUser()->useRCPatrol() ) {
+                       if ( $lastmod && $this->getOutput()->checkLastModified( $lastmod ) ) {
+                               # Client cache fresh and headers sent, nothing more to do.
+                               return false;
                        }
                }
-               # (+-123)
-               $legend .= Xml::tags( 'dt',
-                       array( 'class' => 'mw-plusminus-pos' ),
-                       $context->msg( 'recentchanges-legend-plusminus' )->parse()
-               ) . "\n";
-               $legend .= Xml::element(
-                       'dd',
-                       array( 'class' => 'mw-changeslist-legend-plusminus' ),
-                       $context->msg( 'recentchanges-label-plusminus' )->text()
-               ) . "\n";
-               $legend .= Xml::closeElement( 'dl' ) . "\n";
-
-               # Collapsibility
-               $legend =
-                       '<div class="mw-changeslist-legend">' .
-                               $context->msg( 'recentchanges-legend-heading' )->parse() .
-                               '<div class="mw-collapsible-content">' . $legend . '</div>' .
-                       '</div>';
-
-               return $legend;
+
+               return $lastmod;
        }
 
        /**
-        * Send the text to be displayed above the options
+        * Return an array with a ChangesFeed object and ChannelFeed object
         *
-        * @param FormOptions $opts Unused
+        * @param string $feedFormat Feed's format (either 'rss' or 'atom')
+        * @return array
         */
-       function setTopText( FormOptions $opts ) {
-               global $wgContLang;
+       public function getFeedObject( $feedFormat ) {
+               $changesFeed = new ChangesFeed( $feedFormat, 'rcfeed' );
+               $formatter = $changesFeed->getFeedObject(
+                       $this->msg( 'recentchanges' )->inContentLanguage()->text(),
+                       $this->msg( 'recentchanges-feed-description' )->inContentLanguage()->text(),
+                       $this->getPageTitle()->getFullURL()
+               );
 
-               $message = $this->msg( 'recentchangestext' )->inContentLanguage();
-               if ( !$message->isDisabled() ) {
-                       $this->getOutput()->addWikiText(
-                               Html::rawElement( 'p',
-                                       array( 'lang' => $wgContLang->getCode(), 'dir' => $wgContLang->getDir() ),
-                                       "\n" . $message->plain() . "\n"
-                               ),
-                               /* $lineStart */ false,
-                               /* $interface */ false
-                       );
-               }
+               return array( $changesFeed, $formatter );
        }
 
        /**
-        * Send the text to be displayed after the options, for use in subclasses.
+        * Get the query string to append to feed link URLs.
         *
-        * @param FormOptions $opts
+        * @return string
         */
-       function setBottomText( FormOptions $opts ) {
+       public function getFeedQuery() {
+               global $wgFeedLimit;
+
+               $this->getOptions()->validateIntBounds( 'limit', 0, $wgFeedLimit );
+               $options = $this->getOptions()->getChangedValues();
+
+               // wfArrayToCgi() omits options set to null or false
+               foreach ( $options as &$value ) {
+                       if ( $value === false ) {
+                               $value = '0';
+                       }
+               }
+               unset( $value );
+
+               return wfArrayToCgi( $options );
        }
 
        /**
@@ -862,7 +763,7 @@ class SpecialRecentChanges extends IncludableSpecialPage {
                        $text = '<strong>' . $text . '</strong>';
                }
 
-               return Linker::linkKnown( $this->getTitle(), $text, array(), $params );
+               return Linker::linkKnown( $this->getPageTitle(), $text, array(), $params );
        }
 
        /**
@@ -958,16 +859,7 @@ class SpecialRecentChanges extends IncludableSpecialPage {
                return "{$note}$rclinks<br />$rclistfrom";
        }
 
-       /**
-        * Add page-specific modules.
-        */
-       protected function addModules() {
-               $this->getOutput()->addModules( array(
-                       'mediawiki.special.recentchanges',
-               ) );
-       }
-
-       protected function getGroupName() {
-               return 'changes';
+       public function isIncludable() {
+               return true;
        }
 }