jenkins-bot has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/402884 )

Change subject: Add scope support to DelegatingConstraintChecker
......................................................................


Add scope support to DelegatingConstraintChecker

The “constraint scope” parameter’s validity is checked along with other
common parameters like “exception to constraint” or “constraint status”,
and when it comes to actually checking a constraint,
DelegatingConstraintChecker also takes care of assigning the default
scope and testing whether a constraint can even be checked on a certain
context.

Bug: T183542
Change-Id: Ie9d7c1c9e7a57d0e03ca0cb0f96d47d0f1869921
---
M src/ConstraintCheck/DelegatingConstraintChecker.php
M tests/phpunit/Api/CheckConstraintsTest.php
M tests/phpunit/DelegatingConstraintCheckerTest.php
3 files changed, 233 insertions(+), 0 deletions(-)

Approvals:
  Jonas Kress (WMDE): Looks good to me, approved
  jenkins-bot: Verified



diff --git a/src/ConstraintCheck/DelegatingConstraintChecker.php 
b/src/ConstraintCheck/DelegatingConstraintChecker.php
index cb71871..9cd62cb 100644
--- a/src/ConstraintCheck/DelegatingConstraintChecker.php
+++ b/src/ConstraintCheck/DelegatingConstraintChecker.php
@@ -190,6 +190,23 @@
                return [];
        }
 
+       private function getAllowedContextTypes( Constraint $constraint ) {
+               if ( !array_key_exists( $constraint->getConstraintTypeItemId(), 
$this->checkerMap ) ) {
+                       return [
+                               Context::TYPE_STATEMENT,
+                               Context::TYPE_QUALIFIER,
+                               Context::TYPE_REFERENCE,
+                       ];
+               }
+
+               return array_keys( array_filter(
+                       
$this->checkerMap[$constraint->getConstraintTypeItemId()]->getSupportedContextTypes(),
+                       function ( $resultStatus ) {
+                               return $resultStatus !== 
CheckResult::STATUS_NOT_IN_SCOPE;
+                       }
+               ) );
+       }
+
        /**
         * Like ConstraintChecker::checkConstraintParameters,
         * but for meta-parameters common to all checkers.
@@ -214,6 +231,15 @@
                }
                try {
                        
$this->constraintParameterParser->parseConstraintStatusParameter( 
$constraintParameters );
+               } catch ( ConstraintParameterException $e ) {
+                       $problems[] = $e;
+               }
+               try {
+                       
$this->constraintParameterParser->parseConstraintScopeParameter(
+                               $constraintParameters,
+                               $constraint->getConstraintTypeItemId(),
+                               $this->getAllowedContextTypes( $constraint )
+                       );
                } catch ( ConstraintParameterException $e ) {
                        $problems[] = $e;
                }
@@ -505,6 +531,12 @@
        private function getCheckResultFor( Context $context, Constraint 
$constraint ) {
                if ( array_key_exists( $constraint->getConstraintTypeItemId(), 
$this->checkerMap ) ) {
                        $checker = 
$this->checkerMap[$constraint->getConstraintTypeItemId()];
+                       $result = $this->handleScope( $checker, $context, 
$constraint );
+
+                       if ( $result !== null ) {
+                               $this->addMetadata( $result );
+                               return $result;
+                       }
 
                        $startTime = microtime( true );
                        try {
@@ -558,6 +590,31 @@
                }
        }
 
+       private function handleScope(
+               ConstraintChecker $checker,
+               Context $context,
+               Constraint $constraint
+       ) {
+               try {
+                       $checkedContextTypes = 
$this->constraintParameterParser->parseConstraintScopeParameter(
+                               $constraint->getConstraintParameters(),
+                               $constraint->getConstraintTypeItemId()
+                       );
+               } catch ( ConstraintParameterException $e ) {
+                       return new CheckResult( $context, $constraint, [], 
CheckResult::STATUS_BAD_PARAMETERS, $e->getMessage() );
+               }
+               if ( $checkedContextTypes === null ) {
+                       $checkedContextTypes = 
$checker->getDefaultContextTypes();
+               }
+               if ( !in_array( $context->getType(), $checkedContextTypes ) ) {
+                       return new CheckResult( $context, $constraint, [], 
CheckResult::STATUS_NOT_IN_SCOPE, null );
+               }
+               if ( $checker->getSupportedContextTypes()[$context->getType()] 
=== CheckResult::STATUS_TODO ) {
+                       return new CheckResult( $context, $constraint, [], 
CheckResult::STATUS_TODO, null );
+               }
+               return null;
+       }
+
        private function addMetadata( CheckResult $result ) {
                $result->withMetadata( Metadata::merge( [
                        $result->getMetadata(),
diff --git a/tests/phpunit/Api/CheckConstraintsTest.php 
b/tests/phpunit/Api/CheckConstraintsTest.php
index 4f1b9a3..6570d6f 100644
--- a/tests/phpunit/Api/CheckConstraintsTest.php
+++ b/tests/phpunit/Api/CheckConstraintsTest.php
@@ -110,6 +110,10 @@
                                'WBQualityConstraintsPropertyConstraintId' => 
'P1',
                                'WBQualityConstraintsExceptionToConstraintId' 
=> 'P2',
                                'WBQualityConstraintsConstraintStatusId' => 
'P3',
+                               'WBQualityConstraintsConstraintScopeId' => 'P4',
+                               
'WBQualityConstraintsConstraintCheckedOnMainValueId' => 'Q1',
+                               
'WBQualityConstraintsConstraintCheckedOnQualifiersId' => 'Q2',
+                               
'WBQualityConstraintsConstraintCheckedOnReferencesId' => 'Q3',
                                'WBQualityConstraintsCheckDurationInfoSeconds' 
=> 1.0,
                                
'WBQualityConstraintsCheckDurationWarningSeconds' => 10.0,
                                'WBQualityConstraintsIncludeDetailInApi' => 
true,
diff --git a/tests/phpunit/DelegatingConstraintCheckerTest.php 
b/tests/phpunit/DelegatingConstraintCheckerTest.php
index 592adbd..5e73e32 100644
--- a/tests/phpunit/DelegatingConstraintCheckerTest.php
+++ b/tests/phpunit/DelegatingConstraintCheckerTest.php
@@ -15,9 +15,12 @@
 use Wikibase\Repo\Tests\NewItem;
 use Wikibase\Repo\Tests\NewStatement;
 use WikibaseQuality\ConstraintReport\Constraint;
+use WikibaseQuality\ConstraintReport\ConstraintCheck\ConstraintChecker;
+use WikibaseQuality\ConstraintReport\ConstraintCheck\Context\Context;
 use 
WikibaseQuality\ConstraintReport\ConstraintCheck\DelegatingConstraintChecker;
 use 
WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\ConstraintParameterException;
 use WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\LoggingHelper;
+use WikibaseQuality\ConstraintReport\ConstraintCheck\Result\CheckResult;
 use WikibaseQuality\ConstraintReport\ConstraintCheck\Result\NullResult;
 use WikibaseQuality\ConstraintReport\ConstraintReportFactory;
 use WikibaseQuality\ConstraintReport\Tests\ConstraintParameters;
@@ -627,4 +630,173 @@
                );
        }
 
+       public function testSupportedContextTypes_NotSupported() {
+               $checker = $this->getMock( ConstraintChecker::class );
+               $checker->method( 'getSupportedContextTypes' )
+                       ->willReturn( [
+                               Context::TYPE_STATEMENT => 
CheckResult::STATUS_NOT_IN_SCOPE,
+                       ] );
+               $checker->method( 'getDefaultContextTypes' )
+                       ->willReturn( [] );
+               $checker->expects( $this->never() )->method( 'checkConstraint' 
);
+               $lookup = new InMemoryEntityLookup();
+               $q2 = new ItemId( 'Q2' );
+               $lookup->addEntity(
+                       NewItem::withId( $q2 )
+                               ->andStatement( NewStatement::noValueFor( 'P1' 
) )
+                               ->build()
+               );
+               $delegatingConstraintChecker = new DelegatingConstraintChecker(
+                       $lookup,
+                       [ 'Q1' => $checker ],
+                       new InMemoryConstraintLookup( [
+                               new Constraint( '', new PropertyId( 'P1' ), 
'Q1', [] )
+                       ] ),
+                       $this->getConstraintParameterParser(),
+                       new StatementGuidParser( new ItemIdParser() ),
+                       $this->getMockBuilder( LoggingHelper::class )
+                               ->disableOriginalConstructor()
+                               ->getMock(),
+                       true,
+                       true,
+                       []
+               );
+
+               $results = 
$delegatingConstraintChecker->checkAgainstConstraintsOnEntityId( $q2 );
+
+               $this->assertCount( 1, $results );
+               $this->assertNotInScope( $results[0] );
+       }
+
+       public function testSupportedContextTypes_NotImplemented() {
+               $checker = $this->getMock( ConstraintChecker::class );
+               $checker->method( 'getSupportedContextTypes' )
+                       ->willReturn( [
+                               Context::TYPE_STATEMENT => 
CheckResult::STATUS_TODO,
+                       ] );
+               $checker->method( 'getDefaultContextTypes' )
+                       ->willReturn( [ Context::TYPE_STATEMENT ] );
+               $checker->expects( $this->never() )->method( 'checkConstraint' 
);
+               $lookup = new InMemoryEntityLookup();
+               $q2 = new ItemId( 'Q2' );
+               $lookup->addEntity(
+                       NewItem::withId( $q2 )
+                               ->andStatement( NewStatement::noValueFor( 'P1' 
) )
+                               ->build()
+               );
+               $delegatingConstraintChecker = new DelegatingConstraintChecker(
+                       $lookup,
+                       [ 'Q1' => $checker ],
+                       new InMemoryConstraintLookup( [
+                               new Constraint( '', new PropertyId( 'P1' ), 
'Q1', [] )
+                       ] ),
+                       $this->getConstraintParameterParser(),
+                       new StatementGuidParser( new ItemIdParser() ),
+                       $this->getMockBuilder( LoggingHelper::class )
+                               ->disableOriginalConstructor()
+                               ->getMock(),
+                       true,
+                       true,
+                       []
+               );
+
+               $results = 
$delegatingConstraintChecker->checkAgainstConstraintsOnEntityId( $q2 );
+
+               $this->assertCount( 1, $results );
+               $this->assertTodo( $results[0] );
+       }
+
+       public function testSupportedContextTypes_DefaultScope() {
+               $checker = $this->getMock( ConstraintChecker::class );
+               $checker->method( 'getSupportedContextTypes' )
+                       ->willReturn( [
+                               Context::TYPE_STATEMENT => 
CheckResult::STATUS_COMPLIANCE,
+                               Context::TYPE_QUALIFIER => 
CheckResult::STATUS_COMPLIANCE,
+                       ] );
+               $checker->method( 'getDefaultContextTypes' )
+                       ->willReturn( [ Context::TYPE_QUALIFIER ] );
+               $checker->expects( $this->once() )
+                       ->method( 'checkConstraint' )
+                       ->willReturnCallback( function( Context $context, 
Constraint $constraint ) {
+                               $this->assertSame( Context::TYPE_QUALIFIER, 
$context->getType() );
+                               return new CheckResult( $context, $constraint );
+                       } );
+               $lookup = new InMemoryEntityLookup();
+               $q2 = new ItemId( 'Q2' );
+               $lookup->addEntity(
+                       NewItem::withId( $q2 )
+                               ->andStatement(
+                                       NewStatement::noValueFor( 'P1' )
+                                               ->withQualifier( 'P1', 'value' )
+                               )
+                               ->build()
+               );
+               $delegatingConstraintChecker = new DelegatingConstraintChecker(
+                       $lookup,
+                       [ 'Q1' => $checker ],
+                       new InMemoryConstraintLookup( [
+                               new Constraint( '', new PropertyId( 'P1' ), 
'Q1', [] )
+                       ] ),
+                       $this->getConstraintParameterParser(),
+                       new StatementGuidParser( new ItemIdParser() ),
+                       $this->getMockBuilder( LoggingHelper::class )
+                               ->disableOriginalConstructor()
+                               ->getMock(),
+                       true,
+                       true,
+                       []
+               );
+
+               $results = 
$delegatingConstraintChecker->checkAgainstConstraintsOnEntityId( $q2 );
+       }
+
+       public function testSupportedContextTypes_ExplicitScope() {
+               $checker = $this->getMock( ConstraintChecker::class );
+               $checker->method( 'getSupportedContextTypes' )
+                       ->willReturn( [
+                               Context::TYPE_STATEMENT => 
CheckResult::STATUS_COMPLIANCE,
+                               Context::TYPE_QUALIFIER => 
CheckResult::STATUS_COMPLIANCE,
+                       ] );
+               $checker->method( 'getDefaultContextTypes' )
+                       ->willReturn( [ Context::TYPE_QUALIFIER ] );
+               $checker->expects( $this->once() )
+                       ->method( 'checkConstraint' )
+                       ->willReturnCallback( function( Context $context, 
Constraint $constraint ) {
+                               $this->assertSame( Context::TYPE_STATEMENT, 
$context->getType() );
+                               return new CheckResult( $context, $constraint );
+                       } );
+               $lookup = new InMemoryEntityLookup();
+               $q2 = new ItemId( 'Q2' );
+               $lookup->addEntity(
+                       NewItem::withId( $q2 )
+                               ->andStatement(
+                                       NewStatement::noValueFor( 'P1' )
+                                               ->withQualifier( 'P1', 'value' )
+                               )
+                               ->build()
+               );
+               $delegatingConstraintChecker = new DelegatingConstraintChecker(
+                       $lookup,
+                       [ 'Q1' => $checker ],
+                       new InMemoryConstraintLookup( [
+                               new Constraint(
+                                       '',
+                                       new PropertyId( 'P1' ),
+                                       'Q1',
+                                       $this->scopeParameter( [ 
Context::TYPE_STATEMENT ] )
+                               )
+                       ] ),
+                       $this->getConstraintParameterParser(),
+                       new StatementGuidParser( new ItemIdParser() ),
+                       $this->getMockBuilder( LoggingHelper::class )
+                               ->disableOriginalConstructor()
+                               ->getMock(),
+                       true,
+                       true,
+                       []
+               );
+
+               $results = 
$delegatingConstraintChecker->checkAgainstConstraintsOnEntityId( $q2 );
+       }
+
 }

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

Gerrit-MessageType: merged
Gerrit-Change-Id: Ie9d7c1c9e7a57d0e03ca0cb0f96d47d0f1869921
Gerrit-PatchSet: 6
Gerrit-Project: mediawiki/extensions/WikibaseQualityConstraints
Gerrit-Branch: master
Gerrit-Owner: Lucas Werkmeister (WMDE) <lucas.werkmeis...@wikimedia.de>
Gerrit-Reviewer: Jonas Kress (WMDE) <jonas.kr...@wikimedia.de>
Gerrit-Reviewer: jenkins-bot <>

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

Reply via email to