Completed
Push — master ( e27104...d49389 )
by
unknown
02:40
created

TimeValueComparer::resultOfDiffWithPrecision()   D

Complexity

Conditions 21
Paths 104

Size

Total Lines 39
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 39
rs 4.7951
c 0
b 0
f 0
cc 21
eloc 35
nc 104
nop 2

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace WikibaseQuality\ExternalValidation\CrossCheck\Comparer;
4
5
use DataValues\DataValue;
6
use DataValues\TimeValue;
7
use DateInterval;
8
use InvalidArgumentException;
9
use MWTimestamp;
10
use ValueParsers\ParserOptions;
11
use ValueParsers\ValueParser;
12
use Wikibase\Repo\Parsers\TimeParserFactory;
13
use WikibaseQuality\ExternalValidation\CrossCheck\Result\ComparisonResult;
14
use WikibaseQuality\ExternalValidation\DumpMetaInformation\DumpMetaInformation;
15
use Wikimedia\Timestamp\TimestampException;
16
17
/**
18
 * @author BP2014N1
19
 * @license GPL-2.0-or-later
20
 */
21
class TimeValueComparer implements DataValueComparer {
22
23
	/**
24
	 * @see DataValueComparer::compare
25
	 *
26
	 * @param DataValue $value
27
	 * @param DataValue $comparativeValue
28
	 *
29
	 * @throws InvalidArgumentException
30
	 * @return string One of the ComparisonResult::STATUS_... constants.
31
	 */
32
	public function compare( DataValue $value, DataValue $comparativeValue ) {
33
		if ( !$this->canCompare( $value, $comparativeValue ) ) {
34
			throw new InvalidArgumentException( 'Given values can not be compared using this comparer.' );
35
		}
36
37
		/**
38
		 * @var TimeValue $value
39
		 * @var TimeValue $comparativeValue
40
		 */
41
42
		$result = ComparisonResult::STATUS_MISMATCH;
43
44
		if ( !preg_match( '/^([-+]?)(\d*)((\d{4}\b).*)/', $value->getTime(), $localMatches )
45
			|| !preg_match( '/^([-+]?)(\d*)((\d{4}\b).*)/', $comparativeValue->getTime(), $externalMatches )
46
		) {
47
			return ComparisonResult::STATUS_MISMATCH;
48
		}
49
		list( , $localSign, $localYearHigh, $localMwTime, $localYearLow ) = $localMatches;
50
		list( , $externalSign, $externalYearHigh, $externalMwTime, $externalYearLow ) = $externalMatches;
51
		if ( $localSign !== $externalSign && ( $localYearHigh . $localYearLow !== '0000'
52
				|| $externalYearHigh . $externalYearLow !== '0000' )
53
		) {
54
			return ComparisonResult::STATUS_MISMATCH;
55
		}
56
57
		$localYearHigh = $localYearHigh === '' ? 0 : (int)$localYearHigh;
58
		$externalYearHigh = $externalYearHigh === '' ? 0 : (int)$externalYearHigh;
59
60
		try {
61
			$localTimestamp = new MWTimestamp( $localMwTime );
62
			$externalTimestamp = new MWTimestamp( $externalMwTime );
63
			$diff = $localTimestamp->diff( $externalTimestamp );
64
			$diff->y += abs( $localYearHigh - $externalYearHigh ) * 10000;
65
66
			if ( $value->getPrecision() === $comparativeValue->getPrecision()
67
				&& $this->resultOfDiffWithPrecision( $diff, $value->getPrecision() )
68
			) {
69
				$result = ComparisonResult::STATUS_MATCH;
70
			} elseif (
71
				$this->resultOfDiffWithPrecision(
72
					$diff,
73
					min( $value->getPrecision(), $comparativeValue->getPrecision() )
74
				)
75
			) {
76
				$result = ComparisonResult::STATUS_PARTIAL_MATCH;
77
			}
78
		} catch ( TimestampException $ex ) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
Bug introduced by
The class Wikimedia\Timestamp\TimestampException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
79
		}
80
81
		return $result;
82
	}
83
84
	/**
85
	 * Returns boolean if diff is equal depending on the given precision
86
	 *
87
	 * @param DateInterval $diff
88
	 * @param int $precision
89
	 *
90
	 * @return bool
91
	 */
92
	private function resultOfDiffWithPrecision( DateInterval $diff, $precision ) {
93
		$result = true;
94
95
		switch ( $precision ) {
96
			case TimeValue::PRECISION_SECOND:
97
				$result = $diff->s === 0;
98
				// Fall through with no break/return. This is critical for this algorithm.
99
			case TimeValue::PRECISION_MINUTE:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
100
				$result = $result && $diff->i === 0;
101
			case TimeValue::PRECISION_HOUR:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
102
				$result = $result && $diff->h === 0;
103
			case TimeValue::PRECISION_DAY:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
104
				$result = $result && $diff->d === 0;
105
			case TimeValue::PRECISION_MONTH:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
106
				$result = $result && $diff->m === 0;
107
			case TimeValue::PRECISION_YEAR:
108
				return $result && $diff->y === 0;
109
			case TimeValue::PRECISION_YEAR10:
110
				return $diff->y < 10;
111
			case TimeValue::PRECISION_YEAR100:
112
				return $diff->y < 100;
113
			case TimeValue::PRECISION_YEAR1K:
114
				return $diff->y < 1000;
115
			case TimeValue::PRECISION_YEAR10K:
116
				return $diff->y < 10000;
117
			case TimeValue::PRECISION_YEAR100K:
118
				return $diff->y < 100000;
119
			case TimeValue::PRECISION_YEAR1M:
120
				return $diff->y < 1000000;
121
			case TimeValue::PRECISION_YEAR10M:
122
				return $diff->y < 10000000;
123
			case TimeValue::PRECISION_YEAR100M:
124
				return $diff->y < 100000000;
125
			case TimeValue::PRECISION_YEAR1G:
126
				return $diff->y < 1000000000;
127
			default:
128
				return false;
129
		}
130
	}
131
132
	/**
133
	 * @see DataValueComparerBase::getExternalValueParser
134
	 *
135
	 * @param DumpMetaInformation $dumpMetaInformation
136
	 *
137
	 * @return ValueParser
138
	 */
139
	protected function getExternalValueParser( DumpMetaInformation $dumpMetaInformation ) {
140
		$parserOptions = new ParserOptions();
141
		$parserOptions->setOption( ValueParser::OPT_LANG, $dumpMetaInformation->getLanguageCode() );
142
		$timeParserFactory = new TimeParserFactory( $parserOptions );
143
144
		return $timeParserFactory->getTimeParser();
145
	}
146
147
	/**
148
	 * @see DataValueComparer::canCompare
149
	 *
150
	 * @param DataValue $value
151
	 * @param DataValue $comparativeValue
152
	 *
153
	 * @return bool
154
	 */
155
	public function canCompare( DataValue $value, DataValue $comparativeValue ) {
156
		return $value instanceof TimeValue && $comparativeValue instanceof TimeValue;
157
	}
158
159
}
160