__construct()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 9.7666
c 0
b 0
f 0
cc 2
nc 2
nop 4
1
<?php
2
3
namespace Wikibase\Client\Usage;
4
5
use InvalidArgumentException;
6
use Wikibase\DataModel\Entity\EntityId;
7
use Wikibase\DataModel\Services\Lookup\LabelDescriptionLookupException;
8
use Wikibase\DataModel\Term\TermFallback;
9
use Wikibase\Lib\Store\FallbackLabelDescriptionLookup;
10
use Wikibase\Lib\TermLanguageFallbackChain;
11
12
/**
13
 * LanguageFallbackLabelDescriptionLookup decorator that records label usage in an UsageAccumulator.
14
 *
15
 * @see UsageAccumulator
16
 *
17
 * @license GPL-2.0-or-later
18
 * @author Marius Hoch
19
 */
20
class UsageTrackingLanguageFallbackLabelDescriptionLookup implements FallbackLabelDescriptionLookup {
21
22
	/**
23
	 * @var FallbackLabelDescriptionLookup
24
	 */
25
	private $labelDescriptionLookup;
26
27
	/**
28
	 * @var UsageAccumulator
29
	 */
30
	private $usageAccumulator;
31
32
	/**
33
	 * @var TermLanguageFallbackChain
34
	 */
35
	private $termLanguageFallbackChain;
36
37
	/**
38
	 * @var bool
39
	 */
40
	private $trackUsagesInAllLanguages;
41
42
	/**
43
	 * @param FallbackLabelDescriptionLookup $labelDescriptionLookup
44
	 * @param UsageAccumulator $usageAccumulator
45
	 * @param TermLanguageFallbackChain $termLanguageFallbackChain
46
	 * @param bool $trackUsagesInAllLanguages
47
	 */
48
	public function __construct(
49
		FallbackLabelDescriptionLookup $labelDescriptionLookup,
50
		UsageAccumulator $usageAccumulator,
51
		TermLanguageFallbackChain $termLanguageFallbackChain,
52
		$trackUsagesInAllLanguages
53
	) {
54
		if ( !is_bool( $trackUsagesInAllLanguages ) ) {
55
			throw new InvalidArgumentException( '$trackUsagesInAllLanguages must be a bool' );
56
		}
57
58
		$this->labelDescriptionLookup = $labelDescriptionLookup;
59
		$this->usageAccumulator = $usageAccumulator;
60
		$this->termLanguageFallbackChain = $termLanguageFallbackChain;
61
		$this->trackUsagesInAllLanguages = $trackUsagesInAllLanguages;
62
	}
63
64
	/**
65
	 * @param EntityId $entityId
66
	 *
67
	 * @throws LabelDescriptionLookupException
68
	 * @return TermFallback|null
69
	 */
70
	public function getLabel( EntityId $entityId ) {
71
		$termFallback = $this->labelDescriptionLookup->getLabel( $entityId );
72
73
		foreach ( $this->getTouchedLanguages( $termFallback ) as $lang ) {
74
			$this->usageAccumulator->addLabelUsage( $entityId, $lang );
75
		}
76
77
		return $termFallback;
78
	}
79
80
	/**
81
	 * @param EntityId $entityId
82
	 *
83
	 * @throws LabelDescriptionLookupException
84
	 * @return TermFallback|null
85
	 */
86
	public function getDescription( EntityId $entityId ) {
87
		$termFallback = $this->labelDescriptionLookup->getDescription( $entityId );
88
89
		foreach ( $this->getTouchedLanguages( $termFallback ) as $lang ) {
90
			$this->usageAccumulator->addDescriptionUsage( $entityId, $lang );
91
		}
92
93
		return $termFallback;
94
	}
95
96
	/**
97
	 * Get the languages from the TermLanguageFallbackChain used to get a given TermFallback.
98
	 *
99
	 * @param TermFallback|null $termFallback
100
	 *
101
	 * @return string[]|null[]
102
	 */
103
	private function getTouchedLanguages( TermFallback $termFallback = null ) {
104
		if ( $this->trackUsagesInAllLanguages ) {
105
			// On multi-lingual wikis where users can request pages in any language, we can not
106
			// optimize for one language fallback chain only. Since all possible language fallback
107
			// chains must cover all languages, we can simply track an "all languages" usage.
108
			return [ null ];
109
		}
110
111
		$fetchLanguages = $this->termLanguageFallbackChain->getFetchLanguageCodes();
112
113
		if ( $termFallback === null ) {
114
			// Nothing found: Record the full fallback chains as used.
115
			return $fetchLanguages;
116
		}
117
118
		// Found something: Find out which language it was originally in
119
		$languageUsed = $termFallback->getSourceLanguageCode();
120
		if ( !$languageUsed ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $languageUsed of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
121
			$languageUsed = $termFallback->getActualLanguageCode();
122
		}
123
124
		// Record the relevant part of the fallback chain as used.
125
		return array_slice(
126
			$fetchLanguages,
127
			0,
128
			array_search( $languageUsed, $fetchLanguages ) + 1
129
		);
130
	}
131
132
}
133