Completed
Push — master ( 1aa771...794333 )
by
unknown
06:53
created

SciteParserFunction::addPropertyValuesFor()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 53
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 32
CRAP Score 6.001

Importance

Changes 0
Metric Value
dl 0
loc 53
rs 8.7155
c 0
b 0
f 0
ccs 32
cts 33
cp 0.9697
cc 6
eloc 28
nc 8
nop 2
crap 6.001

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 = array();
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 ) {
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
		}
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
		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...
206
	}
207
208 15
	private function tryToMatchCitationTextByPrecept( ParserParameterProcessor $parserParameterProcessor, $reference, $type = '' ) {
209
210 15
		$template = '';
211
212 15
		if ( $this->strictParserValidationState && $type === '' ) {
213
214 1
			$parserParameterProcessor->addParameter(
215 1
				DIProperty::TYPE_ERROR,
216
				PropertyRegistry::SCI_CITE
217 1
			);
218
219 1
			return $this->createErrorMessageFor( 'sci-scite-parser-no-type', $reference );
220
		}
221
222
		// An injected text trumps a template
223 14
		if ( $parserParameterProcessor->hasParameter( 'citation text' ) ) {
224 13
			return '';
225
		}
226
227
		// An explicit template precedes the assignment found for the type
228 2
		if ( $parserParameterProcessor->hasParameter( 'template' ) ) {
229 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...
230 2
			$template = trim( end( $template ) );
231 2
		} elseif ( $this->mediaWikiNsContentMapper->findTemplateForType( $type ) !== null ) {
232 2
			$template = $this->mediaWikiNsContentMapper->findTemplateForType( $type );
233 2
		}
234
235 2
		if ( $template !== '' ) {
236 2
			$this->citationTextTemplateRenderer->packFieldsForTemplate( $template );
237
238
			// Fixed identifier
239 2
			$parserParameterProcessor->addParameter(
240 2
				'citation text',
241 2
				$this->citationTextTemplateRenderer->renderFor( $parserParameterProcessor->toArray() )
242 2
			);
243 2
		} elseif ( $this->strictParserValidationState ) {
244
245
			$parserParameterProcessor->addParameter(
246
				DIProperty::TYPE_ERROR,
247
				PropertyRegistry::SCI_CITE_TEXT
248
			);
249
250
			return $this->createErrorMessageFor( 'sci-scite-parser-no-citation-text', $reference, $type );
251
		}
252
253 2
		return '';
254
	}
255
256 15
	private function addPropertyValuesFor( ParserParameterProcessor $parserParameterProcessor, $reference ) {
257
258 15
		$subobject = new Subobject( $this->parserData->getTitle() );
259 15
		$subobject->setEmptyContainerForId( '_SCITE' . md5( $reference ) );
260
261 15
		$subject = $this->parserData->getSemanticData()->getSubject();
262
263 15
		foreach ( $parserParameterProcessor->toArray() as $key => $values ) {
264
265 15
			if ( $key === DIProperty::TYPE_ERROR ) {
266
267 1
				$value = new DIProperty( end( $values ) );
268
269 1
				$subobject->getSemanticData()->addPropertyObjectValue(
270 1
					new DIProperty( DIProperty::TYPE_ERROR ),
271 1
					$value->getDiWikiPage()
0 ignored issues
show
Bug introduced by
It seems like $value->getDiWikiPage() can be null; however, addPropertyObjectValue() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
272 1
				);
273
274 1
				continue;
275
			}
276
277 14
			$property = $this->mediaWikiNsContentMapper->findPropertyForId( $key );
278
279
			// No mapping, no annotation
280 14
			if ( $property === null ) {
281 13
				continue;
282
			}
283
284 14
			foreach ( $values as $value ) {
285
286 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...
287 14
						$property,
288 14
						trim( $value ),
289 14
						false,
290
						$subject
291 14
					);
292
293 14
				$subobject->addDataValue( $dataValue );
294 14
			}
295 15
		}
296
297 15
		if ( $subobject->getSemanticData()->isEmpty() ) {
298
			return;
299
		}
300
301 15
		$this->parserData->getSemanticData()->addPropertyObjectValue(
302 15
			new DIProperty( PropertyRegistry::SCI_CITE ),
303 15
			$subobject->getContainer()
304 15
		);
305
306 15
		$this->parserData->getSubject()->setContextReference( 'scitep:' . uniqid() );
307 15
		$this->parserData->pushSemanticDataToParserOutput();
308 15
	}
309
310 3
	private function createErrorMessageFor( $messageKey, $arg1 = '',  $arg2 = '' ) {
311 3
		return \Html::rawElement(
312 3
			'div',
313 3
			array( 'class' => 'smw-callout smw-callout-error' ),
314 3
			wfMessage( $messageKey, $arg1, $arg2 )->inContentLanguage()->text()
315 3
		);
316
	}
317
318
}
319