Completed
Push — master ( 204f66...0e54bc )
by mw
8s
created

src/InterlanguageLinksLookup.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

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
It seems like $linkReferenceDataValue->getProperty() can be null; however, __construct() does not accept null, maybe add an additional type check?

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:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
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