Completed
Pull Request — master (#27)
by mw
05:03 queued 21s
created

CachedReferenceListOutputRenderer::getSubject()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 8
ccs 5
cts 5
cp 1
rs 9.4285
cc 2
eloc 4
nc 2
nop 0
crap 2
1
<?php
2
3
namespace SCI;
4
5
use Onoi\Cache\Cache;
6
use SMW\NamespaceExaminer;
7
use SMW\DIWikiPage;
8
9
/**
10
 * @license GNU GPL v2+
11
 * @since 1.0
12
 *
13
 * @author mwjames
14
 */
15
class CachedReferenceListOutputRenderer {
16
17
	/**
18
	 * @var ReferenceListOutputRenderer
19
	 */
20
	private $referenceListOutputRenderer;
21
22
	/**
23
	 * @var MediaWikiContextInteractor
24
	 */
25
	private $contextInteractor;
26
27
	/**
28
	 * @var NamespaceExaminer
29
	 */
30
	private $namespaceExaminer;
31
32
	/**
33
	 * @var Cache
34
	 */
35
	private $cache;
36
37
	/**
38
	 * @var CacheKeyProvider
39
	 */
40
	private $cacheKeyProvider;
41
42
	/**
43
	 * @var DIWikiPage
44
	 */
45
	private $subject;
46
47
	/**
48
	 * @var array
49
	 */
50
	private $defaultOptions = array();
51
52
	/**
53
	 * @since 1.0
54
	 *
55
	 * @param ReferenceListOutputRenderer $referenceListOutputRenderer
56
	 * @param MediaWikiContextInteractor $contextInteractor
57
	 * @param NamespaceExaminer $namespaceExaminer
58
	 * @param Cache $cache
59
	 * @param CacheKeyProvider $cacheKeyProvider
60
	 */
61 13
	public function __construct( ReferenceListOutputRenderer $referenceListOutputRenderer, MediaWikiContextInteractor $contextInteractor, NamespaceExaminer $namespaceExaminer, Cache $cache, CacheKeyProvider $cacheKeyProvider ) {
62 13
		$this->referenceListOutputRenderer = $referenceListOutputRenderer;
63 13
		$this->contextInteractor = $contextInteractor;
64 13
		$this->namespaceExaminer = $namespaceExaminer;
65 13
		$this->cache = $cache;
66 13
		$this->cacheKeyProvider = $cacheKeyProvider;
67 13
	}
68
69
	/**
70
	 * @since 1.0
71
	 *
72
	 * @return DIWikiPage
73
	 */
74 11
	public function getSubject() {
75
76 11
		if (  $this->subject === null ) {
77 11
			$this->subject = DIWikiPage::newFromTitle( $this->contextInteractor->getTitle() );
78 11
		}
79
80 11
		return $this->subject;
81
	}
82
83
	/**
84
	 * @since 1.0
85
	 *
86
	 * @param string &$text
87
	 */
88 12
	public function addReferenceListToText( &$text ) {
89
90 12
		if ( $this->contextInteractor->hasMagicWord( 'SCI_NOREFERENCELIST' ) || !$this->contextInteractor->hasAction( 'view' ) ) {
91 2
			return $this->removeReferenceListPlaceholder( $text );
92
		}
93
94 11
		if ( !$this->namespaceExaminer->isSemanticEnabled( $this->getSubject()->getNamespace() ) ) {
95 1
			return '';
96
		}
97
98 10
		$this->addReferenceListToCorrectTextPosition( $text );
99 10
	}
100
101 2
	private function removeReferenceListPlaceholder( &$text ) {
102
103 2
		if ( strpos( $text, 'scite-custom-referencelist' ) === false ) {
104
			return null;
105
		}
106
107 2
		return $text = preg_replace(
108 2
			"/" . "<div id=\"scite-custom-referencelist\"(.*)?>(<h2>|<span>)(.*)?<\/div>" . "/m",
109 2
			'',
110
			$text
111 2
		);
112
	}
113
114 10
	private function addReferenceListToCorrectTextPosition( &$text ) {
115
116
		// Remember the default options before trying to replace all list
117
		// placeholders to ensure to reset options to the default option
118
		// for when a list doesn't specify an option
119 10
		$this->defaultOptions = array(
120 10
			'listtype' => $this->referenceListOutputRenderer->getReferenceListType(),
121 10
			'columns'  => $this->referenceListOutputRenderer->getNumberOfReferenceListColumns(),
122 10
			'browse'   => $this->referenceListOutputRenderer->getBrowseLinkToCitationResourceState()
123 10
		);
124
125
		// Find out whether to place the list into a custom position or not
126 10
		if ( strpos( $text, 'scite-custom-referencelist' ) !== false ) {
127 5
			return $text = preg_replace_callback(
128 5
				"/" . "<div id=\"scite-custom-referencelist\"(.*)?>(<h2>|<span>)(.*)?<\/div>" . "/m",
129 5
				'self::getCustomizedRenderedHtmlReferenceList',
130
				$text
131 5
			);
132
		}
133
134 5
		if ( $this->contextInteractor->getTitle()->getNamespace() !== NS_FILE ) {
135 4
			$text .= $this->getRenderedHtmlReferenceList();
136 4
		}
137 5
	}
138
139 5
	private function getCustomizedRenderedHtmlReferenceList( $customOptions ) {
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
140
141 5
		$this->searchForReferenceListHeaderTocId( $customOptions );
142
143
		// Reset options
144 5
		$this->referenceListOutputRenderer->setReferenceListHeader( '' );
145 5
		$this->referenceListOutputRenderer->setReferenceListType( $this->defaultOptions['listtype'] );
146 5
		$this->referenceListOutputRenderer->setNumberOfReferenceListColumns( $this->defaultOptions['columns'] );
147 5
		$this->referenceListOutputRenderer->setBrowseLinkToCitationResourceState( $this->defaultOptions['browse'] );
148
149 5
		$customOptions = explode( 'data-', $customOptions[1] );
150
151 5
		$references = '';
152 5
		$fingerprint = '';
153
154 5
		foreach ( $customOptions as $options ) {
155
156 5
			if ( strpos( $options, '=' ) === false ) {
157 5
				continue;
158
			}
159
160 4
			$options = explode( '=', trim( str_replace( '"', '', $options ) ) );
161 4
			$this->doFilterValidOption( $options, $references, $fingerprint );
162 5
		}
163
164 5
		return $this->getRenderedHtmlReferenceList( $references, $fingerprint );
165
	}
166
167 5
	private function searchForReferenceListHeaderTocId( array $options ) {
168
169 5
		$headerId = array();
170 5
		$this->referenceListOutputRenderer->setReferenceListHeaderTocId( '' );
171
172
		// We know where to expect the index from preg_*
173 5
		if ( isset( $options[3] ) ) {
174 5
			preg_match("/id=\"(.*)\"/", $options[3], $headerId );
175 5
		}
176
177 5
		if ( $headerId !== array() ) {
178 1
			$this->referenceListOutputRenderer->setReferenceListHeaderTocId( $headerId[1] );
179 1
		}
180 5
	}
181
182 4
	private function doFilterValidOption( $options, &$references, &$fingerprint ) {
183
184 4
		$columns = '';
185 4
		$header = '';
186
187 4
		switch ( $options[0] ) {
188 4
			case 'browselinks':
189 1
				$this->referenceListOutputRenderer->setBrowseLinkToCitationResourceState(
190 1
					filter_var( $options[1], FILTER_VALIDATE_BOOLEAN )
191 1
				);
192 1
				break;
193 4
			case 'listtype':
194 4
				$this->referenceListOutputRenderer->setReferenceListType( $options[1] );
195 4
				break;
196 3
			case 'columns':
197 1
				$columns = $options[1] < 0 ? 0 : $options[1];
198 1
				$this->referenceListOutputRenderer->setNumberOfReferenceListColumns(
199
					$columns
200 1
				);
201 1
				break;
202 3
			case 'header':
203 3
				$header = $options[1];
204 3
				$this->referenceListOutputRenderer->setReferenceListHeader( $header );
205 3
				break;
206 2
			case 'references':
207 2
				$references = $options[1];
208 2
				break;
209 4
		}
210
211 4
		$fingerprint = $header . $columns;
212 4
	}
213
214 9
	private function getRenderedHtmlReferenceList( $references = '', $fingerprint = ''  ) {
215
216 9
		$container = array();
217 9
		$oldId = $this->contextInteractor->getOldId();
218 9
		$lang  = $this->contextInteractor->getLanguageCode();
219
220
		// Keep the root cache entry based on the subject to ensure
221
		// that it can be flushed at once
222 9
		$key = $this->cacheKeyProvider->getCacheKeyForReferenceList(
223 9
			$this->getSubject()->getHash()
224 9
		);
225
226 9
		$revId = $oldId != 0 ? $oldId : $this->contextInteractor->getTitle()->getLatestRevID();
227
228
		// Create an individual hash for when loose references are used
229 9
		$renderedReferenceListHash = md5( $this->getSubject()->getHash() . $references . $fingerprint );
230
231 9
		if ( $this->cache->contains( $key ) ) {
232 1
			$container = $this->cache->fetch( $key );
233
234
			// Match against revision, languageCode, and hash
235 1
			if ( isset( $container['revId'] ) &&
236 1
				$container['revId'] == $revId &&
237 1
				isset( $container['text'][$lang][$renderedReferenceListHash] ) ) {
238
				return $container['text'][$lang][$renderedReferenceListHash];
239
			}
240 1
		}
241
242 9
		$renderedReferenceList = $this->referenceListOutputRenderer->doRenderReferenceListFor(
243 9
			$this->getSubject(),
244 9
			json_decode( html_entity_decode( $references ) )
245 9
		);
246
247
		// Don't cache a history/diff view
248 9
		if ( $oldId != 0 ) {
249
			return $renderedReferenceList;
250
		}
251
252 9
		$container['revId'] = $revId;
253 9
		$container['text'][$lang][$renderedReferenceListHash] = $renderedReferenceList;
254
255 9
		$this->cache->save(
256 9
			$key,
257
			$container
258 9
		);
259
260 9
		return $renderedReferenceList;
261
	}
262
263
}
264