Completed
Push — master ( 8f3f49...77bd7b )
by mw
14s
created

doAugmentSortKeyForWhenDisplayTitleIsAccessible()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 18
ccs 8
cts 8
cp 1
rs 9.4285
cc 3
eloc 10
nc 2
nop 1
crap 3
1
<?php
2
3
namespace SMW;
4
5
use Parser;
6
7
/**
8
 * Provides the {{#subobject}} parser function
9
 *
10
 * @see http://www.semantic-mediawiki.org/wiki/Help:ParserFunction
11
 *
12
 * @license GNU GPL v2+
13
 * @since 1.9
14
 *
15
 * @author mwjames
16
 */
17
class SubobjectParserFunction {
18
19
	/**
20
	 * Fixed identifier that describes the sortkey annotation parameter
21
	 */
22
	const PARAM_SORTKEY = '@sortkey';
23
24
	/**
25
	 * Fixed identifier that describes the subobject category parameter.
26
	 *
27
	 * We keep it as a @ fixed parameter since the standard annotation would
28
	 * require special attention (Category:;instead of ::) when annotating a
29
	 * category
30
	 */
31
	const PARAM_CATEGORY = '@category';
32
33
	/**
34
	 * @var ParserData
35
	 */
36
	protected $parserData;
37
38
	/**
39
	 * @var Subobject
40
	 */
41
	protected $subobject;
42
43
	/**
44
	 * @var MessageFormatter
45
	 */
46
	protected $messageFormatter;
47
48
	/**
49
	 * @var DataValueFactory
50
	 */
51
	private $dataValueFactory = null;
52
53
	/**
54
	 * @var boolean
55
	 */
56
	private $isEnabledFirstElementPropertyLabel = false;
57
58
	/**
59
	 * @since 1.9
60
	 *
61
	 * @param ParserData $parserData
62
	 * @param Subobject $subobject
63
	 * @param MessageFormatter $messageFormatter
64
	 */
65 87
	public function __construct( ParserData $parserData, Subobject $subobject, MessageFormatter $messageFormatter ) {
66 87
		$this->parserData = $parserData;
67 87
		$this->subobject = $subobject;
68 87
		$this->messageFormatter = $messageFormatter;
69 87
		$this->dataValueFactory = DataValueFactory::getInstance();
70 87
	}
71
72
	/**
73
	 * @since 1.9
74
	 *
75
	 * @param boolean $isEnabledFirstElementPropertyLabel
76
	 *
77
	 * @return SubobjectParserFunction
78
	 */
79 5
	public function setFirstElementForPropertyLabel( $isEnabledFirstElementPropertyLabel = true ) {
80 5
		$this->isEnabledFirstElementPropertyLabel = (bool)$isEnabledFirstElementPropertyLabel;
81 5
		return $this;
82
	}
83
84
	/**
85
	 * @since 1.9
86
	 *
87
	 * @param ParserParameterProcessor $params
0 ignored issues
show
Bug introduced by
There is no parameter named $params. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
88
	 *
89
	 * @return string|null
90
	 */
91 84
	public function parse( ParserParameterProcessor $parameters ) {
92
93
		if (
94 84
			$this->parserData->canModifySemanticData() &&
95 84
			$this->addDataValuesToSubobject( $parameters ) &&
96 84
			!$this->subobject->getSemanticData()->isEmpty()  ) {
97 83
			$this->parserData->getSemanticData()->addSubobject( $this->subobject );
98
		}
99
100 84
		$this->parserData->pushSemanticDataToParserOutput();
101
102 84
		return $this->messageFormatter
103 84
			->addFromArray( $this->subobject->getErrors() )
104 84
			->addFromArray( $this->parserData->getErrors() )
105 84
			->addFromArray( $parameters->getErrors() )
106 84
			->getHtml();
107
	}
108
109 86
	protected function addDataValuesToSubobject( ParserParameterProcessor $parserParameterProcessor ) {
110
111
		// Named subobjects containing a "." in the first five characters are reserved to be
112
		// used by extensions only in order to separate them from user land and avoid having
113
		// them accidentally to refer to the same named ID
114
		// (i.e. different access restrictions etc.)
115 86
		if ( strpos( mb_substr( $parserParameterProcessor->getFirst(), 0, 5 ), '.' ) !== false ) {
0 ignored issues
show
Deprecated Code introduced by
The method SMW\ParserParameterProcessor::getFirst() has been deprecated with message: since 2.3, use ParserParameterProcessor::getFirstParameter

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...
116 2
			return $this->addErrorWithMsg(
117 2
				$this->parserData->getSemanticData()->getSubject(),
118 2
				wfMessage( 'smw-subobject-parser-invalid-naming-scheme', $parserParameterProcessor->getFirst() )->escaped()
0 ignored issues
show
Deprecated Code introduced by
The method SMW\ParserParameterProcessor::getFirst() has been deprecated with message: since 2.3, use ParserParameterProcessor::getFirstParameter

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...
119
			);
120
		}
121
122 85
		list( $parameters, $id ) = $this->getParameters(
123
			$parserParameterProcessor
124
		);
125
126 85
		$this->subobject->setEmptyContainerForId(
127
			$id
128
		);
129
130 85
		$subject = $this->subobject->getSubject();
131
132 85
		foreach ( $parameters as $property => $values ) {
133
134 85
			if ( $property === self::PARAM_SORTKEY ) {
135 7
				$property = DIProperty::TYPE_SORTKEY;
136
			}
137
138 85
			if ( $property === self::PARAM_CATEGORY ) {
139 11
				$property = DIProperty::TYPE_CATEGORY;
140
			}
141
142 85
			foreach ( $values as $value ) {
143
144 85
				$dataValue = $this->dataValueFactory->newPropertyObjectValueByText(
145
						$property,
146
						$value,
147 85
						false,
148
						$subject
149
					);
150
151 85
				$this->subobject->addDataValue( $dataValue );
152
			}
153
		}
154
155 85
		$this->doAugmentSortKeyForWhenDisplayTitleIsAccessible(
156 85
			$this->subobject->getSemanticData()
157
		);
158
159 85
		return true;
160
	}
161
162 85
	private function getParameters( ParserParameterProcessor $parserParameterProcessor ) {
163
164 85
		$id = $parserParameterProcessor->getFirst();
0 ignored issues
show
Deprecated Code introduced by
The method SMW\ParserParameterProcessor::getFirst() has been deprecated with message: since 2.3, use ParserParameterProcessor::getFirstParameter

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...
165 85
		$isAnonymous = in_array( $id, array( null, '' ,'-' ) );
166
167 85
		$this->isEnabledFirstElementPropertyLabel = $this->isEnabledFirstElementPropertyLabel && !$isAnonymous;
168
169 85
		$parameters = $this->doPrepareParameters(
170
			$parserParameterProcessor
171
		);
172
173
		// Reclaim the ID to be hash based on the content
174 85
		if ( $this->isEnabledFirstElementPropertyLabel || $isAnonymous ) {
175 53
			$id = HashBuilder::createHashIdForContent( $parameters, '_' );
176
		}
177
178 85
		return array( $parameters, $id );
179
	}
180
181 85
	private function doPrepareParameters( ParserParameterProcessor $parserParameterProcessor ) {
182
183 85
		if ( $this->isEnabledFirstElementPropertyLabel ) {
184 3
			$parserParameterProcessor->addParameter(
185 3
				$parserParameterProcessor->getFirst(),
0 ignored issues
show
Deprecated Code introduced by
The method SMW\ParserParameterProcessor::getFirst() has been deprecated with message: since 2.3, use ParserParameterProcessor::getFirstParameter

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...
186 3
				$this->parserData->getTitle()->getPrefixedText()
187
			);
188
		}
189
190 85
		$parameters = $parserParameterProcessor->toArray();
191
192
		// FIXME 3.0 make sorting default by 3.0
193
		// Only sort for a modified sobj otherwise existing ID will change
194 85
		$sort = false;
195
196
		// This ensures that an unordered array is ordered and will produce
197
		// the same ID even if elements are placed differently
198 85
		if ( $sort ) {
199
			ksort( $parameters );
200
		}
201
202 85
		return $parameters;
203
	}
204
205 85
	private function doAugmentSortKeyForWhenDisplayTitleIsAccessible( $semanticData ) {
206
207 85
		$sortkey = new DIProperty( DIProperty::TYPE_SORTKEY );
208 85
		$displayTitle = new DIProperty( DIProperty::TYPE_DISPLAYTITLE );
209
210 85
		if ( $semanticData->hasProperty( $sortkey ) || !$semanticData->hasProperty( $displayTitle ) ) {
211 84
			return null;
212
		}
213
214 2
		$pv = $semanticData->getPropertyValues(
215
			$displayTitle
216
		);
217
218 2
		$semanticData->addPropertyObjectValue(
219
			$sortkey,
220
			end( $pv )
221
		);
222 2
	}
223
224 2
	private function addErrorWithMsg( $subject, $errorMsg ) {
225
226 2
		$error = new Error( $subject );
227
228 2
		$this->parserData->getSemanticData()->addPropertyObjectValue(
229 2
			$error->getProperty(),
230 2
			$error->getContainerFor(
231 2
				new DIProperty( '_SOBJ' ),
232
				$errorMsg
233
			)
234
		);
235
236 2
		$this->parserData->addError( $errorMsg );
237
238 2
		return false;
239
	}
240
241
}
242