API: Requesting a token you aren't allowed to request no longer dies with an error...
[lhc/web/wiklou.git] / includes / SpecialRecentchanges.php
index 763f136..7afd21f 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 /**
- *
- * @addtogroup SpecialPage
+ * @file
+ * @ingroup SpecialPage
  */
 
 /**
@@ -102,11 +102,8 @@ function wfSpecialRecentchanges( $par, $specialPage ) {
 
        if ( $limit < 0 || $limit > 5000 ) $limit = $defaults['limit'];
 
-
        # Database connection and caching
        $dbr = wfGetDB( DB_SLAVE );
-       list( $recentchanges, $watchlist ) = $dbr->tableNamesN( 'recentchanges', 'watchlist' );
-
 
        $cutoff_unixtime = time() - ( $days * 86400 );
        $cutoff_unixtime = $cutoff_unixtime - ($cutoff_unixtime % 86400);
@@ -159,22 +156,51 @@ function wfSpecialRecentchanges( $par, $specialPage ) {
                }
        }
 
-       # Namespace filtering
-       $hidem .= is_null( $namespace ) ?  '' : ' AND rc_namespace' . ($invert ? '!=' : '=') . $namespace;
-
-       // This is the big thing!
-
+       // JOIN on watchlist for users
        $uid = $wgUser->getID();
-
-       // Perform query
-       $forceclause = $dbr->useIndexClause("rc_timestamp");
-       $sql2 = "SELECT * FROM $recentchanges $forceclause".
-         ($uid ? "LEFT OUTER JOIN $watchlist ON wl_user={$uid} AND wl_title=rc_title AND wl_namespace=rc_namespace " : "") .
-         "WHERE rc_timestamp >= '{$cutoff}' {$hidem} " .
-         "ORDER BY rc_timestamp DESC";
-       $sql2 = $dbr->limitResult($sql2, $limit, 0);
-       $res = $dbr->query( $sql2, $fname );
-
+       if( $uid ) {
+               $tables = array( 'recentchanges', 'watchlist' );
+               $join_conds = array( 'watchlist' => array('LEFT JOIN',"wl_user={$uid} AND wl_title=rc_title AND wl_namespace=rc_namespace") );
+       } else {
+               $tables = array( 'recentchanges' );
+               $join_conds = array();
+       }
+       
+       # Namespace filtering
+       $hidem .= is_null($namespace) ?  '' : ' AND rc_namespace' . ($invert ? '!=' : '=') . $namespace;
+       
+       // Is there either one namespace selected or excluded?
+       // Also, if this is "all" or main namespace, just use timestamp index.
+       if( is_null($namespace) || $invert || $namespace == NS_MAIN ) {
+               $res = $dbr->select( $tables, '*',
+                       array( "rc_timestamp >= '{$cutoff}' {$hidem}" ),
+                       __METHOD__,
+                       array( 'ORDER BY' => 'rc_timestamp DESC', 'LIMIT' => $limit, 
+                               'USE INDEX' => array('recentchanges' => 'rc_timestamp') ),
+                       $join_conds );
+       // We have a new_namespace_time index! UNION over new=(0,1) and sort result set!
+       } else {
+               // New pages
+               $sqlNew = $dbr->selectSQLText( $tables, '*',
+                       array( 'rc_new' => 1,
+                               "rc_timestamp >= '{$cutoff}' {$hidem}" ),
+                       __METHOD__,
+                       array( 'ORDER BY' => 'rc_timestamp DESC', 'LIMIT' => $limit, 
+                               'USE INDEX' =>  array('recentchanges' => 'new_name_timestamp') ),
+                       $join_conds );
+               // Old pages
+               $sqlOld = $dbr->selectSQLText( $tables, '*',
+                       array( 'rc_new' => 0,
+                               "rc_timestamp >= '{$cutoff}' {$hidem}" ),
+                       __METHOD__,
+                       array( 'ORDER BY' => 'rc_timestamp DESC', 'LIMIT' => $limit, 
+                               'USE INDEX' =>  array('recentchanges' => 'new_name_timestamp') ),
+                       $join_conds );
+               # Join the two fast queries, and sort the result set
+               $sql = "($sqlNew) UNION ($sqlOld) ORDER BY rc_timestamp DESC LIMIT $limit";
+               $res = $dbr->query( $sql, __METHOD__ );
+       }
+       
        // Fetch results, prepare a batch link existence check query
        $rows = array();
        $batch = new LinkBatch;
@@ -300,7 +326,7 @@ function rcFilterByCategories ( &$rows , $categories , $any ) {
        $articles = array () ;
        $a2r = array () ;
        foreach ( $rows AS $k => $r ) {
-               $nt = Title::makeTitle( $r->rc_title , $r->rc_namespace );
+               $nt = Title::makeTitle( $r->rc_namespace, $r->rc_title );
                $id = $nt->getArticleID() ;
                if ( $id == 0 ) continue ; # Page might have been deleted...
                if ( !in_array ( $id , $articles ) ) {
@@ -451,24 +477,26 @@ function rcDoOutputFeed( $rows, &$feed ) {
 /**
  *
  */
-function rcCountLink( $lim, $d, $page='Recentchanges', $more='' ) {
+function rcCountLink( $lim, $d, $page='Recentchanges', $more='', $active = false ) {
        global $wgUser, $wgLang, $wgContLang;
        $sk = $wgUser->getSkin();
        $s = $sk->makeKnownLink( $wgContLang->specialPage( $page ),
          ($lim ? $wgLang->formatNum( "{$lim}" ) : wfMsg( 'recentchangesall' ) ), "{$more}" .
-         ($d ? "days={$d}&" : '') . 'limit='.$lim );
+         ($d ? "days={$d}&" : '') . 'limit='.$lim, '', '',
+         $active ? 'style="font-weight: bold;"' : '' );
        return $s;
 }
 
 /**
  *
  */
-function rcDaysLink( $lim, $d, $page='Recentchanges', $more='' ) {
+function rcDaysLink( $lim, $d, $page='Recentchanges', $more='', $active = false ) {
        global $wgUser, $wgLang, $wgContLang;
        $sk = $wgUser->getSkin();
        $s = $sk->makeKnownLink( $wgContLang->specialPage( $page ),
          ($d ? $wgLang->formatNum( "{$d}" ) : wfMsg( 'recentchangesall' ) ), $more.'days='.$d .
-         ($lim ? '&limit='.$lim : '') );
+         ($lim ? '&limit='.$lim : ''), '', '',
+         $active ? 'style="font-weight: bold;"' : '' );
        return $s;
 }
 
@@ -477,19 +505,31 @@ function rcDaysLink( $lim, $d, $page='Recentchanges', $more='' ) {
  */
 function rcDayLimitLinks( $days, $limit, $page='Recentchanges', $more='', $doall = false, $minorLink = '',
        $botLink = '', $liuLink = '', $patrLink = '', $myselfLink = '' ) {
+       global $wgRCLinkLimits, $wgRCLinkDays;
        if ($more != '') $more .= '&';
-       $cl = rcCountLink( 50, $days, $page, $more ) . ' | ' .
-         rcCountLink( 100, $days, $page, $more  ) . ' | ' .
-         rcCountLink( 250, $days, $page, $more  ) . ' | ' .
-         rcCountLink( 500, $days, $page, $more  ) .
-         ( $doall ? ( ' | ' . rcCountLink( 0, $days, $page, $more ) ) : '' );
-       $dl = rcDaysLink( $limit, 1, $page, $more  ) . ' | ' .
-         rcDaysLink( $limit, 3, $page, $more  ) . ' | ' .
-         rcDaysLink( $limit, 7, $page, $more  ) . ' | ' .
-         rcDaysLink( $limit, 14, $page, $more  ) . ' | ' .
-         rcDaysLink( $limit, 30, $page, $more  ) .
-         ( $doall ? ( ' | ' . rcDaysLink( $limit, 0, $page, $more ) ) : '' );
-
+       
+       # Sort data for display and make sure it's unique after we've added user data.
+       $wgRCLinkLimits[] = $limit;
+       $wgRCLinkDays[] = $days;
+       sort($wgRCLinkLimits);
+       sort($wgRCLinkDays);
+       $wgRCLinkLimits = array_unique($wgRCLinkLimits);
+       $wgRCLinkDays = array_unique($wgRCLinkDays);
+       
+       $cl = array();
+       foreach( $wgRCLinkLimits as $countLink ) {
+               $cl[] = rcCountLink( $countLink, $days, $page, $more, $countLink == $limit );
+       }
+       if( $doall ) $cl[] = rcCountLink( 0, $days, $page, $more );
+       $cl = implode( ' | ', $cl);
+       
+       $dl = array();
+       foreach( $wgRCLinkDays as $daysLink ) {
+               $dl[] = rcDaysLink( $limit, $daysLink, $page, $more, $daysLink == $days );
+       }
+       if( $doall ) $dl[] = rcDaysLink( $limit, 0, $page, $more );
+       $dl = implode( ' | ', $dl);
+       
        $linkParts = array( 'minorLink' => 'minor', 'botLink' => 'bots', 'liuLink' => 'liu', 'patrLink' => 'patr', 'myselfLink' => 'mine' );
        foreach( $linkParts as $linkVar => $linkMsg ) {
                if( $$linkVar != '' )
@@ -508,11 +548,12 @@ function rcDayLimitLinks( $days, $limit, $page='Recentchanges', $more='', $doall
  * @param $override
  * @param $options
  */
-function makeOptionsLink( $title, $override, $options ) {
+function makeOptionsLink( $title, $override, $options, $active = false ) {
        global $wgUser, $wgContLang;
        $sk = $wgUser->getSkin();
        return $sk->makeKnownLink( $wgContLang->specialPage( 'Recentchanges' ),
-               htmlspecialchars( $title ), wfArrayToCGI( $override, $options ) );
+               htmlspecialchars( $title ), wfArrayToCGI( $override, $options ), '', '',
+               $active ? 'style="font-weight: bold;"' : '' );
 }
 
 /**
@@ -521,7 +562,7 @@ function makeOptionsLink( $title, $override, $options ) {
  * @param $nondefaults
  */
 function rcOptionsPanel( $defaults, $nondefaults ) {
-       global $wgLang, $wgUser;
+       global $wgLang, $wgUser, $wgRCLinkLimits, $wgRCLinkDays;
 
        $options = $nondefaults + $defaults;
 
@@ -535,19 +576,25 @@ function rcOptionsPanel( $defaults, $nondefaults ) {
                        $wgLang->formatNum( $options['days'] ),
                        $wgLang->timeAndDate( wfTimestampNow(), true ) );
 
+       # Sort data for display and make sure it's unique after we've added user data.
+       $wgRCLinkLimits[] = $options['limit'];
+       $wgRCLinkDays[] = $options['days'];
+       sort($wgRCLinkLimits);
+       sort($wgRCLinkDays);
+       $wgRCLinkLimits = array_unique($wgRCLinkLimits);
+       $wgRCLinkDays = array_unique($wgRCLinkDays);
+       
        // limit links
-       $options_limit = array(50, 100, 250, 500);
-       foreach( $options_limit as $value ) {
+       foreach( $wgRCLinkLimits as $value ) {
                $cl[] = makeOptionsLink( $wgLang->formatNum( $value ),
-                       array( 'limit' => $value ), $nondefaults) ;
+                       array( 'limit' => $value ), $nondefaults, $value == $options['limit'] ) ;
        }
        $cl = implode( ' | ', $cl);
 
        // day links, reset 'from' to none
-       $options_days = array(1, 3, 7, 14, 30);
-       foreach( $options_days as $value ) {
+       foreach( $wgRCLinkDays as $value ) {
                $dl[] = makeOptionsLink( $wgLang->formatNum( $value ),
-                       array( 'days' => $value, 'from' => ''  ), $nondefaults) ;
+                       array( 'days' => $value, 'from' => '' ), $nondefaults, $value == $options['days'] ) ;
        }
        $dl = implode( ' | ', $dl);