Completed
Push — master ( 57d748...8786f4 )
by
unknown
02:30
created

RangeChecker   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 173
Duplicated Lines 13.29 %

Coupling/Cohesion

Components 1
Dependencies 10

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 22
c 1
b 0
f 0
lcom 1
cbo 10
dl 23
loc 173
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 1
A getSupportedContextTypes() 0 7 1
A getDefaultContextTypes() 0 7 1
C checkConstraint() 0 47 8
D getViolationMessage() 6 32 9
A checkConstraintParameters() 17 17 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace WikibaseQuality\ConstraintReport\ConstraintCheck\Checker;
4
5
use DataValues\DataValue;
6
use Wikibase\DataModel\Entity\PropertyId;
7
use Wikibase\DataModel\Services\Lookup\PropertyDataTypeLookup;
8
use Wikibase\DataModel\Snak\PropertyValueSnak;
9
use WikibaseQuality\ConstraintReport\Constraint;
10
use WikibaseQuality\ConstraintReport\ConstraintCheck\ConstraintChecker;
11
use WikibaseQuality\ConstraintReport\ConstraintCheck\Context\Context;
12
use WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\ConstraintParameterException;
13
use WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\ConstraintParameterParser;
14
use WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\NowValue;
15
use WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\RangeCheckerHelper;
16
use WikibaseQuality\ConstraintReport\ConstraintCheck\Message\ViolationMessage;
17
use WikibaseQuality\ConstraintReport\ConstraintCheck\Result\CheckResult;
18
use WikibaseQuality\ConstraintReport\ConstraintParameterRenderer;
19
use WikibaseQuality\ConstraintReport\Role;
20
use Wikibase\DataModel\Statement\Statement;
21
22
/**
23
 * @author BP2014N1
24
 * @license GNU GPL v2+
25
 */
26
class RangeChecker implements ConstraintChecker {
27
28
	/**
29
	 * @var PropertyDataTypeLookup
30
	 */
31
	private $propertyDataTypeLookup;
32
33
	/**
34
	 * @var ConstraintParameterParser
35
	 */
36
	private $constraintParameterParser;
37
38
	/**
39
	 * @var RangeCheckerHelper
40
	 */
41
	private $rangeCheckerHelper;
42
43
	/**
44
	 * @var ConstraintParameterRenderer
45
	 */
46
	private $constraintParameterRenderer;
47
48
	public function __construct(
49
		PropertyDataTypeLookup $propertyDataTypeLookup,
50
		ConstraintParameterParser $constraintParameterParser,
51
		RangeCheckerHelper $rangeCheckerHelper,
52
		ConstraintParameterRenderer $constraintParameterRenderer
53
	) {
54
		$this->propertyDataTypeLookup = $propertyDataTypeLookup;
55
		$this->constraintParameterParser = $constraintParameterParser;
56
		$this->rangeCheckerHelper = $rangeCheckerHelper;
57
		$this->constraintParameterRenderer = $constraintParameterRenderer;
58
	}
59
60
	/**
61
	 * @codeCoverageIgnore This method is purely declarative.
62
	 */
63
	public function getSupportedContextTypes() {
64
		return [
65
			Context::TYPE_STATEMENT => CheckResult::STATUS_COMPLIANCE,
66
			Context::TYPE_QUALIFIER => CheckResult::STATUS_COMPLIANCE,
67
			Context::TYPE_REFERENCE => CheckResult::STATUS_COMPLIANCE,
68
		];
69
	}
70
71
	/**
72
	 * @codeCoverageIgnore This method is purely declarative.
73
	 */
74
	public function getDefaultContextTypes() {
75
		return [
76
			Context::TYPE_STATEMENT,
77
			Context::TYPE_QUALIFIER,
78
			Context::TYPE_REFERENCE,
79
		];
80
	}
81
82
	/**
83
	 * Checks 'Range' constraint.
84
	 *
85
	 * @param Context $context
86
	 * @param Constraint $constraint
87
	 *
88
	 * @throws ConstraintParameterException
89
	 * @return CheckResult
90
	 */
91
	public function checkConstraint( Context $context, Constraint $constraint ) {
92
		if ( $context->getSnakRank() === Statement::RANK_DEPRECATED ) {
93
			return new CheckResult( $context, $constraint, [], CheckResult::STATUS_DEPRECATED );
94
		}
95
96
		$parameters = [];
97
		$constraintParameters = $constraint->getConstraintParameters();
98
99
		$snak = $context->getSnak();
100
101
		if ( !$snak instanceof PropertyValueSnak ) {
102
			// nothing to check
103
			return new CheckResult( $context, $constraint, $parameters, CheckResult::STATUS_COMPLIANCE );
104
		}
105
106
		$dataValue = $snak->getDataValue();
107
108
		list( $min, $max ) = $this->constraintParameterParser->parseRangeParameter(
109
			$constraintParameters,
110
			$constraint->getConstraintTypeItemId(),
111
			$dataValue->getType()
112
		);
113
		$parameterKey = $dataValue->getType() === 'quantity' ? 'quantity' : 'date';
114
		if ( $min !== null ) {
115
			$parameters['minimum_' . $parameterKey] = [ $min ];
116
		}
117
		if ( $max !== null ) {
118
			$parameters['maximum_' . $parameterKey] = [ $max ];
119
		}
120
121
		if ( $this->rangeCheckerHelper->getComparison( $min, $dataValue ) > 0 ||
122
			 $this->rangeCheckerHelper->getComparison( $dataValue, $max ) > 0
123
		) {
124
			$message = $this->getViolationMessage(
125
				$context->getSnak()->getPropertyId(),
126
				$dataValue,
127
				$min,
128
				$max
129
			);
130
			$status = CheckResult::STATUS_VIOLATION;
131
		} else {
132
			$message = null;
133
			$status = CheckResult::STATUS_COMPLIANCE;
134
		}
135
136
		return new CheckResult( $context, $constraint, $parameters, $status, $message );
137
	}
138
139
	/**
140
	 * @param PropertyId $predicate
141
	 * @param DataValue $value
142
	 * @param DataValue|null $min
143
	 * @param DataValue|null $max
144
	 *
145
	 * @return ViolationMessage
146
	 */
147
	private function getViolationMessage( PropertyId $predicate, DataValue $value, $min, $max ) {
148
		// possible message keys:
149
		// wbqc-violation-message-range-quantity-closed
150
		// wbqc-violation-message-range-quantity-leftopen
151
		// wbqc-violation-message-range-quantity-rightopen
152
		// wbqc-violation-message-range-time-closed
153
		// wbqc-violation-message-range-time-closed-leftnow
154
		// wbqc-violation-message-range-time-closed-rightnow
155
		// wbqc-violation-message-range-time-leftopen
156
		// wbqc-violation-message-range-time-leftopen-rightnow
157
		// wbqc-violation-message-range-time-rightopen
158
		// wbqc-violation-message-range-time-rightopen-leftnow
159
		$messageKey = 'wbqc-violation-message-range';
160
		$messageKey .= '-' . $value->getType();
161
		// at least one of $min, $max is set, otherwise there could be no violation
162
		$messageKey .= '-' . ( $min !== null ? ( $max !== null ? 'closed' : 'rightopen' ) : 'leftopen' );
163
		if ( $min instanceof NowValue ) {
164
			$messageKey .= '-leftnow';
165
		} elseif ( $max instanceof  NowValue ) {
166
			$messageKey .= '-rightnow';
167
		}
168
		$message = ( new ViolationMessage( $messageKey ) )
169
			->withEntityId( $predicate, Role::PREDICATE )
170
			->withDataValue( $value, Role::OBJECT );
171 View Code Duplication
		if ( $min !== null && !( $min instanceof NowValue ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
172
			$message = $message->withDataValue( $min, Role::OBJECT );
173
		}
174 View Code Duplication
		if ( $max !== null && !( $max instanceof  NowValue ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
175
			$message = $message->withDataValue( $max, Role::OBJECT );
176
		}
177
		return $message;
178
	}
179
180 View Code Duplication
	public function checkConstraintParameters( Constraint $constraint ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
181
		$constraintParameters = $constraint->getConstraintParameters();
182
		$exceptions = [];
183
		try {
184
			// we don’t have a data value here, so get the type from the property instead
185
			// (the distinction between data type and data value type is irrelevant for 'quantity' and 'time')
186
			$type = $this->propertyDataTypeLookup->getDataTypeIdForProperty( $constraint->getPropertyId() );
187
			$this->constraintParameterParser->parseRangeParameter(
188
				$constraintParameters,
189
				$constraint->getConstraintTypeItemId(),
190
				$type
191
			);
192
		} catch ( ConstraintParameterException $e ) {
193
			$exceptions[] = $e;
194
		}
195
		return $exceptions;
196
	}
197
198
}
199