From fcbdd58326d49b8a41ff2c639b7c1a4106d5941c Mon Sep 17 00:00:00 2001 From: Aaron Schulz Date: Mon, 23 May 2011 04:28:58 +0000 Subject: [PATCH] * In core: ** Added hooks for custom RC/newpages filters ** Added tables,fields,and join_conds to SpecialNewPagesConditions hook ** Removed superflous $nameSpace logic in watchlist code ** Removed some copy-paste code for RC/watchlist filters ** Updates hooks.txt * In FlaggedRevs: * Added "hide reviewed edits" filter to RC/newpages * Combined two handlers into modifyChangesListQuery. Removed is_array() check - always true now. * Fixed onBeforePageDisplay() so that CSS worked on sp:Watchlist * @TODO: remove $wgUseRCPatrol stuff...this gets us closer. --- docs/hooks.txt | 20 +++- includes/specials/SpecialNewpages.php | 39 ++++--- includes/specials/SpecialRecentchanges.php | 54 +++++---- includes/specials/SpecialWatchlist.php | 126 +++++++++++---------- 4 files changed, 142 insertions(+), 97 deletions(-) diff --git a/docs/hooks.txt b/docs/hooks.txt index 2be47a80a0..46900367cb 100644 --- a/docs/hooks.txt +++ b/docs/hooks.txt @@ -1610,6 +1610,14 @@ $newTitle: new title (object) &$special: NewPagesPager object (subclass of ReverseChronologicalPager) $opts: FormOptions object containing special page options &$conds: array of WHERE conditionals for query +&tables: array of tables to be queried +&$fields: array of columns to select +&$join_conds: join conditions for the tables + +'SpecialNewPagesFilters': called after building form options at NewPages +$special: the special page object +&$filters: associative array of filter definitions. The keys are the HTML name/URL parameters. +Each key maps to an associative array with a 'msg' (message key) and a 'default' value. 'SpecialPage_initList': called when setting up SpecialPage::$mList, use this hook to remove a core special page @@ -1624,6 +1632,11 @@ use this to change some selection criteria or substitute a different title &$title: If the hook returns false, a Title object to use instead of the result from the normal query +'SpecialRecentChangesFilters': called after building form options at RecentChanges +$special: the special page object +&$filters: associative array of filter definitions. The keys are the HTML name/URL parameters. +Each key maps to an associative array with a 'msg' (message key) and a 'default' value. + 'SpecialRecentChangesPanel': called when building form options in SpecialRecentChanges &$extraOpts: array of added items, to which can be added @@ -1636,7 +1649,7 @@ SpecialRecentChanges and SpecialRecentChangesLinked &$join_conds: join conditions for the tables $opts: FormOptions for this request &$query_options: array of options for the database request -&$select: String '*' or array of columns to select +&$select: Array of columns to select 'SpecialSearchGo': called when user clicked the "Go" &$title: title object generated from the text entered by the user @@ -1683,6 +1696,11 @@ $form: The SpecialUpload object use this to change the tables headers $extTypes: associative array of extensions types +'SpecialWatchlistFilters': called after building form options at Watchlist +$special: the special page object +&$filters: associative array of filter definitions. The keys are the HTML name/URL parameters. +Each key maps to an associative array with a 'msg' (message key) and a 'default' value. + 'SpecialWatchlistQuery': called when building sql query for SpecialWatchlist &$conds: array of WHERE conditionals for query &$tables: array of tables to be queried diff --git a/includes/specials/SpecialNewpages.php b/includes/specials/SpecialNewpages.php index 123d539e91..81be335cbc 100644 --- a/includes/specials/SpecialNewpages.php +++ b/includes/specials/SpecialNewpages.php @@ -34,6 +34,7 @@ class SpecialNewpages extends IncludableSpecialPage { * @var FormOptions */ protected $opts; + protected $customFilters; // Some internal settings protected $showNavigation = false; @@ -59,6 +60,12 @@ class SpecialNewpages extends IncludableSpecialPage { $opts->add( 'feed', '' ); $opts->add( 'tagfilter', '' ); + $this->customFilters = array(); + wfRunHooks( 'SpecialNewPagesFilters', array( $this, &$this->customFilters ) ); + foreach( $this->customFilters as $key => $params ) { + $opts->add( $key, $params['default'] ); + } + // Set values $opts->fetchValuesFromRequest( $this->getRequest() ); if ( $par ) $this->parseParams( $par ); @@ -167,13 +174,15 @@ class SpecialNewpages extends IncludableSpecialPage { 'hidebots' => 'rcshowhidebots', 'hideredirs' => 'whatlinkshere-hideredirs' ); + foreach ( $this->customFilters as $key => $params ) { + $filters[$key] = $params['msg']; + } // Disable some if needed # @todo FIXME: Throws E_NOTICEs if not set; and doesn't obey hooks etc. if ( $wgGroupPermissions['*']['createpage'] !== true ) { unset( $filters['hideliu'] ); } - if ( !$this->getUser()->useNPPatrol() ) { unset( $filters['hidepatrolled'] ); } @@ -507,21 +516,23 @@ class NewPagesPager extends ReverseChronologicalPager { } // Allow changes to the New Pages query - wfRunHooks( 'SpecialNewpagesConditions', array( &$this, $this->opts, &$conds ) ); + $tables = array( 'recentchanges', 'page' ); + $fields = array( + 'rc_namespace', 'rc_title', 'rc_cur_id', 'rc_user', 'rc_user_text', + 'rc_comment', 'rc_timestamp', 'rc_patrolled','rc_id', 'rc_deleted', + 'page_len AS length', 'page_latest AS rev_id', 'ts_tags' + ); + $join_conds = array( 'page' => array( 'INNER JOIN', 'page_id=rc_cur_id' ) ); + + wfRunHooks( 'SpecialNewpagesConditions', + array( &$this, $this->opts, &$conds, &$tables, &$fields, &$join_conds ) ); $info = array( - 'tables' => array( 'recentchanges', 'page' ), - 'fields' => array( - 'rc_namespace', 'rc_title', 'rc_cur_id', 'rc_user', - 'rc_user_text', 'rc_comment', 'rc_timestamp', 'rc_patrolled', - 'rc_id', 'rc_deleted', 'page_len AS length', 'page_latest AS rev_id', - 'ts_tags' - ), - 'conds' => $conds, - 'options' => array( 'USE INDEX' => array( 'recentchanges' => $rcIndexes ) ), - 'join_conds' => array( - 'page' => array( 'INNER JOIN', 'page_id=rc_cur_id' ), - ), + 'tables' => $tables, + 'fields' => $fields, + 'conds' => $conds, + 'options' => array( 'USE INDEX' => array( 'recentchanges' => $rcIndexes ) ), + 'join_conds' => $join_conds ); // Empty array for fields, it'll be set by us anyway. diff --git a/includes/specials/SpecialRecentchanges.php b/includes/specials/SpecialRecentchanges.php index 5840917918..e67b1e416c 100644 --- a/includes/specials/SpecialRecentchanges.php +++ b/includes/specials/SpecialRecentchanges.php @@ -28,6 +28,7 @@ */ class SpecialRecentChanges extends IncludableSpecialPage { var $rcOptions, $rcSubpage; + protected $customFilters; public function __construct( $name = 'Recentchanges' ) { parent::__construct( $name ); @@ -71,6 +72,13 @@ class SpecialRecentChanges extends IncludableSpecialPage { global $wgRequest, $wgRCMaxAge; $opts = $this->getDefaultOptions(); + + $this->customFilters = array(); + wfRunHooks( 'SpecialRecentChangesFilters', array( $this, &$this->customFilters ) ); + foreach( $this->customFilters as $key => $params ) { + $opts->add( $key, $params['default'] ); + } + $opts->fetchValuesFromRequest( $wgRequest ); $opts->validateIntBounds( 'days', 1, $wgRCMaxAge / ( 3600 * 24 ) ); @@ -789,28 +797,28 @@ class SpecialRecentChanges extends IncludableSpecialPage { // show/hide links $showhide = array( wfMsg( 'show' ), wfMsg( 'hide' ) ); - $minorLink = $this->makeOptionsLink( $showhide[1 - $options['hideminor']], - array( 'hideminor' => 1-$options['hideminor'] ), $nondefaults ); - $botLink = $this->makeOptionsLink( $showhide[1 - $options['hidebots']], - array( 'hidebots' => 1-$options['hidebots'] ), $nondefaults ); - $anonsLink = $this->makeOptionsLink( $showhide[ 1 - $options['hideanons'] ], - array( 'hideanons' => 1 - $options['hideanons'] ), $nondefaults ); - $liuLink = $this->makeOptionsLink( $showhide[1 - $options['hideliu']], - array( 'hideliu' => 1-$options['hideliu'] ), $nondefaults ); - $patrLink = $this->makeOptionsLink( $showhide[1 - $options['hidepatrolled']], - array( 'hidepatrolled' => 1-$options['hidepatrolled'] ), $nondefaults ); - $myselfLink = $this->makeOptionsLink( $showhide[1 - $options['hidemyself']], - array( 'hidemyself' => 1-$options['hidemyself'] ), $nondefaults ); - - $links[] = wfMsgHtml( 'rcshowhideminor', $minorLink ); - $links[] = wfMsgHtml( 'rcshowhidebots', $botLink ); - $links[] = wfMsgHtml( 'rcshowhideanons', $anonsLink ); - $links[] = wfMsgHtml( 'rcshowhideliu', $liuLink ); - if( $this->getUser()->useRCPatrol() ) { - $links[] = wfMsgHtml( 'rcshowhidepatr', $patrLink ); - } - $links[] = wfMsgHtml( 'rcshowhidemine', $myselfLink ); - $hl = $wgLang->pipeList( $links ); + $filters = array( + 'hideminor' => 'rcshowhideminor', + 'hidebots' => 'rcshowhidebots', + 'hideanons' => 'rcshowhideanons', + 'hideliu' => 'rcshowhideliu', + 'hidepatrolled' => 'rcshowhidepatr', + 'hidemyself' => 'rcshowhidemine' + ); + foreach ( $this->customFilters as $key => $params ) { + $filters[$key] = $params['msg']; + } + // Disable some if needed + if ( !$this->getUser()->useRCPatrol() ) { + unset( $filters['hidepatrolled'] ); + } + + $links = array(); + foreach ( $filters as $key => $msg ) { + $link = $this->makeOptionsLink( $showhide[1 - $options[$key]], + array( $key => 1-$options[$key] ), $nondefaults ); + $links[] = wfMsgHtml( $msg, $link ); + } // show from this onward link $now = $wgLang->timeanddate( wfTimestampNow(), true ); @@ -819,7 +827,7 @@ class SpecialRecentChanges extends IncludableSpecialPage { ); $rclinks = wfMsgExt( 'rclinks', array( 'parseinline', 'replaceafter' ), - $cl, $dl, $hl ); + $cl, $dl, $wgLang->pipeList( $links ) ); $rclistfrom = wfMsgExt( 'rclistfrom', array( 'parseinline', 'replaceafter' ), $tl ); return "{$note}$rclinks
$rclistfrom"; } diff --git a/includes/specials/SpecialWatchlist.php b/includes/specials/SpecialWatchlist.php index f0529bbc05..0d471b336e 100644 --- a/includes/specials/SpecialWatchlist.php +++ b/includes/specials/SpecialWatchlist.php @@ -21,6 +21,7 @@ * @ingroup SpecialPage Watchlist */ class SpecialWatchlist extends SpecialPage { + protected $customFilters; /** * Constructor @@ -109,6 +110,7 @@ class SpecialWatchlist extends SpecialPage { return; } + // @TODO: use FormOptions! $defaults = array( /* float */ 'days' => floatval( $wgUser->getOption( 'watchlistdays' ) ), /* 3.0 or 0.5, watch further below */ /* bool */ 'hideMinor' => (int)$wgUser->getBoolOption( 'watchlisthideminor' ), @@ -120,6 +122,11 @@ class SpecialWatchlist extends SpecialPage { /* ? */ 'namespace' => 'all', /* ? */ 'invert' => false, ); + $this->customFilters = array(); + wfRunHooks( 'SpecialWatchlistFilters', array( $this, &$this->customFilters ) ); + foreach( $this->customFilters as $key => $params ) { + $defaults[$key] = $params['msg']; + } # Extract variables from the request, falling back to user preferences or # other default values if these don't exist @@ -132,20 +139,24 @@ class SpecialWatchlist extends SpecialPage { $prefs['hidepatrolled' ] = $wgUser->getBoolOption( 'watchlisthidepatrolled' ); # Get query variables - $days = $wgRequest->getVal( 'days' , $prefs['days'] ); - $hideMinor = $wgRequest->getBool( 'hideMinor', $prefs['hideminor'] ); - $hideBots = $wgRequest->getBool( 'hideBots' , $prefs['hidebots'] ); - $hideAnons = $wgRequest->getBool( 'hideAnons', $prefs['hideanons'] ); - $hideLiu = $wgRequest->getBool( 'hideLiu' , $prefs['hideliu'] ); - $hideOwn = $wgRequest->getBool( 'hideOwn' , $prefs['hideown'] ); - $hidePatrolled = $wgRequest->getBool( 'hidePatrolled' , $prefs['hidepatrolled'] ); + $values = array(); + $values['days'] = $wgRequest->getVal( 'days', $prefs['days'] ); + $values['hideMinor'] = (int)$wgRequest->getBool( 'hideMinor', $prefs['hideminor'] ); + $values['hideBots'] = (int)$wgRequest->getBool( 'hideBots' , $prefs['hidebots'] ); + $values['hideAnons'] = (int)$wgRequest->getBool( 'hideAnons', $prefs['hideanons'] ); + $values['hideLiu'] = (int)$wgRequest->getBool( 'hideLiu' , $prefs['hideliu'] ); + $values['hideOwn'] = (int)$wgRequest->getBool( 'hideOwn' , $prefs['hideown'] ); + $values['hidePatrolled'] = (int)$wgRequest->getBool( 'hidePatrolled', $prefs['hidepatrolled'] ); + foreach( $this->customFilters as $key => $params ) { + $values[$key] = (int)$wgRequest->getBool( $key ); + } # Get namespace value, if supplied, and prepare a WHERE fragment $nameSpace = $wgRequest->getIntOrNull( 'namespace' ); $invert = $wgRequest->getIntOrNull( 'invert' ); - if( !is_null( $nameSpace ) ) { - $nameSpace = intval( $nameSpace ); - if( $invert && $nameSpace !== 'all' ) { + if ( !is_null( $nameSpace ) ) { + $nameSpace = intval( $nameSpace ); // paranioa + if ( $invert ) { $nameSpaceClause = "rc_namespace != $nameSpace"; } else { $nameSpaceClause = "rc_namespace = $nameSpace"; @@ -154,6 +165,8 @@ class SpecialWatchlist extends SpecialPage { $nameSpace = ''; $nameSpaceClause = ''; } + $values['namespace'] = $nameSpace; + $values['invert'] = $invert; $dbr = wfGetDB( DB_SLAVE, 'watchlist' ); $recentchanges = $dbr->tableName( 'recentchanges' ); @@ -164,29 +177,23 @@ class SpecialWatchlist extends SpecialPage { // but treated together $nitems = floor( $watchlistCount / 2 ); - if( is_null( $days ) || !is_numeric( $days ) ) { + if( is_null( $values['days'] ) || !is_numeric( $values['days'] ) ) { $big = 1000; /* The magical big */ if( $nitems > $big ) { # Set default cutoff shorter - $days = $defaults['days'] = (12.0 / 24.0); # 12 hours... + $values['days'] = $defaults['days'] = (12.0 / 24.0); # 12 hours... } else { - $days = $defaults['days']; # default cutoff for shortlisters + $values['days'] = $defaults['days']; # default cutoff for shortlisters } } else { - $days = floatval( $days ); + $values['days'] = floatval( $values['days'] ); } // Dump everything here $nondefaults = array(); - - wfAppendToArrayIfNotDefault( 'days' , $days , $defaults, $nondefaults); - wfAppendToArrayIfNotDefault( 'hideMinor', (int)$hideMinor, $defaults, $nondefaults ); - wfAppendToArrayIfNotDefault( 'hideBots' , (int)$hideBots , $defaults, $nondefaults); - wfAppendToArrayIfNotDefault( 'hideAnons', (int)$hideAnons, $defaults, $nondefaults ); - wfAppendToArrayIfNotDefault( 'hideLiu' , (int)$hideLiu , $defaults, $nondefaults ); - wfAppendToArrayIfNotDefault( 'hideOwn' , (int)$hideOwn , $defaults, $nondefaults); - wfAppendToArrayIfNotDefault( 'namespace', $nameSpace , $defaults, $nondefaults); - wfAppendToArrayIfNotDefault( 'hidePatrolled', (int)$hidePatrolled, $defaults, $nondefaults ); + foreach ( $defaults as $name => $defValue ) { + wfAppendToArrayIfNotDefault( $name, $values[$name], $defaults, $nondefaults ); + } if( $nitems == 0 ) { $wgOut->addWikiMsg( 'nowatchlist' ); @@ -196,8 +203,8 @@ class SpecialWatchlist extends SpecialPage { # Possible where conditions $conds = array(); - if( $days > 0 ) { - $conds[] = "rc_timestamp > '".$dbr->timestamp( time() - intval( $days * 86400 ) )."'"; + if( $values['days'] > 0 ) { + $conds[] = "rc_timestamp > '".$dbr->timestamp( time() - intval( $values['days'] * 86400 ) )."'"; } # If the watchlist is relatively short, it's simplest to zip @@ -209,25 +216,25 @@ class SpecialWatchlist extends SpecialPage { # Up estimate of watched items by 15% to compensate for talk pages... # Toggles - if( $hideOwn ) { + if( $values['hideOwn'] ) { $conds[] = "rc_user != $uid"; } - if( $hideBots ) { + if( $values['hideBots'] ) { $conds[] = 'rc_bot = 0'; } - if( $hideMinor ) { + if( $values['hideMinor'] ) { $conds[] = 'rc_minor = 0'; } - if( $hideLiu ) { + if( $values['hideLiu'] ) { $conds[] = 'rc_user = 0'; } - if( $hideAnons ) { + if( $values['hideAnons'] ) { $conds[] = 'rc_user != 0'; } - if ( $wgUser->useRCPatrol() && $hidePatrolled ) { + if ( $wgUser->useRCPatrol() && $values['hidePatrolled'] ) { $conds[] = 'rc_patrolled != 1'; } - if( $nameSpaceClause ) { + if ( $nameSpaceClause ) { $conds[] = $nameSpaceClause; } @@ -299,34 +306,45 @@ class SpecialWatchlist extends SpecialPage { /* Start bottom header */ $wlInfo = ''; - if( $days >= 1 ) { + if( $values['days'] >= 1 ) { $wlInfo = wfMsgExt( 'rcnote', 'parseinline', $wgLang->formatNum( $numRows ), - $wgLang->formatNum( $days ), + $wgLang->formatNum( $values['days'] ), $wgLang->timeAndDate( wfTimestampNow(), true ), $wgLang->date( wfTimestampNow(), true ), $wgLang->time( wfTimestampNow(), true ) ) . '
'; - } elseif( $days > 0 ) { + } elseif( $values['days'] > 0 ) { $wlInfo = wfMsgExt( 'wlnote', 'parseinline', $wgLang->formatNum( $numRows ), - $wgLang->formatNum( round( $days * 24 ) ) + $wgLang->formatNum( round( $values['days'] * 24 ) ) ) . '
'; } - $cutofflinks = "\n" . self::cutoffLinks( $days, 'Watchlist', $nondefaults ) . "
\n"; + $cutofflinks = "\n" . self::cutoffLinks( $values['days'], 'Watchlist', $nondefaults ) . "
\n"; $thisTitle = SpecialPage::getTitleFor( 'Watchlist' ); # Spit out some control panel links - $links[] = self::showHideLink( $nondefaults, 'rcshowhideminor', 'hideMinor', $hideMinor ); - $links[] = self::showHideLink( $nondefaults, 'rcshowhidebots', 'hideBots', $hideBots ); - $links[] = self::showHideLink( $nondefaults, 'rcshowhideanons', 'hideAnons', $hideAnons ); - $links[] = self::showHideLink( $nondefaults, 'rcshowhideliu', 'hideLiu', $hideLiu ); - $links[] = self::showHideLink( $nondefaults, 'rcshowhidemine', 'hideOwn', $hideOwn ); + $filters = array( + 'hideMinor' => 'rcshowhideminor', + 'hideBots' => 'rcshowhidebots', + 'hideAnons' => 'rcshowhideanons', + 'hideLiu' => 'rcshowhideliu', + 'hideOwn' => 'rcshowhidemine', + 'hidePatrolled' => 'rcshowhidepatr' + ); + foreach ( $this->customFilters as $key => $params ) { + $filters[$key] = $params['msg']; + } + // Disable some if needed + if ( !$wgUser->useNPPatrol() ) { + unset( $filters['hidePatrolled'] ); + } - if( $wgUser->useRCPatrol() ) { - $links[] = self::showHideLink( $nondefaults, 'rcshowhidepatr', 'hidePatrolled', $hidePatrolled ); + $links = array(); + foreach( $filters as $name => $msg ) { + $links[] = self::showHideLink( $nondefaults, $msg, $name, $values[$name] ); } # Namespace filter and put the whole form together. @@ -339,21 +357,11 @@ class SpecialWatchlist extends SpecialPage { $form .= Xml::namespaceSelector( $nameSpace, '' ) . ' '; $form .= Xml::checkLabel( wfMsg('invert'), 'invert', 'nsinvert', $invert ) . ' '; $form .= Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . '

'; - $form .= Html::hidden( 'days', $days ); - if( $hideMinor ) { - $form .= Html::hidden( 'hideMinor', 1 ); - } - if( $hideBots ) { - $form .= Html::hidden( 'hideBots', 1 ); - } - if( $hideAnons ) { - $form .= Html::hidden( 'hideAnons', 1 ); - } - if( $hideLiu ) { - $form .= Html::hidden( 'hideLiu', 1 ); - } - if( $hideOwn ) { - $form .= Html::hidden( 'hideOwn', 1 ); + $form .= Html::hidden( 'days', $values['days'] ); + foreach ( $filters as $key => $msg ) { + if ( $values[$key] ) { + $form .= Html::hidden( $key, 1 ); + } } $form .= Xml::closeElement( 'form' ); $form .= Xml::closeElement( 'fieldset' ); -- 2.20.1