CachedReferenceListOutputRenderer::getSubject()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
c 1
b 0
f 0
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 10
cc 2
nc 2
nop 0
crap 2
1
<?php
2
3
namespace SCI;
4
5
use Onoi\Cache\Cache;
6
use SMW\NamespaceExaminer;
0 ignored issues
show
Bug introduced by
The type SMW\NamespaceExaminer was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
7
use SMW\DIWikiPage;
0 ignored issues
show
Bug introduced by
The type SMW\DIWikiPage was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
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 = [];
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
		}
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 2
			$text
111
		);
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 = [
120 10
			'listtype' => $this->referenceListOutputRenderer->getReferenceListType(),
121 10
			'columns'  => $this->referenceListOutputRenderer->getNumberOfReferenceListColumns(),
122 10
			'browse'   => $this->referenceListOutputRenderer->getBrowseLinkToCitationResourceVisibility()
123
		];
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 5
				$text
131
			);
132
		}
133
134
		// #27 auto-referencelist for the NS_FILE can not be managed accurately therefore
135
		// disable such list
136 5
		if ( $this->contextInteractor->getTitle()->getNamespace() !== NS_FILE ) {
0 ignored issues
show
Bug introduced by
The constant SCI\NS_FILE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
137 4
			$text .= $this->getRenderedHtmlReferenceList();
138
		}
139 5
	}
140
141 5
	private function getCustomizedRenderedHtmlReferenceList( $customOptions ) {
142
143 5
		$this->searchForReferenceListHeaderTocId( $customOptions );
144
145
		// Reset options
146 5
		$this->referenceListOutputRenderer->setReferenceListHeader( '' );
147 5
		$this->referenceListOutputRenderer->setReferenceListType( $this->defaultOptions['listtype'] );
148 5
		$this->referenceListOutputRenderer->setNumberOfReferenceListColumns( $this->defaultOptions['columns'] );
149 5
		$this->referenceListOutputRenderer->setBrowseLinkToCitationResourceVisibility( $this->defaultOptions['browse'] );
150
151 5
		$customOptions = explode( 'data-', $customOptions[1] );
152
153 5
		$references = '';
154 5
		$fingerprint = '';
155
156 5
		foreach ( $customOptions as $options ) {
157
158 5
			if ( strpos( $options, '=' ) === false ) {
159 5
				continue;
160
			}
161
162 4
			$options = explode( '=', trim( str_replace( '"', '', $options ) ) );
163 4
			$this->doFilterValidOption( $options, $references, $fingerprint );
164
		}
165
166 5
		return $this->getRenderedHtmlReferenceList( $references, $fingerprint );
167
	}
168
169 5
	private function searchForReferenceListHeaderTocId( array $options ) {
170
171 5
		$headerId = [];
172 5
		$this->referenceListOutputRenderer->setReferenceListHeaderTocId( '' );
173
174
		// We know where to expect the index from preg_*
175 5
		if ( isset( $options[3] ) ) {
176 5
			preg_match("/id=\"(.*)\"/", $options[3], $headerId );
177
		}
178
179 5
		if ( $headerId !== [] ) {
180 1
			$this->referenceListOutputRenderer->setReferenceListHeaderTocId( $headerId[1] );
181
		}
182 5
	}
183
184 4
	private function doFilterValidOption( $options, &$references, &$fingerprint ) {
185
186 4
		$columns = '';
187 4
		$header = '';
188
189 4
		switch ( $options[0] ) {
190 4
			case 'browselinks':
191 1
				$this->referenceListOutputRenderer->setBrowseLinkToCitationResourceVisibility(
192 1
					filter_var( $options[1], FILTER_VALIDATE_BOOLEAN )
193
				);
194 1
				break;
195 4
			case 'listtype':
196 4
				$this->referenceListOutputRenderer->setReferenceListType( $options[1] );
197 4
				break;
198 3
			case 'columns':
199 1
				$columns = $options[1] < 0 ? 0 : $options[1];
200 1
				$this->referenceListOutputRenderer->setNumberOfReferenceListColumns(
201 1
					$columns
202
				);
203 1
				break;
204 3
			case 'header':
205 3
				$header = $options[1];
206 3
				$this->referenceListOutputRenderer->setReferenceListHeader( $header );
207 3
				break;
208 2
			case 'references':
209 2
				$references = $options[1];
210 2
				break;
211
		}
212
213 4
		$fingerprint = $header . $columns;
214 4
	}
215
216 9
	private function getRenderedHtmlReferenceList( $references = '', $fingerprint = ''  ) {
217
218 9
		$container = [];
219 9
		$oldId = $this->contextInteractor->getOldId();
220 9
		$lang  = $this->contextInteractor->getLanguageCode();
221
222
		// Keep the root cache entry based on the subject to ensure
223
		// that it can be flushed at once
224 9
		$key = $this->cacheKeyProvider->getCacheKeyForReferenceList(
225 9
			$this->getSubject()->getHash()
226
		);
227
228 9
		$revId = $oldId != 0 ? $oldId : $this->contextInteractor->getTitle()->getLatestRevID();
229
230
		// Create an individual hash for when loose references are used
231 9
		$renderedReferenceListHash = md5( $this->getSubject()->getHash() . $references . $fingerprint );
232
233 9
		if ( $this->cache->contains( $key ) ) {
234 1
			$container = $this->cache->fetch( $key );
235
236
			// Match against revision, languageCode, and hash
237 1
			if ( isset( $container['revId'] ) &&
238 1
				$container['revId'] == $revId &&
239 1
				isset( $container['text'][$lang][$renderedReferenceListHash] ) ) {
240
				return $container['text'][$lang][$renderedReferenceListHash];
241
			}
242
		}
243
244 9
		$renderedReferenceList = $this->referenceListOutputRenderer->doRenderReferenceListFor(
245 9
			$this->getSubject(),
246 9
			json_decode( html_entity_decode( $references ) )
247
		);
248
249
		// Don't cache a history/diff view
250 9
		if ( $oldId != 0 ) {
251
			return $renderedReferenceList;
252
		}
253
254 9
		$container['revId'] = $revId;
255 9
		$container['text'][$lang][$renderedReferenceListHash] = $renderedReferenceList;
256
257 9
		$this->cache->save(
258 9
			$key,
259 9
			$container
260
		);
261
262 9
		return $renderedReferenceList;
263
	}
264
265
}
266