jenkins-bot has submitted this change and it was merged.
Change subject: Create a new special page to list properties by data type
......................................................................
Create a new special page to list properties by data type
The new special page is called Special:ListProperties.
Queries can be done via the form or in the format
Special:ListProperties/dataType, eg Special:ListProperties/url.
Note: Split into Id9775659
Bug: T55618
Change-Id: I79a08ec87bf76adba869d4b7eb22098b41fbdb72
---
M repo/Wikibase.i18n.alias.php
M repo/Wikibase.php
M repo/i18n/en.json
M repo/i18n/qqq.json
M repo/includes/DataTypeSelector.php
M repo/includes/WikibaseRepo.php
A repo/includes/specials/SpecialListProperties.php
A repo/tests/phpunit/includes/specials/SpecialListPropertiesTest.php
8 files changed, 455 insertions(+), 13 deletions(-)
Approvals:
Aude: Looks good to me, but someone else must approve
Daniel Kinzler: Looks good to me, approved
jenkins-bot: Verified
diff --git a/repo/Wikibase.i18n.alias.php b/repo/Wikibase.i18n.alias.php
index a449b40..be8a5bc 100644
--- a/repo/Wikibase.i18n.alias.php
+++ b/repo/Wikibase.i18n.alias.php
@@ -22,6 +22,7 @@
'GoToLinkedPage' => array( 'GoToLinkedPage' ),
'ItemDisambiguation' => array( 'ItemDisambiguation' ),
'ListDatatypes' => array( 'ListDatatypes' ),
+ 'ListProperties' => array( 'ListProperties' ),
'SetLabel' => array( 'SetLabel' ),
'SetDescription' => array( 'SetDescription' ),
'SetAliases' => array( 'SetAliases' ),
diff --git a/repo/Wikibase.php b/repo/Wikibase.php
index 6509446..411b17e 100644
--- a/repo/Wikibase.php
+++ b/repo/Wikibase.php
@@ -180,6 +180,7 @@
$wgSpecialPages['EntitiesWithoutLabel'] =
array( 'Wikibase\Repo\Specials\SpecialEntitiesWithoutPageFactory',
'newSpecialEntitiesWithoutLabel' );
$wgSpecialPages['EntitiesWithoutDescription'] = array(
'Wikibase\Repo\Specials\SpecialEntitiesWithoutPageFactory',
'newSpecialEntitiesWithoutDescription' );
$wgSpecialPages['ListDatatypes']
= 'Wikibase\Repo\Specials\SpecialListDatatypes';
+ $wgSpecialPages['ListProperties']
= 'Wikibase\Repo\Specials\SpecialListProperties';
$wgSpecialPages['DispatchStats']
= 'Wikibase\Repo\Specials\SpecialDispatchStats';
$wgSpecialPages['EntityData']
= 'Wikibase\Repo\Specials\SpecialEntityData';
$wgSpecialPages['MyLanguageFallbackChain'] =
'Wikibase\Repo\Specials\SpecialMyLanguageFallbackChain';
diff --git a/repo/i18n/en.json b/repo/i18n/en.json
index 8ca930e..14c0b70 100644
--- a/repo/i18n/en.json
+++ b/repo/i18n/en.json
@@ -242,6 +242,12 @@
"wikibase-listdatatypes-intro": "This is a list of all data types
available on this installation:",
"wikibase-history-title-with-label": "Revision history of \"$2\" ($1)",
"wikibase-history-title-without-label": "Revision history of ($1)",
+ "special-listproperties": "List of properties",
+ "wikibase-listproperties-legend": "Get a list of properties by data
type",
+ "wikibase-listproperties-datatype": "Data type:",
+ "wikibase-listproperties-all": "All data types",
+ "wikibase-listproperties-submit": "Find",
+ "wikibase-listproperties-invalid-datatype": "\"$1\" is not a valid data
type.",
"special-entitieswithoutdescription": "Entities without description",
"wikibase-entitieswithoutdescription-legend": "Get list of entities
without description",
"special-entitieswithoutlabel": "Entities without label",
diff --git a/repo/i18n/qqq.json b/repo/i18n/qqq.json
index fb7ee41..d36e48d 100644
--- a/repo/i18n/qqq.json
+++ b/repo/i18n/qqq.json
@@ -270,6 +270,12 @@
"wikibase-listdatatypes-intro": "Intro text for the ListDatatypes
special page.",
"wikibase-history-title-with-label": "The title of the history page
with label and prefixed id. Parameters:\n* $1 - the prefixed id, the id is
usually in parenthesis\n* $2 - the localized label, it is usually in quotes",
"wikibase-history-title-without-label": "The title of the history page
with only a prefixed id. Parameters:\n* $1 - the prefixed id, the id is usually
in parenthesis",
+ "special-listproperties": "{{doc-special|ListProperties}}\nThis special
page returns a list of properties for a given datatype (such as commonsMedia)",
+ "wikibase-listproperties-legend": "Legend for the ListProperties
special page.",
+ "wikibase-listproperties-datatype": "Label for the datatype
dropdown.\n{{Identical|Data type}}",
+ "wikibase-listproperties-all": "Option to select that properties with
all data types should be shown.",
+ "wikibase-listproperties-submit": "Label for the button that activates
the action.\n{{Identical|Find}}",
+ "wikibase-listproperties-invalid-datatype": "Error message shown when
the data type passed in parameter is invalid.\n\nParameters:\n* $1 - data type",
"special-entitieswithoutdescription":
"{{doc-special|EntitiesWithoutDescription}}\nThis special page returns a list
of entities without description for a given language",
"wikibase-entitieswithoutdescription-legend": "Legend of the form that
allow to change the language.",
"special-entitieswithoutlabel":
"{{doc-special|EntitiesWithoutLabel}}\nThis special page returns a list of
entities without label for a given language",
diff --git a/repo/includes/DataTypeSelector.php
b/repo/includes/DataTypeSelector.php
index f0ae7fa..5e89dad 100644
--- a/repo/includes/DataTypeSelector.php
+++ b/repo/includes/DataTypeSelector.php
@@ -1,6 +1,7 @@
<?php
namespace Wikibase;
+
use DataTypes\DataType;
use Html;
use MWException;
@@ -55,10 +56,36 @@
*
* @param string $id
* @param string $name
+ * @param string $selectedTypeId
*
* @return string
*/
- public function getHtml( $id = 'datatype', $name = 'datatype' ) {
+ public function getHtml( $id = 'datatype', $name = 'datatype',
$selectedTypeId = '' ) {
+ $options = $this->getOptionsHtml( $selectedTypeId );
+
+ $html = Html::rawElement(
+ 'select',
+ array(
+ 'name' => $name,
+ 'id' => $id,
+ 'class' => 'wb-select'
+ ),
+ $options
+ );
+
+ return $html;
+ }
+
+ /**
+ * Builds and returns the html for the options of the DataType selector.
+ *
+ * @since 0.5
+ *
+ * @param string $selectedTypeId
+ *
+ * @return string
+ */
+ public function getOptionsHtml( $selectedTypeId = '' ) {
$dataTypes = array();
foreach ( $this->dataTypes as $dataType ) {
@@ -72,20 +99,13 @@
foreach ( $dataTypes as $typeId => $typeLabel ) {
$html .= Html::element(
'option',
- array( 'value' => $typeId ),
+ array(
+ 'value' => $typeId,
+ 'selected' => $typeId ===
$selectedTypeId
+ ),
$typeLabel
);
}
-
- $html = Html::rawElement(
- 'select',
- array(
- 'name' => $name,
- 'id' => $id,
- 'class' => 'wb-select'
- ),
- $html
- );
return $html;
}
diff --git a/repo/includes/WikibaseRepo.php b/repo/includes/WikibaseRepo.php
index 54574b7..9f37b90 100644
--- a/repo/includes/WikibaseRepo.php
+++ b/repo/includes/WikibaseRepo.php
@@ -1002,7 +1002,10 @@
return $this->entityNamespaceLookup;
}
- private function getEntityIdHtmlLinkFormatterFactory() {
+ /**
+ * @return EntityIdHtmlLinkFormatterFactory
+ */
+ public function getEntityIdHtmlLinkFormatterFactory() {
return new EntityIdHtmlLinkFormatterFactory(
$this->getEntityTitleLookup(),
new LanguageNameLookup()
diff --git a/repo/includes/specials/SpecialListProperties.php
b/repo/includes/specials/SpecialListProperties.php
new file mode 100644
index 0000000..2732232
--- /dev/null
+++ b/repo/includes/specials/SpecialListProperties.php
@@ -0,0 +1,246 @@
+<?php
+
+namespace Wikibase\Repo\Specials;
+
+use DataTypes\DataTypeFactory;
+use Html;
+use Wikibase\DataModel\Entity\PropertyId;
+use Wikibase\DataTypeSelector;
+use Wikibase\LanguageFallbackChainFactory;
+use Wikibase\Lib\Store\LanguageFallbackLabelDescriptionLookup;
+use Wikibase\Lib\Store\TermLookup;
+use Wikibase\PropertyInfoStore;
+use Wikibase\Repo\WikibaseRepo;
+use Wikibase\Store\TermBuffer;
+use Wikibase\View\EntityIdFormatterFactory;
+
+/**
+ * Special page to list properties by data type
+ *
+ * @since 0.5
+ * @licence GNU GPL v2+
+ * @author Bene* < [email protected] >
+ */
+class SpecialListProperties extends SpecialWikibasePage {
+
+ /**
+ * Max server side caching time in seconds.
+ *
+ * @type integer
+ */
+ const CACHE_TTL_IN_SECONDS = 30;
+
+ /**
+ * @var DataTypeFactory
+ */
+ private $dataTypeFactory;
+
+ /**
+ * @var PropertyInfoStore
+ */
+ private $propertyInfoStore;
+
+ /**
+ * @var LanguageFallbackChainFactory
+ */
+ private $languageFallbackChainFactory;
+
+ /**
+ * @var TermLookup
+ */
+ private $termLookup;
+
+ /**
+ * @var TermBuffer
+ */
+ private $termBuffer;
+
+ /**
+ * @var EntityIdFormatterFactory
+ */
+ private $entityIdFormatterFactory;
+
+ /**
+ * @var string
+ */
+ private $dataType;
+
+ public function __construct() {
+ parent::__construct( 'ListProperties' );
+
+ $this->initServices(
+
WikibaseRepo::getDefaultInstance()->getDataTypeFactory(),
+
WikibaseRepo::getDefaultInstance()->getStore()->getPropertyInfoStore(),
+
WikibaseRepo::getDefaultInstance()->getLanguageFallbackChainFactory(),
+ WikibaseRepo::getDefaultInstance()->getTermLookup(),
+ WikibaseRepo::getDefaultInstance()->getTermBuffer(),
+
WikibaseRepo::getDefaultInstance()->getEntityIdHtmlLinkFormatterFactory()
+ );
+ }
+
+ /**
+ * Set service objects to use. Unit tests may call this to substitute
mock
+ * services.
+ */
+ public function initServices(
+ DataTypeFactory $dataTypeFactory,
+ PropertyInfoStore $propertyInfoStore,
+ LanguageFallbackChainFactory $languageFallbackChainFactory,
+ TermLookup $termLookup,
+ TermBuffer $termBuffer,
+ EntityIdFormatterFactory $entityIdFormatterFactory
+ ) {
+ $this->dataTypeFactory = $dataTypeFactory;
+ $this->propertyInfoStore = $propertyInfoStore;
+ $this->languageFallbackChainFactory =
$languageFallbackChainFactory;
+ $this->termLookup = $termLookup;
+ $this->termBuffer = $termBuffer;
+ $this->entityIdFormatterFactory = $entityIdFormatterFactory;
+ }
+
+ /**
+ * @see SpecialWikibasePage::execute
+ *
+ * @since 0.5
+ *
+ * @param string|null $subPage
+ */
+ public function execute( $subPage ) {
+ parent::execute( $subPage );
+
+ $output = $this->getOutput();
+ $output->setSquidMaxage( static::CACHE_TTL_IN_SECONDS );
+
+ $this->prepareArguments( $subPage );
+ $this->showForm();
+
+ if ( $this->dataType !== null ) {
+ $this->showQuery();
+ }
+ }
+
+ private function prepareArguments( $subPage ) {
+ $request = $this->getRequest();
+
+ $this->dataType = $request->getText( 'datatype', $subPage );
+ if ( $this->dataType !== '' && !in_array( $this->dataType,
$this->dataTypeFactory->getTypeIds() ) ) {
+ $this->showErrorHTML( $this->msg(
'wikibase-listproperties-invalid-datatype', $this->dataType )->escaped() );
+ $this->dataType = null;
+ }
+ }
+
+ private function showForm() {
+ $dataTypeSelect = new DataTypeSelector(
+ $this->dataTypeFactory->getTypes() + array( 'all' ),
+ $this->getLanguage()->getCode()
+ );
+
+ $this->getOutput()->addHTML(
+ Html::openElement(
+ 'form',
+ array(
+ 'action' =>
$this->getPageTitle()->getLocalURL(),
+ 'name' => 'listproperties',
+ 'id' => 'wb-listproperties-form'
+ )
+ ) .
+ Html::openElement( 'fieldset' ) .
+ Html::element(
+ 'legend',
+ array(),
+ $this->msg( 'wikibase-listproperties-legend'
)->text()
+ ) .
+ Html::openElement( 'p' ) .
+ Html::element(
+ 'label',
+ array(
+ 'for' => 'wb-listproperties-datatype'
+ ),
+ $this->msg( 'wikibase-listproperties-datatype'
)->text()
+ ) . ' ' .
+ Html::rawElement(
+ 'select',
+ array(
+ 'name' => 'datatype',
+ 'id' => 'wb-listproperties-datatype',
+ 'class' => 'wb-select'
+ ),
+ Html::element(
+ 'option',
+ array(
+ 'value' => '',
+ 'selected' => $this->dataType
=== ''
+ ),
+ $this->msg(
'wikibase-listproperties-all' )->text()
+ ) .
+ $dataTypeSelect->getOptionsHtml(
$this->dataType )
+ ) . ' ' .
+ Html::input(
+ '',
+ $this->msg( 'wikibase-listproperties-submit'
)->text(),
+ 'submit',
+ array(
+ 'id' =>
'wikibase-listproperties-submit',
+ 'class' => 'wb-input-button'
+ )
+ ) .
+ Html::closeElement( 'p' ) .
+ Html::closeElement( 'fieldset' ) .
+ Html::closeElement( 'form' )
+ );
+ }
+
+ private function showQuery() {
+ $propertyIds = $this->getPropertyIds();
+
+ if ( empty( $propertyIds ) ) {
+ $this->getOutput()->addWikiMsg( 'specialpage-empty' );
+ return;
+ }
+
+ $languageFallbackChain =
$this->languageFallbackChainFactory->newFromLanguage(
+ $this->getLanguage(),
+ LanguageFallbackChainFactory::FALLBACK_SELF
+ |
LanguageFallbackChainFactory::FALLBACK_VARIANTS
+ | LanguageFallbackChainFactory::FALLBACK_OTHERS
+ );
+ $languages = $languageFallbackChain->getFetchLanguageCodes();
+ $labelDescriptionLookup = new
LanguageFallbackLabelDescriptionLookup(
+ $this->termLookup,
+ $languageFallbackChain
+ );
+ $formatter =
$this->entityIdFormatterFactory->getEntityIdFormater( $labelDescriptionLookup );
+
+ $this->termBuffer->prefetchTerms( $propertyIds, array( 'label'
), $languages );
+
+ $html = Html::openElement( 'ul' );
+
+ foreach ( $propertyIds as $propertyId ) {
+ $html .= Html::rawElement( 'li', array(),
$formatter->formatEntityId( $propertyId ) );
+ }
+
+ $html .= Html::closeElement( 'ul' );
+ $this->getOutput()->addHTML( $html );
+ }
+
+ /**
+ * @return PropertyId[]
+ */
+ private function getPropertyIds() {
+ if ( $this->dataType === '' ) {
+ $propertyInfoForDataType =
$this->propertyInfoStore->getAllPropertyInfo();
+ } else {
+ $propertyInfoForDataType =
$this->propertyInfoStore->getPropertyInfoForDataType( $this->dataType );
+ }
+
+ $propertyIds = array();
+
+ foreach ( $propertyInfoForDataType as $numericId => $info ) {
+ $propertyIds[] = PropertyId::newFromNumber( $numericId
);
+ }
+
+ return $propertyIds;
+ }
+
+}
+
diff --git a/repo/tests/phpunit/includes/specials/SpecialListPropertiesTest.php
b/repo/tests/phpunit/includes/specials/SpecialListPropertiesTest.php
new file mode 100644
index 0000000..4297813
--- /dev/null
+++ b/repo/tests/phpunit/includes/specials/SpecialListPropertiesTest.php
@@ -0,0 +1,159 @@
+<?php
+
+namespace Wikibase\Test;
+
+use DataTypes\DataType;
+use DataTypes\DataTypeFactory;
+use Language;
+use Title;
+use Wikibase\DataModel\Entity\EntityId;
+use Wikibase\DataModel\Entity\PropertyId;
+use Wikibase\LanguageFallbackChainFactory;
+use Wikibase\Lib\LanguageNameLookup;
+use Wikibase\PropertyInfoStore;
+use Wikibase\Repo\EntityIdHtmlLinkFormatterFactory;
+use Wikibase\Repo\Specials\SpecialListProperties;
+use Wikibase\Test\SpecialPageTestBase;
+
+/**
+ * @covers Wikibase\Repo\Specials\SpecialListProperties
+ *
+ * @group Wikibase
+ * @group WikibaseRepo
+ * @group SpecialPage
+ * @group WikibaseSpecialPage
+ *
+ * @licence GNU GPL v2+
+ * @author Bene* < [email protected] >
+ */
+class SpecialListPropertiesTest extends SpecialPageTestBase {
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->setMwGlobals( array(
+ 'wgContLang' => Language::factory( 'qqx' )
+ ) );
+ }
+
+ private function getDataTypeFactory() {
+ $dataTypeFactory = DataTypeFactory::newFromTypes( array(
+ new DataType( 'wikibase-item', 'wikibase-item', array()
),
+ new DataType( 'string', 'string', array() ),
+ new DataType( 'quantity', 'quantity', array() )
+ ) );
+
+ return $dataTypeFactory;
+ }
+
+ private function getPropertyInfoStore() {
+ $propertyInfoStore = new MockPropertyInfoStore();
+
+ $propertyInfoStore->setPropertyInfo(
+ new PropertyId( 'P123' ),
+ array( PropertyInfoStore::KEY_DATA_TYPE =>
'wikibase-item' )
+ );
+
+ $propertyInfoStore->setPropertyInfo(
+ new PropertyId( 'P456' ),
+ array( PropertyInfoStore::KEY_DATA_TYPE =>
'wikibase-item' )
+ );
+
+ $propertyInfoStore->setPropertyInfo(
+ new PropertyId( 'P789' ),
+ array( PropertyInfoStore::KEY_DATA_TYPE => 'string' )
+ );
+
+ return $propertyInfoStore;
+ }
+
+ private function getTermLookup() {
+ $termLookup = $this->getMock( 'Wikibase\Lib\Store\TermLookup' );
+ $termLookup->expects( $this->any() )
+ ->method( 'getLabels' )
+ ->will( $this->returnCallback( function( PropertyId
$propertyId ) {
+ return array( 'en' => 'Property with label ' .
$propertyId->getSerialization() );
+ } ) );
+
+ return $termLookup;
+ }
+
+ private function getTermBuffer() {
+ $termBuffer = $this->getMock( 'Wikibase\Store\TermBuffer' );
+ $termBuffer->expects( $this->any() )
+ ->method( 'prefetchTerms' );
+
+ return $termBuffer;
+ }
+
+ private function getEntityTitleLookup() {
+ $entityTitleLookup = $this->getMock(
'Wikibase\Lib\Store\EntityTitleLookup' );
+ $entityTitleLookup->expects( $this->any() )
+ ->method( 'getTitleForId' )
+ ->will( $this->returnCallback(
+ function ( EntityId $id ) {
+ return Title::makeTitle( NS_MAIN,
$id->getSerialization() );
+ }
+ ) );
+
+ return $entityTitleLookup;
+ }
+
+ protected function newSpecialPage() {
+ $specialPage = new SpecialListProperties();
+
+ $specialPage->initServices(
+ $this->getDataTypeFactory(),
+ $this->getPropertyInfoStore(),
+ new LanguageFallbackChainFactory(),
+ $this->getTermLookup(),
+ $this->getTermBuffer(),
+ new EntityIdHtmlLinkFormatterFactory(
$this->getEntityTitleLookup(), new LanguageNameLookup() )
+ );
+
+ return $specialPage;
+ }
+
+ public function testExecute() {
+ // This also tests that there is no fatal error, that the
restriction handling is working
+ // and doesn't block. That is, the default should let the user
execute the page.
+ list( $output, ) = $this->executeSpecialPage( '' );
+
+ $this->assertInternalType( 'string', $output );
+ $this->assertContains( 'wikibase-listproperties-summary',
$output );
+ $this->assertContains( 'wikibase-listproperties-legend',
$output );
+ $this->assertNotContains(
'wikibase-listproperties-invalid-datatype', $output );
+ }
+
+ public function testExecute_empty() {
+ list( $output, ) = $this->executeSpecialPage( 'quantity' );
+
+ $this->assertContains( 'specialpage-empty', $output );
+ }
+
+ public function testExecute_error() {
+ list( $output, ) = $this->executeSpecialPage( 'test<>' );
+
+ $this->assertContains(
'wikibase-listproperties-invalid-datatype', $output );
+ $this->assertContains( 'test<>', $output );
+ }
+
+ public function testExecute_wikibase_item() {
+ // Use en-gb as language to test language fallback
+ list( $output, ) = $this->executeSpecialPage( 'wikibase-item',
null, 'en-gb' );
+
+ $this->assertContains( 'Property with label P123', $output );
+ $this->assertContains( 'Property with label P456', $output );
+ $this->assertNotContains( 'P789', $output );
+ }
+
+ public function testExecute_string() {
+ list( $output, ) = $this->executeSpecialPage( 'string', null,
'en-gb' );
+
+ $this->assertNotContains( 'P123', $output );
+ $this->assertNotContains( 'P456', $output );
+ $this->assertContains( 'Property with label P789', $output );
+ }
+
+}
+
--
To view, visit https://gerrit.wikimedia.org/r/203527
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I79a08ec87bf76adba869d4b7eb22098b41fbdb72
Gerrit-PatchSet: 13
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Bene <[email protected]>
Gerrit-Reviewer: Addshore <[email protected]>
Gerrit-Reviewer: Aude <[email protected]>
Gerrit-Reviewer: Bene <[email protected]>
Gerrit-Reviewer: Daniel Kinzler <[email protected]>
Gerrit-Reviewer: Hoo man <[email protected]>
Gerrit-Reviewer: Jeroen De Dauw <[email protected]>
Gerrit-Reviewer: Legoktm <[email protected]>
Gerrit-Reviewer: Lydia Pintscher <[email protected]>
Gerrit-Reviewer: Siebrand <[email protected]>
Gerrit-Reviewer: Thiemo Mättig (WMDE) <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits