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