MovePage::moveSubpagesIfAllowed.
* The MWNamespace class is deprecated. Use MediaWikiServices::getNamespaceInfo.
* (T62260) Hard deprecate Language::getExtraUserToggles() method.
+* Language::viewPrevNext function is deprecated, use
+ PrevNextNavigationRenderer::buildPrevNextNavigation instead
=== Other changes in 1.34 ===
* …
'MediaWiki\\Logger\\NullSpi' => __DIR__ . '/includes/debug/logger/NullSpi.php',
'MediaWiki\\Logger\\Spi' => __DIR__ . '/includes/debug/logger/Spi.php',
'MediaWiki\\MediaWikiServices' => __DIR__ . '/includes/MediaWikiServices.php',
+ 'MediaWiki\\Navigation\\PrevNextNavigationRenderer' => __DIR__ . '/includes/Navigation/PrevNextNavigationRenderer.php',
'MediaWiki\\OutputHandler' => __DIR__ . '/includes/OutputHandler.php',
'MediaWiki\\ProcOpenError' => __DIR__ . '/includes/exception/ProcOpenError.php',
'MediaWiki\\Search\\ParserOutputSearchDataExtractor' => __DIR__ . '/includes/search/ParserOutputSearchDataExtractor.php',
--- /dev/null
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+namespace MediaWiki\Navigation;
+
+use MediaWiki\Linker\LinkTarget;
+use MessageLocalizer;
+use Html;
+
+/**
+ * Helper class for generating prev/next links for paging.
+ *
+ * @since 1.34
+ */
+class PrevNextNavigationRenderer {
+
+ /**
+ * @var MessageLocalizer
+ */
+ private $messageLocalizer;
+
+ public function __construct( MessageLocalizer $messageLocalizer ) {
+ $this->messageLocalizer = $messageLocalizer;
+ }
+
+ /**
+ * Generate (prev x| next x) (20|50|100...) type links for paging
+ *
+ * @param LinkTarget $title LinkTarget object to link
+ * @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
+ */
+ public function buildPrevNextNavigation( LinkTarget $title, $offset, $limit,
+ array $query = [], $atend = false
+ ) {
+ # Make 'previous' link
+ $prev = $this->messageLocalizer->msg( 'prevn' )->title( $title )
+ ->numParams( $limit )->text();
+
+ if ( $offset > 0 ) {
+ $plink = $this->numLink( $title, max( $offset - $limit, 0 ), $limit, $query,
+ $prev, 'prevn-title', 'mw-prevlink' );
+ } else {
+ $plink = htmlspecialchars( $prev );
+ }
+
+ # Make 'next' link
+ $next = $this->messageLocalizer->msg( 'nextn' )->title( $title )
+ ->numParams( $limit )->text();
+ if ( $atend ) {
+ $nlink = htmlspecialchars( $next );
+ } else {
+ $nlink = $this->numLink( $title, $offset + $limit, $limit,
+ $query, $next, 'nextn-title', 'mw-nextlink' );
+ }
+
+ # Make links to set number of items per page
+ $numLinks = [];
+ $lang = $this->messageLocalizer->getLanguage();
+ foreach ( [ 20, 50, 100, 250, 500 ] as $num ) {
+ $numLinks[] = $this->numLink( $title, $offset, $num, $query,
+ $lang->formatNum( $num ), 'shown-title', 'mw-numlink' );
+ }
+
+ return $this->messageLocalizer->msg( 'viewprevnext' )->title( $title
+ )->rawParams( $plink, $nlink, $lang->pipeList( $numLinks ) )->escaped();
+ }
+
+ /**
+ * Helper function for buildPrevNextNavigation() that generates links
+ *
+ * @param LinkTarget $title LinkTarget object to link
+ * @param int $offset
+ * @param int $limit
+ * @param array $query Extra query parameters
+ * @param string $link Text to use for the link; will be escaped
+ * @param string $tooltipMsg Name of the message to use as tooltip
+ * @param string $class Value of the "class" attribute of the link
+ * @return string HTML fragment
+ */
+ private function numLink( LinkTarget $title, $offset, $limit, array $query, $link,
+ $tooltipMsg, $class
+ ) {
+ $query = [ 'limit' => $limit, 'offset' => $offset ] + $query;
+ $tooltip = $this->messageLocalizer->msg( $tooltipMsg )->title( $title )
+ ->numParams( $limit )->text();
+ return Html::element( 'a', [ 'href' => $title->getLocalURL( $query ),
+ 'title' => $tooltip, 'class' => $class ], $link );
+ }
+
+}
use Wikimedia\Rdbms\IResultWrapper;
use Wikimedia\Rdbms\IDatabase;
+use MediaWiki\Linker\LinkTarget;
+use MediaWiki\Navigation\PrevNextNavigationRenderer;
/**
* IndexPager is an efficient pager which uses a (roughly unique) index in the
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 );
+ }
}
use MediaWiki\Auth\AuthManager;
use MediaWiki\Linker\LinkRenderer;
use MediaWiki\MediaWikiServices;
+use MediaWiki\Navigation\PrevNextNavigationRenderer;
/**
* Parent class for all special pages.
* @return string
*/
protected function buildPrevNextNavigation( $offset, $limit,
- array $query = [], $atend = false, $subpage = false
+ array $query = [], $atend = false, $subpage = false
) {
- $lang = $this->getLanguage();
+ $title = $this->getPageTitle( $subpage );
+ $prevNext = new PrevNextNavigationRenderer( $this );
- # Make 'previous' link
- $prev = $this->msg( 'prevn' )->numParams( $limit )->text();
- if ( $offset > 0 ) {
- $plink = $this->numLink( max( $offset - $limit, 0 ), $limit, $query,
- $prev, 'prevn-title', 'mw-prevlink', $subpage );
- } else {
- $plink = htmlspecialchars( $prev );
- }
-
- # Make 'next' link
- $next = $this->msg( 'nextn' )->numParams( $limit )->text();
- if ( $atend ) {
- $nlink = htmlspecialchars( $next );
- } else {
- $nlink = $this->numLink( $offset + $limit, $limit,
- $query, $next, 'nextn-title', 'mw-nextlink', $subpage );
- }
-
- # Make links to set number of items per page
- $numLinks = [];
- foreach ( [ 20, 50, 100, 250, 500 ] as $num ) {
- $numLinks[] = $this->numLink( $offset, $num, $query,
- $lang->formatNum( $num ), 'shown-title', 'mw-numlink', $subpage );
- }
-
- return $this->msg( 'viewprevnext' )->rawParams( $plink, $nlink, $lang->pipeList( $numLinks ) )->
- escaped();
- }
-
- /**
- * Helper function for buildPrevNextNavigation() that generates links
- *
- * @param int $offset
- * @param int $limit
- * @param array $query Extra query parameters
- * @param string $link Text to use for the link; will be escaped
- * @param string $tooltipMsg Name of the message to use as tooltip
- * @param string $class Value of the "class" attribute of the link
- * @param string|bool $subpage Optional param for specifying subpage
- * @return string HTML fragment
- */
- private function numLink( $offset, $limit, array $query, $link,
- $tooltipMsg, $class, $subpage = false
- ) {
- $query = [ 'limit' => $limit, 'offset' => $offset ] + $query;
- $tooltip = $this->msg( $tooltipMsg )->numParams( $limit )->text();
- $href = $this->getPageTitle( $subpage )->getLocalURL( $query );
- return Html::element( 'a', [ 'href' => $href,
- 'title' => $tooltip, 'class' => $class ], $link );
+ return $prevNext->buildPrevNextNavigation( $title, $offset, $limit, $query, $atend );
}
}
$offset = $this->offset;
}
- $prevnext = $this->buildPrevNextNavigation(
+ $prevNext = $this->buildPrevNextNavigation(
$offset,
$this->limit,
$this->powerSearchOptions() + [ 'search' => $term ],
$this->limit + $this->offset >= $totalRes
);
- $out->addHTML( "<p class='mw-search-pager-bottom'>{$prevnext}</p>\n" );
+ $out->addHTML( "<p class='mw-search-pager-bottom'>{$prevNext}</p>\n" );
}
// Close <div class='searchresults'>
* @param array $query Optional URL query parameter string
* @param bool $atend Optional param for specified if this is the last page
* @return string
- * @deprecated since 1.33, use SpecialPage::viewPrevNext()
+ * @deprecated since 1.34, use PrevNextNavigationRenderer::buildPrevNextNavigation()
* instead.
*/
public function viewPrevNext( Title $title, $offset, $limit,
--- /dev/null
+<?php
+
+use Wikimedia\TestingAccessWrapper;
+use MediaWiki\Navigation\PrevNextNavigationRenderer;
+
+/**
+ * @covers \MediaWiki\Navigation\PrevNextNavigationRenderer
+ */
+class PrevNextNavigationRendererTest extends MediaWikiTestCase {
+
+ public function provideBuildPrevNextNavigation() {
+ yield [ 0, 20, false, false ];
+ yield [ 17, 20, false, false ];
+ yield [ 0, 17, false, false ];
+ yield [ 0, 20, true, 'Foo' ];
+ yield [ 17, 20, true, 'Föö_Bär' ];
+ }
+
+ /**
+ * @dataProvider provideBuildPrevNextNavigation
+ */
+ public function testBuildPrevNextNavigation( $offset, $limit, $atEnd, $subPage ) {
+ $this->setUserLang( Language::factory( 'qqx' ) ); // disable i18n
+
+ $prevNext = new PrevNextNavigationRenderer( RequestContext::getMain() );
+ $prevNext = TestingAccessWrapper::newFromObject( $prevNext );
+
+ $html = $prevNext->buildPrevNextNavigation(
+ SpecialPage::getTitleFor( 'Watchlist', $subPage ),
+ $offset,
+ $limit,
+ [ 'x' => 25 ],
+ $atEnd
+ );
+
+ $this->assertStringStartsWith( '(viewprevnext:', $html );
+
+ preg_match_all( '!<a.*?</a>!', $html, $m, PREG_PATTERN_ORDER );
+ $links = $m[0];
+
+ foreach ( $links as $a ) {
+ if ( $subPage ) {
+ $this->assertContains( 'Special:Watchlist/' . wfUrlencode( $subPage ), $a );
+ } else {
+ $this->assertContains( 'Special:Watchlist', $a );
+ $this->assertNotContains( 'Special:Watchlist/', $a );
+ }
+ $this->assertContains( 'x=25', $a );
+ }
+
+ $i = 0;
+
+ if ( $offset > 0 ) {
+ $this->assertContains(
+ 'limit=' . $limit . '&offset=' . max( 0, $offset - $limit ) . '&',
+ $links[ $i ]
+ );
+ $this->assertContains( 'title="(prevn-title: ' . $limit . ')"', $links[$i] );
+ $this->assertContains( 'class="mw-prevlink"', $links[$i] );
+ $this->assertContains( '>(prevn: ' . $limit . ')<', $links[$i] );
+ $i += 1;
+ }
+
+ if ( !$atEnd ) {
+ $this->assertContains(
+ 'limit=' . $limit . '&offset=' . ( $offset + $limit ) . '&',
+ $links[ $i ]
+ );
+ $this->assertContains( 'title="(nextn-title: ' . $limit . ')"', $links[$i] );
+ $this->assertContains( 'class="mw-nextlink"', $links[$i] );
+ $this->assertContains( '>(nextn: ' . $limit . ')<', $links[$i] );
+ $i += 1;
+ }
+
+ $this->assertCount( 5 + $i, $links );
+
+ $this->assertContains( 'limit=20&offset=' . $offset, $links[$i] );
+ $this->assertContains( 'title="(shown-title: 20)"', $links[$i] );
+ $this->assertContains( 'class="mw-numlink"', $links[$i] );
+ $this->assertContains( '>20<', $links[$i] );
+ $i += 4;
+
+ $this->assertContains( 'limit=500&offset=' . $offset, $links[$i] );
+ $this->assertContains( 'title="(shown-title: 500)"', $links[$i] );
+ $this->assertContains( 'class="mw-numlink"', $links[$i] );
+ $this->assertContains( '>500<', $links[$i] );
+ }
+}
<?php
-use Wikimedia\TestingAccessWrapper;
-
/**
* @covers SpecialPage
*
// no exception thrown, logged in use can access special page
$this->assertTrue( true );
}
-
- public function provideBuildPrevNextNavigation() {
- yield [ 0, 20, false, false ];
- yield [ 17, 20, false, false ];
- yield [ 0, 17, false, false ];
- yield [ 0, 20, true, 'Foo' ];
- yield [ 17, 20, true, 'Föö_Bär' ];
- }
-
- /**
- * @dataProvider provideBuildPrevNextNavigation
- */
- public function testBuildPrevNextNavigation( $offset, $limit, $atEnd, $subPage ) {
- $this->setUserLang( Language::factory( 'qqx' ) ); // disable i18n
-
- $specialPage = new SpecialPage( 'Watchlist' );
- $specialPage = TestingAccessWrapper::newFromObject( $specialPage );
-
- $html = $specialPage->buildPrevNextNavigation(
- $offset,
- $limit,
- [ 'x' => 25 ],
- $atEnd,
- $subPage
- );
-
- $this->assertStringStartsWith( '(viewprevnext:', $html );
-
- preg_match_all( '!<a.*?</a>!', $html, $m, PREG_PATTERN_ORDER );
- $links = $m[0];
-
- foreach ( $links as $a ) {
- if ( $subPage ) {
- $this->assertContains( 'Special:Watchlist/' . wfUrlencode( $subPage ), $a );
- } else {
- $this->assertContains( 'Special:Watchlist', $a );
- $this->assertNotContains( 'Special:Watchlist/', $a );
- }
- $this->assertContains( 'x=25', $a );
- }
-
- $i = 0;
-
- if ( $offset > 0 ) {
- $this->assertContains(
- 'limit=' . $limit . '&offset=' . max( 0, $offset - $limit ) . '&',
- $links[ $i ]
- );
- $this->assertContains( 'title="(prevn-title: ' . $limit . ')"', $links[$i] );
- $this->assertContains( 'class="mw-prevlink"', $links[$i] );
- $this->assertContains( '>(prevn: ' . $limit . ')<', $links[$i] );
- $i += 1;
- }
-
- if ( !$atEnd ) {
- $this->assertContains(
- 'limit=' . $limit . '&offset=' . ( $offset + $limit ) . '&',
- $links[ $i ]
- );
- $this->assertContains( 'title="(nextn-title: ' . $limit . ')"', $links[$i] );
- $this->assertContains( 'class="mw-nextlink"', $links[$i] );
- $this->assertContains( '>(nextn: ' . $limit . ')<', $links[$i] );
- $i += 1;
- }
-
- $this->assertCount( 5 + $i, $links );
-
- $this->assertContains( 'limit=20&offset=' . $offset, $links[$i] );
- $this->assertContains( 'title="(shown-title: 20)"', $links[$i] );
- $this->assertContains( 'class="mw-numlink"', $links[$i] );
- $this->assertContains( '>20<', $links[$i] );
- $i += 4;
-
- $this->assertContains( 'limit=500&offset=' . $offset, $links[$i] );
- $this->assertContains( 'title="(shown-title: 500)"', $links[$i] );
- $this->assertContains( 'class="mw-numlink"', $links[$i] );
- $this->assertContains( '>500<', $links[$i] );
- }
-
}