jenkins-bot has submitted this change and it was merged.
Change subject: Add SpecialPagesWithBadges
......................................................................
Add SpecialPagesWithBadges
Caching of this query doesn't work because the query
depends on the user input.
Bug: T72209
Change-Id: I690b94af0ac11163c80e4422e6d72dacce447959
---
M client/WikibaseClient.hooks.php
M client/WikibaseClient.i18n.alias.php
M client/WikibaseClient.php
M client/i18n/en.json
M client/includes/WikibaseClient.php
A client/includes/specials/SpecialPagesWithBadges.php
M client/tests/phpunit/MockClientStore.php
A client/tests/phpunit/includes/specials/SpecialPagesWithBadgesTest.php
M repo/includes/WikibaseRepo.php
9 files changed, 417 insertions(+), 10 deletions(-)
Approvals:
Daniel Kinzler: Looks good to me, approved
jenkins-bot: Verified
diff --git a/client/WikibaseClient.hooks.php b/client/WikibaseClient.hooks.php
index 0de0d8e..0725b88 100644
--- a/client/WikibaseClient.hooks.php
+++ b/client/WikibaseClient.hooks.php
@@ -601,6 +601,7 @@
public static function onwgQueryPages( &$queryPages ) {
$queryPages[] = array(
'Wikibase\Client\Specials\SpecialUnconnectedPages', 'UnconnectedPages' );
+ $queryPages[] = array(
'Wikibase\Client\Specials\SpecialPagesWithBadges', 'Badges' );
return true;
}
diff --git a/client/WikibaseClient.i18n.alias.php
b/client/WikibaseClient.i18n.alias.php
index beb0626..0d60cd3 100644
--- a/client/WikibaseClient.i18n.alias.php
+++ b/client/WikibaseClient.i18n.alias.php
@@ -15,6 +15,7 @@
/** English (English) */
$specialPageAliases['en'] = array(
'UnconnectedPages' => array( 'UnconnectedPages', 'WithoutConnection',
'WithoutSitelinks' ),
+ 'PagesWithBadges' => array( 'PagesWithBadges', 'QueryBadges' ),
);
/** Arabic (العربية) */
diff --git a/client/WikibaseClient.php b/client/WikibaseClient.php
index 6e79fae..0ee65c3 100644
--- a/client/WikibaseClient.php
+++ b/client/WikibaseClient.php
@@ -153,6 +153,7 @@
// Special page registration
$wgSpecialPages['UnconnectedPages'] =
'Wikibase\Client\Specials\SpecialUnconnectedPages';
+ $wgSpecialPages['PagesWithBadges'] =
'Wikibase\Client\Specials\SpecialPagesWithBadges';
$wgHooks['wgQueryPages'][] = 'Wikibase\ClientHooks::onwgQueryPages';
// Resource loader modules
diff --git a/client/i18n/en.json b/client/i18n/en.json
index 0e5df98..27180c0 100644
--- a/client/i18n/en.json
+++ b/client/i18n/en.json
@@ -66,12 +66,13 @@
"wikibase-error-exceeded-entity-access-limit": "Too many {{WBREPONAME}}
entities accessed.",
"unconnectedpages": "Pages not connected to items",
"unconnectedpages-summary": "This page lists pages with no connected
data item (in namespaces that support connected items). The list is sorted by
descending page ID, so that newer pages are listed first.",
- "wikibase-unconnectedpages-page": "Start result list with page:",
- "wikibase-unconnectedpages-submit": "Go",
- "wikibase-unconnectedpages-invalid-language": "\"$1\" is not a valid
language code.",
- "wikibase-unconnectedpages-page-warning": "The page title could not be
used for the query and is ignored.",
- "wikibase-unconnectedpages-iwdata-label": "Only pages with
interlanguage links",
"wikibase-unconnectedpages-format-row": "($1 {{PLURAL:$1|interlanguage
link|interlanguage links}} on the page)",
+ "pageswithbadges": "Pages with badges",
+ "pageswithbadges-summary": "This page lists pages with badges (eg. good
article or featured article). The list is sorted by descending page ID, so that
newer pages are listed first.",
+ "wikibase-pageswithbadges-invalid-id": "$1 is not a valid item id",
+ "wikibase-pageswithbadges-legend": "List of pages with a given badge",
+ "wikibase-pageswithbadges-badge": "Badge:",
+ "wikibase-pageswithbadges-submit": "Show pages",
"wikibase-pageinfo-entity-id": "{{WBREPONAME}} item ID",
"wikibase-pageinfo-entity-id-none": "None",
"wikibase-property-render-error": "Failed to render property $1: $2",
diff --git a/client/includes/WikibaseClient.php
b/client/includes/WikibaseClient.php
index 2254217..dd09569 100644
--- a/client/includes/WikibaseClient.php
+++ b/client/includes/WikibaseClient.php
@@ -39,9 +39,9 @@
use Wikibase\DataModel\Services\EntityId\SuffixEntityIdParser;
use Wikibase\DataModel\Services\Lookup\EntityLookup;
use Wikibase\DataModel\Services\Lookup\EntityRetrievingDataTypeLookup;
-use Wikibase\DataModel\Services\Lookup\EntityRetrievingTermLookup;
use Wikibase\DataModel\Services\Lookup\PropertyDataTypeLookup;
use Wikibase\DataModel\Services\Lookup\TermLookup;
+use Wikibase\DataModel\Services\Term\TermBuffer;
use Wikibase\DirectSqlStore;
use Wikibase\EntityFactory;
use Wikibase\InternalSerialization\DeserializerFactory as
InternalDeserializerFactory;
@@ -60,6 +60,7 @@
use Wikibase\Lib\WikibaseValueFormatterBuilders;
use Wikibase\NamespaceChecker;
use Wikibase\SettingsArray;
+use Wikibase\Store\BufferingTermLookup;
use Wikibase\StringNormalizer;
/**
@@ -164,6 +165,13 @@
private $dataTypeDefinitions;
/**
+ * @var TermLookup|null
+ */
+ private $termLookup = null;
+
+ /**
+ * @since 0.4
+ *
* @param SettingsArray $settings
* @param Language $contentLanguage
* @param DataTypeDefinitions $dataTypeDefinitions
@@ -216,10 +224,31 @@
}
/**
+ * @return TermBuffer
+ */
+ public function getTermBuffer() {
+ return $this->getBufferingTermLookup();
+ }
+
+ /**
* @return TermLookup
*/
- private function getTermLookup() {
- return new EntityRetrievingTermLookup( $this->getEntityLookup()
);
+ public function getTermLookup() {
+ return $this->getBufferingTermLookup();
+ }
+
+ /**
+ * @return BufferingTermLookup
+ */
+ public function getBufferingTermLookup() {
+ if ( !$this->termLookup ) {
+ $this->termLookup = new BufferingTermLookup(
+ $this->getStore()->getTermIndex(),
+ 1000 // @todo: configure buffer size
+ );
+ }
+
+ return $this->termLookup;
}
/**
diff --git a/client/includes/specials/SpecialPagesWithBadges.php
b/client/includes/specials/SpecialPagesWithBadges.php
new file mode 100644
index 0000000..0ac493f
--- /dev/null
+++ b/client/includes/specials/SpecialPagesWithBadges.php
@@ -0,0 +1,281 @@
+<?php
+
+
+namespace Wikibase\Client\Specials;
+
+use Html;
+use InvalidArgumentException;
+use Linker;
+use OutOfBoundsException;
+use QueryPage;
+use Skin;
+use Title;
+use Wikibase\Client\WikibaseClient;
+use Wikibase\DataModel\Entity\ItemId;
+use Wikibase\Lib\Store\LanguageFallbackLabelDescriptionLookupFactory;
+
+/**
+ * Show a list of pages with a given badge.
+ *
+ * @since 0.5
+ * @licence GNU GPL v2+
+ * @author Bene* < [email protected] >
+ */
+class SpecialPagesWithBadges extends QueryPage {
+
+ /**
+ * @var LanguageFallbackLabelDescriptionLookupFactory
+ */
+ private $labelDescriptionLookupFactory;
+
+ /**
+ * @var string[]
+ */
+ private $badgeIds;
+
+ /**
+ * @var string
+ */
+ private $siteId;
+
+ /**
+ * @var ItemId|null
+ */
+ private $badgeId;
+
+ /**
+ * @see SpecialPage::__construct
+ *
+ * @param string $name
+ */
+ public function __construct( $name = 'PagesWithBadges' ) {
+ parent::__construct( $name );
+
+ $wikibaseClient = WikibaseClient::getDefaultInstance();
+ $this->initServices(
+ new LanguageFallbackLabelDescriptionLookupFactory(
+
$wikibaseClient->getLanguageFallbackChainFactory(),
+ $wikibaseClient->getTermLookup(),
+ $wikibaseClient->getTermBuffer()
+ ),
+ array_keys( $wikibaseClient->getSettings()->getSetting(
'badgeClassNames' ) ),
+ $wikibaseClient->getSettings()->getSetting(
'siteGlobalID' )
+ );
+ }
+
+ /**
+ * @param LanguageFallbackLabelDescriptionLookupFactory
$labelDescriptionLookupFactory
+ * @param string[] $badgeIds
+ * @param string $siteId
+ */
+ public function initServices(
+ LanguageFallbackLabelDescriptionLookupFactory
$labelDescriptionLookupFactory,
+ array $badgeIds,
+ $siteId
+ ) {
+ $this->labelDescriptionLookupFactory =
$labelDescriptionLookupFactory;
+ $this->badgeIds = $badgeIds;
+ $this->siteId = $siteId;
+ }
+
+ /**
+ * @see QueryPage::execute
+ *
+ * @param string $subPage
+ */
+ public function execute( $subPage ) {
+ $this->prepareParams( $subPage );
+
+ if ( $this->badgeId !== null ) {
+ parent::execute( $subPage );
+ } else {
+ $this->setHeaders();
+ $this->outputHeader();
+ $this->getOutput()->addHTML( $this->getPageHeader() );
+ }
+ }
+
+ private function prepareParams( $subPage ) {
+ $badge = $this->getRequest()->getText( 'badge', $subPage );
+
+ try {
+ $this->badgeId = new ItemId( $badge );
+ } catch ( InvalidArgumentException $ex ) {
+ if ( $badge ) {
+ $this->getOutput()->addHTML(
+ Html::element(
+ 'p',
+ array(
+ 'class' => 'error'
+ ),
+ $this->msg(
'wikibase-pageswithbadges-invalid-id', $badge )
+ )
+ );
+ }
+ }
+ }
+
+ /**
+ * @see QueryPage::getPageHeader
+ *
+ * @return string
+ */
+ public function getPageHeader() {
+ return Html::openElement(
+ 'form',
+ array(
+ 'action' => $this->getPageTitle()->getLocalURL()
+ )
+ ) .
+ Html::openElement( 'fieldset' ) .
+ Html::element(
+ 'legend',
+ array(),
+ $this->msg( 'wikibase-pageswithbadges-legend' )->text()
+ ) .
+ Html::openElement( 'p' ) .
+ Html::element(
+ 'label',
+ array(
+ 'for' => 'wb-pageswithbadges-badge'
+ ),
+ $this->msg( 'wikibase-pageswithbadges-badge' )->text()
+ ) . ' ' .
+ Html::rawElement(
+ 'select',
+ array(
+ 'name' => 'badge',
+ 'id' => 'wb-pageswithbadges-badge',
+ 'class' => 'wb-select'
+ ),
+ $this->getOptionsHtml()
+ ) . ' ' .
+ Html::input(
+ '',
+ $this->msg( 'wikibase-pageswithbadges-submit' )->text(),
+ 'submit',
+ array(
+ 'id' => 'wikibase-pageswithbadges-submit',
+ 'class' => 'wb-input-button'
+ )
+ ) .
+ Html::closeElement( 'p' ) .
+ Html::closeElement( 'fieldset' ) .
+ Html::closeElement( 'form' );
+ }
+
+ private function getOptionsHtml() {
+ /** @var ItemId[] $badgeItemIds */
+ $badgeItemIds = array_map(
+ function( $badgeId ) {
+ return new ItemId( $badgeId );
+ },
+ $this->badgeIds
+ );
+
+ $labelLookup =
$this->labelDescriptionLookupFactory->newLabelDescriptionLookup(
+ $this->getLanguage(),
+ $badgeItemIds
+ );
+
+ $html = '';
+
+ foreach ( $this->badgeIds as $badgeId ) {
+ try {
+ $label = $labelLookup->getLabel( new ItemId(
$badgeId ) )->getText();
+ } catch ( OutOfBoundsException $ex ) {
+ // show plain id if no label has been found
+ $label = $badgeId;
+ }
+
+ $html .= Html::element(
+ 'option',
+ array(
+ 'value' => $badgeId,
+ 'selected' => $this->badgeId !== null
&& $this->badgeId->getSerialization() === $badgeId
+ ),
+ $label
+ );
+ }
+
+ return $html;
+ }
+
+ /**
+ * @see QueryPage::getQueryInfo
+ *
+ * @return array[]
+ */
+ public function getQueryInfo() {
+ return array(
+ 'tables' => array(
+ 'page',
+ 'page_props'
+ ),
+ 'fields' => array(
+ 'value' => 'page_id',
+ 'namespace' => 'page_namespace',
+ 'title' => 'page_title',
+ ),
+ 'conds' => array(
+ 'pp_propname' => 'wikibase-badge-' .
$this->badgeId->getSerialization()
+ ),
+ 'options' => array(), // sorting is determined
getOrderFields(), which returns array( 'value' ) per default.
+ 'join_conds' => array(
+ 'page_props' => array( 'JOIN', array( 'page_id
= pp_page' ) )
+ )
+ );
+ }
+
+ /**
+ * @see QueryPage::formatResult
+ *
+ * @param Skin $skin
+ * @param object $result
+ *
+ * @return string
+ */
+ public function formatResult( $skin, $result ) {
+ $title = Title::newFromID( $result->value );
+ $out = Linker::linkKnown( $title );
+
+ return $out;
+ }
+
+ /**
+ * @see QueryPage::isSyndicated
+ *
+ * @return bool
+ */
+ public function isSyndicated() {
+ return false;
+ }
+
+ /**
+ * @see QueryPage::isCacheable
+ *
+ * @return bool
+ */
+ public function isCacheable() {
+ return false;
+ }
+
+ /**
+ * @see QueryPage::linkParameters
+ *
+ * @return array
+ */
+ public function linkParameters() {
+ return array( 'badge' => $this->badgeId->getSerialization() );
+ }
+
+ /**
+ * @see SpecialPage::getGroupName
+ *
+ * @return string
+ */
+ protected function getGroupName() {
+ return 'pages';
+ }
+
+}
diff --git a/client/tests/phpunit/MockClientStore.php
b/client/tests/phpunit/MockClientStore.php
index 08ded61..6a10b3f 100644
--- a/client/tests/phpunit/MockClientStore.php
+++ b/client/tests/phpunit/MockClientStore.php
@@ -90,6 +90,7 @@
*/
public function getTermIndex() {
// FIXME: Incomplete
+ return new MockTermIndex( array() );
}
/**
diff --git
a/client/tests/phpunit/includes/specials/SpecialPagesWithBadgesTest.php
b/client/tests/phpunit/includes/specials/SpecialPagesWithBadgesTest.php
new file mode 100644
index 0000000..2a9b8c9
--- /dev/null
+++ b/client/tests/phpunit/includes/specials/SpecialPagesWithBadgesTest.php
@@ -0,0 +1,92 @@
+<?php
+
+
+namespace Wikibase\Client\Tests\Specials;
+
+use Wikibase\Client\Specials\SpecialPagesWithBadges;
+use Wikibase\DataModel\Entity\ItemId;
+use Wikibase\DataModel\Services\Lookup\LabelDescriptionLookup;
+use Wikibase\DataModel\Term\Term;
+use Wikibase\Lib\Store\LanguageFallbackLabelDescriptionLookupFactory;
+use Wikibase\Test\SpecialPageTestBase;
+
+/**
+ * @covers Wikibase\Client\Specials\SpecialPagesWithBadges
+ *
+ * @group WikibaseClient
+ * @group SpecialPage
+ * @group WikibaseSpecialPage
+ * @group Wikibase
+ * @group Database
+ *
+ * @licence GNU GPL v2+
+ * @author Bene* < [email protected] >
+ */
+class SpecialPagesWithBadgesTest extends SpecialPageTestBase {
+
+ /**
+ * @return LabelDescriptionLookup
+ */
+ private function getLabelLookup() {
+ $labelLookup = $this->getMock(
'Wikibase\DataModel\Services\Lookup\LabelDescriptionLookup' );
+ $labelLookup->expects( $this->any() )
+ ->method( 'getLabel' )
+ ->will( $this->returnCallback( function( ItemId $itemId
) {
+ return new Term( 'en', 'Label of ' .
$itemId->getSerialization() );
+ } ) );
+
+ return $labelLookup;
+ }
+
+ /**
+ * @return LanguageFallbackLabelDescriptionLookupFactory
+ */
+ private function getLabelDescriptionLookupFactory() {
+ $itemIds = array(
+ new ItemId( 'Q123' ),
+ new ItemId( 'Q456' )
+ );
+
+ $labelDescriptionLookupFactory = $this->getMockBuilder(
'\Wikibase\Lib\Store\LanguageFallbackLabelDescriptionLookupFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ $labelDescriptionLookupFactory->expects( $this->once() )
+ ->method( 'newLabelDescriptionLookup' )
+ ->with( $this->anything(), $this->equalTo( $itemIds ) )
+ ->will( $this->returnValue( $this->getLabelLookup() ) );
+
+ return $labelDescriptionLookupFactory;
+ }
+
+ protected function newSpecialPage() {
+ $specialPage = new SpecialPagesWithBadges();
+ $specialPage->initServices(
$this->getLabelDescriptionLookupFactory(), array( 'Q123', 'Q456' ), 'enwiki' );
+
+ return $specialPage;
+ }
+
+ public function testExecuteWithoutAnyParams() {
+ list( $result, ) = $this->executeSpecialPage( '' );
+
+ $this->assertContains( '<select name="badge"', $result );
+ $this->assertContains( '<option value="Q123"', $result );
+ $this->assertContains( '<option value="Q456"', $result );
+
+ $this->assertContains( 'Label of Q123', $result );
+ $this->assertContains( 'Label of Q456', $result );
+ }
+
+ public function testExecuteWithValidParam() {
+ list( $result, ) = $this->executeSpecialPage( 'Q456' );
+
+ $this->assertContains( '<option value="Q456" selected=""',
$result );
+ }
+
+ public function testExecuteWithInvalidParam() {
+ list( $result, ) = $this->executeSpecialPage( 'FooBar' );
+
+ $this->assertContains( '<p class="error"', $result );
+ $this->assertContains( 'FooBar is not a valid item id', $result
);
+ }
+
+}
diff --git a/repo/includes/WikibaseRepo.php b/repo/includes/WikibaseRepo.php
index a844700..cfc6e7b 100644
--- a/repo/includes/WikibaseRepo.php
+++ b/repo/includes/WikibaseRepo.php
@@ -192,7 +192,7 @@
/**
* @var TermLookup|null
*/
- private $termLookup;
+ private $termLookup = null;
/**
* @var ContentLanguages|null
@@ -661,7 +661,7 @@
* @return TermBuffer
*/
public function getTermBuffer() {
- return $this->getTermLookup();
+ return $this->getBufferingTermLookup();
}
/**
--
To view, visit https://gerrit.wikimedia.org/r/234961
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I690b94af0ac11163c80e4422e6d72dacce447959
Gerrit-PatchSet: 8
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Bene <[email protected]>
Gerrit-Reviewer: Addshore <[email protected]>
Gerrit-Reviewer: Bene <[email protected]>
Gerrit-Reviewer: Daniel Kinzler <[email protected]>
Gerrit-Reviewer: Jeroen De Dauw <[email protected]>
Gerrit-Reviewer: Siebrand <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits