Completed
Push — master ( 8a9c18...741c63 )
by mw
04:13 queued 15s
created

pushPageLanguageToCache()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 5
cts 5
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 2
crap 1
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 12
	public function getPageLanguageFromCache( Title $title ) {
77 12
		return $this->fetch( $title );
78
	}
79
80
	/**
81
	 * @since 1.0
82
	 *
83
	 * @param Title $title
84
	 * @param string $languageCode
85
	 */
86 10
	public function pushPageLanguageToCache( Title $title, $languageCode ) {
87
88
		$normalizedLanguageTargetLink = array(
89 10
			$languageCode => $title->getPrefixedText()
90 10
		);
91
92 10
		$this->save( $normalizedLanguageTargetLink );
93 10
	}
94
95
	/**
96
	 * @since 1.0
97
	 *
98
	 * @param InterlanguageLink $interlanguageLink
99
	 *
100
	 * @return boolean|array
101
	 */
102 20
	public function getLanguageTargetLinksFromCache( InterlanguageLink $interlanguageLink ) {
103
104
		// Call to a member function getPrefixedText() on null in ...SemanticInterlanguageLinks/src/LanguageTargetLinksCache.php on line 105
105 20
		if ( $interlanguageLink->getLinkReference() === null ) {
106 1
			return false;
107
		}
108
109 19
		$cachedLanguageTargetLinks = $this->cache->fetch(
110 19
			$this->cacheKeyProvider->getSiteCacheKey( $interlanguageLink->getLinkReference()->getPrefixedText() )
111 19
		);
112
113 19
		if ( $interlanguageLink->getLanguageCode() === null ) {
114 3
			return $cachedLanguageTargetLinks;
115
		}
116
117 17
		if ( !isset( $cachedLanguageTargetLinks[ $interlanguageLink->getLanguageCode() ] ) ) {
118 13
			return false;
119
		}
120
121 6
		return $cachedLanguageTargetLinks;
122
	}
123
124
	/**
125
	 * @since 1.0
126
	 *
127
	 * @param InterlanguageLink $interlanguageLink
128
	 * @param array $languageTargetLinks
129
	 */
130 21
	public function saveLanguageTargetLinksToCache( InterlanguageLink $interlanguageLink, array $languageTargetLinks ) {
131
132 21
		$normalizedLanguageTargetLinks = array();
133
134 21
		foreach ( $languageTargetLinks as $languageCode => $title ) {
135
136 19
			if ( $title instanceof Title ) {
137 15
				$title = $title->getPrefixedText();
138 15
			}
139
140 19
			$normalizedLanguageTargetLinks[ $languageCode ] = $title;
141 21
		}
142
143 21
		if ( $normalizedLanguageTargetLinks === array() ) {
144 2
			return;
145
		}
146
147 19
		$this->cache->save(
148 19
			$this->cacheKeyProvider->getSiteCacheKey( $interlanguageLink->getLinkReference()->getPrefixedText() ),
149
			$normalizedLanguageTargetLinks
150 19
		);
151
152 19
		$this->save( $normalizedLanguageTargetLinks );
153 19
	}
154
155
	/**
156
	 * @since 1.0
157
	 *
158
	 * @param DIWikiPage[] $linkReferences
159
	 */
160 14
	public function deleteLanguageTargetLinksFromCache( array $linkReferences ) {
161
162 14
		foreach ( $linkReferences as $linkReference ) {
163
164 11
			if ( !$linkReference instanceof DIWikiPage ) {
165 2
				continue;
166
			}
167
168 11
			$siteCacheKey = $this->cacheKeyProvider->getSiteCacheKey(
169 11
				$linkReference->getTitle()->getPrefixedText()
170 11
			);
171
172 11
			$cachedLanguageTargetLinks = $this->cache->fetch( $siteCacheKey );
173
174 11
			if ( !is_array( $cachedLanguageTargetLinks ) ) {
175 8
				continue;
176
			}
177
178 9
			foreach ( $cachedLanguageTargetLinks as $cachedLanguageTargetLink ) {
179 9
				Title::newFromText( $cachedLanguageTargetLink )->invalidateCache();
180 9
			}
181
182 9
			$this->cache->delete( $siteCacheKey );
183 14
		}
184
185 14
		return true;
186
	}
187
188
	/**
189
	 * @since 1.0
190
	 *
191
	 * @param Title $title
192
	 */
193 12
	public function deletePageLanguageForTargetFromCache( Title $title ) {
194 12
		$this->delete( $title );
195 12
	}
196
197 12
	private function fetch( Title $title ) {
198
199 12
		$pageCacheKey = $this->cacheKeyProvider->getPageCacheKey(
200 12
			$title->getPrefixedText(),
201 12
			$this->pageLanguageCacheStrategy === 'blob'
202 12
		);
203
204 12
		if ( $this->pageLanguageCacheStrategy !== 'blob' ) {
205 10
			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 22
	private function save( array $normalizedLanguageTargetLinks ) {
214
215 22
		if ( $this->pageLanguageCacheStrategy !== 'blob' ) {
216
217 15
			foreach ( $normalizedLanguageTargetLinks as $languageCode => $target ) {
218 15
				$this->cache->save(
219 15
					$this->cacheKeyProvider->getPageCacheKey( $target, false ),
220
					$languageCode
221 15
				);
222 15
			}
223
224 15
			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 7
		}
232
233 7
		$this->cache->save(
234 7
			$this->cacheKeyProvider->getPageLanguageCacheBlobKey(),
235
			$pageLanguageCacheBlob
236 7
		);
237 7
	}
238
239 12
	private function delete( Title $title ) {
240
241 12
		if ( $this->pageLanguageCacheStrategy !== 'blob' ) {
242 10
			return $this->cache->delete(
243 10
				$this->cacheKeyProvider->getPageCacheKey( $title->getPrefixedText(), false )
244 10
			);
245
		}
246
247 2
		$pageLanguageCacheBlob = $this->getPageLanguageCacheBlob();
248 2
		unset( $pageLanguageCacheBlob[ $this->cacheKeyProvider->getPageCacheKey( $title->getPrefixedText(), true ) ] );
249
250 2
		$this->cache->save(
251 2
			$this->cacheKeyProvider->getPageLanguageCacheBlobKey(),
252
			$pageLanguageCacheBlob
253 2
		);
254 2
	}
255
256 7
	private function getPageLanguageCacheBlob() {
257
258 7
		$pageLanguageCacheBlob = $this->cache->fetch(
259 7
			$this->cacheKeyProvider->getPageLanguageCacheBlobKey()
260 7
		);
261
262 7
		if ( $pageLanguageCacheBlob === false ) {
263 6
			$pageLanguageCacheBlob = array();
264 6
		}
265
266 7
		return $pageLanguageCacheBlob;
267
	}
268
269
}
270