extractPreferredValueOrAny()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 16
rs 9.7333
c 0
b 0
f 0
cc 4
nc 4
nop 1
1
<?php
2
declare( strict_types = 1 );
3
4
namespace Wikibase\Lib;
5
6
use InvalidArgumentException;
7
use Language;
8
9
/**
10
 * FIXME: this class is not a language fallback chain. It takes and uses a fallback chain.
11
 * The name thus needs to be updated to not be misleading.
12
 *
13
 * @license GPL-2.0-or-later
14
 * @author Liangent < [email protected] >
15
 * @author Thiemo Kreuz
16
 */
17
class TermLanguageFallbackChain {
18
19
	/**
20
	 * @var LanguageWithConversion[]
21
	 */
22
	private $chain;
23
24
	/**
25
	 * @param LanguageWithConversion[] $chain
26
	 * @param ContentLanguages|null $termLanguages
27
	 */
28
	public function __construct( array $chain, ContentLanguages $termLanguages ) {
29
		$this->chain = array_values( array_filter(
0 ignored issues
show
Documentation Bug introduced by
It seems like array_values(array_filte...getLanguageCode()); })) of type array<integer,?> is incompatible with the declared type array<integer,object<Wik...anguageWithConversion>> of property $chain.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
30
			$chain,
31
			static function ( $language ) use ( $termLanguages ) {
32
				return $termLanguages->hasLanguage( $language->getLanguageCode() );
33
			}
34
		) );
35
		if ( !empty( $chain ) && empty( $this->chain ) ) {
36
			$this->chain = [ LanguageWithConversion::factory( 'en' ) ];
37
		}
38
	}
39
40
	/**
41
	 * Get raw fallback chain as an array. Semi-private for testing.
42
	 *
43
	 * @return LanguageWithConversion[]
44
	 */
45
	public function getFallbackChain(): array {
46
		return $this->chain;
47
	}
48
49
	/**
50
	 * Return language codes to use when fetching entries from the database.
51
	 *
52
	 * @see LanguageWithConversion::getFetchLanguageCode
53
	 *
54
	 * @return string[]
55
	 */
56
	public function getFetchLanguageCodes(): array {
57
		$codes = [];
58
59
		foreach ( $this->chain as $language ) {
60
			$codes[] = $language->getFetchLanguageCode();
61
		}
62
63
		return $codes;
64
	}
65
66
	/**
67
	 * Try to fetch the best value in a multilingual data array.
68
	 *
69
	 * @param string[]|array[] $data Multilingual data with language codes as keys
70
	 *
71
	 * @throws InvalidArgumentException
72
	 * @return string[]|null of three items: array(
73
	 * 	'value' => finally fetched and translated value
74
	 * 	'language' => language code of the language which final value is in
75
	 * 	'source' => language code of the language where the value is translated from
76
	 * ), or null when no "acceptable" data can be found.
77
	 */
78
	public function extractPreferredValue( array $data ): ?array {
79
		if ( empty( $data ) ) {
80
			return null;
81
		}
82
83
		foreach ( $this->chain as $languageWithConversion ) {
84
			$languageCode = $languageWithConversion->getFetchLanguageCode();
85
86
			if ( isset( $data[$languageCode] ) ) {
87
				$value = $data[$languageCode];
88
89
				// Data from an EntityInfoBuilder is already made of pre-build arrays
90
				if ( is_array( $value ) ) {
91
					$value = $value['value'];
92
				}
93
94
				return $this->getValueArray(
95
					$languageWithConversion->translate( $value ),
96
					$languageWithConversion->getLanguageCode(),
97
					$languageWithConversion->getSourceLanguageCode()
98
				);
99
			}
100
		}
101
102
		return null;
103
	}
104
105
	/**
106
	 * Try to fetch the best value in a multilingual data array first.
107
	 * If no "acceptable" value exists, return any value known.
108
	 *
109
	 * @param string[]|array[] $data Multilingual data with language codes as keys
110
	 *
111
	 * @return string[]|null of three items: array(
112
	 * 	'value' => finally fetched and translated value
113
	 * 	'language' => language code of the language which final value is in
114
	 * 	'source' => language code of the language where the value is translated from
115
	 * ), or null when no data with a valid language code can be found.
116
	 */
117
	public function extractPreferredValueOrAny( array $data ): ?array {
118
		$preferred = $this->extractPreferredValue( $data );
119
120
		if ( $preferred !== null ) {
121
			return $preferred;
122
		}
123
124
		foreach ( $data as $languageCode => $value ) {
125
			if ( Language::isValidCode( $languageCode ) ) {
126
				// We cannot translate here, we do not have a LanguageWithConversion object
127
				return $this->getValueArray( $value, $languageCode );
0 ignored issues
show
Bug introduced by
It seems like $value defined by $value on line 124 can also be of type array; however, Wikibase\Lib\TermLanguag...kChain::getValueArray() does only seem to accept string|array<integer,string>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
128
			}
129
		}
130
131
		return null;
132
	}
133
134
	/**
135
	 * @param string|string[] $value
136
	 * @param string $languageCode
137
	 * @param string|null $sourceLanguageCode
138
	 *
139
	 * @return string[]
140
	 */
141
	private function getValueArray( $value, string $languageCode, ?string $sourceLanguageCode = null ): array {
142
		if ( !is_array( $value ) ) {
143
			$value = [
144
				'value' => $value,
145
				'language' => $languageCode,
146
				'source' => $sourceLanguageCode,
147
			];
148
		}
149
150
		return $value;
151
	}
152
153
}
154