Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
92.16% covered (success)
92.16%
47 / 51
50.00% covered (danger)
50.00%
3 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
MediaInfoPrefetchingTermLookup
92.16% covered (success)
92.16%
47 / 51
50.00% covered (danger)
50.00%
3 / 6
30.43
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 prefetchTerm
91.67% covered (success)
91.67%
22 / 24
0.00% covered (danger)
0.00%
0 / 1
10.06
 prefetchTerms
87.50% covered (warning)
87.50%
7 / 8
0.00% covered (danger)
0.00%
0 / 1
7.10
 getPrefetchedTerm
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
4
 getTermsOfType
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
7
 getPrefetchedAliases
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace Wikibase\MediaInfo\Services;
4
5use Wikibase\DataAccess\PrefetchingTermLookup;
6use Wikibase\DataModel\Entity\EntityId;
7use Wikibase\DataModel\Services\Lookup\TermLookupException;
8use Wikibase\DataModel\Term\TermList;
9use Wikibase\Lib\Store\EntityRevisionLookup;
10use Wikibase\Lib\Store\EntityTermLookupBase;
11use Wikibase\MediaInfo\DataModel\MediaInfo;
12
13/**
14 * Alternative term lookup for MediaInfo items, who do not require
15 * a term index to look up the data.
16 */
17class MediaInfoPrefetchingTermLookup extends EntityTermLookupBase implements PrefetchingTermLookup {
18
19    /**
20     * @var EntityRevisionLookup
21     */
22    private $entityRevisionLookup;
23
24    /**
25     * @var array
26     */
27    private $supportedTermTypes = [ 'label', 'description' ];
28
29    /**
30     * @var array
31     */
32    private $terms = [];
33
34    /**
35     * @param EntityRevisionLookup $entityRevisionLookup
36     */
37    public function __construct( EntityRevisionLookup $entityRevisionLookup ) {
38        $this->entityRevisionLookup = $entityRevisionLookup;
39    }
40
41    /**
42     * Fetch the terms for a specific entity.
43     *
44     * @param EntityId $entityId
45     * @param string[]|null $termTypes The types of terms to return: "label" or  "description".
46     *        If null, all types are prefetched.
47     * @param string[]|null $languageCodes The desired languages, given as language codes.
48     *        If null, all languages are prefetched.
49     */
50    private function prefetchTerm( EntityId $entityId, ?array $termTypes = null, ?array $languageCodes = null ) {
51        $termTypes = $termTypes ?: $this->supportedTermTypes;
52
53        // init term cache, indicating these entity/term combinations were
54        // requested (but might not have been found)
55        $this->terms[$entityId->getSerialization()] = [];
56        foreach ( $termTypes as $termType ) {
57            $this->terms[$entityId->getSerialization()][$termType] = [];
58        }
59
60        $revision = $this->entityRevisionLookup->getEntityRevision( $entityId );
61        if ( $revision === null ) {
62            // entity does not exist - make term cache unusable
63            $this->terms[$entityId->getSerialization()] = false;
64            return;
65        }
66        $entity = $revision->getEntity();
67        if ( !$entity instanceof MediaInfo ) {
68            $class = get_class( $entity );
69            throw new TermLookupException( $entityId, $languageCodes, "Entity of class $class is not supported" );
70        }
71
72        foreach ( $termTypes as $termType ) {
73            switch ( $termType ) {
74                case 'label':
75                    $termList = $entity->getLabels();
76                    break;
77                case 'description':
78                    $termList = $entity->getDescriptions();
79                    break;
80                default:
81                    // term type not supported, there is no data here
82                    $termList = new TermList( [] );
83                    break;
84            }
85
86            $terms = $termList->toTextArray();
87            foreach ( $terms as $languageCode => $text ) {
88                $this->terms[$entityId->getSerialization()][$termType][$languageCode] = $text;
89            }
90        }
91    }
92
93    /**
94     * @inheritDoc
95     */
96    public function prefetchTerms( array $entityIds, array $termTypes, array $languageCodes ) {
97        foreach ( $entityIds as $entityId ) {
98            $serialization = $entityId->getSerialization();
99            if ( isset( $this->terms[$serialization] ) && $this->terms[$serialization] === false ) {
100                // entity is already known not to exist
101                continue;
102            }
103            // omit term types that we've already fetched before
104            // there's no need to omit (or even check for) existing language codes -
105            // they don't matter: if we have the term type, we have it in all languages
106            $existingTermTypes = array_keys( $this->terms[$serialization] ?? [] );
107            $diffTermTypes = array_diff( $termTypes ?: $this->supportedTermTypes, $existingTermTypes );
108            // if there were no $termTypes to begin with, call prefetchTerm anyway
109            // (might be intentional for the side-effect of checking entity existence)
110            if ( $diffTermTypes || $termTypes === [] ) {
111                $this->prefetchTerm( $entityId, $termTypes, $languageCodes );
112            }
113        }
114    }
115
116    /**
117     * @inheritDoc
118     */
119    public function getPrefetchedTerm( EntityId $entityId, $termType, $languageCode ) {
120        $serialization = $entityId->getSerialization();
121        if ( isset( $this->terms[$serialization] ) && $this->terms[$serialization] === false ) {
122            // entity does not exist
123            return false;
124        }
125
126        if ( !isset( $this->terms[$serialization][$termType] ) ) {
127            // term not yet fetched
128            return null;
129        }
130
131        return $this->terms[$serialization][$termType][$languageCode] ?? false;
132    }
133
134    /**
135     * @inheritDoc
136     */
137    protected function getTermsOfType( EntityId $entityId, $termType, array $languageCodes ) {
138        if ( !isset( $this->terms[$entityId->getSerialization()] ) ) {
139            // not yet prefetched
140            $this->prefetchTerms( [ $entityId ], [ $termType ], $languageCodes );
141        }
142
143        $serialization = $entityId->getSerialization();
144        if ( isset( $this->terms[$serialization] ) && $this->terms[$serialization] === false ) {
145            throw new TermLookupException( $entityId, $languageCodes, 'The entity could not be loaded' );
146        }
147
148        $terms = [];
149        foreach ( $languageCodes as $languageCode ) {
150            $text = $this->getPrefetchedTerm( $entityId, $termType, $languageCode );
151
152            if ( $text !== null && $text !== false ) {
153                $terms[$languageCode] = $text;
154            }
155        }
156        return $terms;
157    }
158
159    public function getPrefetchedAliases( EntityId $entityId, $languageCode ) {
160        return [];
161    }
162}