Completed
Push — master ( 0591cb...33c12c )
by
unknown
07:17
created

tryToMatchCitationTextByPrecept()   B

Complexity

Conditions 8
Paths 11

Size

Total Lines 47

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 8.2078

Importance

Changes 0
Metric Value
dl 0
loc 47
ccs 23
cts 27
cp 0.8519
rs 7.9119
c 0
b 0
f 0
cc 8
nc 11
nop 3
crap 8.2078
1
<?php
2
3
namespace SCI;
4
5
use SCI\Bibtex\BibtexProcessor;
6
use SMW\NamespaceExaminer;
7
use SMW\ParserParameterProcessor;
8
use SMW\DataValueFactory;
9
use SMW\DIProperty;
10
use SMW\ParserData;
11
use SMW\Subobject;
12
use Html;
13
14
/**
15
 * #scite: is used the create a citation resource with a reference to be
16
 * accessible wiki-wide trough a unique citation key.
17
 *
18
 * [[CiteRef: ... ]] | [[Citation reference:: ...]] is used to create an in-text
19
 * reference link to a citation resource.
20
 *
21
 * @license GNU GPL v2+
22
 * @since 1.0
23
 *
24
 * @author mwjames
25
 */
26
class SciteParserFunction {
27
28
	/**
29
	 * @var ParserData
30
	 */
31
	private $parserData;
32
33
	/**
34
	 * @var NamespaceExaminer
35
	 */
36
	private $namespaceExaminer;
37
38
	/**
39
	 * @var CitationTextTemplateRenderer
40
	 */
41
	private $citationTextTemplateRenderer;
42
43
	/**
44
	 * @var MediaWikiNsContentMapper
45
	 */
46
	private $mediaWikiNsContentMapper;
47
48
	/**
49
	 * @var BibtexProcessor
50
	 */
51
	private $bibtexProcessor;
52
53
	/**
54
	 * @var DataValueFactory
55
	 */
56
	private $dataValueFactory;
57
58
	/**
59
	 * @var boolean
60
	 */
61
	private $strictParserValidationState = true;
62
63
	/**
64
	 * @var array
65
	 */
66
	private $parameters = [];
0 ignored issues
show
Unused Code introduced by
The property $parameters is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
67
68
	/**
69
	 * @since 1.0
70
	 *
71
	 * @param ParserData $parserData
72
	 * @param NamespaceExaminer $namespaceExaminer
73
	 * @param CitationTextTemplateRenderer $citationTextTemplateRenderer
74
	 * @param MediaWikiNsContentMapper $mediaWikiNsContentMapper
75
	 * @param BibtexProcessor $bibtexProcessor
76
	 */
77 18
	public function __construct( ParserData $parserData, NamespaceExaminer $namespaceExaminer, CitationTextTemplateRenderer $citationTextTemplateRenderer, MediaWikiNsContentMapper $mediaWikiNsContentMapper, BibtexProcessor $bibtexProcessor ) {
78 18
		$this->parserData = $parserData;
79 18
		$this->namespaceExaminer = $namespaceExaminer;
80 18
		$this->citationTextTemplateRenderer = $citationTextTemplateRenderer;
81 18
		$this->mediaWikiNsContentMapper = $mediaWikiNsContentMapper;
82 18
		$this->bibtexProcessor = $bibtexProcessor;
83 18
		$this->dataValueFactory = DataValueFactory::getInstance();
84 18
	}
85
86
	/**
87
	 * @since 1.0
88
	 *
89
	 * @param boolean $strictParserValidationState
90
	 */
91 15
	public function setStrictParserValidationState ( $strictParserValidationState ) {
92 15
		$this->strictParserValidationState = (bool)$strictParserValidationState;
93 15
	}
94
95
	/**
96
	 * Identifiers that have a id-property mapping are to be annotated as semantic
97
	 * property. The property mapped to an identifier should be maintained
98
	 * accordantly with the the expected type it ought to represent
99
	 * (e.g. 'url' => 'Has url', with 'Has url' being of [[Has type::URL]])
100
	 *
101
	 * Only identifiers used in #scite: that have an appropriate mapping
102
	 * will be created as semantic annotation. For example, identifiers important
103
	 * for the citation output are not necessarily notable for a semantic
104
	 * assignment (e.g. 'pages', 'page reference', or 'available').
105
	 *
106
	 * {{#scite:Segon & Booth 2011
107
	 * |type=online
108
	 * |author=Segon, M;Booth, C|+sep=;
109
	 * |year=2011
110
	 * |title=Bribery: what do Australian managers know and what do they do?
111
	 * |journal=Journal of Business Systems, Governance and Ethics
112
	 * |volumn=vol. 6, no. 3
113
	 * |pages=15-29
114
	 * |url=http://www.jbsge.vu.edu.au/issues/vol06no3/Segon_&_Booth.pdf
115
	 * |available=20 October 2014
116
	 * |template=scite-formatter-online
117
	 * }}
118
	 *
119
	 * OR
120
	 *
121
	 * {{#scite:Einstein, Podolsky, and Nathan 1935
122
	 * |bibtex=@article{einstein1935can,
123
	 *  title={Can quantum-mechanical description of physical reality be considered complete?},
124
	 *  author={Einstein, Albert and Podolsky, Boris and Rosen, Nathan},
125
	 *  journal={Physical review},
126
	 *  volume={47},
127
	 *  number={10},
128
	 *  pages={777},
129
	 *  year={1935},
130
	 *  publisher={APS}
131
	 * }
132
	 * |authors=Albert Einstein, Boris Podolsky, Nathan Rosen|+sep=,
133
	 * }}
134
	 *
135
	 * The citation style is determined by the template assigned and stored in
136
	 * its own semantic property. To apply for individual formatting rules, use
137
	 * |template=
138
	 *
139
	 * For any free text assignment use,
140
	 * |citation text=
141
	 *
142
	 * @since 1.0
143
	 *
144
	 * @param ParserParameterProcessor $parserParameterProcessor
145
	 */
146 17
	public function doProcess( ParserParameterProcessor $parserParameterProcessor, PreTextFormatter $preTextFormatter = null ) {
147
148 17
		if ( !$this->namespaceExaminer->isSemanticEnabled( $this->parserData->getTitle()->getNamespace() ) ) {
149 1
			return $this->createErrorMessageFor( 'sci-scite-parser-not-enabled-namespace' );
150
		}
151
152
		// Hopefully the bibtex processor will add all required parameters and values
153 16
		if ( $parserParameterProcessor->hasParameter( 'bibtex' ) ) {
154 1
			$this->bibtexProcessor->doProcess( $parserParameterProcessor );
155 1
		}
156
157 16
		$reference = str_replace( '_', ' ', $parserParameterProcessor->getFirstParameter() );
158 16
		$type = '';
159
160
		// Explicit reference precedes
161 16
		if ( $parserParameterProcessor->hasParameter( 'reference' ) ) {
162 2
			$reference = $parserParameterProcessor->getParameterValuesFor( 'reference' );
0 ignored issues
show
Deprecated Code introduced by
The method SMW\ParserParameterProce...getParameterValuesFor() has been deprecated with message: since 2.5, use ParserParameterProcessor::getParameterValuesByKey

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
163 2
			$reference = end( $reference );
164 2
		}
165
166 16
		if ( $reference === '' ) {
167 1
			return $this->createErrorMessageFor( 'sci-scite-parser-no-reference' );
168 1
		}
169
170
		// Fixed identifier
171 15
		$parserParameterProcessor->addParameter(
172 15
			'reference',
173
			$reference
174 15
		);
175
176 15
		if ( $parserParameterProcessor->hasParameter( 'type' ) ) {
177 14
			$type = $parserParameterProcessor->getParameterValuesFor( 'type' );
0 ignored issues
show
Deprecated Code introduced by
The method SMW\ParserParameterProce...getParameterValuesFor() has been deprecated with message: since 2.5, use ParserParameterProcessor::getParameterValuesByKey

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
178 14
			sort( $type );
179 14
			$type = end( $type );
180 14
		}
181
182 15
		$returnText = $this->tryToMatchCitationTextByPrecept(
183 15
			$parserParameterProcessor,
184 15
			$reference,
185
			$type
186 15
		);
187
188 15
		$this->addPropertyValuesFor(
189 15
			$parserParameterProcessor,
190
			$reference
191 15
		);
192
193
		// If the parser function returns an empty string then the MW Parser will
194
		// add a <br> section leaving the text around a #scite call adding extra
195
		// white space.
196
		// In order to mitigate the issue when several {{#scite:...}} calls are
197
		// placed next to each other, have the first occurrence to mark its
198
		// existence explicitly by outputting an empty paragraph and so avoid a
199
		// <br> element.
200 15
		if ( $returnText === '' && $this->parserData->getOutput()->getExtensionData( 'sci-parserfunction' ) === null ) {
201 14
			$this->parserData->getOutput()->setExtensionData( 'sci-parserfunction', true );
202 14
			$returnText = '<p></p>';
203 14
		}
204
205 15
		if ( $parserParameterProcessor->hasParameter( '@show' ) && $preTextFormatter !== null ) {
206
			$returnText = $preTextFormatter->getFormattedSciteFuncFrom( $parserParameterProcessor->getRaw() ) . $returnText;
207
		}
208
209 15
		return $returnText; //array( '', 'noparse' => true, 'isHTML' => true );
0 ignored issues
show
Unused Code Comprehensibility introduced by
53% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
210
	}
211
212 15
	private function tryToMatchCitationTextByPrecept( ParserParameterProcessor $parserParameterProcessor, $reference, $type = '' ) {
213
214 15
		$template = '';
215
216 15
		if ( $this->strictParserValidationState && $type === '' ) {
217
218 1
			$parserParameterProcessor->addParameter(
219 1
				DIProperty::TYPE_ERROR,
220
				PropertyRegistry::SCI_CITE
221 1
			);
222
223 1
			return $this->createErrorMessageFor( 'sci-scite-parser-no-type', $reference );
224
		}
225
226
		// An injected text trumps a template
227 14
		if ( $parserParameterProcessor->hasParameter( 'citation text' ) ) {
228 13
			return '';
229
		}
230
231
		// An explicit template precedes the assignment found for the type
232 2
		if ( $parserParameterProcessor->hasParameter( 'template' ) ) {
233 2
			$template = $parserParameterProcessor->getParameterValuesFor( 'template' );
0 ignored issues
show
Deprecated Code introduced by
The method SMW\ParserParameterProce...getParameterValuesFor() has been deprecated with message: since 2.5, use ParserParameterProcessor::getParameterValuesByKey

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
234 2
			$template = trim( end( $template ) );
235 2
		} elseif ( $this->mediaWikiNsContentMapper->findTemplateForType( $type ) !== null ) {
236 2
			$template = $this->mediaWikiNsContentMapper->findTemplateForType( $type );
237 2
		}
238
239 2
		if ( $template !== '' ) {
240 2
			$this->citationTextTemplateRenderer->packFieldsForTemplate( $template );
241
242
			// Fixed identifier
243 2
			$parserParameterProcessor->addParameter(
244 2
				'citation text',
245 2
				$this->citationTextTemplateRenderer->renderFor( $parserParameterProcessor->toArray() )
246 2
			);
247 2
		} elseif ( $this->strictParserValidationState ) {
248
249
			$parserParameterProcessor->addParameter(
250
				DIProperty::TYPE_ERROR,
251
				PropertyRegistry::SCI_CITE_TEXT
252
			);
253
254
			return $this->createErrorMessageFor( 'sci-scite-parser-no-citation-text', $reference, $type );
255
		}
256
257 2
		return '';
258
	}
259
260 15
	private function addPropertyValuesFor( ParserParameterProcessor $parserParameterProcessor, $reference ) {
261
262 15
		$subobject = new Subobject( $this->parserData->getTitle() );
263 15
		$subobject->setEmptyContainerForId( '_SCITE' . md5( $reference ) );
264
265 15
		$subject = $this->parserData->getSemanticData()->getSubject();
266
267 15
		foreach ( $parserParameterProcessor->toArray() as $key => $values ) {
268
269 15
			if ( $key === DIProperty::TYPE_ERROR ) {
270
271 1
				$value = new DIProperty( end( $values ) );
272
273 1
				$subobject->getSemanticData()->addPropertyObjectValue(
274 1
					new DIProperty( DIProperty::TYPE_ERROR ),
275 1
					$value->getDiWikiPage()
276 1
				);
277
278 1
				continue;
279
			}
280
281 14
			$property = $this->mediaWikiNsContentMapper->findPropertyForId( $key );
282
283
			// No mapping, no annotation
284 14
			if ( $property === null ) {
285 13
				continue;
286
			}
287
288 14
			foreach ( $values as $value ) {
289
290 14
				$dataValue = $this->dataValueFactory->newPropertyValue(
0 ignored issues
show
Deprecated Code introduced by
The method SMW\DataValueFactory::newPropertyValue() has been deprecated with message: since 2.4, use DataTypeRegistry::newDataValueByText

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
291 14
						$property,
292 14
						trim( $value ),
293 14
						false,
294
						$subject
295 14
					);
296
297 14
				$subobject->addDataValue( $dataValue );
298 14
			}
299 15
		}
300
301 15
		if ( $subobject->getSemanticData()->isEmpty() ) {
302
			return;
303
		}
304
305 15
		$this->parserData->getSemanticData()->addPropertyObjectValue(
306 15
			new DIProperty( PropertyRegistry::SCI_CITE ),
307 15
			$subobject->getContainer()
308 15
		);
309
310 15
		$this->parserData->getSubject()->setContextReference( 'scitep:' . uniqid() );
311 15
		$this->parserData->pushSemanticDataToParserOutput();
0 ignored issues
show
Deprecated Code introduced by
The method SMW\ParserData::pushSemanticDataToParserOutput() has been deprecated with message: since 3.0, use copyToParserOutput

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
312 15
	}
313
314 3
	private function createErrorMessageFor( $messageKey, $arg1 = '',  $arg2 = '' ) {
315 3
		return \Html::rawElement(
316 3
			'div',
317 3
			[ 'class' => 'smw-callout smw-callout-error' ],
318 3
			wfMessage( $messageKey, $arg1, $arg2 )->inContentLanguage()->text()
319 3
		);
320
	}
321
322
}
323