WikidataBuilder has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/381526 )

Change subject: New Wikidata Build - 2017-09-30T10:00:02+0000
......................................................................

New Wikidata Build - 2017-09-30T10:00:02+0000

Change-Id: Ia73eb3a326437b3bd906acb53297c8090e395c3c
---
M Wikidata.localisation.php
M Wikidata.php
M composer.lock
M extensions/Constraints/README.md
M extensions/Constraints/extension.json
M extensions/Constraints/i18n/en.json
M extensions/Constraints/i18n/qqq.json
A extensions/Constraints/includes/ConstraintCheck/Checker/ValueOnlyChecker.php
M 
extensions/Constraints/includes/ConstraintCheck/DelegatingConstraintChecker.php
M extensions/Constraints/includes/ConstraintReportFactory.php
M extensions/Constraints/tests/phpunit/Api/CheckConstraintsTest.php
A extensions/Constraints/tests/phpunit/Checker/ValueOnlyCheckerTest.php
M extensions/Wikibase/client/WikibaseClient.php
M extensions/Wikibase/lib/includes/Formatters/EntityIdHtmlLinkFormatter.php
M vendor/composer/autoload_classmap.php
M vendor/composer/autoload_static.php
M vendor/composer/installed.json
17 files changed, 410 insertions(+), 78 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikidata 
refs/changes/26/381526/1

diff --git a/Wikidata.localisation.php b/Wikidata.localisation.php
index e1cad1c..e166629 100644
--- a/Wikidata.localisation.php
+++ b/Wikidata.localisation.php
@@ -4,10 +4,6 @@
        die( 'Not an entry point.' );
 }
 
-// no magic, use wmf configs instead to control which entry points to load
-$wgEnableWikibaseRepo = false;
-$wgEnableWikibaseClient = false;
-
 $wgWikidataBaseDir = $IP;
 
 if ( file_exists(  __DIR__ . '/vendor/autoload.php' ) ) {
diff --git a/Wikidata.php b/Wikidata.php
index dcb4143..b96b27c 100755
--- a/Wikidata.php
+++ b/Wikidata.php
@@ -12,10 +12,6 @@
        $wmgUseArticlePlaceholder = true;
 }
 
-// no magic, use wmf configs instead to control which entry points to load
-$wgEnableWikibaseRepo = false;
-$wgEnableWikibaseClient = false;
-
 $wgWikidataBaseDir = $IP;
 
 if ( file_exists(  __DIR__ . '/vendor/autoload.php' ) ) {
diff --git a/composer.lock b/composer.lock
index 4612f5e..79c8573 100644
--- a/composer.lock
+++ b/composer.lock
@@ -977,7 +977,7 @@
             "source": {
                 "type": "git",
                 "url": 
"https://gerrit.wikimedia.org/r/mediawiki/extensions/WikibaseQualityConstraints";,
-                "reference": "0a46d56c378cd40d15bc4e0e479f1588261648b1"
+                "reference": "0d4d91f03dafd535e231900ae510c92634682b3e"
             },
             "require": {
                 "php": ">=5.5.9",
@@ -1037,7 +1037,7 @@
             "support": {
                 "issues": 
"https://phabricator.wikimedia.org/project/profile/1202/";
             },
-            "time": "2017-09-29 09:37:36"
+            "time": "2017-09-29 10:04:34"
         },
         {
             "name": "wikibase/data-model",
@@ -1548,12 +1548,12 @@
             "source": {
                 "type": "git",
                 "url": 
"https://github.com/wikimedia/mediawiki-extensions-Wikibase.git";,
-                "reference": "79f95b564f54ae5499e665a75ffa24860abb9f4b"
+                "reference": "151dde0e4154467a0195a468ef2468daed1c88ee"
             },
             "dist": {
                 "type": "zip",
-                "url": 
"https://api.github.com/repos/wikimedia/mediawiki-extensions-Wikibase/zipball/79f95b564f54ae5499e665a75ffa24860abb9f4b";,
-                "reference": "79f95b564f54ae5499e665a75ffa24860abb9f4b",
+                "url": 
"https://api.github.com/repos/wikimedia/mediawiki-extensions-Wikibase/zipball/151dde0e4154467a0195a468ef2468daed1c88ee";,
+                "reference": "151dde0e4154467a0195a468ef2468daed1c88ee",
                 "shasum": ""
             },
             "require": {
@@ -1631,7 +1631,7 @@
                 "wikibaserepo",
                 "wikidata"
             ],
-            "time": "2017-09-29 09:36:10"
+            "time": "2017-09-29 15:47:38"
         },
         {
             "name": "wikibase/wikimedia-badges",
diff --git a/extensions/Constraints/README.md b/extensions/Constraints/README.md
index 5ff3655..099b55a 100644
--- a/extensions/Constraints/README.md
+++ b/extensions/Constraints/README.md
@@ -146,3 +146,94 @@
 
   This runs the tests without coverage report
   and is therefore much faster.
+
+### Adding a new constraint type
+
+To add a new constraint type, the following steps are necessary:
+
+* Define the constraint checker class.
+  * It should be defined in a new file in `includes/ConstraintCheck/Checker/`,
+    named after the class name.
+    It should be in the 
`WikibaseQuality\ConstraintReport\ConstraintCheck\Checker` namespace.
+  * The class name should follow the constraint type name (in English), ending 
in “Checker”.
+  * The class must implement the `ConstraintChecker` interface.
+  * It should have at least the following class-level documentation comment:
+    ```php
+    /**
+     * @package WikibaseQuality\ConstraintReport\ConstraintCheck\Checker
+     * @author YOUR NAME HERE
+     * @license GNU GPL v2+
+     */
+    ```
+  * Any services you need (`Config`, `EntityLookup`, …) should be injected as 
constructor parameters.
+  * If the constraint has parameters,
+    add support for parsing them to `ConstraintParameterParser`
+    (add a config setting for the associated property in `extension.json`
+    and a method to parse the parameter in `ConstraintParameterParser`),
+    and then add tests for them in `ConstraintParameterParserTest`.
+    This should be done in a separate commit.
+* Define new messages (at least a violation message for the constraint type).
+  * Define the message in `i18n/en.json`.
+    A violation message should have a key like 
`wbqc-violation-message-constraintType`.
+  * Document the message in `i18n/qqq.json`.
+    Use the same message key,
+    and insert the documentation in the same location where you also added the 
message in `en.json`
+    (that is, `en.json` and `qqq.json` should contain message keys in the same 
order).
+* Add a configuration setting for the constraint type item ID.
+  * Configuration settings are defined in `extension.json`,
+    as members of the `config` object.
+  * It should be added right after the current last `…ConstraintId` entry.
+  * It should be named after the constraint type item’s English label,
+    following the pattern `WBQualityConstraints___ConstraintId`.
+  * The default value should be the item ID on Wikidata,
+    so that no extra configuration is required for Wikidata
+    and importing the constraint type item (see “Data import” section) works.
+  * The first part of the description can be copied from similar settings,
+    the rest should contain a short description of the constraint type.
+  * The ID can always be public (`"public": true`).
+* Configure the constraint type checker in `ConstraintReportFactory`.
+  * Add an array entry like
+    ```php
+    $this->config->get( 'WBQualityConstraints___ConstraintId' )
+       => new ___Checker(
+               // injected services
+       ),
+    ```
+    at the end of the `getConstraintCheckerMap()` function.
+* Add tests for the new constraint checker.
+  * The test class name should be the same as the checker class name,
+    with an additional suffix `Test` (i. e., `…CheckerTest`).
+  * The test class should be placed somewhere in `tests/phpunit/Checker/`,
+    either in the most suitable subdirectory
+    or directly in that directory if none of the subdirectories are suitable.
+    (The division into subdirectories there is dubious anyways,
+    and we may get rid of it in the future.)
+  * It should have at least the following class-level documentation comment:
+    ```php
+    /**
+     * @covers 
\WikibaseQuality\ConstraintReport\ConstraintCheck\Checker\___Checker
+     *
+     * @group WikibaseQualityConstraints
+     *
+     * @uses 
\WikibaseQuality\ConstraintReport\ConstraintCheck\Result\CheckResult
+     *
+     * @author YOUR NAME HERE
+     * @license GNU GPL v2+
+     */
+    ```
+  * It should have at least one test for compliance with a constraint,
+    one test for a constraint violation,
+    one test for behavior on a deprecated statement,
+    and one test for the `checkConstraintParameters` method.
+  * Use the `ResultAssertions` trait’s methods to check constraint check 
results.
+  * Use the `NewItem` and `NewStatement` builders to construct test data.
+    (You might see `JsonFileEntityLookup` and separate JSON files used in some 
existing tests,
+    but that’s a lot less readable.)
+  * If the checker uses a `Config`, use the `DefaultConfig` trait.
+  * If the constraint has parameters,
+    add methods for them to the `ConstraintParameterns` trait and use it in 
the tests.
+  * You can copy+paste a `getConstraintMock` function from one of the existing 
tests,
+    adjusting the `getConstraintTypeItemId` mocked return value.
+    (Hopefully we’ll improve this in the future.)
+
+An example commit that performs all of these steps is [Change 
Id45d80e7a0](https://gerrit.wikimedia.org/r/381005).
diff --git a/extensions/Constraints/extension.json 
b/extensions/Constraints/extension.json
index f48a3f0..e550c7a 100644
--- a/extensions/Constraints/extension.json
+++ b/extensions/Constraints/extension.json
@@ -121,6 +121,16 @@
                        "description": "Whether to use the new API output 
format, based on the Wikibase entity JSON format, which can accommodate 
constraint results on qualifiers and references.",
                        "public": true
                },
+               "WBQualityConstraintsCheckQualifiers": {
+                       "value": false,
+                       "description": "Whether to check constraints on 
qualifiers. Requires the new API output format (otherwise ignored).",
+                       "public": true
+               },
+               "WBQualityConstraintsCheckReferences": {
+                       "value": false,
+                       "description": "Whether to check constraints on 
references. Requires the new API output format (otherwise ignored).",
+                       "public": true
+               },
                "WBQualityConstraintsSparqlEndpoint": {
                        "value": "",
                        "description": "The URL of the SPARQL endpoint. Should 
accept the URL parameters 'query', 'format' and 'maxQueryTimeMillis'. Set to '' 
(empty string, default) to disable SPARQL functionality.",
@@ -269,6 +279,11 @@
                        "description": "The item ID of the 'format constraint' 
item, which, when used in a 'property constraint' statement on a property, 
indicates that the value of a given statement should conform to a given 
pattern.",
                        "public": true
                },
+               "WBQualityConstraintsUsedForValuesOnlyConstraintId": {
+                       "value": "Q21528958",
+                       "description": "The item ID of the 'used for values 
only constraint' item, which, when used in a 'property constraint' statement on 
a property, indicates that the property should only be used for the main value 
of a statement, not for qualifiers or references.",
+                       "public": true
+               },
                "WBQualityConstraintsClassId": {
                        "value": "P2308",
                        "description": "The property ID of the 'relation' 
property (data type: item), which specifies the class/type of a 'type' or 
'value type' constraint.",
diff --git a/extensions/Constraints/i18n/en.json 
b/extensions/Constraints/i18n/en.json
index 2b9c2cf..265731a 100644
--- a/extensions/Constraints/i18n/en.json
+++ b/extensions/Constraints/i18n/en.json
@@ -124,6 +124,7 @@
        "wbqc-violation-message-valueType-subclass": "Values of $1 statements 
should be subclasses of {{PLURAL:$3|1=$5|2=$5 or $6|one of the following 
classes}} (or of {{PLURAL:$3|1=a subclass of it|2=a subclass of them|one of 
their subclasses}}), but $2 currently {{PLURAL:$3|1=isn't.|2=isn't.|isn't: 
$4}}",
        "wbqc-violation-message-target-required-claim": "$1 should have 
{{PLURAL:$3|0=a statement $2.|1=a statement $2 $5.|a statement for $2 with one 
of the following values:$4}}",
        "wbqc-violation-message-unique-value": "This property's value must not 
be present on any other item, but is also present on {{PLURAL:$1|1=$3.|2=$3 and 
$4.|the following items: $2}}",
+       "wbqc-violation-message-valueOnly": "This property should only be used 
for the main value of a statement, not for qualifiers or references.",
 
        "wbqc-exception-message": "This entity is a known exception for this 
constraint and has been marked as such."
 }
diff --git a/extensions/Constraints/i18n/qqq.json 
b/extensions/Constraints/i18n/qqq.json
index f31c8b1..3d169ce 100644
--- a/extensions/Constraints/i18n/qqq.json
+++ b/extensions/Constraints/i18n/qqq.json
@@ -120,5 +120,6 @@
        "wbqc-violation-message-valueType-subclass": "Message for a violation 
of the “Value type” constraint, when the value of a statement should have be a 
subclass of a certain type but isn't. $1 is the property of the statement, $2 
is the value of the statement, $3 is the number of classes, $4 is an HTML list 
of all classes, and $5, $6 etc. are the individual 
classes.\n{{Related|wbqc-violation-message-valueType-instance}}",
        "wbqc-violation-message-target-required-claim": "Message for a 
violation of the “Target required claim” constraint, when the target entity of 
a statement is missing an expected statement. Parameters:\n* $1 is the subject 
entity of the missing statement, i. e. the target entity of the statement that 
has the constraint.\n* $2 is the property of the missing statement.\n* $3 is 
the number of values permitted for the missing statement (or 0, in which case 
the constraint only specifies that there should be a statement but not the 
values it should have).\n* $4 is an HTML list of all values permitted for the 
missing statement.\n* $5, $6 etc. are the individual values permitted for the 
missing statement.\n{{Related|wbqc-violation-message-item}}",
        "wbqc-violation-message-unique-value": "Message for violation of the 
Unique Value constraint, when other items are found. Parameters:\n* $1 is the 
number of other items with the same value.\n* $2 is an HTML list of all other 
items found with the same value.\n* $3, $4 etc. are the individual other items 
with the same value.",
+       "wbqc-violation-message-valueOnly": "Message for a violation of the 
“used for values only” constraint, when a property intended for the main value 
only was used in a qualifier or reference.",
        "wbqc-exception-message": "Message for a constraint check result on an 
entity that has been marked as an exception to the constraint. This message 
only appears on [[Special:ConstraintReport]]; the gadget does not show 
exception reports."
 }
diff --git 
a/extensions/Constraints/includes/ConstraintCheck/Checker/ValueOnlyChecker.php 
b/extensions/Constraints/includes/ConstraintCheck/Checker/ValueOnlyChecker.php
new file mode 100644
index 0000000..03c8adf
--- /dev/null
+++ 
b/extensions/Constraints/includes/ConstraintCheck/Checker/ValueOnlyChecker.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace WikibaseQuality\ConstraintReport\ConstraintCheck\Checker;
+
+use WikibaseQuality\ConstraintReport\Constraint;
+use WikibaseQuality\ConstraintReport\ConstraintCheck\ConstraintChecker;
+use WikibaseQuality\ConstraintReport\ConstraintCheck\Context\Context;
+use WikibaseQuality\ConstraintReport\ConstraintCheck\Result\CheckResult;
+
+/**
+ * @package WikibaseQuality\ConstraintReport\ConstraintCheck\Checker
+ * @author Lucas Werkmeister
+ * @license GNU GPL v2+
+ */
+class ValueOnlyChecker implements ConstraintChecker {
+
+       public function checkConstraint( Context $context, Constraint 
$constraint ) {
+               if ( $context->getType() === Context::TYPE_STATEMENT ) {
+                       return new CheckResult( $context, $constraint, [], 
CheckResult::STATUS_COMPLIANCE, '' );
+               } else {
+                       $message = wfMessage( 
'wbqc-violation-message-valueOnly' )->escaped();
+                       return new CheckResult( $context, $constraint, [], 
CheckResult::STATUS_VIOLATION, $message );
+               }
+       }
+
+       public function checkConstraintParameters( Constraint $constraint ) {
+               // no parameters
+               return [];
+       }
+
+}
diff --git 
a/extensions/Constraints/includes/ConstraintCheck/DelegatingConstraintChecker.php
 
b/extensions/Constraints/includes/ConstraintCheck/DelegatingConstraintChecker.php
index 7514830..887fc1c 100644
--- 
a/extensions/Constraints/includes/ConstraintCheck/DelegatingConstraintChecker.php
+++ 
b/extensions/Constraints/includes/ConstraintCheck/DelegatingConstraintChecker.php
@@ -13,6 +13,8 @@
 use Wikibase\DataModel\Statement\StatementListProvider;
 use WikibaseQuality\ConstraintReport\ConstraintCheck\Context\Context;
 use WikibaseQuality\ConstraintReport\ConstraintCheck\Context\MainSnakContext;
+use WikibaseQuality\ConstraintReport\ConstraintCheck\Context\QualifierContext;
+use WikibaseQuality\ConstraintReport\ConstraintCheck\Context\ReferenceContext;
 use WikibaseQuality\ConstraintReport\ConstraintCheck\Context\StatementContext;
 use 
WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\ConstraintParameterException;
 use 
WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\ConstraintParameterParser;
@@ -71,6 +73,16 @@
        private $apiV2;
 
        /**
+        * @var bool
+        */
+       private $checkQualifiers;
+
+       /**
+        * @var bool
+        */
+       private $checkReferences;
+
+       /**
         * @param EntityLookup $lookup
         * @param ConstraintChecker[] $checkerMap
         * @param ConstraintLookup $constraintRepository
@@ -78,6 +90,8 @@
         * @param StatementGuidParser $statementGuidParser
         * @param LoggingHelper $loggingHelper
         * @param bool $apiV2 whether to use the new API output format
+        * @param bool $checkQualifiers whether to check qualifiers
+        * @param bool $checkReferences whether to check references
         */
        public function __construct(
                EntityLookup $lookup,
@@ -86,7 +100,9 @@
                ConstraintParameterParser $constraintParameterParser,
                StatementGuidParser $statementGuidParser,
                LoggingHelper $loggingHelper,
-               $apiV2
+               $apiV2,
+               $checkQualifiers,
+               $checkReferences
        ) {
                $this->entityLookup = $lookup;
                $this->checkerMap = $checkerMap;
@@ -95,6 +111,8 @@
                $this->statementGuidParser = $statementGuidParser;
                $this->loggingHelper = $loggingHelper;
                $this->apiV2 = $apiV2;
+               $this->checkQualifiers = $apiV2 && $checkQualifiers;
+               $this->checkReferences = $apiV2 && $checkReferences;
        }
 
        /**
@@ -254,9 +272,33 @@
        private function checkStatement( EntityDocument $entity, Statement 
$statement, $constraintIds = null ) {
                $result = [];
 
-               $constraints = 
$this->constraintLookup->queryConstraintsForProperty(
-                       $statement->getPropertyId()
-               );
+               $result = array_merge( $result,
+                       $this->checkConstraintsForMainSnak( $entity, 
$statement, $constraintIds ) );
+
+               if ( $this->checkQualifiers ) {
+                       $result = array_merge( $result,
+                               $this->checkConstraintsForQualifiers( $entity, 
$statement, $constraintIds ) );
+               }
+
+               if ( $this->checkReferences ) {
+                       $result = array_merge( $result,
+                               $this->checkConstraintsForReferences( $entity, 
$statement, $constraintIds ) );
+               }
+
+               return $result;
+       }
+
+       /**
+        * Get the constraints to actually check for a given property ID.
+        * If $constraintIds is not null, only check constraints with those 
constraint IDs,
+        * otherwise check all constraints for that property.
+        *
+        * @param PropertyId $propertyId
+        * @param string[]|null $constraintIds
+        * @return Constraint[]
+        */
+       private function getConstraintsToUse( PropertyId $propertyId, array 
$constraintIds = null ) {
+               $constraints = 
$this->constraintLookup->queryConstraintsForProperty( $propertyId );
                if ( $constraintIds !== null ) {
                        $constraintsToUse = [];
                        foreach ( $constraints as $constraint ) {
@@ -264,30 +306,31 @@
                                        $constraintsToUse[] = $constraint;
                                }
                        }
+                       return $constraintsToUse;
                } else {
-                       $constraintsToUse = $constraints;
+                       return $constraints;
                }
-               $result = array_merge(
-                       $result,
-                       $this->checkConstraintsForStatementOnEntity( 
$constraintsToUse, $entity, $statement )
-               );
-
-               return $result;
        }
 
        /**
-        * @param Constraint[] $constraints
-        * @param EntityDocument|StatementListProvider $entity
+        * @param EntityDocument $entity
         * @param Statement $statement
-        *
+        * @param string[]|null $constraintIds list of constraints to check (if 
null: all constraints)
         * @return CheckResult[]
         */
-       private function checkConstraintsForStatementOnEntity( array 
$constraints, EntityDocument $entity, $statement ) {
-               $entityId = $entity->getId();
+       private function checkConstraintsForMainSnak(
+               EntityDocument $entity,
+               Statement $statement,
+               array $constraintIds = null
+       ) {
                $result = [];
                $context = $this->apiV2 ?
                        new MainSnakContext( $entity, $statement ) :
                        new StatementContext( $entity, $statement );
+               $constraints = $this->getConstraintsToUse(
+                       $statement->getPropertyId(),
+                       $constraintIds
+               );
 
                foreach ( $constraints as $constraint ) {
                        $parameters = $constraint->getConstraintParameters();
@@ -298,13 +341,74 @@
                                continue;
                        }
 
-                       if ( in_array( $entityId, $exceptions ) ) {
+                       if ( in_array( $entity->getId(), $exceptions ) ) {
                                $message = wfMessage( 'wbqc-exception-message' 
)->escaped();
                                $result[] = new CheckResult( $context, 
$constraint, [], CheckResult::STATUS_EXCEPTION, $message );
                                continue;
                        }
 
-                       $result[ ] = $this->getCheckResultFor( $context, 
$constraint );
+                       $result[] = $this->getCheckResultFor( $context, 
$constraint );
+               }
+
+               return $result;
+       }
+
+       /**
+        * @param EntityDocument $entity
+        * @param Statement $statement
+        * @param string[]|null $constraintIds list of constraints to check (if 
null: all constraints)
+        * @return CheckResult[]
+        */
+       private function checkConstraintsForQualifiers(
+               EntityDocument $entity,
+               Statement $statement,
+               array $constraintIds = null
+       ) {
+               $result = [];
+
+               foreach ( $statement->getQualifiers() as $qualifier ) {
+                       $qualifierContext = new QualifierContext( $entity, 
$statement, $qualifier );
+                       $qualifierConstraints = $this->getConstraintsToUse(
+                               $qualifierContext->getSnak()->getPropertyId(),
+                               $constraintIds
+                       );
+                       foreach ( $qualifierConstraints as $qualifierConstraint 
) {
+                               $result[] = $this->getCheckResultFor( 
$qualifierContext, $qualifierConstraint );
+                       }
+               }
+
+               return $result;
+       }
+
+       /**
+        * @param EntityDocument $entity
+        * @param Statement $statement
+        * @param string[]|null $constraintIds list of constraints to check (if 
null: all constraints)
+        * @return CheckResult[]
+        */
+       private function checkConstraintsForReferences(
+               EntityDocument $entity,
+               Statement $statement,
+               array $constraintIds = null
+       ) {
+               $result = [];
+
+               foreach ( $statement->getReferences() as $reference ) {
+                       foreach ( $reference->getSnaks() as $snak ) {
+                               $referenceContext = new ReferenceContext(
+                                       $entity, $statement, $reference, $snak
+                               );
+                               $referenceConstraints = 
$this->getConstraintsToUse(
+                                       
$referenceContext->getSnak()->getPropertyId(),
+                                       $constraintIds
+                               );
+                               foreach ( $referenceConstraints as 
$referenceConstraint ) {
+                                       $result[] = $this->getCheckResultFor(
+                                               $referenceContext,
+                                               $referenceConstraint
+                                       );
+                               }
+                       }
                }
 
                return $result;
diff --git a/extensions/Constraints/includes/ConstraintReportFactory.php 
b/extensions/Constraints/includes/ConstraintReportFactory.php
index dfe82d5..7750506 100644
--- a/extensions/Constraints/includes/ConstraintReportFactory.php
+++ b/extensions/Constraints/includes/ConstraintReportFactory.php
@@ -35,6 +35,7 @@
 use 
WikibaseQuality\ConstraintReport\ConstraintCheck\Checker\SingleValueChecker;
 use WikibaseQuality\ConstraintReport\ConstraintCheck\Checker\MultiValueChecker;
 use 
WikibaseQuality\ConstraintReport\ConstraintCheck\Checker\UniqueValueChecker;
+use WikibaseQuality\ConstraintReport\ConstraintCheck\Checker\ValueOnlyChecker;
 use WikibaseQuality\ConstraintReport\ConstraintCheck\ConstraintChecker;
 use 
WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\ConnectionCheckerHelper;
 use WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\LoggingHelper;
@@ -193,7 +194,9 @@
                                        LoggerFactory::getInstance( 
'WikibaseQualityConstraints' ),
                                        $this->config
                                ),
-                               $this->config->get( 
'WBQualityConstraintsNewApiOutputFormat' )
+                               $this->config->get( 
'WBQualityConstraintsNewApiOutputFormat' ),
+                               $this->config->get( 
'WBQualityConstraintsCheckQualifiers' ),
+                               $this->config->get( 
'WBQualityConstraintsCheckReferences' )
                        );
                }
 
@@ -326,6 +329,8 @@
                                                
$this->constraintParameterParser,
                                                
$this->constraintParameterRenderer
                                        ),
+                               $this->config->get( 
'WBQualityConstraintsUsedForValuesOnlyConstraintId' )
+                                       => new ValueOnlyChecker(),
                        ];
                }
 
diff --git a/extensions/Constraints/tests/phpunit/Api/CheckConstraintsTest.php 
b/extensions/Constraints/tests/phpunit/Api/CheckConstraintsTest.php
index a59d405..63cf1a9 100644
--- a/extensions/Constraints/tests/phpunit/Api/CheckConstraintsTest.php
+++ b/extensions/Constraints/tests/phpunit/Api/CheckConstraintsTest.php
@@ -131,6 +131,8 @@
                                        LoggerFactory::getInstance( 
'WikibaseQualityConstraints' ),
                                        $config
                                ),
+                               false,
+                               false,
                                false
                        );
 
diff --git 
a/extensions/Constraints/tests/phpunit/Checker/ValueOnlyCheckerTest.php 
b/extensions/Constraints/tests/phpunit/Checker/ValueOnlyCheckerTest.php
new file mode 100644
index 0000000..56c43d5
--- /dev/null
+++ b/extensions/Constraints/tests/phpunit/Checker/ValueOnlyCheckerTest.php
@@ -0,0 +1,97 @@
+<?php
+
+namespace WikibaseQuality\ConstraintReport\Test;
+
+use Wikibase\Repo\Tests\NewItem;
+use Wikibase\Repo\Tests\NewStatement;
+use WikibaseQuality\ConstraintReport\Constraint;
+use WikibaseQuality\ConstraintReport\ConstraintCheck\Checker\ValueOnlyChecker;
+use WikibaseQuality\ConstraintReport\ConstraintCheck\Context\Context;
+use WikibaseQuality\ConstraintReport\ConstraintCheck\Context\StatementContext;
+use WikibaseQuality\ConstraintReport\Tests\ResultAssertions;
+
+/**
+ * @covers 
\WikibaseQuality\ConstraintReport\ConstraintCheck\Checker\ValueOnlyChecker
+ *
+ * @group WikibaseQualityConstraints
+ *
+ * @uses \WikibaseQuality\ConstraintReport\ConstraintCheck\Result\CheckResult
+ *
+ * @author Lucas Werkmeister
+ * @license GNU GPL v2+
+ */
+class ValueOnlyCheckerTest extends \PHPUnit_Framework_TestCase {
+
+       use ResultAssertions;
+
+       /**
+        * @param string $type context type
+        * @param string|null $messageKey key of violation message, or null if 
compliance is expected
+        * @dataProvider contextTypes
+        */
+       public function testQualifierConstraint( $type, $messageKey ) {
+               $context = $this->getMock( Context::class );
+               $context->method( 'getType' )->willReturn( $type );
+               $checker = new ValueOnlyChecker();
+               $constraint = $this->getConstraintMock( [] );
+
+               $checkResult = $checker->checkConstraint( $context, $constraint 
);
+
+               if ( $messageKey === null ) {
+                       $this->assertCompliance( $checkResult );
+               } else {
+                       $this->assertViolation( $checkResult, $messageKey );
+               }
+       }
+
+       public function contextTypes() {
+               return [
+                       [ Context::TYPE_STATEMENT, null ],
+                       [ Context::TYPE_QUALIFIER, 
'wbqc-violation-message-valueOnly' ],
+                       [ Context::TYPE_REFERENCE, 
'wbqc-violation-message-valueOnly' ],
+               ];
+       }
+
+       public function testQualifierConstraintDeprecatedStatement() {
+               $checker = new ValueOnlyChecker();
+               $statement = NewStatement::noValueFor( 'P1' )
+                       ->withDeprecatedRank()
+                       ->build();
+               $constraint = $this->getConstraintMock( [] );
+               $entity = NewItem::withId( 'Q1' )
+                       ->build();
+
+               $checkResult = $checker->checkConstraint( new StatementContext( 
$entity, $statement ), $constraint );
+
+               // this constraint is still checked on deprecated statements
+               $this->assertCompliance( $checkResult );
+       }
+
+       public function testCheckConstraintParameters() {
+               $checker = new ValueOnlyChecker();
+               $constraint = $this->getConstraintMock( [] );
+
+               $result = $checker->checkConstraintParameters( $constraint );
+
+               $this->assertCount( 0, $result );
+       }
+
+       /**
+        * @return Constraint
+        */
+       private function getConstraintMock() {
+               $mock = $this
+                       ->getMockBuilder( Constraint::class )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+               $mock->expects( $this->any() )
+                       ->method( 'getConstraintParameters' )
+                       ->will( $this->returnValue( [] ) );
+               $mock->expects( $this->any() )
+                       ->method( 'getConstraintTypeItemId' )
+                       ->will( $this->returnValue( 'ValueOnly' ) );
+
+               return $mock;
+       }
+
+}
diff --git a/extensions/Wikibase/client/WikibaseClient.php 
b/extensions/Wikibase/client/WikibaseClient.php
index baf0bec..cae926c 100644
--- a/extensions/Wikibase/client/WikibaseClient.php
+++ b/extensions/Wikibase/client/WikibaseClient.php
@@ -70,6 +70,7 @@
        global $wgAPIListModules,
                $wgAPIMetaModules,
                $wgAPIPropModules,
+               $wgAPIUselessQueryPages,
                $wgExtensionCredits,
                $wgExtensionFunctions,
                $wgExtensionMessagesFiles,
@@ -267,6 +268,7 @@
                        );
                }
        ];
+       $wgAPIUselessQueryPages[] = 'PagesWithBadges';
 
        // Special page registration
        $wgSpecialPages['UnconnectedPages'] = 
Wikibase\Client\Specials\SpecialUnconnectedPages::class;
diff --git 
a/extensions/Wikibase/lib/includes/Formatters/EntityIdHtmlLinkFormatter.php 
b/extensions/Wikibase/lib/includes/Formatters/EntityIdHtmlLinkFormatter.php
index 2377f1b..2066f6c 100644
--- a/extensions/Wikibase/lib/includes/Formatters/EntityIdHtmlLinkFormatter.php
+++ b/extensions/Wikibase/lib/includes/Formatters/EntityIdHtmlLinkFormatter.php
@@ -3,6 +3,7 @@
 namespace Wikibase\Lib;
 
 use Html;
+use Title;
 use Wikibase\DataModel\Entity\EntityId;
 use Wikibase\DataModel\Services\EntityId\EntityIdLabelFormatter;
 use Wikibase\DataModel\Services\Lookup\LabelDescriptionLookup;
@@ -20,14 +21,14 @@
 class EntityIdHtmlLinkFormatter extends EntityIdLabelFormatter {
 
        /**
-        * @var LanguageFallbackIndicator
-        */
-       private $languageFallbackIndicator;
-
-       /**
         * @var EntityTitleLookup
         */
        protected $entityTitleLookup;
+
+       /**
+        * @var LanguageFallbackIndicator
+        */
+       private $languageFallbackIndicator;
 
        public function __construct(
                LabelDescriptionLookup $labelDescriptionLookup,
@@ -56,60 +57,48 @@
 
                $term = $this->lookupEntityLabel( $entityId );
 
-               $url = $title->isLocal() ? $title->getLocalURL() : 
$title->getFullURL();
-               $isRedirect = $title->isLocal() && $title->isRedirect();
-
-               if ( $term ) {
-                       return $this->getHtmlForTerm( $url, $term, 
$title->getPrefixedText(), $isRedirect );
+               // We can skip the expensive exists() check if we found a term.
+               if ( $term !== null ) {
+                       $label = $term->getText();
                } elseif ( $title->isLocal() && !$title->exists() ) {
                        return $this->getHtmlForNonExistent( $entityId );
+               } else {
+                       $label = $entityId->getSerialization();
                }
 
-               $attributes = [
-                       'title' => $title->getPrefixedText(),
-                       'href' => $url
-               ];
-               if ( $isRedirect ) {
-                       $attributes['class'] = 'mw-redirect';
-               }
+               $html = Html::element( 'a', $this->getAttributes( $title, $term 
), $label );
 
-               $html = Html::element( 'a', $attributes, 
$entityId->getSerialization() );
+               if ( $term instanceof TermFallback ) {
+                       $html .= $this->languageFallbackIndicator->getHtml( 
$term );
+               }
 
                return $html;
        }
 
        /**
-        * @param string $targetUrl
-        * @param Term $term
-        * @param string $titleText
-        * @param bool $isRedirect
+        * @param Title $title
+        * @param Term|null $term
         *
-        * @return string HTML
+        * @return string[]
         */
-       private function getHtmlForTerm( $targetUrl, Term $term, $titleText = 
'', $isRedirect = false ) {
-               $fallbackIndicatorHtml = '';
-
+       private function getAttributes( Title $title, Term $term = null ) {
                $attributes = [
-                       'title' => $titleText,
-                       'href' => $targetUrl
+                       'title' => $title->getPrefixedText(),
+                       'href' => $title->isLocal() ? $title->getLocalURL() : 
$title->getFullURL()
                ];
 
-               if ( $term instanceof TermFallback ) {
-                       $fallbackIndicatorHtml = 
$this->languageFallbackIndicator->getHtml( $term );
-
-                       if ( $term->getActualLanguageCode() !== 
$term->getLanguageCode() ) {
-                               $attributes['lang'] = 
$term->getActualLanguageCode();
-                               //TODO: mark as rtl/ltr if appropriate.
-                       }
+               if ( $term instanceof TermFallback
+                       && $term->getActualLanguageCode() !== 
$term->getLanguageCode()
+               ) {
+                       $attributes['lang'] = $term->getActualLanguageCode();
+                       // TODO: Mark as RTL/LTR if appropriate.
                }
 
-               if ( $isRedirect ) {
+               if ( $title->isLocal() && $title->isRedirect() ) {
                        $attributes['class'] = 'mw-redirect';
                }
 
-               $html = Html::element( 'a', $attributes, $term->getText() );
-
-               return $html . $fallbackIndicatorHtml;
+               return $attributes;
        }
 
        /**
diff --git a/vendor/composer/autoload_classmap.php 
b/vendor/composer/autoload_classmap.php
index fd16fec..3a442e1 100644
--- a/vendor/composer/autoload_classmap.php
+++ b/vendor/composer/autoload_classmap.php
@@ -270,6 +270,7 @@
     
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Checker\\TargetRequiredClaimChecker'
 => $baseDir . 
'/extensions/Constraints/includes/ConstraintCheck/Checker/TargetRequiredClaimChecker.php',
     'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Checker\\TypeChecker' 
=> $baseDir . 
'/extensions/Constraints/includes/ConstraintCheck/Checker/TypeChecker.php',
     
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Checker\\UniqueValueChecker'
 => $baseDir . 
'/extensions/Constraints/includes/ConstraintCheck/Checker/UniqueValueChecker.php',
+    
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Checker\\ValueOnlyChecker' 
=> $baseDir . 
'/extensions/Constraints/includes/ConstraintCheck/Checker/ValueOnlyChecker.php',
     
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Checker\\ValueTypeChecker' 
=> $baseDir . 
'/extensions/Constraints/includes/ConstraintCheck/Checker/ValueTypeChecker.php',
     'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\ConstraintChecker' => 
$baseDir . 
'/extensions/Constraints/includes/ConstraintCheck/ConstraintChecker.php',
     
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Context\\AbstractContext' 
=> $baseDir . 
'/extensions/Constraints/includes/ConstraintCheck/Context/AbstractContext.php',
diff --git a/vendor/composer/autoload_static.php 
b/vendor/composer/autoload_static.php
index 1011b6d..6ccb2b1 100644
--- a/vendor/composer/autoload_static.php
+++ b/vendor/composer/autoload_static.php
@@ -574,6 +574,7 @@
         
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Checker\\TargetRequiredClaimChecker'
 => __DIR__ . '/../..' . 
'/extensions/Constraints/includes/ConstraintCheck/Checker/TargetRequiredClaimChecker.php',
         
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Checker\\TypeChecker' => 
__DIR__ . '/../..' . 
'/extensions/Constraints/includes/ConstraintCheck/Checker/TypeChecker.php',
         
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Checker\\UniqueValueChecker'
 => __DIR__ . '/../..' . 
'/extensions/Constraints/includes/ConstraintCheck/Checker/UniqueValueChecker.php',
+        
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Checker\\ValueOnlyChecker' 
=> __DIR__ . '/../..' . 
'/extensions/Constraints/includes/ConstraintCheck/Checker/ValueOnlyChecker.php',
         
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Checker\\ValueTypeChecker' 
=> __DIR__ . '/../..' . 
'/extensions/Constraints/includes/ConstraintCheck/Checker/ValueTypeChecker.php',
         
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\ConstraintChecker' => 
__DIR__ . '/../..' . 
'/extensions/Constraints/includes/ConstraintCheck/ConstraintChecker.php',
         
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Context\\AbstractContext' 
=> __DIR__ . '/../..' . 
'/extensions/Constraints/includes/ConstraintCheck/Context/AbstractContext.php',
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index 16b4245..8f580d7 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -1389,12 +1389,12 @@
         "source": {
             "type": "git",
             "url": 
"https://github.com/wikimedia/mediawiki-extensions-Wikibase.git";,
-            "reference": "79f95b564f54ae5499e665a75ffa24860abb9f4b"
+            "reference": "151dde0e4154467a0195a468ef2468daed1c88ee"
         },
         "dist": {
             "type": "zip",
-            "url": 
"https://api.github.com/repos/wikimedia/mediawiki-extensions-Wikibase/zipball/79f95b564f54ae5499e665a75ffa24860abb9f4b";,
-            "reference": "79f95b564f54ae5499e665a75ffa24860abb9f4b",
+            "url": 
"https://api.github.com/repos/wikimedia/mediawiki-extensions-Wikibase/zipball/151dde0e4154467a0195a468ef2468daed1c88ee";,
+            "reference": "151dde0e4154467a0195a468ef2468daed1c88ee",
             "shasum": ""
         },
         "require": {
@@ -1429,7 +1429,7 @@
             "mediawiki/minus-x": "0.1.0",
             "wikibase/wikibase-codesniffer": "^0.1.0"
         },
-        "time": "2017-09-29 09:36:10",
+        "time": "2017-09-29 15:47:38",
         "type": "mediawiki-extension",
         "installation-source": "dist",
         "autoload": {
@@ -1780,7 +1780,7 @@
         "source": {
             "type": "git",
             "url": 
"https://gerrit.wikimedia.org/r/mediawiki/extensions/WikibaseQualityConstraints";,
-            "reference": "0a46d56c378cd40d15bc4e0e479f1588261648b1"
+            "reference": "0d4d91f03dafd535e231900ae510c92634682b3e"
         },
         "require": {
             "php": ">=5.5.9",
@@ -1796,7 +1796,7 @@
             "satooshi/php-coveralls": "master-dev",
             "wikibase/wikibase-codesniffer": "^0.1.0"
         },
-        "time": "2017-09-29 09:37:36",
+        "time": "2017-09-29 10:04:34",
         "type": "mediawiki-extension",
         "installation-source": "source",
         "autoload": {

-- 
To view, visit https://gerrit.wikimedia.org/r/381526
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ia73eb3a326437b3bd906acb53297c8090e395c3c
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Wikidata
Gerrit-Branch: master
Gerrit-Owner: WikidataBuilder <wikidata-servi...@wikimedia.de>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to