Completed
Push — master ( cd2f8d...f0067b )
by mw
37:19 queued 02:22
created

getDisplayPrecisionFor()   B

Complexity

Conditions 4
Paths 3

Size

Total Lines 33
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 5.024

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 33
ccs 3
cts 5
cp 0.6
rs 8.5806
c 1
b 0
f 0
cc 4
eloc 18
nc 3
nop 1
crap 5.024
1
<?php
2
3
namespace SMW;
4
5
use RuntimeException;
6
use Onoi\BlobStore\BlobStore;
7
8
/**
9
 * This class should be accessed via ApplicationFactory::getPropertySpecificationLookup
10
 * to ensure a singleton instance.
11
 *
12
 * @license GNU GPL v2+
13
 * @since 2.4
14
 *
15
 * @author mwjames
16
 */
17
class PropertySpecificationLookup {
18
19
	/**
20
	 * @var string
21
	 */
22
	const VERSION = '0.2';
23
24
	/**
25
	 * @var Store
26
	 */
27
	private $store;
28
29
	/**
30
	 * @var string
31
	 */
32
	private $languageCode = 'en';
33
34
	/**
35
	 * @var BlobStore
36
	 */
37
	private $blobStore;
38
39
	/**
40
	 * @since 2.4
41
	 *
42
	 * @param Store $store
43
	 * @param BlobStore $blobStore
44
	 */
45
	public function __construct( Store $store, BlobStore $blobStore ) {
46
		$this->store = $store;
47
		$this->blobStore = $blobStore;
48
	}
49
50
	/**
51
	 * @since 2.4
52
	 */
53
	public function resetCacheFor( DIWikiPage $subject ) {
54
		$this->blobStore->delete( md5( $subject->getHash() . self::VERSION ) );
55
	}
56 101
57 101
	/**
58 101
	 * @since 2.4
59
	 *
60 101
	 * @param string
61 3
	 */
62 3
	public function getLanguageCode() {
63 101
		return $this->languageCode;
64
	}
65
66
	/**
67
	 * @since 2.4
68 95
	 *
69 95
	 * @param string $languageCode
70 95
	 */
71 95
	public function setLanguageCode( $languageCode ) {
72 95
		$this->languageCode = Localizer::asBCP47FormattedLanguageCode( $languageCode );
73
	}
74
75
	/**
76
	 * @since 2.4
77
	 *
78
	 * @param DIProperty $property
79 98
	 *
80 98
	 * @return integer|false
81 98
	 */
82
	public function getDisplayPrecisionFor( DIProperty $property ) {
83
84
		$displayPrecision = false;
85
		$key = 'prec';
86
87
		$hash = md5(
88
			$property->getDiWikiPage()->getHash() . self::VERSION
89
		);
90
91
		$container = $this->blobStore->read( $hash );
92
93
		if ( $container->has( $key ) ) {
94
			return $container->get( $key );
95
		}
96
97 98
		$dataItems = $this->store->getPropertyValues(
98 98
			$property->getDiWikiPage(),
99 98
			new DIProperty( '_PREC' )
100
		);
101
102
		if ( $dataItems !== false && $dataItems !== array() ) {
103
			$dataItem = end( $dataItems );
104
			$displayPrecision = abs( (int)$dataItem->getNumber() );
0 ignored issues
show
Bug Compatibility introduced by
The expression abs((int) $dataItem->getNumber()); of type integer|double adds the type double to the return on line 113 which is incompatible with the return type documented by SMW\PropertySpecificatio...:getDisplayPrecisionFor of type integer|false.
Loading history...
105
		}
106
107
		$container->set( $key, $displayPrecision );
108
109
		$this->blobStore->save(
110
			$container
111
		);
112
113
		return $displayPrecision;
114
	}
115 28
116
	/**
117 28
	 * @since 2.4
118
	 *
119
	 * @param DIProperty $property
120 28
	 *
121
	 * @return array
122 28
	 */
123 28
	public function getDisplayUnitsFor( DIProperty $property ) {
124 28
125
		$units = array();
126 28
		$key = 'unit';
127 20
128
		$hash = md5(
129 20
			$property->getDiWikiPage()->getHash() . self::VERSION
130 20
		);
131
132
		$container = $this->blobStore->read( $hash );
133
134 27
		if ( $container->has( $key ) ) {
135
			return $container->get( $key );
136
		}
137
138 27
		$dataItems = $this->store->getPropertyValues(
139 5
			$property->getDiWikiPage(),
140 5
			new DIProperty( '_UNIT' )
141
		);
142 27
143 27
		if ( $dataItems !== false && $dataItems !== array() ) {
144 27
			foreach ( $dataItems as $dataItem ) {
145 27
				$units = array_merge( $units, preg_split( '/\s*,\s*/u', $dataItem->getString() ) );
146 27
			}
147
		}
148
149 27
		$container->set( $key, $units );
150
151
		$this->blobStore->save(
152 5
			$container
153
		);
154 5
155 5
		return $units;
156
	}
157 5
158
	/**
159
	 * We try to cache anything to avoid unnecessary store connections or DB
160
	 * lookups. For cases where a property was changed, the EventDipatcher will
161 5
	 * receive a 'property.spec.change' event (emitted as soon as the content of
162 5
	 * a property page was altered) with PropertySpecificationLookup::resetCacheFor
163 5
	 * being invoked to remove the cache entry for that specific property.
164
	 *
165 5
	 * @since 2.4
166
	 *
167
	 * @param DIProperty $property
168 27
	 * @param mixed|null $linker
169
	 *
170 27
	 * @return string
171
	 */
172 27
	public function getPropertyDescriptionFor( DIProperty $property, $linker = null ) {
173 27
174 27
		$propertyDescription = '';
0 ignored issues
show
Unused Code introduced by
$propertyDescription is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
175 27
176
		// Take the linker into account (Special vs. in page rendering etc.)
177 27
		$key = 'pdesc:' . $this->languageCode . ':' . ( $linker === null ? '0' : '1' );
178 1
179 1
		$hash = md5(
180
			$property->getDiWikiPage()->getHash() . self::VERSION
181 27
		);
182
183
		$container = $this->blobStore->read( $hash );
184 27
185
		if ( $container->has( $key ) ) {
186 27
			return $container->get( $key );
187 25
		}
188
189
		$propertyDescription = $this->tryToFindLocalPropertyDescription( $property, $linker );
190 2
191
		// If a local property description wasn't available for a predefined property
192 2
		// the try to find a system translation
193 2
		if ( trim( $propertyDescription ) === '' && !$property->isUserDefined() ) {
194 2
			$propertyDescription = $this->getPredefinedPropertyDescription( $property, $linker );
195 2
		}
196
197
		$container->set( $key, $propertyDescription );
198
199 2
		$this->blobStore->save(
200
			$container
201 2
		);
202 1
203
		return $propertyDescription;
204 1
	}
205
206 1
	private function getPredefinedPropertyDescription( $property, $linker ) {
207
208
		$description = '';
209
		$msgKey = 'smw-pa-property-predefined' . strtolower( $property->getKey() );
210
211
		if ( !wfMessage( $msgKey )->exists() ) {
212
			return $description;
213
		}
214
215
		$message = wfMessage( $msgKey, $property->getLabel() )->inLanguage(
216
			$this->languageCode
217
		);
218
219
		return $linker === null ? $message->escaped() : $message->parse();
220
	}
221
222
	private function tryToFindLocalPropertyDescription( $property, $linker ) {
223
224
		$description = '';
225
226
		$dataItems = $this->store->getPropertyValues(
227
			$property->getDiWikiPage(),
228
			new DIProperty( '_PDESC' )
229
		);
230
231
		if ( ( $dataValue = $this->findDataValueByLanguage( $dataItems, $this->languageCode ) ) !== null ) {
232
			$description = $dataValue->getShortWikiText( $linker );
233
		}
234
235
		return $description;
236
	}
237
238
	private function findDataValueByLanguage( $dataItems, $languageCode ) {
239
240
		if ( $dataItems === null || $dataItems === array() ) {
241
			return null;
242
		}
243
244
		foreach ( $dataItems as $dataItem ) {
245
246
			$dataValue = DataValueFactory::getInstance()->newDataItemValue(
247
				$dataItem,
248
				new DIProperty( '_PDESC' )
249
			);
250
251
			// Here a MonolingualTextValue was retunred therefore the method
252
			// can be called without validation
253
			$dv = $dataValue->getTextValueByLanguage( $languageCode );
254
255
			if ( $dv !== null ) {
256
				return $dv;
257
			}
258
		}
259
260
		return null;
261
	}
262
263
}
264