Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
96.77% covered (success)
96.77%
60 / 62
66.67% covered (warning)
66.67%
2 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
ConflictsWithChecker
96.77% covered (success)
96.77%
60 / 62
66.67% covered (warning)
66.67%
2 / 3
12
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getSupportedContextTypes
n/a
0 / 0
n/a
0 / 0
1
 getDefaultContextTypes
n/a
0 / 0
n/a
0 / 0
1
 getSupportedEntityTypes
n/a
0 / 0
n/a
0 / 0
1
 checkConstraint
100.00% covered (success)
100.00%
43 / 43
100.00% covered (success)
100.00%
1 / 1
5
 checkConstraintParameters
88.24% covered (warning)
88.24%
15 / 17
0.00% covered (danger)
0.00%
0 / 1
3.01
1<?php
2
3namespace WikibaseQuality\ConstraintReport\ConstraintCheck\Checker;
4
5use Wikibase\DataModel\Statement\Statement;
6use WikibaseQuality\ConstraintReport\Constraint;
7use WikibaseQuality\ConstraintReport\ConstraintCheck\ConstraintChecker;
8use WikibaseQuality\ConstraintReport\ConstraintCheck\Context\Context;
9use WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\ConnectionCheckerHelper;
10use WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\ConstraintParameterException;
11use WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\ConstraintParameterParser;
12use WikibaseQuality\ConstraintReport\ConstraintCheck\ItemIdSnakValue;
13use WikibaseQuality\ConstraintReport\ConstraintCheck\Message\ViolationMessage;
14use WikibaseQuality\ConstraintReport\ConstraintCheck\Result\CheckResult;
15use WikibaseQuality\ConstraintReport\Role;
16
17/**
18 * @author BP2014N1
19 * @license GPL-2.0-or-later
20 */
21class ConflictsWithChecker implements ConstraintChecker {
22
23    /**
24     * @var ConstraintParameterParser
25     */
26    private $constraintParameterParser;
27
28    /**
29     * @var ConnectionCheckerHelper
30     */
31    private $connectionCheckerHelper;
32
33    public function __construct(
34        ConstraintParameterParser $constraintParameterParser,
35        ConnectionCheckerHelper $connectionCheckerHelper
36    ) {
37        $this->constraintParameterParser = $constraintParameterParser;
38        $this->connectionCheckerHelper = $connectionCheckerHelper;
39    }
40
41    /**
42     * @codeCoverageIgnore This method is purely declarative.
43     */
44    public function getSupportedContextTypes() {
45        return [
46            Context::TYPE_STATEMENT => CheckResult::STATUS_COMPLIANCE,
47            // TODO T175562
48            Context::TYPE_QUALIFIER => CheckResult::STATUS_TODO,
49            Context::TYPE_REFERENCE => CheckResult::STATUS_TODO,
50        ];
51    }
52
53    /**
54     * @codeCoverageIgnore This method is purely declarative.
55     */
56    public function getDefaultContextTypes() {
57        return [
58            Context::TYPE_STATEMENT,
59            // TODO T175562
60            // Context::TYPE_QUALIFIER,
61            // Context::TYPE_REFERENCE,
62        ];
63    }
64
65    /** @codeCoverageIgnore This method is purely declarative. */
66    public function getSupportedEntityTypes() {
67        return self::ALL_ENTITY_TYPES_SUPPORTED;
68    }
69
70    /**
71     * Checks 'Conflicts with' constraint.
72     *
73     * @param Context $context
74     * @param Constraint $constraint
75     *
76     * @throws ConstraintParameterException
77     * @return CheckResult
78     */
79    public function checkConstraint( Context $context, Constraint $constraint ) {
80        if ( $context->getSnakRank() === Statement::RANK_DEPRECATED ) {
81            return new CheckResult( $context, $constraint, CheckResult::STATUS_DEPRECATED );
82        }
83
84        $constraintParameters = $constraint->getConstraintParameters();
85        $constraintTypeItemId = $constraint->getConstraintTypeItemId();
86
87        $propertyId = $this->constraintParameterParser->parsePropertyParameter(
88            $constraintParameters,
89            $constraintTypeItemId
90        );
91
92        $items = $this->constraintParameterParser->parseItemsParameter(
93            $constraintParameters,
94            $constraintTypeItemId,
95            false
96        );
97
98        $statementList = $context->getEntity()
99            ->getStatements()
100            ->getByRank( [ Statement::RANK_PREFERRED, Statement::RANK_NORMAL ] );
101
102        /*
103         * 'Conflicts with' can be defined with
104         *   a) a property only
105         *   b) a property and a number of items (each combination of property and item forming an individual claim)
106         */
107        if ( $items === [] ) {
108            $offendingStatement = $this->connectionCheckerHelper->findStatementWithProperty(
109                $statementList,
110                $propertyId
111            );
112            if ( $offendingStatement !== null ) {
113                $message = ( new ViolationMessage( 'wbqc-violation-message-conflicts-with-property' ) )
114                    ->withEntityId( $context->getSnak()->getPropertyId(), Role::CONSTRAINT_PROPERTY )
115                    ->withEntityId( $propertyId, Role::PREDICATE );
116                $status = CheckResult::STATUS_VIOLATION;
117            } else {
118                $message = null;
119                $status = CheckResult::STATUS_COMPLIANCE;
120            }
121        } else {
122            $offendingStatement = $this->connectionCheckerHelper->findStatementWithPropertyAndItemIdSnakValues(
123                $statementList,
124                $propertyId,
125                $items
126            );
127            if ( $offendingStatement !== null ) {
128                $offendingValue = ItemIdSnakValue::fromSnak( $offendingStatement->getMainSnak() );
129                $message = ( new ViolationMessage( 'wbqc-violation-message-conflicts-with-claim' ) )
130                    ->withEntityId( $context->getSnak()->getPropertyId(), Role::CONSTRAINT_PROPERTY )
131                    ->withEntityId( $propertyId, Role::PREDICATE )
132                    ->withItemIdSnakValue( $offendingValue, Role::OBJECT );
133                $status = CheckResult::STATUS_VIOLATION;
134            } else {
135                $message = null;
136                $status = CheckResult::STATUS_COMPLIANCE;
137            }
138        }
139
140        return new CheckResult( $context, $constraint, $status, $message );
141    }
142
143    public function checkConstraintParameters( Constraint $constraint ) {
144        $constraintParameters = $constraint->getConstraintParameters();
145        $constraintTypeItemId = $constraint->getConstraintTypeItemId();
146        $exceptions = [];
147        try {
148            $this->constraintParameterParser->parsePropertyParameter(
149                $constraintParameters,
150                $constraintTypeItemId
151            );
152        } catch ( ConstraintParameterException $e ) {
153            $exceptions[] = $e;
154        }
155        try {
156            $this->constraintParameterParser->parseItemsParameter(
157                $constraintParameters,
158                $constraintTypeItemId,
159                false
160            );
161        } catch ( ConstraintParameterException $e ) {
162            $exceptions[] = $e;
163        }
164        return $exceptions;
165    }
166
167}