These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace SIL; |
||
4 | |||
5 | use SMW\Query\Language\Conjunction; |
||
6 | use SMW\Query\Language\SomeProperty; |
||
7 | use SMW\Query\Language\ValueDescription; |
||
8 | |||
9 | use SMW\Store; |
||
10 | use SMW\DIWikiPage; |
||
11 | use SMW\DIProperty; |
||
12 | |||
13 | use SMWPrintRequest as PrintRequest; |
||
14 | use SMWPropertyValue as PropertyValue; |
||
15 | use SMWQuery as Query; |
||
16 | use SMWDIBlob as DIBlob; |
||
17 | |||
18 | use Title; |
||
19 | |||
20 | /** |
||
21 | * This class is the most critical component of SIL as it combines the store |
||
22 | * interface with the cache interface. |
||
23 | * |
||
24 | * Any request either for a target link or language code lookup are channelled |
||
25 | * through this class in order to make a decision whether to use an existing |
||
26 | * cache entry or to make a "fresh" query request to the storage back-end. |
||
27 | * |
||
28 | * No other component of SIL should communicate to the store directly and let |
||
29 | * the lookup class to handle those requests. |
||
30 | * |
||
31 | * @license GNU GPL v2+ |
||
32 | * @since 1.0 |
||
33 | * |
||
34 | * @author mwjames |
||
35 | */ |
||
36 | class InterlanguageLinksLookup { |
||
37 | |||
38 | const NO_LANG = ''; |
||
39 | |||
40 | /** |
||
41 | * @var LanguageTargetLinksCache |
||
42 | */ |
||
43 | private $languageTargetLinksCache; |
||
44 | |||
45 | /** |
||
46 | * @var Store |
||
47 | */ |
||
48 | private $store; |
||
49 | |||
50 | /** |
||
51 | * @since 1.0 |
||
52 | * |
||
53 | * @param LanguageTargetLinksCache $languageTargetLinksCache |
||
54 | */ |
||
55 | 16 | public function __construct( LanguageTargetLinksCache $languageTargetLinksCache ) { |
|
56 | 16 | $this->languageTargetLinksCache = $languageTargetLinksCache; |
|
57 | 16 | } |
|
58 | |||
59 | /** |
||
60 | * @since 1.0 |
||
61 | * |
||
62 | * @param Store $store |
||
63 | */ |
||
64 | 21 | public function setStore( Store $store ) { |
|
65 | 21 | $this->store = $store; |
|
66 | 21 | } |
|
67 | |||
68 | |||
69 | /** |
||
70 | * @since 1.2 |
||
71 | * |
||
72 | * @param Title $title |
||
73 | * |
||
74 | * @return Title |
||
75 | */ |
||
76 | 8 | public function getRedirectTargetFor( Title $title ) { |
|
77 | 8 | return $this->store->getRedirectTarget( DIWikiPage::newFromTitle( $title ) )->getTitle(); |
|
78 | } |
||
79 | |||
80 | /** |
||
81 | * @since 1.0 |
||
82 | * |
||
83 | * @param Title $title |
||
84 | */ |
||
85 | 9 | public function invalidateLookupCache( Title $title ) { |
|
86 | |||
87 | 9 | $this->languageTargetLinksCache->deleteLanguageTargetLinksFromCache( |
|
88 | 9 | $this->findFullListOfReferenceTargetLinks( $title ) |
|
89 | 9 | ); |
|
90 | |||
91 | 9 | $this->languageTargetLinksCache->deletePageLanguageForTargetFromCache( |
|
92 | $title |
||
93 | 9 | ); |
|
94 | 9 | } |
|
95 | |||
96 | /** |
||
97 | * @since 1.0 |
||
98 | * |
||
99 | * @param Title|null $title |
||
100 | * @param string $languageCode |
||
101 | */ |
||
102 | 12 | public function updatePageLanguageToLookupCache( Title $title = null, $languageCode ) { |
|
103 | |||
104 | 12 | if ( $title !== null && $this->languageTargetLinksCache->getPageLanguageFromCache( $title ) === $languageCode ) { |
|
105 | 7 | return; |
|
106 | } |
||
107 | |||
108 | 12 | $this->languageTargetLinksCache->updatePageLanguageToCache( |
|
109 | 12 | $title, |
|
110 | $languageCode |
||
111 | 12 | ); |
|
112 | 12 | } |
|
113 | |||
114 | /** |
||
115 | * @since 1.0 |
||
116 | * |
||
117 | * @param InterlanguageLink $interlanguageLink |
||
118 | * @param Title|null $target |
||
119 | * |
||
120 | * @return array |
||
121 | */ |
||
122 | 11 | public function queryLanguageTargetLinks( InterlanguageLink $interlanguageLink, Title $target = null ) { |
|
123 | |||
124 | 11 | $languageTargetLinks = $this->languageTargetLinksCache->getLanguageTargetLinksFromCache( |
|
125 | $interlanguageLink |
||
126 | 11 | ); |
|
127 | |||
128 | 11 | if ( is_array( $languageTargetLinks ) && $languageTargetLinks !== array() ) { |
|
129 | 3 | return $languageTargetLinks; |
|
130 | } |
||
131 | |||
132 | 10 | $languageTargetLinks = array(); |
|
133 | |||
134 | 10 | if ( $target !== null && $interlanguageLink->getLanguageCode() !== '' ) { |
|
135 | 8 | $languageTargetLinks[ $interlanguageLink->getLanguageCode() ] = $target; |
|
136 | 8 | } |
|
137 | |||
138 | 10 | $queryResult = $this->getQueryResultForInterlanguageLink( $interlanguageLink ); |
|
139 | |||
140 | 10 | $this->iterateQueryResultToFindLanguageTargetLinks( |
|
141 | 10 | $queryResult, |
|
142 | $languageTargetLinks |
||
143 | 10 | ); |
|
144 | |||
145 | 10 | $this->languageTargetLinksCache->saveLanguageTargetLinksToCache( |
|
146 | 10 | $interlanguageLink, |
|
147 | $languageTargetLinks |
||
148 | 10 | ); |
|
149 | |||
150 | 10 | return $languageTargetLinks; |
|
151 | } |
||
152 | |||
153 | /** |
||
154 | * @since 1.0 |
||
155 | * |
||
156 | * @param Title $title |
||
157 | * |
||
158 | * @return string |
||
159 | */ |
||
160 | 14 | public function findPageLanguageForTarget( Title $title ) { |
|
161 | |||
162 | // @note $title->getPageLanguage()->getLanguageCode() cannot be called |
||
163 | // here as this would cause a recursive chain |
||
164 | |||
165 | 14 | $lookupLanguageCode = $this->languageTargetLinksCache->getPageLanguageFromCache( $title ); |
|
166 | |||
167 | 14 | if ( $lookupLanguageCode !== null && $lookupLanguageCode !== false ) { |
|
168 | 3 | return $lookupLanguageCode; |
|
169 | } |
||
170 | |||
171 | 12 | $lookupLanguageCode = $this->lookupLastPageLanguageForTarget( $title ); |
|
172 | |||
173 | 12 | $this->updatePageLanguageToLookupCache( |
|
174 | 12 | $title, |
|
175 | $lookupLanguageCode |
||
176 | 12 | ); |
|
177 | |||
178 | 12 | return $lookupLanguageCode; |
|
179 | } |
||
180 | |||
181 | /** |
||
182 | * @since 1.1 |
||
183 | * |
||
184 | * @param Title $title |
||
185 | * |
||
186 | * @return boolean |
||
187 | */ |
||
188 | 2 | public function hasSilAnnotationFor( Title $title ) { |
|
189 | |||
190 | 2 | $propertyValues = $this->store->getPropertyValues( |
|
191 | 2 | DIWikiPage::newFromTitle( $title ), |
|
192 | 2 | new DIProperty( PropertyRegistry::SIL_CONTAINER ) |
|
193 | 2 | ); |
|
194 | |||
195 | 2 | return $propertyValues !== array(); |
|
196 | } |
||
197 | |||
198 | /** |
||
199 | * @since 1.0 |
||
200 | * |
||
201 | * @param Title $title |
||
202 | * |
||
203 | * @return DIWikiPage[]|[] |
||
204 | */ |
||
205 | 12 | public function findFullListOfReferenceTargetLinks( Title $title ) { |
|
206 | |||
207 | 12 | $linkReferences = array(); |
|
208 | |||
209 | try{ |
||
210 | 12 | $property = new DIProperty( PropertyRegistry::SIL_CONTAINER ); |
|
211 | 12 | } catch ( \Exception $e ) { |
|
212 | return $linkReferences; |
||
213 | } |
||
214 | |||
215 | 12 | $propertyValues = $this->store->getPropertyValues( |
|
216 | 12 | DIWikiPage::newFromTitle( $title ), |
|
217 | $property |
||
218 | 12 | ); |
|
219 | |||
220 | 12 | if ( !is_array( $propertyValues ) || $propertyValues === array() ) { |
|
221 | 11 | return $linkReferences; |
|
222 | } |
||
223 | |||
224 | 9 | foreach ( $propertyValues as $containerSubject ) { |
|
225 | |||
226 | 9 | $values = $this->store->getPropertyValues( |
|
227 | 9 | $containerSubject, |
|
228 | 9 | new DIProperty( PropertyRegistry::SIL_ILL_REF ) |
|
229 | 9 | ); |
|
230 | |||
231 | 9 | $linkReferences = array_merge( $linkReferences, $values ); |
|
232 | 9 | } |
|
233 | |||
234 | 9 | return $linkReferences; |
|
235 | } |
||
236 | |||
237 | /** |
||
238 | * @return QueryResult |
||
239 | */ |
||
240 | 10 | private function getQueryResultForInterlanguageLink( InterlanguageLink $interlanguageLink ) { |
|
241 | |||
242 | 10 | $description = new Conjunction(); |
|
243 | |||
244 | 10 | $languageDataValue = $interlanguageLink->newLanguageDataValue(); |
|
245 | |||
246 | 10 | $linkReferenceDataValue = $interlanguageLink->newLinkReferenceDataValue(); |
|
247 | |||
248 | 10 | $description->addDescription( |
|
249 | 10 | new SomeProperty( |
|
250 | 10 | $linkReferenceDataValue->getProperty(), |
|
0 ignored issues
–
show
|
|||
251 | 10 | new ValueDescription( $linkReferenceDataValue->getDataItem(), null, SMW_CMP_EQ ) |
|
252 | 10 | ) |
|
253 | 10 | ); |
|
254 | |||
255 | 10 | $propertyValue = new PropertyValue( '__pro' ); |
|
256 | 10 | $propertyValue->setDataItem( $languageDataValue->getProperty() ); |
|
257 | |||
258 | 10 | $description->addPrintRequest( |
|
259 | 10 | new PrintRequest( PrintRequest::PRINT_PROP, null, $propertyValue ) |
|
260 | 10 | ); |
|
261 | |||
262 | 10 | $query = new Query( |
|
263 | 10 | $description, |
|
264 | 10 | false, |
|
265 | false |
||
266 | 10 | ); |
|
267 | |||
268 | // $query->sort = true; |
||
269 | // $query->sortkey = array( $languageDataValue->getProperty()->getLabel() => 'asc' ); |
||
270 | |||
271 | // set query limit to certain threshold |
||
272 | |||
273 | 10 | return $this->store->getQueryResult( $query ); |
|
274 | } |
||
275 | |||
276 | 10 | private function iterateQueryResultToFindLanguageTargetLinks( $queryResult, array &$languageTargetLinks ) { |
|
277 | |||
278 | 10 | while ( $resultArray = $queryResult->getNext() ) { |
|
279 | 7 | foreach ( $resultArray as $row ) { |
|
280 | |||
281 | 7 | $dataValue = $row->getNextDataValue(); |
|
282 | |||
283 | 7 | if ( $dataValue === false ) { |
|
284 | 1 | continue; |
|
285 | } |
||
286 | |||
287 | 7 | $languageTargetLinks[ $dataValue->getWikiValue() ] = $row->getResultSubject()->getTitle(); |
|
288 | 7 | } |
|
289 | 7 | } |
|
290 | 10 | } |
|
291 | |||
292 | 12 | private function lookupLastPageLanguageForTarget( Title $title ) { |
|
293 | |||
294 | try{ |
||
295 | 12 | $property = new DIProperty( PropertyRegistry::SIL_CONTAINER ); |
|
296 | 12 | } catch ( \Exception $e ) { |
|
297 | return self::NO_LANG; |
||
298 | } |
||
299 | |||
300 | 12 | $propertyValues = $this->store->getPropertyValues( |
|
301 | 12 | DIWikiPage::newFromTitle( $title ), |
|
302 | $property |
||
303 | 12 | ); |
|
304 | |||
305 | 12 | if ( !is_array( $propertyValues ) || $propertyValues === array() ) { |
|
306 | 10 | return self::NO_LANG; |
|
307 | } |
||
308 | |||
309 | 3 | $containerSubject = end( $propertyValues ); |
|
310 | |||
311 | 3 | $propertyValues = $this->store->getPropertyValues( |
|
312 | 3 | $containerSubject, |
|
313 | 3 | new DIProperty( PropertyRegistry::SIL_ILL_LANG ) |
|
314 | 3 | ); |
|
315 | |||
316 | 3 | $languageCodeValue = end( $propertyValues ); |
|
317 | |||
318 | 3 | if ( $languageCodeValue instanceOf DIBlob ) { |
|
319 | 2 | return $languageCodeValue->getString(); |
|
320 | } |
||
321 | |||
322 | 1 | return self::NO_LANG; |
|
323 | } |
||
324 | |||
325 | } |
||
326 |
Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code: