X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2Fpager%2FIndexPager.php;h=472bcdd8a2b4c80b84f430e7309050de7f599647;hb=2ec627ea02ad07db4842d3d53a1cce2b3c1384ee;hp=ce1d2d076ce829d3000be2e699e2f80ad5f8324f;hpb=c2cedf71ee1464f8b4c974906cbca4c8cd80a4e6;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/pager/IndexPager.php b/includes/pager/IndexPager.php index ce1d2d076c..472bcdd8a2 100644 --- a/includes/pager/IndexPager.php +++ b/includes/pager/IndexPager.php @@ -21,8 +21,12 @@ * @ingroup Pager */ -use Wikimedia\Rdbms\IResultWrapper; +use MediaWiki\Linker\LinkRenderer; +use MediaWiki\Linker\LinkTarget; +use MediaWiki\MediaWikiServices; +use MediaWiki\Navigation\PrevNextNavigationRenderer; use Wikimedia\Rdbms\IDatabase; +use Wikimedia\Rdbms\IResultWrapper; /** * IndexPager is an efficient pager which uses a (roughly unique) index in the @@ -67,21 +71,23 @@ use Wikimedia\Rdbms\IDatabase; * @ingroup Pager */ abstract class IndexPager extends ContextSource implements Pager { - /** - * Constants for the $mDefaultDirection field. - * - * These are boolean for historical reasons and should stay boolean for backwards-compatibility. - */ + /** Backwards-compatible constant for $mDefaultDirection field (do not change) */ const DIR_ASCENDING = false; + /** Backwards-compatible constant for $mDefaultDirection field (do not change) */ const DIR_DESCENDING = true; + /** Backwards-compatible constant for reallyDoQuery() (do not change) */ + const QUERY_ASCENDING = true; + /** Backwards-compatible constant for reallyDoQuery() (do not change) */ + const QUERY_DESCENDING = false; + /** @var WebRequest */ public $mRequest; /** @var int[] List of default entry limit options to be presented to clients */ public $mLimitsShown = [ 20, 50, 100, 250, 500 ]; /** @var int The default entry limit choosen for clients */ public $mDefaultLimit = 50; - /** @var string|int The starting point to enumerate entries */ + /** @var mixed The starting point to enumerate entries */ public $mOffset; /** @var int The maximum number of entries to show */ public $mLimit; @@ -89,20 +95,23 @@ abstract class IndexPager extends ContextSource implements Pager { public $mQueryDone = false; /** @var IDatabase */ public $mDb; - /** @var stdClass|null Extra row fetched at the end to see if the end was reached */ + /** @var stdClass|bool|null Extra row fetched at the end to see if the end was reached */ public $mPastTheEndRow; /** * The index to actually be used for ordering. This is a single column, * for one ordering, even if multiple orderings are supported. + * @var string */ protected $mIndexField; /** * An array of secondary columns to order by. These fields are not part of the offset. * This is a column list for one ordering, even if multiple orderings are supported. + * @var string[] */ protected $mExtraSortFields; /** For pages that support multiple types of ordering, which one to use. + * @var string|null */ protected $mOrderType; /** @@ -115,18 +124,31 @@ abstract class IndexPager extends ContextSource implements Pager { * * Like $mIndexField, $mDefaultDirection will be a single value even if the * class supports multiple default directions for different order types. + * @var bool */ public $mDefaultDirection; + /** @var bool */ public $mIsBackwards; - /** True if the current result set is the first one */ + /** @var bool True if the current result set is the first one */ public $mIsFirst; + /** @var bool */ public $mIsLast; - protected $mLastShown, $mFirstShown, $mPastTheEndIndex, $mDefaultQuery, $mNavigationBar; + /** @var mixed */ + protected $mLastShown; + /** @var mixed */ + protected $mFirstShown; + /** @var mixed */ + protected $mPastTheEndIndex; + /** @var array */ + protected $mDefaultQuery; + /** @var string */ + protected $mNavigationBar; /** * Whether to include the offset in the query + * @var bool */ protected $mIncludeOffset = false; @@ -137,7 +159,10 @@ abstract class IndexPager extends ContextSource implements Pager { */ public $mResult; - public function __construct( IContextSource $context = null ) { + /** @var LinkRenderer */ + private $linkRenderer; + + public function __construct( IContextSource $context = null, LinkRenderer $linkRenderer = null ) { if ( $context ) { $this->setContext( $context ); } @@ -189,6 +214,7 @@ abstract class IndexPager extends ContextSource implements Pager { ? $dir[$this->mOrderType] : $dir; } + $this->linkRenderer = $linkRenderer; } /** @@ -208,11 +234,13 @@ abstract class IndexPager extends ContextSource implements Pager { public function doQuery() { # Use the child class name for profiling $fname = __METHOD__ . ' (' . static::class . ')'; + /** @noinspection PhpUnusedLocalVariableInspection */ $section = Profiler::instance()->scopedProfileIn( $fname ); - $descending = $this->mIsBackwards - ? ( $this->mDefaultDirection === self::DIR_DESCENDING ) - : ( $this->mDefaultDirection === self::DIR_ASCENDING ); + $defaultOrder = ( $this->mDefaultDirection === self::DIR_ASCENDING ) + ? self::QUERY_ASCENDING + : self::QUERY_DESCENDING; + $order = $this->mIsBackwards ? self::oppositeOrder( $defaultOrder ) : $defaultOrder; # Plus an extra row so that we can tell the "next" link should be shown $queryLimit = $this->mLimit + 1; @@ -225,14 +253,15 @@ abstract class IndexPager extends ContextSource implements Pager { // direction see if we get a row. $oldIncludeOffset = $this->mIncludeOffset; $this->mIncludeOffset = !$this->mIncludeOffset; - $isFirst = !$this->reallyDoQuery( $this->mOffset, 1, !$descending )->numRows(); + $oppositeOrder = self::oppositeOrder( $order ); + $isFirst = !$this->reallyDoQuery( $this->mOffset, 1, $oppositeOrder )->numRows(); $this->mIncludeOffset = $oldIncludeOffset; } $this->mResult = $this->reallyDoQuery( $this->mOffset, $queryLimit, - $descending + $order ); $this->extractResultInfo( $isFirst, $queryLimit, $this->mResult ); @@ -242,6 +271,16 @@ abstract class IndexPager extends ContextSource implements Pager { $this->mResult->rewind(); // Paranoia } + /** + * @param bool $order One of the IndexPager::QUERY_* class constants + * @return bool The opposite query order as an IndexPager::QUERY_ constant + */ + final protected static function oppositeOrder( $order ) { + return ( $order === self::QUERY_ASCENDING ) + ? self::QUERY_DESCENDING + : self::QUERY_ASCENDING; + } + /** * @return IResultWrapper The result wrapper. */ @@ -364,17 +403,18 @@ abstract class IndexPager extends ContextSource implements Pager { } /** - * Do a query with specified parameters, rather than using the object - * context + * Do a query with specified parameters, rather than using the object context + * + * @note For b/c, query direction is true for ascending and false for descending * * @param string $offset Index offset, inclusive * @param int $limit Exact query limit - * @param bool $descending Query direction, false for ascending, true for descending + * @param bool $order IndexPager::QUERY_ASCENDING or IndexPager::QUERY_DESCENDING * @return IResultWrapper */ - public function reallyDoQuery( $offset, $limit, $descending ) { + public function reallyDoQuery( $offset, $limit, $order ) { list( $tables, $fields, $conds, $fname, $options, $join_conds ) = - $this->buildQueryInfo( $offset, $limit, $descending ); + $this->buildQueryInfo( $offset, $limit, $order ); return $this->mDb->select( $tables, $fields, $conds, $fname, $options, $join_conds ); } @@ -382,12 +422,14 @@ abstract class IndexPager extends ContextSource implements Pager { /** * Build variables to use by the database wrapper. * + * @note For b/c, query direction is true for ascending and false for descending + * * @param string $offset Index offset, inclusive * @param int $limit Exact query limit - * @param bool $descending Query direction, false for ascending, true for descending + * @param bool $order IndexPager::QUERY_ASCENDING or IndexPager::QUERY_DESCENDING * @return array */ - protected function buildQueryInfo( $offset, $limit, $descending ) { + protected function buildQueryInfo( $offset, $limit, $order ) { $fname = __METHOD__ . ' (' . $this->getSqlComment() . ')'; $info = $this->getQueryInfo(); $tables = $info['tables']; @@ -396,7 +438,7 @@ abstract class IndexPager extends ContextSource implements Pager { $options = $info['options'] ?? []; $join_conds = $info['join_conds'] ?? []; $sortColumns = array_merge( [ $this->mIndexField ], $this->mExtraSortFields ); - if ( $descending ) { + if ( $order === self::QUERY_ASCENDING ) { $options['ORDER BY'] = $sortColumns; $operator = $this->mIncludeOffset ? '>=' : '>'; } else { @@ -490,9 +532,9 @@ abstract class IndexPager extends ContextSource implements Pager { $attrs['class'] = "mw-{$type}link"; } - return Linker::linkKnown( + return $this->getLinkRenderer()->makeKnownLink( $this->getTitle(), - $text, + new HtmlArmor( $text ), $attrs, $query + $this->getDefaultQuery() ); @@ -750,4 +792,29 @@ abstract class IndexPager extends ContextSource implements Pager { protected function getDefaultDirections() { return self::DIR_ASCENDING; } + + /** + * Generate (prev x| next x) (20|50|100...) type links for paging + * + * @param LinkTarget $title + * @param int $offset + * @param int $limit + * @param array $query Optional URL query parameter string + * @param bool $atend Optional param for specified if this is the last page + * @return string + */ + protected function buildPrevNextNavigation( LinkTarget $title, $offset, $limit, + array $query = [], $atend = false + ) { + $prevNext = new PrevNextNavigationRenderer( $this ); + + return $prevNext->buildPrevNextNavigation( $title, $offset, $limit, $query, $atend ); + } + + protected function getLinkRenderer() { + if ( $this->linkRenderer === null ) { + $this->linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer(); + } + return $this->linkRenderer; + } }