1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace SMW\DataValues; |
4
|
|
|
|
5
|
|
|
use SMW\ApplicationFactory; |
6
|
|
|
use SMW\DataValueFactory; |
7
|
|
|
use SMW\DataValues\ValueFormatters\DataValueFormatter; |
8
|
|
|
use SMW\DIProperty; |
9
|
|
|
use SMW\DIWikiPage; |
10
|
|
|
use SMW\Localizer; |
11
|
|
|
use SMWContainerSemanticData as ContainerSemanticData; |
12
|
|
|
use SMWDataItem as DataItem; |
13
|
|
|
use SMWDataValue as DataValue; |
14
|
|
|
use SMWDIContainer as DIContainer; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* MonolingualTextValue requires two components, a language code and a |
18
|
|
|
* text. |
19
|
|
|
* |
20
|
|
|
* A text `foo@en` is expected to be invoked with a BCP47 language |
21
|
|
|
* code tag and a language dependent text component. |
22
|
|
|
* |
23
|
|
|
* Internally, the value is stored as container object that represents |
24
|
|
|
* the language code and text as separate entities in order to be queried |
25
|
|
|
* individually. |
26
|
|
|
* |
27
|
|
|
* External output representation depends on the context (wiki, html) |
28
|
|
|
* whether the language code is omitted or not. |
29
|
|
|
* |
30
|
|
|
* @license GNU GPL v2+ |
31
|
|
|
* @since 2.4 |
32
|
|
|
* |
33
|
|
|
* @author mwjames |
34
|
|
|
*/ |
35
|
|
|
class MonolingualTextValue extends DataValue { |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* @var DIProperty[]|null |
39
|
|
|
*/ |
40
|
|
|
private static $properties = null; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* @var MonolingualTextValueParser |
44
|
|
|
*/ |
45
|
|
|
private $monolingualTextValueParser = null; |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* @var DataValueFactory |
49
|
|
|
*/ |
50
|
|
|
private $dataValueFactory = null; |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* @param string $typeid |
54
|
|
|
*/ |
55
|
16 |
|
public function __construct( $typeid = '' ) { |
56
|
16 |
|
parent::__construct( '_mlt_rec' ); |
57
|
16 |
|
$this->dataValueFactory = DataValueFactory::getInstance(); |
58
|
16 |
|
} |
59
|
16 |
|
|
60
|
|
|
/** |
61
|
|
|
* @see RecordValue::setFieldProperties |
62
|
|
|
* |
63
|
|
|
* @param SMWDIProperty[] $properties |
64
|
|
|
*/ |
65
|
|
|
public function setFieldProperties( array $properties ) { |
|
|
|
|
66
|
|
|
// Keep the interface while the properties for this type |
67
|
|
|
// are fixed. |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* @see DataValue::parseUserValue |
72
|
|
|
* @note called by DataValue::setUserValue |
73
|
|
|
* |
74
|
|
|
* @param string $value |
|
|
|
|
75
|
|
|
*/ |
76
|
|
|
protected function parseUserValue( $userValue ) { |
77
|
14 |
|
|
78
|
|
|
list( $text, $languageCode ) = $this->getValuesFromString( $userValue ); |
79
|
14 |
|
|
80
|
|
|
$languageCodeValue = $this->newLanguageCodeValue( $languageCode ); |
81
|
14 |
|
|
82
|
|
|
if ( |
83
|
|
|
( $languageCode !== '' && $languageCodeValue->getErrors() !== array() ) || |
84
|
14 |
|
( $languageCode === '' && $this->isEnabledFeature( SMW_DV_MLTV_LCODE ) ) ) { |
85
|
14 |
|
$this->addError( $languageCodeValue->getErrors() ); |
86
|
3 |
|
return; |
87
|
3 |
|
} |
88
|
|
|
|
89
|
|
|
$dataValues = array(); |
90
|
11 |
|
|
91
|
|
|
foreach ( $this->getPropertyDataItems() as $property ) { |
|
|
|
|
92
|
11 |
|
|
93
|
|
|
if ( |
94
|
|
|
( $languageCode === '' && $property->getKey() === '_LCODE' ) || |
95
|
11 |
|
( $text === '' && $property->getKey() === '_TEXT' ) ) { |
96
|
11 |
|
continue; |
97
|
1 |
|
} |
98
|
|
|
|
99
|
|
|
$value = $text; |
100
|
11 |
|
|
101
|
|
|
if ( $property->getKey() === '_LCODE' ) { |
102
|
11 |
|
$value = $languageCode; |
103
|
10 |
|
} |
104
|
|
|
|
105
|
|
|
$dataValue = $this->dataValueFactory->newDataValueByProperty( |
106
|
11 |
|
$property, |
107
|
|
|
$value, |
108
|
|
|
false, |
109
|
11 |
|
$this->m_contextPage |
110
|
11 |
|
); |
111
|
|
|
|
112
|
|
|
$dataValues[] = $dataValue; |
113
|
11 |
|
} |
114
|
|
|
|
115
|
|
|
// Generate a hash from the normalized representation so that foo@en being |
116
|
|
|
// the same as foo@EN independent of a user input |
117
|
|
|
$containerSemanticData = $this->newContainerSemanticData( $text . '@' . $languageCode ); |
118
|
11 |
|
|
119
|
|
|
foreach ( $dataValues as $dataValue ) { |
120
|
11 |
|
$containerSemanticData->addDataValue( $dataValue ); |
121
|
11 |
|
} |
122
|
|
|
|
123
|
|
|
$this->m_dataitem = new DIContainer( $containerSemanticData ); |
124
|
11 |
|
} |
125
|
11 |
|
|
126
|
|
|
/** |
127
|
|
|
* @note called by MonolingualTextValueDescriptionDeserializer::deserialize |
128
|
|
|
* and MonolingualTextValue::parseUserValue |
129
|
|
|
* |
130
|
|
|
* No explicit check is made on the validity of a language code and is |
131
|
|
|
* expected to be done before calling this method. |
132
|
|
|
* |
133
|
|
|
* @since 2.4 |
134
|
|
|
* |
135
|
|
|
* @param string $userValue |
136
|
|
|
* |
137
|
|
|
* @return array |
138
|
|
|
*/ |
139
|
|
|
public function getValuesFromString( $userValue ) { |
140
|
14 |
|
return $this->getValueParser()->parse( $userValue ); |
141
|
14 |
|
} |
142
|
|
|
|
143
|
|
|
/** |
144
|
|
|
* @see DataValue::loadDataItem |
145
|
|
|
* |
146
|
|
|
* @param DataItem $dataItem |
147
|
|
|
* |
148
|
|
|
* @return boolean |
149
|
|
|
*/ |
150
|
|
|
protected function loadDataItem( DataItem $dataItem ) { |
151
|
4 |
|
|
152
|
|
|
if ( $dataItem->getDIType() === DataItem::TYPE_CONTAINER ) { |
153
|
4 |
|
$this->m_dataitem = $dataItem; |
154
|
|
|
return true; |
155
|
|
|
} elseif ( $dataItem->getDIType() === DataItem::TYPE_WIKIPAGE ) { |
156
|
4 |
|
$semanticData = new ContainerSemanticData( $dataItem ); |
|
|
|
|
157
|
4 |
|
$semanticData->copyDataFrom( ApplicationFactory::getInstance()->getStore()->getSemanticData( $dataItem ) ); |
|
|
|
|
158
|
4 |
|
$this->m_dataitem = new DIContainer( $semanticData ); |
159
|
4 |
|
return true; |
160
|
4 |
|
} |
161
|
|
|
|
162
|
|
|
return false; |
163
|
1 |
|
} |
164
|
|
|
|
165
|
|
|
/** |
166
|
|
|
* @see DataValue::getShortWikiText |
167
|
|
|
*/ |
168
|
|
|
public function getShortWikiText( $linker = null ) { |
169
|
7 |
|
return $this->getDataValueFormatter()->format( DataValueFormatter::WIKI_SHORT, $linker ); |
170
|
7 |
|
} |
171
|
|
|
|
172
|
|
|
/** |
173
|
|
|
* @see DataValue::getShortHTMLText |
174
|
|
|
*/ |
175
|
|
|
public function getShortHTMLText( $linker = null ) { |
176
|
|
|
return $this->getDataValueFormatter()->format( DataValueFormatter::HTML_SHORT, $linker ); |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
/** |
180
|
|
|
* @see DataValue::getLongWikiText |
181
|
|
|
*/ |
182
|
|
|
public function getLongWikiText( $linker = null ) { |
183
|
|
|
return $this->getDataValueFormatter()->format( DataValueFormatter::WIKI_LONG, $linker ); |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
/** |
187
|
|
|
* @see DataValue::getLongHTMLText |
188
|
|
|
*/ |
189
|
|
|
public function getLongHTMLText( $linker = null ) { |
190
|
|
|
return $this->getDataValueFormatter()->format( DataValueFormatter::HTML_LONG, $linker ); |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
/** |
194
|
|
|
* @see DataValue::getWikiValue |
195
|
|
|
*/ |
196
|
|
|
public function getWikiValue() { |
197
|
5 |
|
return $this->getDataValueFormatter()->format( DataValueFormatter::VALUE ); |
198
|
5 |
|
} |
199
|
|
|
|
200
|
|
|
/** |
201
|
|
|
* @since 2.4 |
202
|
|
|
* @note called by SMWResultArray::getNextDataValue |
203
|
|
|
* |
204
|
|
|
* @return DIProperty[] |
205
|
|
|
*/ |
206
|
|
|
public static function getPropertyDataItems() { |
207
|
12 |
|
|
208
|
|
|
if ( self::$properties !== null && self::$properties !== array() ) { |
209
|
12 |
|
return self::$properties; |
210
|
11 |
|
} |
211
|
|
|
|
212
|
|
|
foreach ( array( '_TEXT', '_LCODE' ) as $id ) { |
213
|
1 |
|
self::$properties[] = new DIProperty( $id ); |
214
|
1 |
|
} |
215
|
|
|
|
216
|
|
|
return self::$properties; |
217
|
1 |
|
} |
218
|
|
|
|
219
|
|
|
/** |
220
|
|
|
* @since 2.4 |
221
|
|
|
* @note called by SMWResultArray::loadContent |
222
|
|
|
* |
223
|
|
|
* @return DataItem[] |
224
|
|
|
*/ |
225
|
|
|
public function getDataItems() { |
226
|
2 |
|
|
227
|
|
|
if ( !$this->isValid() ) { |
228
|
2 |
|
return array(); |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
$result = array(); |
232
|
2 |
|
$index = 0; |
233
|
2 |
|
|
234
|
|
|
foreach ( $this->getPropertyDataItems() as $diProperty ) { |
|
|
|
|
235
|
2 |
|
$values = $this->getDataItem()->getSemanticData()->getPropertyValues( $diProperty ); |
|
|
|
|
236
|
2 |
|
if ( count( $values ) > 0 ) { |
237
|
2 |
|
$result[$index] = reset( $values ); |
238
|
2 |
|
} else { |
239
|
|
|
$result[$index] = null; |
240
|
|
|
} |
241
|
|
|
$index += 1; |
242
|
2 |
|
} |
243
|
|
|
|
244
|
|
|
return $result; |
245
|
2 |
|
} |
246
|
|
|
|
247
|
|
|
/** |
248
|
|
|
* @since 2.4 |
249
|
|
|
* |
250
|
|
|
* @return DataValue|null |
251
|
|
|
*/ |
252
|
|
|
public function getTextValueByLanguage( $languageCode ) { |
253
|
4 |
|
|
254
|
|
|
if ( !$this->isValid() || $this->getDataItem() === array() ) { |
255
|
4 |
|
return null; |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
$semanticData = $this->getDataItem()->getSemanticData(); |
|
|
|
|
259
|
4 |
|
|
260
|
|
|
$dataItems = $semanticData->getPropertyValues( new DIProperty( '_LCODE' ) ); |
261
|
4 |
|
$dataItem = reset( $dataItems ); |
262
|
4 |
|
|
263
|
|
|
if ( $dataItem === false || ( $dataItem->getString() !== Localizer::asBCP47FormattedLanguageCode( $languageCode ) ) ) { |
264
|
4 |
|
return null; |
265
|
1 |
|
} |
266
|
|
|
|
267
|
|
|
$dataItems = $semanticData->getPropertyValues( new DIProperty( '_TEXT' ) ); |
268
|
3 |
|
$dataItem = reset( $dataItems ); |
269
|
3 |
|
|
270
|
|
|
if ( $dataItem === false ) { |
271
|
3 |
|
return null; |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
$dataValue = $this->dataValueFactory->newDataValueByItem( |
275
|
3 |
|
$dataItem, |
276
|
|
|
new DIProperty( '_TEXT' ) |
277
|
3 |
|
); |
278
|
|
|
|
279
|
|
|
return $dataValue; |
280
|
3 |
|
} |
281
|
|
|
|
282
|
|
|
private function newContainerSemanticData( $value ) { |
283
|
11 |
|
|
284
|
|
|
if ( $this->m_contextPage === null ) { |
285
|
11 |
|
$containerSemanticData = ContainerSemanticData::makeAnonymousContainer(); |
286
|
4 |
|
$containerSemanticData->skipAnonymousCheck(); |
287
|
4 |
|
} else { |
288
|
|
|
$subobjectName = '_ML' . md5( $value ); |
289
|
7 |
|
|
290
|
|
|
$subject = new DIWikiPage( |
291
|
7 |
|
$this->m_contextPage->getDBkey(), |
292
|
7 |
|
$this->m_contextPage->getNamespace(), |
293
|
7 |
|
$this->m_contextPage->getInterwiki(), |
294
|
7 |
|
$subobjectName |
295
|
|
|
); |
296
|
|
|
|
297
|
|
|
$containerSemanticData = new ContainerSemanticData( $subject ); |
298
|
7 |
|
} |
299
|
|
|
|
300
|
|
|
return $containerSemanticData; |
301
|
11 |
|
} |
302
|
|
|
|
303
|
|
|
private function newLanguageCodeValue( $languageCode ) { |
304
|
14 |
|
|
305
|
|
|
$languageCodeValue = new LanguageCodeValue(); |
306
|
14 |
|
|
307
|
|
|
if ( $this->m_property !== null ) { |
308
|
14 |
|
$languageCodeValue->setProperty( $this->m_property ); |
309
|
7 |
|
} |
310
|
|
|
|
311
|
|
|
$languageCodeValue->setUserValue( $languageCode ); |
312
|
14 |
|
|
313
|
|
|
return $languageCodeValue; |
314
|
14 |
|
} |
315
|
|
|
|
316
|
|
|
private function getValueParser() { |
317
|
|
|
|
318
|
|
|
if ( $this->monolingualTextValueParser === null ) { |
319
|
|
|
$this->monolingualTextValueParser = ValueParserFactory::getInstance()->newMonolingualTextValueParser(); |
|
|
|
|
320
|
|
|
} |
321
|
|
|
|
322
|
|
|
return $this->monolingualTextValueParser; |
323
|
|
|
} |
324
|
|
|
|
325
|
|
|
} |
326
|
|
|
|
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.