Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
83.22% covered (warning)
83.22%
124 / 149
57.14% covered (warning)
57.14%
8 / 14
CRAP
0.00% covered (danger)
0.00%
0 / 1
EntitySchemaConverter
83.22% covered (warning)
83.22%
124 / 149
57.14% covered (warning)
57.14%
8 / 14
77.00
0.00% covered (danger)
0.00%
0 / 1
 getFullViewSchemaData
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 getMonolingualNameBadgeData
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 getFullArraySchemaData
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
1 / 1
5
 getPersistenceSchemaData
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
5
 getSchemaID
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getIdFromSchema
60.00% covered (warning)
60.00%
6 / 10
0.00% covered (danger)
0.00%
0 / 1
8.30
 getSchemaText
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getSchemaTextFromSchema
63.64% covered (warning)
63.64%
7 / 11
0.00% covered (danger)
0.00%
0 / 1
7.73
 getSearchEntitySchemaAdapter
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
4
 getNameBadgesFromSchema
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
2
 getSchemaLanguages
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
4
 getLabelFromSchema
66.67% covered (warning)
66.67%
10 / 15
0.00% covered (danger)
0.00%
0 / 1
10.37
 getDescriptionFromSchema
66.67% covered (warning)
66.67%
10 / 15
0.00% covered (danger)
0.00%
0 / 1
10.37
 getAliasGroupFromSchema
66.67% covered (warning)
66.67%
10 / 15
0.00% covered (danger)
0.00%
0 / 1
10.37
1<?php
2
3declare( strict_types = 1 );
4
5namespace EntitySchema\Services\Converter;
6
7use DomainException;
8use LogicException;
9use Wikibase\DataModel\Term\AliasGroupList;
10use Wikibase\DataModel\Term\TermList;
11
12/**
13 * Convert schema data for different uses from the persistence format
14 *
15 * @license GPL-2.0-or-later
16 */
17class EntitySchemaConverter {
18
19    /**
20     * @param string $schemaJSON
21     *
22     * @return FullViewEntitySchemaData
23     *
24     * @throws LogicException
25     */
26    public function getFullViewSchemaData(
27        string $schemaJSON
28    ): FullViewEntitySchemaData {
29        $schema = json_decode( $schemaJSON, true );
30
31        return new FullViewEntitySchemaData(
32            $this->getNameBadgesFromSchema( $schema ),
33            $this->getSchemaTextFromSchema( $schema )
34        );
35    }
36
37    public function getMonolingualNameBadgeData( string $schemaData, string $langCode ): NameBadge {
38        $schema = json_decode( $schemaData, true );
39
40        return new NameBadge(
41            $this->getLabelFromSchema( $schema, $langCode ),
42            $this->getDescriptionFromSchema( $schema, $langCode ),
43            $this->getAliasGroupFromSchema( $schema, $langCode )
44        );
45    }
46
47    public function getFullArraySchemaData( string $schemaJSON ): FullArrayEntitySchemaData {
48        $schema = json_decode( $schemaJSON, true );
49
50        $data = [
51            'labels' => [],
52            'descriptions' => [],
53            'aliases' => [],
54            'schemaText' => $this->getSchemaTextFromSchema( $schema ),
55        ];
56
57        foreach ( $this->getSchemaLanguages( $schema ) as $languageCode ) {
58            $label = $this->getLabelFromSchema( $schema, $languageCode );
59            if ( $label ) {
60                $data['labels'][$languageCode] = $label;
61            }
62            $description = $this->getDescriptionFromSchema( $schema, $languageCode );
63            if ( $description ) {
64                $data['descriptions'][$languageCode] = $description;
65            }
66            $aliases = $this->getAliasGroupFromSchema( $schema, $languageCode );
67            if ( $aliases ) {
68                $data['aliases'][$languageCode] = $aliases;
69            }
70        }
71
72        return new FullArrayEntitySchemaData( $data );
73    }
74
75    public function getPersistenceSchemaData( string $schemaJSON ): PersistenceEntitySchemaData {
76        $schema = json_decode( $schemaJSON, true );
77        $persistenceSchemaData = new PersistenceEntitySchemaData();
78        $persistenceSchemaData->schemaText = $this->getSchemaTextFromSchema( $schema );
79
80        foreach ( $this->getSchemaLanguages( $schema ) as $languageCode ) {
81            $label = $this->getLabelFromSchema( $schema, $languageCode );
82            if ( $label ) {
83                $persistenceSchemaData->labels[$languageCode] = $label;
84            }
85            $description = $this->getDescriptionFromSchema( $schema, $languageCode );
86            if ( $description ) {
87                $persistenceSchemaData->descriptions[$languageCode] = $description;
88            }
89            $aliases = $this->getAliasGroupFromSchema( $schema, $languageCode );
90            if ( $aliases ) {
91                $persistenceSchemaData->aliases[$languageCode] = $aliases;
92            }
93        }
94
95        return $persistenceSchemaData;
96    }
97
98    public function getSchemaID( string $schemaJSON ): ?string {
99        return $this->getIdFromSchema( json_decode( $schemaJSON, true ) );
100    }
101
102    private function getIdFromSchema( array $schema ): ?string {
103        if ( !isset( $schema['serializationVersion'] ) ) {
104            return null;
105        }
106
107        switch ( $schema['serializationVersion'] ) {
108            case '1.0':
109            case '2.0':
110            case '3.0':
111                return $schema['id'] ?? null;
112            default:
113                throw new DomainException(
114                    'Unknown schema serialization version ' . $schema['serializationVersion']
115                );
116        }
117    }
118
119    public function getSchemaText( string $schemaJSON ): string {
120        $schema = json_decode( $schemaJSON, true );
121        return $this->getSchemaTextFromSchema( $schema );
122    }
123
124    private function getSchemaTextFromSchema( array $schema ): string {
125        if ( !isset( $schema['serializationVersion'] ) ) {
126            return '';
127        }
128
129        switch ( $schema['serializationVersion'] ) {
130            case '1.0':
131            case '2.0':
132                return $schema['schema'] ?? '';
133            case '3.0':
134                return $schema['schemaText'] ?? '';
135            default:
136                throw new DomainException(
137                    'Unknown schema serialization version ' . $schema['serializationVersion']
138                );
139        }
140    }
141
142    public function getSearchEntitySchemaAdapter( string $schemaJSON ): SearchEntitySchemaAdapter {
143        $viewData = $this->getFullViewSchemaData( $schemaJSON );
144        $labels = new TermList();
145        $descriptions = new TermList();
146        $aliases = new AliasGroupList();
147        foreach ( $viewData->nameBadges as $lang => $nameBadge ) {
148            if ( $nameBadge->label !== '' ) {
149                $labels->setTextForLanguage( $lang, $nameBadge->label );
150            }
151            if ( $nameBadge->description !== '' ) {
152                $descriptions->setTextForLanguage( $lang, $nameBadge->description );
153            }
154            $aliases->setAliasesForLanguage( $lang, $nameBadge->aliases );
155        }
156        return new SearchEntitySchemaAdapter( $labels, $descriptions, $aliases );
157    }
158
159    /**
160     * Returns an array of NameBadges containing label, description and alias
161     * data for the schema in each language for which data is available.
162     *
163     * @param array $schema
164     *
165     * @return NameBadge[]
166     *
167     * @throws DomainException
168     */
169    private function getNameBadgesFromSchema( array $schema ): array {
170        $langs = $this->getSchemaLanguages( $schema );
171        $nameBadges = [];
172        foreach ( $langs as $langCode ) {
173            $nameBadges[$langCode] = new NameBadge(
174                $this->getLabelFromSchema( $schema, $langCode ),
175                $this->getDescriptionFromSchema( $schema, $langCode ),
176                $this->getAliasGroupFromSchema( $schema, $langCode )
177            );
178        }
179        return $nameBadges;
180    }
181
182    /**
183     * Return an array of language codes for all languages that are present
184     * in the schema
185     *
186     * @param array $schema
187     *
188     * @return string[]
189     */
190    private function getSchemaLanguages( array $schema ): array {
191        $langs = [];
192        if ( !empty( $schema['labels'] ) ) {
193            $langs = array_merge(
194                $langs,
195                array_keys( $schema['labels'] )
196            );
197        }
198        if ( !empty( $schema['descriptions'] ) ) {
199            $langs = array_merge(
200                $langs,
201                array_keys( $schema['descriptions'] )
202            );
203        }
204        if ( !empty( $schema['aliases'] ) ) {
205            $langs = array_merge(
206                $langs,
207                array_keys( $schema['aliases'] )
208            );
209        }
210        return array_unique( $langs );
211    }
212
213    /**
214     * @param array $schema
215     * @param string $langCode
216     *
217     * @return string
218     *
219     * @throws DomainException
220     */
221    private function getLabelFromSchema( array $schema, $langCode ): string {
222        if ( empty( $schema['labels'] ) ) {
223            return '';
224        }
225
226        if ( !isset( $schema['serializationVersion'] ) ) {
227            return '';
228        }
229
230        switch ( $schema['serializationVersion'] ) {
231            case '1.0':
232                if ( isset( $schema['labels'][$langCode] ) ) {
233                    return $schema['labels'][$langCode]['value'];
234                }
235                return '';
236            case '2.0':
237            case '3.0':
238                return $schema['labels'][$langCode] ?? '';
239            default:
240                throw new DomainException(
241                    'Unknown schema serialization version ' . $schema['serializationVersion']
242                );
243        }
244    }
245
246    /**
247     * @param array $schema
248     * @param string $langCode
249     *
250     * @return string
251     *
252     * @throws DomainException
253     */
254    private function getDescriptionFromSchema( array $schema, $langCode ): string {
255        if ( empty( $schema['descriptions'] ) ) {
256            return '';
257        }
258
259        if ( !isset( $schema['serializationVersion'] ) ) {
260            return '';
261        }
262
263        switch ( $schema['serializationVersion'] ) {
264            case '1.0':
265                if ( isset( $schema['descriptions'][$langCode] ) ) {
266                    return $schema['descriptions'][$langCode]['value'];
267                }
268                return '';
269            case '2.0':
270            case '3.0':
271                return $schema['descriptions'][$langCode] ?? '';
272            default:
273                throw new DomainException(
274                    'Unknown schema serialization version ' . $schema['serializationVersion']
275                );
276        }
277    }
278
279    /**
280     * @param array $schema
281     * @param string $langCode
282     *
283     * @return array
284     *
285     * @throws DomainException
286     */
287    private function getAliasGroupFromSchema( array $schema, $langCode ): array {
288        if ( empty( $schema['aliases'] ) ) {
289            return [];
290        }
291
292        if ( !isset( $schema['serializationVersion'] ) ) {
293            return [];
294        }
295
296        switch ( $schema['serializationVersion'] ) {
297            case '1.0':
298                if ( isset( $schema['aliases'][$langCode] ) ) {
299                    return array_column( $schema['aliases'][$langCode], 'value' );
300                }
301                return [];
302            case '2.0':
303            case '3.0':
304                return $schema['aliases'][$langCode] ?? [];
305            default:
306                throw new DomainException(
307                    'Unknown schema serialization version ' . $schema['serializationVersion']
308                );
309        }
310    }
311
312}