Merge "SpecialUserrights: Use session data instead of URL parameter for success"
[lhc/web/wiklou.git] / includes / specialpage / QueryPage.php
index 83e6db3..3592500 100644 (file)
@@ -376,7 +376,7 @@ abstract class QueryPage extends SpecialPage {
         * @return IDatabase
         */
        function getRecacheDB() {
-               return wfGetDB( DB_SLAVE, [ $this->getName(), 'QueryPage::recache', 'vslow' ] );
+               return wfGetDB( DB_REPLICA, [ $this->getName(), 'QueryPage::recache', 'vslow' ] );
        }
 
        /**
@@ -453,7 +453,7 @@ abstract class QueryPage extends SpecialPage {
         * @since 1.18
         */
        public function fetchFromCache( $limit, $offset = false ) {
-               $dbr = wfGetDB( DB_SLAVE );
+               $dbr = wfGetDB( DB_REPLICA );
                $options = [];
                if ( $limit !== false ) {
                        $options['LIMIT'] = intval( $limit );
@@ -477,7 +477,7 @@ abstract class QueryPage extends SpecialPage {
 
        public function getCachedTimestamp() {
                if ( is_null( $this->cachedTimestamp ) ) {
-                       $dbr = wfGetDB( DB_SLAVE );
+                       $dbr = wfGetDB( DB_REPLICA );
                        $fname = get_class( $this ) . '::getCachedTimestamp';
                        $this->cachedTimestamp = $dbr->selectField( 'querycache_info', 'qci_timestamp',
                                [ 'qci_type' => $this->getName() ], $fname );
@@ -490,24 +490,43 @@ abstract class QueryPage extends SpecialPage {
         * Subclasses may override this to further restrict or modify limit and offset.
         *
         * @note Restricts the offset parameter, as most query pages have inefficient paging
-        * @since 1.26
         *
+        * Its generally expected that the returned limit will not be 0, and the returned
+        * offset will be less than the max results.
+        *
+        * @since 1.26
         * @return int[] list( $limit, $offset )
         */
        protected function getLimitOffset() {
                list( $limit, $offset ) = $this->getRequest()->getLimitOffset();
-               if ( !$this->getConfig()->get( 'MiserMode' ) ) {
+               if ( $this->getConfig()->get( 'MiserMode' ) ) {
                        $maxResults = $this->getMaxResults();
                        // Can't display more than max results on a page
                        $limit = min( $limit, $maxResults );
-                       // Can't skip over more than $maxResults
-                       $offset = min( $offset, $maxResults );
-                       // Can't let $offset + $limit > $maxResults
-                       $limit = min( $limit, $maxResults - $offset );
+                       // Can't skip over more than the end of $maxResults
+                       $offset = min( $offset, $maxResults + 1 );
                }
                return [ $limit, $offset ];
        }
 
+       /**
+        * What is limit to fetch from DB
+        *
+        * Used to make it appear the DB stores less results then it actually does
+        * @param int $uiLimit Limit from UI
+        * @param int $uiOffset Offset from UI
+        * @return int Limit to use for DB (not including extra row to see if at end)
+        */
+       protected function getDBLimit( $uiLimit, $uiOffset ) {
+               $maxResults = $this->getMaxResults();
+               if ( $this->getConfig()->get( 'MiserMode' ) ) {
+                       $limit = min( $uiLimit + 1, $maxResults - $uiOffset );
+                       return max( $limit, 0 );
+               } else {
+                       return $uiLimit + 1;
+               }
+       }
+
        /**
         * Get max number of results we can return in miser mode.
         *
@@ -518,7 +537,7 @@ abstract class QueryPage extends SpecialPage {
         * @return int
         */
        protected function getMaxResults() {
-               // Max of 10000, unless we store more than 5000 in query cache.
+               // Max of 10000, unless we store more than 10000 in query cache.
                return max( $this->getConfig()->get( 'QueryCacheLimit' ), 10000 );
        }
 
@@ -549,14 +568,14 @@ abstract class QueryPage extends SpecialPage {
                if ( $this->limit == 0 && $this->offset == 0 ) {
                        list( $this->limit, $this->offset ) = $this->getLimitOffset();
                }
-
+               $dbLimit = $this->getDBLimit( $this->limit, $this->offset );
                // @todo Use doQuery()
                if ( !$this->isCached() ) {
                        # select one extra row for navigation
-                       $res = $this->reallyDoQuery( $this->limit + 1, $this->offset );
+                       $res = $this->reallyDoQuery( $dbLimit, $this->offset );
                } else {
                        # Get the cached result, select one extra row for navigation
-                       $res = $this->fetchFromCache( $this->limit + 1, $this->offset );
+                       $res = $this->fetchFromCache( $dbLimit, $this->offset );
                        if ( !$this->listoutput ) {
 
                                # Fetch the timestamp of this update
@@ -603,8 +622,9 @@ abstract class QueryPage extends SpecialPage {
                                        min( $this->numRows, $this->limit ), # do not show the one extra row, if exist
                                        $this->offset + 1, ( min( $this->numRows, $this->limit ) + $this->offset ) )->parseAsBlock() );
                                # Disable the "next" link when we reach the end
-                               $atEnd = ( $this->numRows <= $this->limit )
-                                       || ( $this->offset + $this-> limit  >= $this->getMaxResults() );
+                               $miserMaxResults = $this->getConfig()->get( 'MiserMode' )
+                                       && ( $this->offset + $this->limit >= $this->getMaxResults() );
+                               $atEnd = ( $this->numRows <= $this->limit ) || $miserMaxResults;
                                $paging = $this->getLanguage()->viewPrevNext( $this->getPageTitle( $par ), $this->offset,
                                        $this->limit, $this->linkParameters(), $atEnd );
                                $out->addHTML( '<p>' . $paging . '</p>' );
@@ -805,4 +825,28 @@ abstract class QueryPage extends SpecialPage {
        function feedUrl() {
                return $this->getPageTitle()->getFullURL();
        }
+
+       /**
+        * Creates a new LinkBatch object, adds all pages from the passed ResultWrapper (MUST include
+        * title and optional the namespace field) and executes the batch. This operation will pre-cache
+        * LinkCache information like page existence and information for stub color and redirect hints.
+        *
+        * @param ResultWrapper $res The ResultWrapper object to process. Needs to include the title
+        *  field and namespace field, if the $ns parameter isn't set.
+        * @param null $ns Use this namespace for the given titles in the ResultWrapper object,
+        *  instead of the namespace value of $res.
+        */
+       protected function executeLBFromResultWrapper( ResultWrapper $res, $ns = null ) {
+               if ( !$res->numRows() ) {
+                       return;
+               }
+
+               $batch = new LinkBatch;
+               foreach ( $res as $row ) {
+                       $batch->add( $ns !== null ? $ns : $row->namespace, $row->title );
+               }
+               $batch->execute();
+
+               $res->seek( 0 );
+       }
 }