saveLanguageTargetLinksToCache()   A
last analyzed

Complexity

Conditions 4
Paths 6

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 24
ccs 12
cts 12
cp 1
rs 9.536
c 0
b 0
f 0
cc 4
nc 6
nop 2
crap 4
1
<?php
2
3
namespace SIL;
4
5
use Onoi\Cache\Cache;
6
use SMW\DIWikiPage;
7
use Title;
8
9
/**
10
 * To make a page view responsive and avoid a repetitive or exhausting query
11
 * process, this class is expected to cache all objects necessary and be
12
 * accessible through the `InterlanguageLinksLookup` class.
13
 *
14
 * It is expected that the cache uses a "Composite" approach in order for short-lived
15
 * requests to be stored in-memory while other information are stored on a
16
 * persistence layer to increase lookup performance for succeeding requests.
17
 *
18
 * @license GNU GPL v2+
19
 * @since 1.0
20
 *
21
 * @author mwjames
22
 */
23
class LanguageTargetLinksCache {
24
25
	/**
26
	 * @var Cache
27
	 */
28
	private $cache;
29
30
	/**
31
	 * @var CacheKeyProvider
32
	 */
33
	private $cacheKeyProvider;
34
35
	/**
36
	 * The current page language cache strategy is to store language by page
37
	 * into a blob value to avoid high cache fragmentation and keep the cache
38
	 * lookup performant on generated category/search lists.
39
	 *
40
	 * Whether the blob language-page strategy has a considerable performance draw
41
	 * back on large lists of stored language-page pairs has yet to be determined
42
	 * but it will be fairly easy to switch to a single language-page strategy
43
	 * if necessary.
44
	 *
45
	 * @var string
46
	 */
47
	private $pageLanguageCacheStrategy = 'single';
48
49
	/**
50
	 * @since 1.0
51
	 *
52
	 * @param Cache $cache
53
	 * @param CacheKeyProvider $cacheKeyProvider
54
	 */
55 18
	public function __construct( Cache $cache, CacheKeyProvider $cacheKeyProvider ) {
56 18
		$this->cache = $cache;
57 18
		$this->cacheKeyProvider = $cacheKeyProvider;
58 18
	}
59
60
	/**
61
	 * @since 1.0
62
	 *
63
	 * @param string $pageLanguageCacheStrategy
64
	 */
65 16
	public function setPageLanguageCacheStrategy( $pageLanguageCacheStrategy ) {
66 16
		$this->pageLanguageCacheStrategy = $pageLanguageCacheStrategy;
67 16
	}
68
69
	/**
70
	 * @since 1.0
71
	 *
72
	 * @param Title $title
73
	 *
74
	 * @param boolean|string
75
	 */
76 6
	public function getPageLanguageFromCache( Title $title ) {
77 6
		return $this->fetch( $title );
78
	}
79
80
	/**
81
	 * @since 1.0
82
	 *
83
	 * @param Title $title
84
	 * @param string $languageCode
85
	 */
86 4
	public function pushPageLanguageToCache( Title $title, $languageCode ) {
87
88
		$normalizedLanguageTargetLink = [
89 4
			$languageCode => $title->getPrefixedText()
90
		];
91
92 4
		$this->save( $normalizedLanguageTargetLink );
93 4
	}
94
95
	/**
96
	 * @since 1.0
97
	 *
98
	 * @param InterlanguageLink $interlanguageLink
99
	 *
100
	 * @return boolean|array
101
	 */
102 15
	public function getLanguageTargetLinksFromCache( InterlanguageLink $interlanguageLink ) {
103
104
		// Call to a member function getPrefixedText() on null in ...SemanticInterlanguageLinks/src/LanguageTargetLinksCache.php on line 105
105 15
		if ( $interlanguageLink->getLinkReference() === null ) {
106 1
			return false;
107
		}
108
109 14
		$cachedLanguageTargetLinks = $this->cache->fetch(
110 14
			$this->cacheKeyProvider->getSiteCacheKey( $interlanguageLink->getLinkReference()->getPrefixedText() )
111
		);
112
113 14
		if ( $interlanguageLink->getLanguageCode() === null ) {
114 2
			return $cachedLanguageTargetLinks;
115
		}
116
117 12
		if ( !isset( $cachedLanguageTargetLinks[ $interlanguageLink->getLanguageCode() ] ) ) {
118 8
			return false;
119
		}
120
121 4
		return $cachedLanguageTargetLinks;
122
	}
123
124
	/**
125
	 * @since 1.0
126
	 *
127
	 * @param InterlanguageLink $interlanguageLink
128
	 * @param array $languageTargetLinks
129
	 */
130 16
	public function saveLanguageTargetLinksToCache( InterlanguageLink $interlanguageLink, array $languageTargetLinks ) {
131
132 16
		$normalizedLanguageTargetLinks = [];
133
134 16
		foreach ( $languageTargetLinks as $languageCode => $title ) {
135
136 14
			if ( $title instanceof Title ) {
137 10
				$title = $title->getPrefixedText();
138
			}
139
140 14
			$normalizedLanguageTargetLinks[ $languageCode ] = $title;
141
		}
142
143 16
		if ( $normalizedLanguageTargetLinks === [] ) {
144 2
			return;
145
		}
146
147 14
		$this->cache->save(
148 14
			$this->cacheKeyProvider->getSiteCacheKey( $interlanguageLink->getLinkReference()->getPrefixedText() ),
149
			$normalizedLanguageTargetLinks
150
		);
151
152 14
		$this->save( $normalizedLanguageTargetLinks );
153 14
	}
154
155
	/**
156
	 * @since 1.0
157
	 *
158
	 * @param DIWikiPage[] $linkReferences
159
	 */
160 8
	public function deleteLanguageTargetLinksFromCache( array $linkReferences ) {
161
162 8
		foreach ( $linkReferences as $linkReference ) {
163
164 6
			if ( !$linkReference instanceof DIWikiPage ) {
165 2
				continue;
166
			}
167
168 6
			$siteCacheKey = $this->cacheKeyProvider->getSiteCacheKey(
169 6
				$linkReference->getTitle()->getPrefixedText()
170
			);
171
172 6
			$cachedLanguageTargetLinks = $this->cache->fetch( $siteCacheKey );
173
174 6
			if ( !is_array( $cachedLanguageTargetLinks ) ) {
175 4
				continue;
176
			}
177
178 4
			foreach ( $cachedLanguageTargetLinks as $cachedLanguageTargetLink ) {
179 4
				Title::newFromText( $cachedLanguageTargetLink )->invalidateCache();
180
			}
181
182 4
			$this->cache->delete( $siteCacheKey );
183
		}
184
185 8
		return true;
186
	}
187
188
	/**
189
	 * @since 1.0
190
	 *
191
	 * @param Title $title
192
	 */
193 6
	public function deletePageLanguageForTargetFromCache( Title $title ) {
194 6
		$this->delete( $title );
195 6
	}
196
197 6
	private function fetch( Title $title ) {
198
199 6
		$pageCacheKey = $this->cacheKeyProvider->getPageCacheKey(
200 6
			$title->getPrefixedText(),
201 6
			$this->pageLanguageCacheStrategy === 'blob'
202
		);
203
204 6
		if ( $this->pageLanguageCacheStrategy !== 'blob' ) {
205 4
			return $this->cache->fetch( $pageCacheKey );
206
		}
207
208 2
		$pageLanguageCacheBlob = $this->getPageLanguageCacheBlob();
209
210 2
		return isset( $pageLanguageCacheBlob[ $pageCacheKey ] ) ? $pageLanguageCacheBlob[ $pageCacheKey ] : false;
211
	}
212
213 16
	private function save( array $normalizedLanguageTargetLinks ) {
214
215 16
		if ( $this->pageLanguageCacheStrategy !== 'blob' ) {
216
217 9
			foreach ( $normalizedLanguageTargetLinks as $languageCode => $target ) {
218 9
				$this->cache->save(
219 9
					$this->cacheKeyProvider->getPageCacheKey( $target, false ),
220
					$languageCode
221
				);
222
			}
223
224 9
			return;
225
		}
226
227 7
		$pageLanguageCacheBlob = $this->getPageLanguageCacheBlob();
228
229 7
		foreach ( $normalizedLanguageTargetLinks as $languageCode => $target ) {
230 7
			$pageLanguageCacheBlob[ $this->cacheKeyProvider->getPageCacheKey( $target, true ) ] = $languageCode;
231
		}
232
233 7
		$this->cache->save(
234 7
			$this->cacheKeyProvider->getPageLanguageCacheBlobKey(),
235
			$pageLanguageCacheBlob
236
		);
237 7
	}
238
239 6
	private function delete( Title $title ) {
240
241 6
		$this->cache->delete(
242 6
			$this->cacheKeyProvider->getSiteCacheKey( $title->getPrefixedText() )
243
		);
244
245 6
		if ( $this->pageLanguageCacheStrategy !== 'blob' ) {
246 4
			return $this->cache->delete(
247 4
				$this->cacheKeyProvider->getPageCacheKey( $title->getPrefixedText(), false )
248
			);
249
		}
250
251 2
		$pageLanguageCacheBlob = $this->getPageLanguageCacheBlob();
252 2
		unset( $pageLanguageCacheBlob[ $this->cacheKeyProvider->getPageCacheKey( $title->getPrefixedText(), true ) ] );
253
254 2
		$this->cache->save(
255 2
			$this->cacheKeyProvider->getPageLanguageCacheBlobKey(),
256
			$pageLanguageCacheBlob
257
		);
258 2
	}
259
260 7
	private function getPageLanguageCacheBlob() {
261
262 7
		$pageLanguageCacheBlob = $this->cache->fetch(
263 7
			$this->cacheKeyProvider->getPageLanguageCacheBlobKey()
264
		);
265
266 7
		if ( $pageLanguageCacheBlob === false ) {
267 6
			$pageLanguageCacheBlob = [];
268
		}
269
270 7
		return $pageLanguageCacheBlob;
271
	}
272
273
}
274