Completed
Push — master ( 97eb7a...5af00b )
by
unknown
06:52 queued 12s
created

CachingFallbackLabelDescriptionLookup::serialize()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.8666
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
3
namespace Wikibase\Lib\Store;
4
5
use Wikibase\DataModel\Entity\EntityId;
6
use Wikibase\DataModel\Services\Lookup\LabelDescriptionLookupException;
7
use Wikibase\DataModel\Term\TermFallback;
8
use Wikibase\Lib\FormatterCache\TermFallbackCacheFacade;
9
use Wikibase\Lib\TermLanguageFallbackChain;
10
11
/**
12
 * @license GPL-2.0-or-later
13
 *
14
 * @note The class uses immutable cache approach: cached data never changes once persisted.
15
 *       For this purpose we not only include Item ID in cache key construction, but also
16
 *       Item's current revision ID. Revisions never change, the cached data does not need
17
 *       to change either, which means that we don't need to purge caches. As soon as new revision
18
 *       is created, cache key will change and old cache data will eventually be purged by
19
 *       the caching system (eg. APC, Memcached, ...) based on a Least Recently Used strategy
20
 *       as soon as no code will request it anymore.
21
 */
22
class CachingFallbackLabelDescriptionLookup implements FallbackLabelDescriptionLookup {
23
24
	use TermCacheKeyBuilder;
25
26
	private const LABEL = 'label';
27
	private const DESCRIPTION = 'description';
28
29
	/**
30
	 * @var TermFallbackCacheFacade
31
	 */
32
	private $cache;
33
34
	/**
35
	 * @var RedirectResolvingLatestRevisionLookup
36
	 */
37
	private $redirectResolvingRevisionLookup;
38
39
	/**
40
	 * @var FallbackLabelDescriptionLookup
41
	 */
42
	private $labelDescriptionLookup;
43
44
	/**
45
	 * @var TermLanguageFallbackChain
46
	 */
47
	private $termLanguageFallbackChain;
48
49
	/**
50
	 * @param TermFallbackCacheFacade $fallbackCache
51
	 * @param RedirectResolvingLatestRevisionLookup $redirectResolvingRevisionLookup
52
	 * @param FallbackLabelDescriptionLookup $labelDescriptionLookup
53
	 * @param TermLanguageFallbackChain $termLanguageFallbackChain
54
	 */
55
	public function __construct(
56
		TermFallbackCacheFacade $fallbackCache,
57
		RedirectResolvingLatestRevisionLookup $redirectResolvingRevisionLookup,
58
		FallbackLabelDescriptionLookup $labelDescriptionLookup,
59
		TermLanguageFallbackChain $termLanguageFallbackChain
60
	) {
61
		$this->cache = $fallbackCache;
62
		$this->redirectResolvingRevisionLookup = $redirectResolvingRevisionLookup;
63
		$this->labelDescriptionLookup = $labelDescriptionLookup;
64
		$this->termLanguageFallbackChain = $termLanguageFallbackChain;
65
	}
66
67
	/**
68
	 * @param EntityId $entityId
69
	 *
70
	 * @throws LabelDescriptionLookupException
71
	 * @return TermFallback|null
72
	 */
73
	public function getDescription( EntityId $entityId ) {
74
		$languageCodes = $this->termLanguageFallbackChain->getFetchLanguageCodes();
75
		if ( !$languageCodes ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $languageCodes of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
76
			// Can happen when the current interface language is not a valid term language, e.g. "de-formal"
77
			return null;
78
		}
79
80
		$languageCode = $languageCodes[0];
81
		$description = $this->getTerm( $entityId, $languageCode, self::DESCRIPTION );
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression $this->getTerm($entityId...de, self::DESCRIPTION); of type null|Wikibase\DataModel\Term\TermFallback|false adds false to the return on line 83 which is incompatible with the return type declared by the interface Wikibase\Lib\Store\Fallb...nLookup::getDescription of type Wikibase\DataModel\Term\TermFallback|null. It seems like you forgot to handle an error condition.
Loading history...
82
83
		return $description;
84
	}
85
86
	/**
87
	 * @param EntityId $entityId
88
	 *
89
	 * @throws LabelDescriptionLookupException
90
	 * @return TermFallback|null
91
	 */
92
	public function getLabel( EntityId $entityId ) {
93
		$languageCodes = $this->termLanguageFallbackChain->getFetchLanguageCodes();
94
		if ( !$languageCodes ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $languageCodes of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
95
			// Can happen when the current interface language is not a valid term language, e.g. "de-formal"
96
			return null;
97
		}
98
99
		$languageCode = $languageCodes[0];
100
		$label = $this->getTerm( $entityId, $languageCode, self::LABEL );
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression $this->getTerm($entityId...uageCode, self::LABEL); of type null|Wikibase\DataModel\Term\TermFallback|false adds false to the return on line 102 which is incompatible with the return type declared by the interface Wikibase\Lib\Store\Fallb...riptionLookup::getLabel of type Wikibase\DataModel\Term\TermFallback|null. It seems like you forgot to handle an error condition.
Loading history...
101
102
		return $label;
103
	}
104
105
	private function getTerm( EntityId $entityId, $languageCode, $termName = self::LABEL ) {
106
		$resolutionResult = $this->redirectResolvingRevisionLookup->lookupLatestRevisionResolvingRedirect( $entityId );
107
		if ( $resolutionResult === null ) {
108
			return null;
109
		}
110
111
		list( $revisionId, $targetEntityId ) = $resolutionResult;
112
113
		$termFallback = $this->cache->get( $targetEntityId, $revisionId, $languageCode, $termName );
114
		if ( $termFallback === TermFallbackCacheFacade::NO_VALUE ) {
115
			$termFallback = $termName === self::LABEL
116
				? $this->labelDescriptionLookup->getLabel( $targetEntityId )
117
				: $this->labelDescriptionLookup->getDescription( $targetEntityId );
118
119
			$this->cache->set( $termFallback, $targetEntityId, $revisionId, $languageCode, $termName );
120
121
			return $termFallback;
122
		}
123
124
		return $termFallback;
125
	}
126
}
127