Completed
Push — master ( d2d28e...1c2760 )
by mw
35:37
created

includes/datavalues/SMW_DataValue.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * This group contains all parts of SMW that relate to the processing of datavalues
5
 * of various types.
6
 *
7
 * @defgroup SMWDataValues SMWDataValues
8
 * @ingroup SMW
9
 */
10
use SMW\ApplicationFactory;
11
use SMW\DataValues\InfoLinksProvider;
12
use SMW\DataValues\ValueFormatterRegistry;
13
use SMW\DataValues\ValueValidatorRegistry;
14
use SMW\Deserializers\DVDescriptionDeserializerRegistry;
15
use SMW\Localizer;
16
use SMW\Message;
17
use SMW\Options;
18
use SMW\Query\QueryComparator;
19
20
/**
21
 * Objects of this type represent all that is known about a certain user-provided
22
 * data value, especially its various representations as strings, tooltips,
23
 * numbers, etc.  Objects can be created as "emtpy" containers of a certain type,
24
 * but are then usually filled with data to present one particular data value.
25
 *
26
 * Data values have two chief representation forms: the user-facing syntax and the
27
 * internal representation. In user syntax, every value is (necessarily) a single
28
 * string, however complex the value is. For example, a string such as "Help:editing"
29
 * may represent a wiki page called "Editing" in the namespace for "Help". The
30
 * internal representation may be any numerical array of strings and numbers. In the
31
 * example, it might be array("Editing",12), where 12 is the number used for identifying
32
 * the namespace "Help:". Of course, the internal representation could also use a single
33
 * string value, such as in array("Help:Editing"), but this might be less useful for
34
 * certain operations (e.g. filterng by namespace). Moreover, all values that are
35
 * restored from the database are given in the internal format, so it wise to choose a
36
 * format that allows for very fast and easy processing without unnecessary parsing.
37
 *
38
 * The main functions of data value objects are:
39
 * - setUserValue() which triggers parseUserValue() to process a user-level string.
40
 *
41
 * In addition, there are a number of get-functions that provide useful output versions
42
 * for displaying and serializing the value.
43
 *
44
 * @ingroup SMWDataValues
45
 *
46
 * @author Markus Krötzsch
47
 */
48
abstract class SMWDataValue {
49
50
	/**
51
	 * Contains the user language a user operates in.
52
	 */
53
	const OPT_USER_LANGUAGE = 'user.language';
54
55
	/**
56
	 * Contains either the global "site" content language or a specified page
57
	 * content language invoked by the context page.
58
	 */
59
	const OPT_CONTENT_LANGUAGE = 'content.language';
60
61
	/**
62
	 * Describes a state where a DataValue is part of a query condition and may
63
	 * (or not) require a different treatment.
64
	 */
65
	const OPT_QUERY_CONTEXT = 'query.context';
66
67
	/**
68
	 * Describes a state where a DataValue is part of a query condition and
69
	 * contains a comparator.
70
	 */
71
	const OPT_QUERY_COMP_CONTEXT = 'query.comparator.context';
72
73
	/**
74
	 * Associated data item. This is the reference to the immutable object
75
	 * that represents the current data content. All other data stored here
76
	 * is only about presentation and parsing, but is not relevant to the
77
	 * actual data that is represented (and stored later on).
78
	 *
79
	 * This variable must always be set to some data item, even if there
80
	 * have been errors in initialising the data.
81
	 * @var SMWDataItem
82
	 */
83
	protected $m_dataitem;
84
85
	/**
86
	 * The property for which this value is constructed or null if none
87
	 * given. Property pages are used to make settings that affect parsing
88
	 * and display, hence it is sometimes needed to know them.
89
	 *
90
	 * @var SMWDIProperty
91
	 */
92
	protected $m_property = null;
93
94
	/**
95
	 * Wiki page in the context of which the value is to be interpreted, or
96
	 * null if not given (or not on a page). This information is used to
97
	 * parse user values such as "#subsection" which only make sense when
98
	 * used on a certain page.
99
	 *
100
	 * @var SMWDIWikiPage
101
	 */
102
	protected $m_contextPage = null;
103
104
	/**
105
	 * The text label to be used for output or false if none given.
106
	 * @var string
107
	 */
108
	protected $m_caption;
109
110
	/**
111
	 * The type id for this value object.
112
	 * @var string
113
	 */
114
	protected $m_typeid;
115
116
	/**
117
	 * Output formatting string, false when not set.
118
	 * @see setOutputFormat()
119
	 * @var mixed
120
	 */
121
	protected $m_outformat = false;
122
123
	/**
124
	 * Array of error text messages. Private to allow us to track error insertion
125
	 * (PHP's count() is too slow when called often) by using $mHasErrors.
126
	 * @var array
127
	 */
128
	private $mErrors = array();
129
130
	/**
131
	 * Boolean indicating if there where any errors.
132
	 * Should be modified accordingly when modifying $mErrors.
133
	 * @var boolean
134
	 */
135
	private $mHasErrors = false;
136
137
	/**
138
	 * Extraneous services and object container
139
	 *
140
	 * @var array
141
	 */
142
	private $extraneousFunctions = array();
143
144
	/**
145
	 * @var Options
146
	 */
147
	private $options;
148
149
	/**
150
	 * @var InfoLinksProvider
151
	 */
152
	private $infoLinksProvider = null;
153
154
	/**
155
	 * Constructor.
156
	 *
157
	 * @param string $typeid
158
	 */
159 226
	public function __construct( $typeid ) {
160 226
		$this->m_typeid = $typeid;
161 226
	}
162
163
///// Set methods /////
164
165
	/**
166
	 * Set the user value (and compute other representations if possible).
167
	 * The given value is a string as supplied by some user. An alternative
168
	 * label for printout might also be specified.
169
	 *
170
	 * @param string $value
171
	 * @param mixed $caption
172
	 */
173 210
	public function setUserValue( $value, $caption = false ) {
174
175 210
		$this->m_dataitem = null;
176 210
		$this->mErrors = array(); // clear errors
177 210
		$this->mHasErrors = false;
178 210
		$this->getInfoLinksProvider()->init();
179 210
		$this->m_caption = is_string( $caption ) ? trim( $caption ) : false;
180
181 210
		$this->parseUserValue( $value ); // may set caption if not set yet, depending on datavalue
182
183
		// The following checks for Strip markers generated by MediaWiki to handle special content,
184
		// from parser and extension tags e.g. <pre>,<nowiki>,<math>,<source>.
185
		// See https://en.wikipedia.org/wiki/Help:Strip_markers
186
		// In general, we are not prepared to handle such content properly, and we
187
		// also have no means of obtaining the user input at this point. Hence the assignment
188
		// just fails, even if parseUserValue() above might not have noticed this issue.
189
		// Note: \x07 was used in MediaWiki 1.11.0, \x7f is used now (backwards compatiblity, b/c)
190 210
		if ( ( strpos( $value, "\x7f" ) !== false ) || ( strpos( $value, "\x07" ) !== false ) ) {
191
			$this->addErrorMsg( array( 'smw-datavalue-stripmarker-parse-error', $value ) );
192
		}
193
194 210
		if ( $this->isValid() && !$this->getOptionBy( self::OPT_QUERY_CONTEXT ) ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->getOptionBy(self::OPT_QUERY_CONTEXT) of type string|false is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
195 209
			$this->checkAllowedValues();
196
		}
197 210
	}
198
199
	/**
200
	 * Set the actual data contained in this object. The method returns
201
	 * true if this was successful (requiring the type of the dataitem
202
	 * to match the data value). If false is returned, the data value is
203
	 * left unchanged (the data item was rejected).
204
	 *
205
	 * @note Even if this function returns true, the data value object
206
	 * might become invalid if the content of the data item caused errors
207
	 * in spite of it being of the right basic type. False is only returned
208
	 * if the data item is fundamentally incompatible with the data value.
209
	 *
210
	 * @param $dataitem SMWDataItem
211
	 * @return boolean
212
	 */
213 165
	public function setDataItem( SMWDataItem $dataItem ) {
214 165
		$this->getInfoLinksProvider()->init();
215 165
		$this->m_dataitem = null;
216 165
		$this->mErrors = array();
217 165
		$this->mHasErrors = $this->m_caption = false;
218 165
		return $this->loadDataItem( $dataItem );
219
	}
220
221
	/**
222
	 * Specify the property to which this value refers. Property pages are
223
	 * used to make settings that affect parsing and display, hence it is
224
	 * sometimes needed to know them.
225
	 *
226
	 * @since 1.6
227
	 *
228
	 * @param SMWDIProperty $property
229
	 */
230 200
	public function setProperty( SMWDIProperty $property ) {
231 200
		$this->m_property = $property;
232 200
	}
233
234
	/**
235
	 * Returns the property to which this value refers.
236
	 *
237
	 * @since 1.8
238
	 *
239
	 * @return SMWDIProperty|null
240
	 */
241 219
	public function getProperty() {
242 219
		return $this->m_property;
243
	}
244
245
	/**
246
	 * Specify the wiki page to which this value refers. This information is
247
	 * used to parse user values such as "#subsection" which only make sense
248
	 * when used on a certain page.
249
	 *
250
	 * @since 1.7
251
	 *
252
	 * @param SMWDIWikiPage|null $contextPage
253
	 */
254 196
	public function setContextPage( SMWDIWikiPage $contextPage = null ) {
255 196
		$this->m_contextPage = $contextPage;
256
257 196
		$this->setOption(
258 196
			self::OPT_CONTENT_LANGUAGE,
259 196
			Localizer::getInstance()->getPreferredContentLanguage( $contextPage )->getCode()
260
		);
261 196
	}
262
263
	/**
264
	 * @since 2.4
265
	 *
266
	 * @return DIWikiPage|null
267
	 */
268 204
	public function getContextPage() {
269 204
		return $this->m_contextPage;
270
	}
271
272
	/**
273
	 * @since 2.4
274
	 *
275
	 * @return Options|null $options
276
	 */
277 223
	public function setOptions( Options $options = null ) {
278
279 223
		if ( $options === null ) {
280 16
			return;
281
		}
282
283 223
		foreach ( $options->getOptions() as $key => $value ) {
284 223
			$this->setOption( $key, $value );
285
		}
286 223
	}
287
288
	/**
289
	 * @since 2.4
290
	 *
291
	 * @return string $key
292
	 * @param mxied $value
293
	 */
294 223
	public function setOption( $key, $value ) {
295
296 223
		if ( $this->options === null ) {
297 223
			$this->options = new Options();
298
		}
299
300 223
		$this->options->set( $key, $value );
301 223
	}
302
303
	/**
304
	 * @since 2.4
305
	 *
306
	 * @param string $key
307
	 *
308
	 * @return mixed|false
309
	 */
310 212
	public function getOptionBy( $key ) {
311
312 212
		if ( $this->options !== null && $this->options->has( $key ) ) {
313 211
			return $this->options->get( $key );
314
		}
315
316 211
		return false;
317
	}
318
319
	/**
320
	 * @since 2.4
321
	 *
322
	 * @param integer $feature
323
	 *
324
	 * @return boolean
325
	 */
326 206
	public function isEnabledFeature( $feature ) {
327 206
		return ( $this->getOptionBy( 'smwgDVFeatures' ) & $feature ) != 0;
328
	}
329
330
	/**
331
	 * Change the caption (the text used for displaying this datavalue). The given
332
	 * value must be a string.
333
	 *
334
	 * @param string $caption
335
	 */
336 108
	public function setCaption( $caption ) {
337 108
		$this->m_caption = $caption;
338 108
	}
339
340
	/**
341
	 * @since 2.4
342
	 *
343
	 * @param string $caption
344
	 */
345 97
	public function getCaption() {
346 97
		return $this->m_caption;
347
	}
348
349
	/**
350
	 * Returns a preferred caption and may deviate from the standard caption as
351
	 * a subclass is permitted to override this method and provide a more
352
	 * contextualized display representation (language or value context etc.).
353
	 *
354
	 * @since 2.4
355
	 *
356
	 * @return string
357
	 */
358 1
	public function getPreferredCaption() {
359 1
		return $this->m_caption;
360
	}
361
362
	/**
363
	 * Adds a single SMWInfolink object to the m_infolinks array.
364
	 *
365
	 * @param SMWInfolink $link
366
	 */
367
	public function addInfolink( SMWInfolink $link ) {
368
		$this->getInfoLinksProvider()->addInfolink( $link );
369
	}
370
371
	/**
372
	 * Define a particular output format. Output formats are user-supplied strings
373
	 * that the datavalue may (or may not) use to customise its return value. For
374
	 * example, quantities with units of measurement may interpret the string as
375
	 * a desired output unit. In other cases, the output format might be built-in
376
	 * and subject to internationalisation (which the datavalue has to implement).
377
	 * In any case, an empty string resets the output format to the default.
378
	 *
379
	 * There is one predefined output format that all datavalues should respect: the
380
	 * format '-' indicates "plain" output that is most useful for further processing
381
	 * the value in a template. It should not use any wiki markup or beautification,
382
	 * and it should also avoid localization to the current language. When users
383
	 * explicitly specify an empty format string in a query, it is normalized to "-"
384
	 * to avoid confusion. Note that empty format strings are not interpreted in
385
	 * this way when directly passed to this function.
386
	 *
387
	 * @param string $formatString
388
	 */
389 109
	public function setOutputFormat( $formatString ) {
390 109
		$this->m_outformat = $formatString; // just store it, subclasses may or may not use this
391 109
	}
392
393
	/**
394
	 * @since 2.4
395
	 *
396
	 * @return string
397
	 */
398 52
	public function getOutputFormat() {
399 52
		return $this->m_outformat;
400
	}
401
402
	/**
403
	 * Add a new error string or array of such strings to the error list.
404
	 *
405
	 * @note Errors should not be escaped here in any way, in contradiction to what
406
	 * the docs used to say here in 1.5 and before. Escaping should happen at the output.
407
	 *
408
	 * @param mixed $error A single string, or array of strings.
409
	 */
410 115
	public function addError( $error ) {
411 115
		if ( is_array( $error ) ) {
412 112
			$this->mErrors = array_merge( $this->mErrors, $error );
413 112
			$this->mHasErrors = $this->mHasErrors || ( count( $error ) > 0 );
414
		} else {
415 7
			$this->mErrors[] = $error;
416 7
			$this->mHasErrors = true;
417
		}
418 115
	}
419
420
	/**
421
	 * Messages are not resolved until the output and instead will be kept with the
422
	 * message and argument keys (e.g. `[2,"smw_baduri","~*0123*"]`). This allows to
423
	 * switch the a representation without requiring language context by the object
424
	 * that reports an error.
425
	 *
426
	 * @since 2.4
427
	 *
428
	 * @param $parameters
429
	 * @param integer|null $type
430
	 * @param integer|null $language
431
	 */
432 33
	public function addErrorMsg( $parameters, $type = null ) {
433 33
		$this->mErrors[] = Message::encode( $parameters, $type );
434 33
		$this->mHasErrors = true;
435 33
	}
436
437
	/**
438
	 * @since 2.4
439
	 */
440
	public function clearErrors() {
441
		$this->mErrors = array();
442
		$this->mHasErrors = false;
443
	}
444
445
///// Abstract processing methods /////
446
447
	/**
448
	 * Initialise the datavalue from the given value string.
449
	 * The format of this strings might be any acceptable user input
450
	 * and especially includes the output of getWikiValue().
451
	 *
452
	 * @param string $value
453
	 */
454
	abstract protected function parseUserValue( $value );
455
456
	/**
457
	 * Set the actual data contained in this object. The method returns
458
	 * true if this was successful (requiring the type of the dataitem
459
	 * to match the data value). If false is returned, the data value is
460
	 * left unchanged (the data item was rejected).
461
	 *
462
	 * @note Even if this function returns true, the data value object
463
	 * might become invalid if the content of the data item caused errors
464
	 * in spite of it being of the right basic type. False is only returned
465
	 * if the data item is fundamentally incompatible with the data value.
466
	 *
467
	 * @since 1.6
468
	 *
469
	 * @param SMWDataItem $dataItem
470
	 *
471
	 * @return boolean
472
	 */
473
	abstract protected function loadDataItem( SMWDataItem $dataItem );
474
475
476
///// Query support /////
477
478
	/**
479
	 * FIXME 3.0, allow NULL as value
480
	 *
481
	 * @see DataValueDescriptionDeserializer::deserialize
482
	 *
483
	 * @note Descriptions of values need to know their property to be able to
484
	 * create a parsable wikitext version of a query condition again. Thus it
485
	 * might be necessary to call setProperty() before using this method.
486
	 *
487
	 * @param string $value
488
	 *
489
	 * @return Description
490
	 * @throws InvalidArgumentException
491
	 */
492 109
	public function getQueryDescription( $value ) {
493
494 109
		$descriptionDeserializer = DVDescriptionDeserializerRegistry::getInstance()->getDescriptionDeserializerBy( $this );
495 109
		$description = $descriptionDeserializer->deserialize( $value );
496
497 109
		foreach ( $descriptionDeserializer->getErrors() as $error ) {
498 1
			$this->addError( $error );
499
		}
500
501 109
		return $description;
502
	}
503
504
	/**
505
	 * Returns a DataValueFormatter that was matched and dispatched for the current
506
	 * DV instance.
507
	 *
508
	 * @since 2.4
509
	 *
510
	 * @return DataValueFormatter
511
	 */
512 128
	public function getDataValueFormatter() {
513 128
		return ValueFormatterRegistry::getInstance()->getDataValueFormatterFor( $this );
514
	}
515
516
	/**
517
	 * @deprecated 2.3
518
	 * @see DescriptionDeserializer::prepareValue
519
	 *
520
	 * This method should no longer be used for direct public access, instead a
521
	 * DataValue is expected to register a DescriptionDeserializer with
522
	 * DVDescriptionDeserializerRegistry.
523
	 *
524
	 * FIXME as of 2.3, SMGeoCoordsValue still uses this method and requires
525
	 * migration before 3.0
526
	 */
527
	static public function prepareValue( &$value, &$comparator ) {
528
		$comparator = QueryComparator::getInstance()->extractComparatorFromString( $value );
529
	}
530
531
///// Get methods /////
532
533
	/**
534
	 * Get the actual data contained in this object or null if the data is
535
	 * not defined (due to errors or due to not being set at all).
536
	 * @note Most implementations ensure that a data item is always set,
537
	 * even if errors occurred, to avoid additional checks for not
538
	 * accessing null. Hence, one must not assume that a non-null return
539
	 * value here implies that isValid() returns true.
540
	 *
541
	 * @since 1.6
542
	 *
543
	 * @return SMWDataItem|SMWDIError
544
	 */
545 212
	public function getDataItem() {
546
547 212
		if ( $this->isValid() ) {
548 212
			return $this->m_dataitem;
549
		}
550
551 1
		return new SMWDIError( $this->mErrors );
552
	}
553
554
	/**
555
	 * @since 2.2
556
	 *
557
	 * @return string
558
	 */
559
	public function __toString() {
560
		return $this->getDataItem()->getSerialization();
561
	}
562
563
	/**
564
	 * Returns a short textual representation for this data value. If the value
565
	 * was initialised from a user supplied string, then this original string
566
	 * should be reflected in this short version (i.e. no normalisation should
567
	 * normally happen). There might, however, be additional parts such as code
568
	 * for generating tooltips. The output is in wiki text.
569
	 *
570
	 * The parameter $linked controls linking of values such as titles and should
571
	 * be non-NULL and non-false if this is desired.
572
	 */
573
	abstract public function getShortWikiText( $linked = null );
574
575
	/**
576
	 * Returns a short textual representation for this data value. If the value
577
	 * was initialised from a user supplied string, then this original string
578
	 * should be reflected in this short version (i.e. no normalisation should
579
	 * normally happen). There might, however, be additional parts such as code
580
	 * for generating tooltips. The output is in HTML text.
581
	 *
582
	 * The parameter $linker controls linking of values such as titles and should
583
	 * be some Linker object (or NULL for no linking).
584
	 */
585
	abstract public function getShortHTMLText( $linker = null );
586
587
	/**
588
	 * Return the long textual description of the value, as printed for
589
	 * example in the factbox. If errors occurred, return the error message
590
	 * The result always is a wiki-source string.
591
	 *
592
	 * The parameter $linked controls linking of values such as titles and should
593
	 * be non-NULL and non-false if this is desired.
594
	 */
595
	abstract public function getLongWikiText( $linked = null );
596
597
	/**
598
	 * Return the long textual description of the value, as printed for
599
	 * example in the factbox. If errors occurred, return the error message
600
	 * The result always is an HTML string.
601
	 *
602
	 * The parameter $linker controls linking of values such as titles and should
603
	 * be some Linker object (or NULL for no linking).
604
	 */
605
	abstract public function getLongHTMLText( $linker = null );
606
607
	/**
608
	 * Returns a short textual representation for this data value. If the value
609
	 * was initialised from a user supplied string, then this original string
610
	 * should be reflected in this short version (i.e. no normalisation should
611
	 * normally happen). There might, however, be additional parts such as code
612
	 * for generating tooltips. The output is in the specified format.
613
	 *
614
	 * The parameter $linker controls linking of values such as titles and should
615
	 * be some Linker object (for HTML output), or NULL for no linking.
616
	 */
617 60
	public function getShortText( $outputformat, $linker = null ) {
618
		switch ( $outputformat ) {
619 60
			case SMW_OUTPUT_WIKI:
620 59
				return $this->getShortWikiText( $linker );
621 1
			case SMW_OUTPUT_HTML:
622
			case SMW_OUTPUT_FILE:
623
			default:
624 1
				return $this->getShortHTMLText( $linker );
625
		}
626
	}
627
628
	/**
629
	 * Return the long textual description of the value, as printed for
630
	 * example in the factbox. If errors occurred, return the error message.
631
	 * The output is in the specified format.
632
	 *
633
	 * The parameter $linker controls linking of values such as titles and should
634
	 * be some Linker object (for HTML output), or NULL for no linking.
635
	 */
636
	public function getLongText( $outputformat, $linker = null ) {
637
		switch ( $outputformat ) {
638
			case SMW_OUTPUT_WIKI:
639
				return $this->getLongWikiText( $linker );
640
			case SMW_OUTPUT_HTML:
641
			case SMW_OUTPUT_FILE:
642
			default:
643
				return $this->getLongHTMLText( $linker );
644
		}
645
	}
646
647
	/**
648
	 * Return text serialisation of info links. Ensures more uniform layout
649
	 * throughout wiki (Factbox, Property pages, ...).
650
	 *
651
	 * @param integer $outputformat Element of the SMW_OUTPUT_ enum
652
	 * @param $linker
653
	 *
654
	 * @return string
655
	 */
656 4
	public function getInfolinkText( $outputformat, $linker = null ) {
657 4
		return $this->getInfoLinksProvider()->getInfolinkText( $outputformat, $linker );
658
	}
659
660
	/**
661
	 * Return the plain wiki version of the value, or
662
	 * FALSE if no such version is available. The returned
663
	 * string suffices to reobtain the same DataValue
664
	 * when passing it as an input string to setUserValue().
665
	 */
666
	abstract public function getWikiValue();
667
668
	/**
669
	 * Return a short string that unambiguously specify the type of this
670
	 * value. This value will globally be used to identify the type of a
671
	 * value (in spite of the class it actually belongs to, which can still
672
	 * implement various types).
673
	 */
674 142
	public function getTypeID() {
675 142
		return $this->m_typeid;
676
	}
677
678
	/**
679
	 * @since 2.1
680
	 */
681 1
	public function disableServiceLinks() {
682 1
		$this->getInfoLinksProvider()->disableServiceLinks();
683 1
	}
684
685
	/**
686
	 * Return an array of SMWLink objects that provide additional resources
687
	 * for the given value. Captions can contain some HTML markup which is
688
	 * admissible for wiki text, but no more. Result might have no entries
689
	 * but is always an array.
690
	 */
691 4
	public function getInfolinks() {
692
693 4
		$this->getInfoLinksProvider()->setServiceLinkParameters(
694 4
			$this->getServiceLinkParams()
695
		);
696
697 4
		return $this->getInfoLinksProvider()->createInfoLinks();
698
	}
699
700
	/**
701
	 * Overwritten by callers to supply an array of parameters that can be used for
702
	 * creating servicelinks. The number and content of values in the parameter array
703
	 * may vary, depending on the concrete datatype.
704
	 */
705 3
	protected function getServiceLinkParams() {
706 3
		return false;
707
	}
708
709
	/**
710
	 * Return a string that identifies the value of the object, and that can
711
	 * be used to compare different value objects.
712
	 * Possibly overwritten by subclasses (e.g. to ensure that returned
713
	 * value is normalized first)
714
	 *
715
	 * @return string
716
	 */
717
	public function getHash() {
718
		return $this->isValid() ? $this->m_dataitem->getHash() : implode( "\t", $this->mErrors );
719
	}
720
721
	/**
722
	 * Convenience method that checks if the value that is used to sort
723
	 * data of this type is numeric. This only works if the value is set.
724
	 *
725
	 * @return boolean
726
	 */
727
	public function isNumeric() {
728
		if ( isset( $this->m_dataitem ) ) {
729
			return is_numeric( $this->m_dataitem->getSortKey() );
730
		} else {
731
			return false;
732
		}
733
	}
734
735
	/**
736
	 * Return true if a value was defined and understood by the given type,
737
	 * and false if parsing errors occurred or no value was given.
738
	 *
739
	 * @return boolean
740
	 */
741 222
	public function isValid() {
742 222
		return !$this->mHasErrors && isset( $this->m_dataitem );
743
	}
744
745
	/**
746
	 * Whether a datavalue can be used or not (can be made more restrictive then
747
	 * isValid).
748
	 *
749
	 * @note Validity defines a processable state without any technical restrictions
750
	 * while usability is determined by its accessibility to a context
751
	 * (permission, convention etc.)
752
	 *
753
	 * @since  2.2
754
	 *
755
	 * @return boolean
756
	 */
757 177
	public function canUse() {
758 177
		return true;
759
	}
760
761
	/**
762
	 * @note Normally set by the DataValueFactory, or during tests
763
	 *
764
	 * @since 2.3
765
	 *
766
	 * @param array
767
	 */
768 223
	public function setExtraneousFunctions( array $extraneousFunctions ) {
769 223
		$this->extraneousFunctions = $extraneousFunctions;
770 223
	}
771
772
	/**
773
	 * @since 2.3
774
	 *
775
	 * @param string $name
776
	 * @param array $parameters
777
	 *
778
	 * @return mixed
779
	 * @throws RuntimeException
780
	 */
781
	public function getExtraneousFunctionFor( $name, array $parameters = array() ) {
782
783
		if ( isset( $this->extraneousFunctions[$name] ) && is_callable( $this->extraneousFunctions[$name] ) ) {
784
			return call_user_func_array( $this->extraneousFunctions[$name], $parameters );
785
		}
786
787
		throw new RuntimeException( "$name is not registered as extraneous function." );
788
	}
789
790
	/**
791
	 * Return a string that displays all error messages as a tooltip, or
792
	 * an empty string if no errors happened.
793
	 *
794
	 * @return string
795
	 */
796 13
	public function getErrorText() {
797 13
		return smwfEncodeMessages( $this->mErrors );
798
	}
799
800
	/**
801
	 * Return an array of error messages, or an empty array
802
	 * if no errors occurred.
803
	 *
804
	 * @return array
805
	 */
806 175
	public function getErrors() {
807 175
		return $this->mErrors;
808
	}
809
810
	/**
811
	 * Check if property is range restricted and, if so, whether the current value is allowed.
812
	 * Creates an error if the value is illegal.
813
	 */
814 209
	protected function checkAllowedValues() {
815 209
		ValueValidatorRegistry::getInstance()->getConstraintValueValidator()->validate( $this );
816 209
	}
817
818
	/**
819
	 * @since 2.4
820
	 *
821
	 * @param string $value
822
	 *
823
	 * @return string
824
	 */
825 42
	protected function convertDoubleWidth( $value ) {
826 42
		return Localizer::convertDoubleWidth( $value );
827
	}
828
829 109
	protected function getOptions() {
830 109
		return $this->options;
831
	}
832
833 223
	private function getInfoLinksProvider() {
834
835 223
		if ( $this->infoLinksProvider === null ) {
836 223
			$this->infoLinksProvider = new InfoLinksProvider( $this );
837
		}
838
839 223
		return $this->infoLinksProvider;
840
	}
841
842
}
843