Completed
Push — master ( a814e8...9f92c8 )
by mw
67:27 queued 50:14
created

PropertySpecificationLookup   B

Complexity

Total Complexity 53

Size/Duplication

Total Lines 442
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 12

Test Coverage

Coverage 99.35%

Importance

Changes 0
Metric Value
dl 0
loc 442
ccs 153
cts 154
cp 0.9935
rs 7.4757
c 0
b 0
f 0
wmc 53
lcom 1
cbo 12

16 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A resetCacheBy() 0 3 1
B getFieldListBy() 0 23 4
A getPreferredPropertyLabelBy() 0 19 3
B getPropertyFromDisplayTitle() 0 27 3
B hasUniquenessConstraintBy() 0 23 4
A getExternalFormatterUriBy() 0 15 3
B getAllowedPatternBy() 0 23 4
B getAllowedValuesBy() 0 23 4
A getDisplayPrecisionBy() 0 16 3
A getDisplayUnitsBy() 0 17 4
B getPropertyDescriptionBy() 0 36 6
B getPredefinedPropertyDescription() 0 27 4
A findLocalPropertyDescription() 0 16 2
A findPreferredPropertyLabel() 0 16 2
B findTextValueByLanguage() 0 24 5

How to fix   Complexity   

Complex Class

Complex classes like PropertySpecificationLookup often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use PropertySpecificationLookup, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace SMW;
4
5
use SMW\Query\DescriptionFactory;
6
use Onoi\Cache\Cache;
7
use SMW\Message;
8
use SMWDIBlob as DIBlob;
9
use SMWQuery as Query;
10
11
/**
12
 * This class should be accessed via ApplicationFactory::getPropertySpecificationLookup
13
 * to ensure a singleton instance.
14
 *
15
 * Changes to a property should trigger a PropertySpecificationLookup::resetCacheBy to
16
 * evict all cached item store to that property.
17
 *
18
 * @license GNU GPL v2+
19
 * @since 2.4
20
 *
21
 * @author mwjames
22
 */
23
class PropertySpecificationLookup {
24
25
	/**
26
	 * Reference used in InMemoryPoolCache
27
	 */
28
	const POOLCACHE_ID = 'property.specification.lookup';
29
30
	/**
31
	 * @var CachedPropertyValuesPrefetcher
32
	 */
33
	private $cachedPropertyValuesPrefetcher;
34
35
	/**
36
	 * @var string
37
	 */
38
	private $languageCode = 'en';
39
40
	/**
41
	 * @var Cache
42
	 */
43
	private $intermediaryMemoryCache;
44
45
	/**
46
	 * @since 2.4
47
	 *
48
	 * @param CachedPropertyValuesPrefetcher $cachedPropertyValuesPrefetcher
49
	 * @param Cache $intermediaryMemoryCache
50
	 */
51 246
	public function __construct( CachedPropertyValuesPrefetcher $cachedPropertyValuesPrefetcher, Cache $intermediaryMemoryCache ) {
52 246
		$this->cachedPropertyValuesPrefetcher = $cachedPropertyValuesPrefetcher;
53 246
		$this->intermediaryMemoryCache = $intermediaryMemoryCache;
54 246
		$this->languageCode = Localizer::getInstance()->getContentLanguage()->getCode();
55 246
	}
56
57
	/**
58
	 * @since 2.4
59
	 *
60
	 * @param DIWikiPage $subject
61
	 */
62 159
	public function resetCacheBy( DIWikiPage $subject ) {
63 159
		$this->cachedPropertyValuesPrefetcher->resetCacheBy( $subject );
64 159
	}
65
66
	/**
67
	 * @since 2.5
68
	 *
69
	 * @param DIProperty $property
70
	 *
71
	 * @return false|DataItem
72
	 */
73 20
	public function getFieldListBy( DIProperty $property ) {
74
75 20
		$fieldList = false;
0 ignored issues
show
Unused Code introduced by
$fieldList 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...
76 20
		$key = 'list:'. $property->getKey();
77
78
		// Guard against high frequency lookup
79 20
		if ( ( $fieldList = $this->intermediaryMemoryCache->fetch( $key ) ) !== false ) {
80 18
			return $fieldList;
81
		}
82
83 15
		$dataItems = $this->cachedPropertyValuesPrefetcher->getPropertyValues(
84 15
			$property->getCanonicalDiWikiPage(),
0 ignored issues
show
Bug introduced by
It seems like $property->getCanonicalDiWikiPage() can be null; however, getPropertyValues() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
85 15
			new DIProperty( '_LIST' )
86
		);
87
88 15
		if ( is_array( $dataItems ) && $dataItems !== array() ) {
89 15
			$fieldList = end( $dataItems );
90
		}
91
92 15
		$this->intermediaryMemoryCache->save( $key, $fieldList );
93
94 15
		return $fieldList;
95
	}
96
97
	/**
98
	 * @since 2.5
99
	 *
100
	 * @param DIProperty $property
101
	 * @param string $languageCode
102
	 *
103
	 * @return string
104
	 */
105 234
	public function getPreferredPropertyLabelBy( DIProperty $property, $languageCode = '' ) {
106
107 234
		$languageCode = $languageCode === '' ? $this->languageCode : $languageCode;
108 234
		$key = 'ppl:' . $languageCode  . ':'. $property->getKey();
109
110
		// Guard against high frequency lookup
111 234
		if ( ( $preferredPropertyLabel = $this->intermediaryMemoryCache->fetch( $key ) ) !== false ) {
112 203
			return $preferredPropertyLabel;
113
		}
114
115 203
		$preferredPropertyLabel = $this->findPreferredPropertyLabel(
116
			$property,
117
			$languageCode
118
		);
119
120 203
		$this->intermediaryMemoryCache->save( $key, $preferredPropertyLabel );
121
122 203
		return $preferredPropertyLabel;
123
	}
124
125
	/**
126
	 * @since 2.4
127
	 *
128
	 * @param string $displayTitle
129
	 *
130
	 * @return DIProperty|false
131
	 */
132 1
	public function getPropertyFromDisplayTitle( $displayTitle ) {
133
134 1
		$descriptionFactory = new DescriptionFactory();
135
136 1
		$description = $descriptionFactory->newSomeProperty(
137 1
			new DIProperty( '_DTITLE' ),
138 1
			$descriptionFactory->newValueDescription( new DIBlob( $displayTitle ) )
139
		);
140
141 1
		$query = new Query( $description );
142 1
		$query->setLimit( 1 );
143
144 1
		$dataItems = $this->cachedPropertyValuesPrefetcher->queryPropertyValuesFor(
145
			$query
146
		);
147
148 1
		if ( is_array( $dataItems ) && $dataItems !== array() ) {
149 1
			$dataItem = end( $dataItems );
150
151
			// Cache results as a linked list attached to
152
			// the property so that it can be purged all together
153
154 1
			return new DIProperty( $dataItem->getDBKey() );
155
		}
156
157
		return false;
158
	}
159
160
	/**
161
	 * @since 2.4
162
	 *
163
	 * @param DIProperty $property
164
	 *
165
	 * @return boolean
166
	 */
167 4
	public function hasUniquenessConstraintBy( DIProperty $property ) {
168
169 4
		$hasUniquenessConstraint = false;
170 4
		$key = 'uc:'. $property->getKey();
171
172
		// Guard against high frequency lookup
173 4
		if ( $this->intermediaryMemoryCache->contains( $key ) ) {
174 3
			return $this->intermediaryMemoryCache->fetch( $key );
175
		}
176
177 4
		$dataItems = $this->cachedPropertyValuesPrefetcher->getPropertyValues(
178 4
			$property->getCanonicalDiWikiPage(),
0 ignored issues
show
Bug introduced by
It seems like $property->getCanonicalDiWikiPage() can be null; however, getPropertyValues() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
179 4
			new DIProperty( '_PVUC' )
180
		);
181
182 4
		if ( is_array( $dataItems ) && $dataItems !== array() ) {
183 4
			$hasUniquenessConstraint = end( $dataItems )->getBoolean();
184
		}
185
186 4
		$this->intermediaryMemoryCache->save( $key, $hasUniquenessConstraint );
187
188 4
		return $hasUniquenessConstraint;
189
	}
190
191
	/**
192
	 * @since 2.5
193
	 *
194
	 * @param DIProperty $property
195
	 *
196
	 * @return DataItem|null
197
	 */
198 2
	public function getExternalFormatterUriBy( DIProperty $property ) {
199
200 2
		$dataItem = null;
201
202 2
		$dataItems = $this->cachedPropertyValuesPrefetcher->getPropertyValues(
203 2
			$property->getCanonicalDiWikiPage(),
0 ignored issues
show
Bug introduced by
It seems like $property->getCanonicalDiWikiPage() can be null; however, getPropertyValues() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
204 2
			new DIProperty( '_PEFU' )
205
		);
206
207 2
		if ( is_array( $dataItems ) && $dataItems !== array() ) {
208 2
			$dataItem = end( $dataItems );
209
		}
210
211 2
		return $dataItem;
212
	}
213
214
	/**
215
	 * @since 2.4
216
	 *
217
	 * @param DIProperty $property
218
	 *
219
	 * @return string
220
	 */
221 199
	public function getAllowedPatternBy( DIProperty $property ) {
222
223 199
		$allowsPattern = '';
224 199
		$key = 'ap:'. $property->getKey();
225
226
		// Guard against high frequency lookup
227 199
		if ( $this->intermediaryMemoryCache->contains( $key ) ) {
228 166
			return $this->intermediaryMemoryCache->fetch( $key );
229
		}
230
231 178
		$dataItems = $this->cachedPropertyValuesPrefetcher->getPropertyValues(
232 178
			$property->getCanonicalDiWikiPage(),
0 ignored issues
show
Bug introduced by
It seems like $property->getCanonicalDiWikiPage() can be null; however, getPropertyValues() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
233 178
			new DIProperty( '_PVAP' )
234
		);
235
236 178
		if ( is_array( $dataItems ) && $dataItems !== array() ) {
237 2
			$allowsPattern = end( $dataItems )->getString();
238
		}
239
240 178
		$this->intermediaryMemoryCache->save( $key, $allowsPattern );
241
242 178
		return $allowsPattern;
243
	}
244
245
	/**
246
	 * @since 2.4
247
	 *
248
	 * @param DIProperty $property
249
	 *
250
	 * @return integer|false
251
	 */
252 207
	public function getAllowedValuesBy( DIProperty $property ) {
253
254 207
		$allowsValues = array();
255 207
		$key = 'al:'. $property->getKey();
256
257
		// Guard against high frequency lookup
258 207
		if ( $this->intermediaryMemoryCache->contains( $key ) ) {
259 176
			return $this->intermediaryMemoryCache->fetch( $key );
260
		}
261
262 186
		$dataItems = $this->cachedPropertyValuesPrefetcher->getPropertyValues(
263 186
			$property->getCanonicalDiWikiPage(),
0 ignored issues
show
Bug introduced by
It seems like $property->getCanonicalDiWikiPage() can be null; however, getPropertyValues() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
264 186
			new DIProperty( '_PVAL' )
265
		);
266
267 186
		if ( is_array( $dataItems ) && $dataItems !== array() ) {
268 5
			$allowsValues = $dataItems;
269
		}
270
271 186
		$this->intermediaryMemoryCache->save( $key, $allowsValues );
272
273 186
		return $allowsValues;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $allowsValues; (array) is incompatible with the return type documented by SMW\PropertySpecificatio...kup::getAllowedValuesBy of type integer|false.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
274
	}
275
276
	/**
277
	 * @since 2.4
278
	 *
279
	 * @param DIProperty $property
280
	 *
281
	 * @return integer|false
282
	 */
283 40
	public function getDisplayPrecisionBy( DIProperty $property ) {
284
285 40
		$displayPrecision = false;
286
287 40
		$dataItems = $this->cachedPropertyValuesPrefetcher->getPropertyValues(
288 40
			$property->getCanonicalDiWikiPage(),
0 ignored issues
show
Bug introduced by
It seems like $property->getCanonicalDiWikiPage() can be null; however, getPropertyValues() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
289 40
			new DIProperty( '_PREC' )
290
		);
291
292 40
		if ( $dataItems !== false && $dataItems !== array() ) {
293 4
			$dataItem = end( $dataItems );
294 4
			$displayPrecision = abs( (int)$dataItem->getNumber() );
295
		}
296
297 40
		return $displayPrecision;
298
	}
299
300
	/**
301
	 * @since 2.4
302
	 *
303
	 * @param DIProperty $property
304
	 *
305
	 * @return array
306
	 */
307 18
	public function getDisplayUnitsBy( DIProperty $property ) {
308
309 18
		$units = array();
310
311 18
		$dataItems = $this->cachedPropertyValuesPrefetcher->getPropertyValues(
312 18
			$property->getCanonicalDiWikiPage(),
0 ignored issues
show
Bug introduced by
It seems like $property->getCanonicalDiWikiPage() can be null; however, getPropertyValues() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
313 18
			new DIProperty( '_UNIT' )
314
		);
315
316 18
		if ( $dataItems !== false && $dataItems !== array() ) {
317 6
			foreach ( $dataItems as $dataItem ) {
318 6
				$units = array_merge( $units, preg_split( '/\s*,\s*/u', $dataItem->getString() ) );
319
			}
320
		}
321
322 18
		return $units;
323
	}
324
325
	/**
326
	 * We try to cache anything to avoid unnecessary store connections or DB
327
	 * lookups. For cases where a property was changed, the EventDipatcher will
328
	 * receive a 'property.specification.change' event (emitted as soon as the content of
329
	 * a property page was altered) with PropertySpecificationLookup::resetCacheBy
330
	 * being invoked to remove the cache entry for that specific property.
331
	 *
332
	 * @since 2.4
333
	 *
334
	 * @param DIProperty $property
335
	 * @param string $languageCode
336
	 * @param mixed|null $linker
337
	 *
338
	 * @return string
339
	 */
340 68
	public function getPropertyDescriptionBy( DIProperty $property, $languageCode = '', $linker = null ) {
341
342
		// Take the linker into account (Special vs. in page rendering etc.)
343 68
		$languageCode = $languageCode === '' ? $this->languageCode : $languageCode;
344 68
		$key = '--pdesc:' . $languageCode . ':' . ( $linker === null ? '0' : '1' );
345
346 68
		$blobStore = $this->cachedPropertyValuesPrefetcher->getBlobStore();
347
348 68
		$container = $blobStore->read(
349 68
			$this->cachedPropertyValuesPrefetcher->getRootHashFrom( $property->getCanonicalDiWikiPage() )
0 ignored issues
show
Bug introduced by
It seems like $property->getCanonicalDiWikiPage() can be null; however, getRootHashFrom() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
350
		);
351
352 68
		if ( $container->has( $key ) ) {
353 53
			return $container->get( $key );
354
		}
355
356 67
		$localPropertyDescription = $this->findLocalPropertyDescription(
357
			$property,
358
			$linker,
359
			$languageCode
360
		);
361
362
		// If a local property description wasn't available for a predefined property
363
		// the try to find a system translation
364 67
		if ( trim( $localPropertyDescription ) === '' && !$property->isUserDefined() ) {
365 14
			$localPropertyDescription = $this->getPredefinedPropertyDescription( $property, $linker, $languageCode );
366
		}
367
368 67
		$container->set( $key, $localPropertyDescription );
369
370 67
		$blobStore->save(
371
			$container
372
		);
373
374 67
		return $localPropertyDescription;
375
	}
376
377 14
	private function getPredefinedPropertyDescription( $property, $linker, $languageCode ) {
378
379 14
		$description = '';
380 14
		$key = $property->getKey();
381
382 14
		if ( ( $msgKey = PropertyRegistry::getInstance()->findPropertyDescriptionMsgKeyById( $key ) ) === '' ) {
383 14
			$msgKey = 'smw-pa-property-predefined' . strtolower( $key );
384
		}
385
386 14
		if ( !Message::exists( $msgKey ) ) {
387 2
			return $description;
388
		}
389
390 14
		$dataValue = DataValueFactory::getInstance()->newDataValueByItem(
391
			$property
392
		);
393
394 14
		$label = $dataValue->getFormattedLabel();
395
396 14
		$message = Message::get(
397 14
			array( $msgKey, $label ),
398 14
			$linker === null ? Message::ESCAPED : Message::PARSE,
399
			$languageCode
400
		);
401
402 14
		return $message;
403
	}
404
405 67
	private function findLocalPropertyDescription( $property, $linker, $languageCode ) {
406
407 67
		$text = '';
408 67
		$descriptionProperty = new DIProperty( '_PDESC' );
409
410 67
		$dataItems = $this->cachedPropertyValuesPrefetcher->getPropertyValues(
411 67
			$property->getCanonicalDiWikiPage(),
412
			$descriptionProperty
413
		);
414
415 67
		if ( ( $dataValue = $this->findTextValueByLanguage( $dataItems, $descriptionProperty, $languageCode ) ) !== null ) {
416 6
			$text = $dataValue->getShortWikiText( $linker );
417
		}
418
419 67
		return $text;
420
	}
421
422 203
	private function findPreferredPropertyLabel( $property, $languageCode ) {
423
424 203
		$text = '';
425 203
		$preferredProperty = new DIProperty( '_PPLB' );
426
427 203
		$dataItems = $this->cachedPropertyValuesPrefetcher->getPropertyValues(
428 203
			$property->getCanonicalDiWikiPage(),
429
			$preferredProperty
430
		);
431
432 203
		if ( ( $dataValue = $this->findTextValueByLanguage( $dataItems, $preferredProperty, $languageCode ) ) !== null ) {
433 4
			$text = $dataValue->getShortWikiText();
434
		}
435
436 203
		return $text;
437
	}
438
439 206
	private function findTextValueByLanguage( $dataItems, $property, $languageCode ) {
440
441 206
		if ( $dataItems === null || $dataItems === array() ) {
442 205
			return null;
443
		}
444
445 8
		foreach ( $dataItems as $dataItem ) {
446
447 8
			$dataValue = DataValueFactory::getInstance()->newDataValueByItem(
448
				$dataItem,
449
				$property
450
			);
451
452
			// Here a MonolingualTextValue was retunred therefore the method
453
			// can be called without validation
454 8
			$dv = $dataValue->getTextValueByLanguage( $languageCode );
455
456 8
			if ( $dv !== null ) {
457 8
				return $dv;
458
			}
459
		}
460
461 1
		return null;
462
	}
463
464
}
465