Test Failed
Pull Request — master (#11)
by Alaa
02:35
created

DatabaseTermIdsAcquirer::acquireTextInLangIds()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 9.584
c 0
b 0
f 0
cc 4
nc 6
nop 1
1
<?php
2
3
namespace Wikibase\TermStore\MediaWiki\PackagePrivate;
4
5
use AppendIterator;
6
use ArrayIterator;
7
use Wikimedia\Rdbms\IDatabase;
8
9
class DatabaseTermIdsAcquirer implements TermIdsAcquirer {
10
11
	const TABLE_TEXT = 'wbt_text';
12
	const TABLE_TEXT_IN_LANG = 'wbt_text_in_lang';
13
	const TABLE_TERM_IN_LANG = 'wbt_term_in_lang';
14
15
	/**
16
	 * @var Database $dbw
17
	 */
18
	private $dbw;
19
20
	/**
21
	 * @var Database $dbr
22
	 */
23
	private $dbr;
24
25
	public function __construct(
26
		IDatabase $dbw,
27
		IDatabase $dbr,
28
		TypeIdsAcquirer $typeIdsAcquirer
29
	) {
30
		$this->dbw = $dbw;
0 ignored issues
show
Documentation Bug introduced by
It seems like $dbw of type object<Wikimedia\Rdbms\IDatabase> is incompatible with the declared type object<Wikibase\TermStor...ackagePrivate\Database> of property $dbw.

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...
31
		$this->dbr = $dbr;
0 ignored issues
show
Documentation Bug introduced by
It seems like $dbr of type object<Wikimedia\Rdbms\IDatabase> is incompatible with the declared type object<Wikibase\TermStor...ackagePrivate\Database> of property $dbr.

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...
32
		$this->typeIdsAcquirer = $typeIdsAcquirer;
0 ignored issues
show
Bug introduced by
The property typeIdsAcquirer does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
33
	}
34
35
	public function acquireTermIds( array $termsArray ): array {
36
		$termsArray = $this->mapToTextIds( $termsArray );
37
		$termsArray = $this->mapToTextInLangIds( $termsArray );
38
		$termsArray = $this->mapToTypeIds( $termsArray );
39
		return $this->mapToTermInLangIds( $termsArray );
40
	}
41
42
	/**
43
	 * replace root keys containing type names in termsArray
44
	 * with their respective ids in wbt_type table
45
	 *
46
	 * @param array $termsArray terms per type per language:
47
	 *	[
48
	 *		'type1' => [ ... ],
49
	 *		'type2' => [ ... ],
50
	 *		...
51
	 *	]
52
	 *
53
	 * @return array
54
	 *	[
55
	 *		<typeId1> => [ ... ],
56
	 *		<typeId2> => [ ... ],
57
	 *		...
58
	 *	]
59
	 */
60
	private function mapToTypeIds( array $termsArray ) {
61
		$typeIds = $this->typeIdsAcquirer->acquireTypeIds( array_keys( $termsArray ) );
62
63
		$termsArrayByTypeId = [];
64
		foreach ( $typeIds as $type => $typeId ) {
65
			$termsArrayByTypeId[$typeId] = $termsArray[$type];
66
		}
67
68
		return $termsArrayByTypeId;
69
	}
70
71
	/**
72
	 * replace text at termsArray leaves with their ids in wbt_text table
73
	 * and return resulting array
74
	 *
75
	 * @param array $termsArray terms per type per language:
76
	 *	[
77
	 *		'type' => [
78
	 *			[ 'language' => 'term' | [ 'term1', 'term2', ... ] ], ...
79
	 *		], ...
80
	 *	]
81
	 *
82
	 * @return array
83
	 *	[
84
	 *		'type' => [
85
	 *			[ 'language' => [ <textId1>, <textId2>, ... ] ], ...
86
	 *		], ...
87
	 *	]
88
	 */
89
	private function mapToTextIds( array $termsArray ) {
90
		$texts = [];
91
92
		array_walk_recursive( $termsArray, function ( $text ) use ( &$texts ) {
93
			$texts[] = $text;
94
		} );
95
96
		$textIds = $this->acquireTextIds( $texts );
97
98
		array_walk_recursive( $termsArray, function ( &$text ) use ( $textIds ) {
99
			$text = $textIds[$text];
100
		} );
101
102
		return $termsArray;
103
	}
104
105
	private function acquireTextIds( array $texts ) {
106
		$textIdsAcquirer = new Util\ReplicaMasterAwareRecordIdsAcquirer(
107
			$this->dbw, $this->dbr, 'wbt_text', 'wbx_id' );
108
109
		$textRecords = [];
110
		foreach ( $texts as $text ) {
111
			$textRecords[] = [ 'wbx_text' => $text ];
112
		}
113
114
		$acquiredIds = $textIdsAcquirer->acquireIds( $textRecords );
115
116
		$textIds = [];
117
		foreach ( $acquiredIds as $acquiredId ) {
118
			$textIds[$acquiredId['wbx_text']] = $acquiredId['wbx_id'];
119
		}
120
121
		return $textIds;
122
	}
123
124
	/**
125
	 * replace ( lang => [ textId, ... ] ) entries with their respective ids
126
	 * in wbt_text_in_lang table and return resulting array
127
	 *
128
	 * @param array $termsArray text ids per type per langauge
129
	 *	[
130
	 *		'type' => [
131
	 *			[ 'language' => [ <textId1>, <textId2>, ... ] ], ...
132
	 *		], ...
133
	 *	]
134
	 *
135
	 * @return array
136
	 *	[
137
	 *		'type' => [ <textInLangId1>, <textInLangId2>, ... ],
138
	 *		...
139
	 *	]
140
	 */
141
	private function mapToTextInLangIds( array $termsArray ) {
142
		$flattenedLangTextIds = [];
143
		foreach ( $termsArray as $langTextIds ) {
144
			foreach ( $langTextIds as $lang => $textIds ) {
145
				if ( !isset( $flattenedLangTextIds[$lang] ) ) {
146
					$flattenedLangTextIds[$lang] = [];
147
				}
148
149
				$flattenedLangTextIds[$lang] = array_unique(
150
					array_merge(
151
						(array)$textIds,
152
						(array)$flattenedLangTextIds[$lang]
153
					)
154
				);
155
156
			}
157
		}
158
159
		$textInLangIds = $this->acquireTextInLangIds( $flattenedLangTextIds );
160
161
		$newTermsArray = [];
162
		foreach ( $termsArray as $type => $langTextIds ) {
163
			$newTermsArray[$type] = [];
164
			foreach ( $langTextIds as $lang => $textIds ) {
165
				foreach ( (array)$textIds as $textId ) {
166
					$newTermsArray[$type][] = $textInLangIds[$lang][$textId];
167
				}
168
			}
169
		}
170
171
		return $newTermsArray;
172
	}
173
174
	private function acquireTextInLangIds( array $langTextIds ) {
175
		$textInLangIdsAcquirer = new Util\ReplicaMasterAwareRecordIdsAcquirer(
176
			$this->dbw, $this->dbr, 'wbt_text_in_lang', 'wbxl_id' );
177
178
		$textInLangRecords = [];
179
		foreach ( $langTextIds as $lang => $textIds ) {
180
			foreach ( $textIds as $textId ) {
181
				$textInLangRecords[] = [ 'wbxl_text_id' => $textId, 'wbxl_language' => $lang ];
182
			}
183
		}
184
185
		$acquiredIds = $textInLangIdsAcquirer->acquireIds( $textInLangRecords );
186
187
		$textInLangIds = [];
188
		foreach ( $acquiredIds as $acquiredId ) {
189
			$textInLangIds[$acquiredId['wbxl_language']][$acquiredId['wbxl_text_id']]
190
				= $acquiredId['wbxl_id'];
191
		}
192
193
		return $textInLangIds;
194
	}
195
196
	/**
197
	 * replace root ( type => [ textInLangId, ... ] ) entries with their respective ids
198
	 * in wbt_term_in_lang table and return resulting array
199
	 *
200
	 * @param array $termsArray text in lang ids per type
201
	 *	[
202
	 *		'type' => [ <textInLangId1>, <textInLangId2>, ... ],
203
	 *		...
204
	 *	]
205
	 *
206
	 * @return array
207
	 *	[
208
	 *		<termInLang1>,
209
	 *		<termInLang2>,
210
	 *		...
211
	 *	]
212
	 */
213
	private function mapToTermInLangIds( array $termsArray ) {
214
		$flattenedTypeTextInLangIds = [];
215
		foreach ( $termsArray as $typeId => $textInLangIds ) {
216
			if ( !isset( $flattenedTypeTextInLangIds[$typeId] ) ) {
217
				$flattenedTypeTextInLangIds[$typeId] = [];
218
			}
219
220
			$flattenedTypeTextInLangIds[$typeId] = array_unique(
221
				array_merge(
222
					(array)$textInLangIds,
223
					(array)$flattenedTypeTextInLangIds[$typeId]
224
				)
225
			);
226
		}
227
228
		$termInLangIds = $this->acquireTermInLangIds( $flattenedTypeTextInLangIds );
229
230
		$newTermsArray = [];
231
		foreach ( $termsArray as $typeId => $textInLangIds ) {
232
			foreach ( $textInLangIds as $textInLangId ) {
233
				$newTermsArray[] = $termInLangIds[$typeId][$textInLangId];
234
			}
235
		}
236
237
		return $newTermsArray;
238
	}
239
240
	private function acquireTermInLangIds( array $typeTextInLangIds ) {
241
		$termInLangIdsAcquirer = new Util\ReplicaMasterAwareRecordIdsAcquirer(
242
			$this->dbw, $this->dbr, 'wbt_term_in_lang', 'wbtl_id' );
243
244
		$termInLangRecords = [];
245
		foreach ( $typeTextInLangIds as $typeId => $textInLangIds ) {
246
			foreach ( $textInLangIds as $textInLangId ) {
247
				$termInLangRecords[] = [
248
					'wbtl_text_in_lang_id' => $textInLangId,
249
					'wbtl_type_id' => (string)$typeId
250
				];
251
			}
252
		}
253
254
		$acquiredIds = $termInLangIdsAcquirer->acquireIds( $termInLangRecords );
255
256
		$termInLangIds = [];
257
		foreach ( $acquiredIds as $acquiredId ) {
258
			$termInLangIds[$acquiredId['wbtl_type_id']][$acquiredId['wbtl_text_in_lang_id']]
259
				= $acquiredId['wbtl_id'];
260
		}
261
262
		return $termInLangIds;
263
	}
264
265
}
266