Completed
Push — master ( 14d2bd...06e609 )
by mw
81:37 queued 59:24
created

includes/datavalues/SMW_DataValue.php (2 issues)

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\ValueFormatterRegistry;
12
use SMW\DataValues\ValueValidatorRegistry;
13
use SMW\Deserializers\DVDescriptionDeserializerRegistry;
14
use SMW\Message;
15
use SMW\Options;
16
use SMW\Localizer;
17
use SMW\Query\QueryComparator;
18
19
/**
20
 * Objects of this type represent all that is known about a certain user-provided
21
 * data value, especially its various representations as strings, tooltips,
22
 * numbers, etc.  Objects can be created as "emtpy" containers of a certain type,
23
 * but are then usually filled with data to present one particular data value.
24
 *
25
 * Data values have two chief representation forms: the user-facing syntax and the
26
 * internal representation. In user syntax, every value is (necessarily) a single
27
 * string, however complex the value is. For example, a string such as "Help:editing"
28
 * may represent a wiki page called "Editing" in the namespace for "Help". The
29
 * internal representation may be any numerical array of strings and numbers. In the
30
 * example, it might be array("Editing",12), where 12 is the number used for identifying
31
 * the namespace "Help:". Of course, the internal representation could also use a single
32
 * string value, such as in array("Help:Editing"), but this might be less useful for
33
 * certain operations (e.g. filterng by namespace). Moreover, all values that are
34
 * restored from the database are given in the internal format, so it wise to choose a
35
 * format that allows for very fast and easy processing without unnecessary parsing.
36
 *
37
 * The main functions of data value objects are:
38
 * - setUserValue() which triggers parseUserValue() to process a user-level string.
39
 *
40
 * In addition, there are a number of get-functions that provide useful output versions
41
 * for displaying and serializing the value.
42
 *
43
 * @ingroup SMWDataValues
44
 *
45
 * @author Markus Krötzsch
46
 */
47
abstract class SMWDataValue {
48
49
	/**
50
	 * Associated data item. This is the reference to the immutable object
51
	 * that represents the current data content. All other data stored here
52
	 * is only about presentation and parsing, but is not relevant to the
53
	 * actual data that is represented (and stored later on).
54
	 *
55
	 * This variable must always be set to some data item, even if there
56
	 * have been errors in initialising the data.
57
	 * @var SMWDataItem
58
	 */
59
	protected $m_dataitem;
60
61
	/**
62
	 * The property for which this value is constructed or null if none
63
	 * given. Property pages are used to make settings that affect parsing
64
	 * and display, hence it is sometimes needed to know them.
65
	 *
66
	 * @var SMWDIProperty
67
	 */
68
	protected $m_property = null;
69
70
	/**
71
	 * Wiki page in the context of which the value is to be interpreted, or
72
	 * null if not given (or not on a page). This information is used to
73
	 * parse user values such as "#subsection" which only make sense when
74
	 * used on a certain page.
75
	 *
76
	 * @var SMWDIWikiPage
77
	 */
78
	protected $m_contextPage = null;
79
80
	/**
81
	 * The text label to be used for output or false if none given.
82
	 * @var string
83
	 */
84
	protected $m_caption;
85
86
	/**
87
	 * The type id for this value object.
88
	 * @var string
89
	 */
90
	protected $m_typeid;
91
92
	/**
93
	 * Array of SMWInfolink objects.
94
	 * @var array
95
	 */
96
	protected $m_infolinks = array();
97
98
	/**
99
	 * Output formatting string, false when not set.
100
	 * @see setOutputFormat()
101
	 * @var mixed
102
	 */
103
	protected $m_outformat = false;
104
105
	/**
106
	 * Used to control the addition of the standard search link.
107
	 * @var boolean
108
	 */
109
	private $mHasSearchLink;
110
111
	/**
112
	 * Used to control service link creation.
113
	 * @var boolean
114
	 */
115
	private $mHasServiceLinks;
116
117
	/**
118
	 * Array of error text messages. Private to allow us to track error insertion
119
	 * (PHP's count() is too slow when called often) by using $mHasErrors.
120
	 * @var array
121
	 */
122
	private $mErrors = array();
123
124
	/**
125
	 * Boolean indicating if there where any errors.
126
	 * Should be modified accordingly when modifying $mErrors.
127
	 * @var boolean
128
	 */
129
	private $mHasErrors = false;
130
131
	/**
132
	 * @var boolean
133
	 */
134
	private $serviceLinksRenderState = true;
135
136
	/**
137
	 * Extraneous services and object container
138
	 *
139
	 * @var array
140
	 */
141
	private $extraneousFunctions = array();
142
143
	/**
144
	 * @var Options
145
	 */
146
	private $options;
147
148
	/**
149
	 * @var boolean
150
	 */
151
	protected $approximateValue = false;
152
153
	/**
154
	 * @var ValueConstraintValidator
155
	 */
156
	private $valueConstraintValidator = null;
157
158
	/**
159
	 * Constructor.
160
	 *
161
	 * @param string $typeid
162
	 */
163 205
	public function __construct( $typeid ) {
164 205
		$this->m_typeid = $typeid;
165 205
	}
166
167
///// Set methods /////
168
169
	/**
170
	 * Set the user value (and compute other representations if possible).
171
	 * The given value is a string as supplied by some user. An alternative
172
	 * label for printout might also be specified.
173
	 *
174
	 * The third argument was added in SMW 1.9 and should not be used from outside SMW.
175
	 *
176
	 * @param string $value
177
	 * @param mixed $caption
178
	 * @param boolean $approximateValue
179
	 */
180 189
	public function setUserValue( $value, $caption = false, $approximateValue = false ) {
181
182 189
		$this->m_dataitem = null;
183 189
		$this->mErrors = array(); // clear errors
184 189
		$this->mHasErrors = false;
185 189
		$this->m_infolinks = array(); // clear links
186 189
		$this->mHasSearchLink = false;
187 189
		$this->mHasServiceLinks = false;
188 189
		$this->m_caption = is_string( $caption ) ? trim( $caption ) : false;
0 ignored issues
show
Documentation Bug introduced by
It seems like is_string($caption) ? trim($caption) : false can also be of type false. However, the property $m_caption is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
189 189
		$this->approximateValue = $approximateValue;
190
191
192 189
		$this->parseUserValue( $value ); // may set caption if not set yet, depending on datavalue
193
194
		// The following checks for Strip markers generated by MediaWiki to handle special content,
195
		// from parser and extension tags e.g. <pre>,<nowiki>,<math>,<source>.
196
		// See https://en.wikipedia.org/wiki/Help:Strip_markers
197
		// In general, we are not prepared to handle such content properly, and we
198
		// also have no means of obtaining the user input at this point. Hence the assignment
199
		// just fails, even if parseUserValue() above might not have noticed this issue.
200
		// Note: \x07 was used in MediaWiki 1.11.0, \x7f is used now (backwards compatiblity, b/c)
201 189
		if ( ( strpos( $value, "\x7f" ) !== false ) || ( strpos( $value, "\x07" ) !== false ) ) {
202
			$this->addError( wfMessage( 'smw_parseerror' )->inContentLanguage()->text() );
203
		}
204
205 189
		if ( $this->isValid() && !$approximateValue ) {
206 188
			$this->checkAllowedValues();
207
		}
208
209 189
	}
210
211
	/**
212
	 * Set the actual data contained in this object. The method returns
213
	 * true if this was successful (requiring the type of the dataitem
214
	 * to match the data value). If false is returned, the data value is
215
	 * left unchanged (the data item was rejected).
216
	 *
217
	 * @note Even if this function returns true, the data value object
218
	 * might become invalid if the content of the data item caused errors
219
	 * in spite of it being of the right basic type. False is only returned
220
	 * if the data item is fundamentally incompatible with the data value.
221
	 *
222
	 * @param $dataitem SMWDataItem
223
	 * @return boolean
224
	 */
225 146
	public function setDataItem( SMWDataItem $dataItem ) {
226 146
		$this->m_dataitem = null;
227 146
		$this->mErrors = $this->m_infolinks = array();
228 146
		$this->mHasErrors = $this->mHasSearchLink = $this->mHasServiceLinks = $this->m_caption = false;
229 146
		return $this->loadDataItem( $dataItem );
230
	}
231
232
	/**
233
	 * Specify the property to which this value refers. Property pages are
234
	 * used to make settings that affect parsing and display, hence it is
235
	 * sometimes needed to know them.
236
	 *
237
	 * @since 1.6
238
	 *
239
	 * @param SMWDIProperty $property
240
	 */
241 184
	public function setProperty( SMWDIProperty $property ) {
242 184
		$this->m_property = $property;
243 184
	}
244
245
	/**
246
	 * Returns the property to which this value refers.
247
	 *
248
	 * @since 1.8
249
	 *
250
	 * @return SMWDIProperty|null
251
	 */
252 198
	public function getProperty() {
253 198
		return $this->m_property;
254
	}
255
256
	/**
257
	 * Specify the wiki page to which this value refers. This information is
258
	 * used to parse user values such as "#subsection" which only make sense
259
	 * when used on a certain page.
260
	 *
261
	 * @since 1.7
262
	 *
263
	 * @param SMWDIWikiPage|null $contextPage
264
	 */
265 180
	public function setContextPage( SMWDIWikiPage $contextPage = null ) {
266 180
		$this->m_contextPage = $contextPage;
267
268 180
		$this->setOption(
269 180
			'content.language',
270 180
			Localizer::getInstance()->getPreferredContentLanguage( $contextPage )->getCode()
271
		);
272 180
	}
273
274
	/**
275
	 * @since 2.4
276
	 *
277
	 * @return DIWikiPage|null
278
	 */
279 173
	public function getContextPage() {
280 173
		return $this->m_contextPage;
281
	}
282
283
	/**
284
	 * @since 2.4
285
	 *
286
	 * @return Options $options
287
	 */
288 202
	public function setOptions( Options $options ) {
289 202
		foreach ( $options->getOptions() as $key => $value ) {
290 202
			$this->setOption( $key, $value );
291
		}
292 202
	}
293
294
	/**
295
	 * @since 2.4
296
	 *
297
	 * @return string $key
298
	 * @param mxied $value
299
	 */
300 202
	public function setOption( $key, $value ) {
301
302 202
		if ( $this->options === null ) {
303 202
			$this->options = new Options();
304
		}
305
306 202
		$this->options->set( $key, $value );
307 202
	}
308
309
	/**
310
	 * @since 2.4
311
	 *
312
	 * @param string $key
313
	 *
314
	 * @return mixed|false
315
	 */
316 187
	public function getOptionValueFor( $key ) {
317
318 187
		if ( $this->options !== null && $this->options->has( $key ) ) {
319 187
			return $this->options->get( $key );
320
		}
321
322 60
		return false;
323
	}
324
325
	/**
326
	 * @since 2.4
327
	 *
328
	 * @param integer $feature
329
	 *
330
	 * @return boolean
331
	 */
332 185
	public function isEnabledFeature( $feature ) {
333 185
		return ( $this->getOptionValueFor( 'smwgDVFeatures' ) & $feature ) != 0;
334
	}
335
336
	/**
337
	 * Change the caption (the text used for displaying this datavalue). The given
338
	 * value must be a string.
339
	 *
340
	 * @param string $caption
341
	 */
342 92
	public function setCaption( $caption ) {
343 92
		$this->m_caption = $caption;
344 92
	}
345
346
	/**
347
	 * @since 2.4
348
	 *
349
	 * @param string $caption
350
	 */
351 85
	public function getCaption() {
352 85
		return $this->m_caption;
353
	}
354
355
	/**
356
	 * Adds a single SMWInfolink object to the m_infolinks array.
357
	 *
358
	 * @param SMWInfolink $link
359
	 */
360
	public function addInfolink( SMWInfolink $link ) {
361
		$this->m_infolinks[] = $link;
362
	}
363
364
	/**
365
	 * Servicelinks are special kinds of infolinks that are created from
366
	 * current parameters and in-wiki specification of URL templates. This
367
	 * method adds the current property's servicelinks found in the
368
	 * messages. The number and content of the parameters is depending on
369
	 * the datatype, and the service link message is usually crafted with a
370
	 * particular datatype in mind.
371
	 */
372 3
	public function addServiceLinks() {
373 3
		if ( $this->mHasServiceLinks ) {
374
			return;
375
		}
376
377 3
		if ( !is_null( $this->m_property ) ) {
378 3
			$propertyDiWikiPage = $this->m_property->getDiWikiPage();
379
		}
380
381 3
		if ( is_null( $this->m_property ) || is_null( $propertyDiWikiPage ) ) {
382
			return; // no property known, or not associated with a page
383
		}
384
385 3
		$args = $this->getServiceLinkParams();
386
387 3
		if ( $args === false ) {
388 3
			return; // no services supported
389
		}
390
391
		array_unshift( $args, '' ); // add a 0 element as placeholder
392
		$servicelinks = \SMW\StoreFactory::getStore()->getPropertyValues( $propertyDiWikiPage, new SMW\DIProperty( '_SERV' ) );
393
394
		foreach ( $servicelinks as $dataItem ) {
395
			if ( !( $dataItem instanceof SMWDIBlob ) ) {
396
				continue;
397
			}
398
399
			$args[0] = 'smw_service_' . str_replace( ' ', '_', $dataItem->getString() ); // messages distinguish ' ' from '_'
400
			$text = call_user_func_array( 'wfMessage', $args )->inContentLanguage()->text();
401
			$links = preg_split( "/[\n][\s]?/u", $text );
402
403
			foreach ( $links as $link ) {
404
				$linkdat = explode( '|', $link, 2 );
405
406
				if ( count( $linkdat ) == 2 ) {
407
					$this->addInfolink( SMWInfolink::newExternalLink( $linkdat[0], trim( $linkdat[1] ) ) );
408
				}
409
			}
410
		}
411
		$this->mHasServiceLinks = true;
412
	}
413
414
	/**
415
	 * Define a particular output format. Output formats are user-supplied strings
416
	 * that the datavalue may (or may not) use to customise its return value. For
417
	 * example, quantities with units of measurement may interpret the string as
418
	 * a desired output unit. In other cases, the output format might be built-in
419
	 * and subject to internationalisation (which the datavalue has to implement).
420
	 * In any case, an empty string resets the output format to the default.
421
	 *
422
	 * There is one predefined output format that all datavalues should respect: the
423
	 * format '-' indicates "plain" output that is most useful for further processing
424
	 * the value in a template. It should not use any wiki markup or beautification,
425
	 * and it should also avoid localization to the current language. When users
426
	 * explicitly specify an empty format string in a query, it is normalized to "-"
427
	 * to avoid confusion. Note that empty format strings are not interpreted in
428
	 * this way when directly passed to this function.
429
	 *
430
	 * @param string $formatString
431
	 */
432 94
	public function setOutputFormat( $formatString ) {
433 94
		$this->m_outformat = $formatString; // just store it, subclasses may or may not use this
434 94
	}
435
436
	/**
437
	 * @since 2.4
438
	 *
439
	 * @return string
440
	 */
441 46
	public function getOutputFormat() {
442 46
		return $this->m_outformat;
443
	}
444
445
	/**
446
	 * Add a new error string or array of such strings to the error list.
447
	 *
448
	 * @note Errors should not be escaped here in any way, in contradiction to what
449
	 * the docs used to say here in 1.5 and before. Escaping should happen at the output.
450
	 *
451
	 * @param mixed $error A single string, or array of strings.
452
	 */
453 116
	public function addError( $error ) {
454 116
		if ( is_array( $error ) ) {
455 94
			$this->mErrors = array_merge( $this->mErrors, $error );
456 94
			$this->mHasErrors = $this->mHasErrors || ( count( $error ) > 0 );
457
		} else {
458 32
			$this->mErrors[] = $error;
459 32
			$this->mHasErrors = true;
460
		}
461 116
	}
462
463
	/**
464
	 * @since 2.4
465
	 *
466
	 * @param $parameters
467
	 * @param integer|null $type
468
	 * @param integer|null $language
469
	 */
470 19
	public function addErrorMsg( $parameters, $type = null, $language = null ) {
471 19
		$this->addError( Message::get( $parameters, $type, $language ) );
472 19
	}
473
474
	/**
475
	 * @since 2.4
476
	 */
477
	public function clearErrors() {
478
		$this->mErrors = array();
479
		$this->mHasErrors = false;
480
	}
481
482
///// Abstract processing methods /////
483
484
	/**
485
	 * Initialise the datavalue from the given value string.
486
	 * The format of this strings might be any acceptable user input
487
	 * and especially includes the output of getWikiValue().
488
	 *
489
	 * @param string $value
490
	 */
491
	abstract protected function parseUserValue( $value );
492
493
	/**
494
	 * Set the actual data contained in this object. The method returns
495
	 * true if this was successful (requiring the type of the dataitem
496
	 * to match the data value). If false is returned, the data value is
497
	 * left unchanged (the data item was rejected).
498
	 *
499
	 * @note Even if this function returns true, the data value object
500
	 * might become invalid if the content of the data item caused errors
501
	 * in spite of it being of the right basic type. False is only returned
502
	 * if the data item is fundamentally incompatible with the data value.
503
	 *
504
	 * @since 1.6
505
	 *
506
	 * @param SMWDataItem $dataItem
507
	 *
508
	 * @return boolean
509
	 */
510
	abstract protected function loadDataItem( SMWDataItem $dataItem );
511
512
513
///// Query support /////
514
515
	/**
516
	 * @see DataValueDescriptionDeserializer::deserialize
517
	 *
518
	 * @note Descriptions of values need to know their property to be able to
519
	 * create a parsable wikitext version of a query condition again. Thus it
520
	 * might be necessary to call setProperty() before using this method.
521
	 *
522
	 * @param string $value
523
	 *
524
	 * @return Description
525
	 * @throws InvalidArgumentException
526
	 */
527 93
	public function getQueryDescription( $value ) {
528
529 93
		$descriptionDeserializer = DVDescriptionDeserializerRegistry::getInstance()->getDescriptionDeserializerFor( $this );
530 93
		$description = $descriptionDeserializer->deserialize( $value );
531
532 93
		foreach ( $descriptionDeserializer->getErrors() as $error ) {
533 1
			$this->addError( $error );
534
		}
535
536 93
		return $description;
537
	}
538
539
	/**
540
	 * Returns a DataValueFormatter that was matched and dispatched for the current
541
	 * DV instance.
542
	 *
543
	 * @since 2.4
544
	 *
545
	 * @return DataValueFormatter
546
	 */
547 115
	public function getDataValueFormatter() {
548 115
		return ValueFormatterRegistry::getInstance()->getDataValueFormatterFor( $this );
549
	}
550
551
	/**
552
	 * @since 2.4
553
	 *
554
	 * @return PropertySpecificationLookup
555
	 */
556 174
	public function getPropertySpecificationLookup() {
557 174
		return ApplicationFactory::getInstance()->getPropertySpecificationLookup();
558
	}
559
560
	/**
561
	 * @deprecated 2.3
562
	 * @see DescriptionDeserializer::prepareValue
563
	 *
564
	 * This method should no longer be used for direct public access, instead a
565
	 * DataValue is expected to register a DescriptionDeserializer with
566
	 * DVDescriptionDeserializerRegistry.
567
	 *
568
	 * FIXME as of 2.3, SMGeoCoordsValue still uses this method and requires
569
	 * migration before 3.0
570
	 */
571
	static public function prepareValue( &$value, &$comparator ) {
572
		$comparator = QueryComparator::getInstance()->extractComparatorFromString( $value );
573
	}
574
575
///// Get methods /////
576
577
	/**
578
	 * Get the actual data contained in this object or null if the data is
579
	 * not defined (due to errors or due to not being set at all).
580
	 * @note Most implementations ensure that a data item is always set,
581
	 * even if errors occurred, to avoid additional checks for not
582
	 * accessing null. Hence, one must not assume that a non-null return
583
	 * value here implies that isValid() returns true.
584
	 *
585
	 * @since 1.6
586
	 *
587
	 * @return SMWDataItem|SMWDIError
588
	 */
589 191
	public function getDataItem() {
590
591 191
		if ( $this->isValid() ) {
592 191
			return $this->m_dataitem;
593
		}
594
595 1
		return new SMWDIError( $this->mErrors );
596
	}
597
598
	/**
599
	 * @since 2.2
600
	 *
601
	 * @return string
602
	 */
603
	public function __toString() {
604
		return $this->getDataItem()->getSerialization();
605
	}
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 wiki text.
613
	 *
614
	 * The parameter $linked controls linking of values such as titles and should
615
	 * be non-NULL and non-false if this is desired.
616
	 */
617
	abstract public function getShortWikiText( $linked = null );
618
619
	/**
620
	 * Returns a short textual representation for this data value. If the value
621
	 * was initialised from a user supplied string, then this original string
622
	 * should be reflected in this short version (i.e. no normalisation should
623
	 * normally happen). There might, however, be additional parts such as code
624
	 * for generating tooltips. The output is in HTML text.
625
	 *
626
	 * The parameter $linker controls linking of values such as titles and should
627
	 * be some Linker object (or NULL for no linking).
628
	 */
629
	abstract public function getShortHTMLText( $linker = null );
630
631
	/**
632
	 * Return the long textual description of the value, as printed for
633
	 * example in the factbox. If errors occurred, return the error message
634
	 * The result always is a wiki-source string.
635
	 *
636
	 * The parameter $linked controls linking of values such as titles and should
637
	 * be non-NULL and non-false if this is desired.
638
	 */
639
	abstract public function getLongWikiText( $linked = null );
640
641
	/**
642
	 * Return the long textual description of the value, as printed for
643
	 * example in the factbox. If errors occurred, return the error message
644
	 * The result always is an HTML string.
645
	 *
646
	 * The parameter $linker controls linking of values such as titles and should
647
	 * be some Linker object (or NULL for no linking).
648
	 */
649
	abstract public function getLongHTMLText( $linker = null );
650
651
	/**
652
	 * Returns a short textual representation for this data value. If the value
653
	 * was initialised from a user supplied string, then this original string
654
	 * should be reflected in this short version (i.e. no normalisation should
655
	 * normally happen). There might, however, be additional parts such as code
656
	 * for generating tooltips. The output is in the specified format.
657
	 *
658
	 * The parameter $linker controls linking of values such as titles and should
659
	 * be some Linker object (for HTML output), or NULL for no linking.
660
	 */
661 47
	public function getShortText( $outputformat, $linker = null ) {
662
		switch ( $outputformat ) {
663 47
			case SMW_OUTPUT_WIKI:
664 47
				return $this->getShortWikiText( $linker );
665
			case SMW_OUTPUT_HTML:
666
			case SMW_OUTPUT_FILE:
667
			default:
668
				return $this->getShortHTMLText( $linker );
669
		}
670
	}
671
672
	/**
673
	 * Return the long textual description of the value, as printed for
674
	 * example in the factbox. If errors occurred, return the error message.
675
	 * The output is in the specified format.
676
	 *
677
	 * The parameter $linker controls linking of values such as titles and should
678
	 * be some Linker object (for HTML output), or NULL for no linking.
679
	 */
680
	public function getLongText( $outputformat, $linker = null ) {
681
		switch ( $outputformat ) {
682
			case SMW_OUTPUT_WIKI:
683
				return $this->getLongWikiText( $linker );
684
			case SMW_OUTPUT_HTML:
685
			case SMW_OUTPUT_FILE:
686
			default:
687
				return $this->getLongHTMLText( $linker );
688
		}
689
	}
690
691
	/**
692
	 * Return text serialisation of info links. Ensures more uniform layout
693
	 * throughout wiki (Factbox, Property pages, ...).
694
	 *
695
	 * @param integer $outputformat Element of the SMW_OUTPUT_ enum
696
	 * @param $linker
697
	 *
698
	 * @return string
699
	 */
700 4
	public function getInfolinkText( $outputformat, $linker = null ) {
701 4
		$result = '';
702 4
		$first = true;
703 4
		$extralinks = array();
704
705
		switch ( $outputformat ) {
706 4
			case SMW_OUTPUT_WIKI:
707 1
				foreach ( $this->getInfolinks() as $link ) {
708 1
					if ( $first ) {
709 1
						$result .= '<!-- -->  ' . $link->getWikiText();
710
							// the comment is needed to prevent MediaWiki from linking URL-strings together with the nbsps!
711 1
						$first = false;
712
					} else {
713 1
						$extralinks[] = $link->getWikiText();
714
					}
715
				}
716 1
				break;
717
718 3
			case SMW_OUTPUT_HTML: case SMW_OUTPUT_FILE: default:
0 ignored issues
show
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
719 3
				foreach ( $this->getInfolinks() as $link ) {
720 3
					if ( $first ) {
721 3
						$result .= '&#160;&#160;' . $link->getHTML( $linker );
722 3
						$first = false;
723
					} else {
724 3
						$extralinks[] = $link->getHTML( $linker );
725
					}
726
				}
727 3
				break;
728
		}
729
730 4
		if ( count( $extralinks ) > 0 ) {
731
			$result .= smwfEncodeMessages( $extralinks, 'service', '', false );
732
		}
733
734
		// #1453 SMW::on/off will break any potential link therefore just don't even try
735 4
		return strpos( $result, 'SMW::off' ) !== false || strpos( $result, 'SMW::on' ) !== false ? '' : $result;
736
	}
737
738
	/**
739
	 * Return the plain wiki version of the value, or
740
	 * FALSE if no such version is available. The returned
741
	 * string suffices to reobtain the same DataValue
742
	 * when passing it as an input string to setUserValue().
743
	 */
744
	abstract public function getWikiValue();
745
746
	/**
747
	 * Return a short string that unambiguously specify the type of this
748
	 * value. This value will globally be used to identify the type of a
749
	 * value (in spite of the class it actually belongs to, which can still
750
	 * implement various types).
751
	 */
752 128
	public function getTypeID() {
753 128
		return $this->m_typeid;
754
	}
755
756
	/**
757
	 * @since 2.1
758
	 * @param boolean $renderState
759
	 */
760 1
	public function setServiceLinksRenderState( $renderState = true ) {
761 1
		$this->serviceLinksRenderState = $renderState;
762 1
	}
763
764
	/**
765
	 * Return an array of SMWLink objects that provide additional resources
766
	 * for the given value. Captions can contain some HTML markup which is
767
	 * admissible for wiki text, but no more. Result might have no entries
768
	 * but is always an array.
769
	 */
770 4
	public function getInfolinks() {
771 4
		if ( $this->isValid() && !is_null( $this->m_property ) ) {
772 4
			if ( !$this->mHasSearchLink ) { // add default search link
773 4
				$this->mHasSearchLink = true;
774 4
				$this->m_infolinks[] = SMWInfolink::newPropertySearchLink( '+',
775 4
					$this->m_property->getLabel(), $this->getWikiValue() );
776
			}
777
778 4
			if ( !$this->mHasServiceLinks && $this->serviceLinksRenderState ) { // add further service links
779 3
				$this->addServiceLinks();
780
			}
781
		}
782
783 4
		return $this->m_infolinks;
784
	}
785
786
	/**
787
	 * Overwritten by callers to supply an array of parameters that can be used for
788
	 * creating servicelinks. The number and content of values in the parameter array
789
	 * may vary, depending on the concrete datatype.
790
	 */
791 3
	protected function getServiceLinkParams() {
792 3
		return false;
793
	}
794
795
	/**
796
	 * Return a string that identifies the value of the object, and that can
797
	 * be used to compare different value objects.
798
	 * Possibly overwritten by subclasses (e.g. to ensure that returned
799
	 * value is normalized first)
800
	 *
801
	 * @return string
802
	 */
803
	public function getHash() {
804
		return $this->isValid() ? $this->m_dataitem->getHash() : implode( "\t", $this->mErrors );
805
	}
806
807
	/**
808
	 * Convenience method that checks if the value that is used to sort
809
	 * data of this type is numeric. This only works if the value is set.
810
	 *
811
	 * @return boolean
812
	 */
813
	public function isNumeric() {
814
		if ( isset( $this->m_dataitem ) ) {
815
			return is_numeric( $this->m_dataitem->getSortKey() );
816
		} else {
817
			return false;
818
		}
819
	}
820
821
	/**
822
	 * Return true if a value was defined and understood by the given type,
823
	 * and false if parsing errors occurred or no value was given.
824
	 *
825
	 * @return boolean
826
	 */
827 201
	public function isValid() {
828 201
		return !$this->mHasErrors && isset( $this->m_dataitem );
829
	}
830
831
	/**
832
	 * Whether a datavalue can be used or not (can be made more restrictive then
833
	 * isValid).
834
	 *
835
	 * @note Validity defines a processable state without any technical restrictions
836
	 * while usability is determined by its accessibility to a context
837
	 * (permission, convention etc.)
838
	 *
839
	 * @since  2.2
840
	 *
841
	 * @return boolean
842
	 */
843 162
	public function canUse() {
844 162
		return true;
845
	}
846
847
	/**
848
	 * @note Normally set by the DataValueFactory, or during tests
849
	 *
850
	 * @since 2.3
851
	 *
852
	 * @param array
853
	 */
854 202
	public function setExtraneousFunctions( array $extraneousFunctions ) {
855 202
		$this->extraneousFunctions = $extraneousFunctions;
856 202
	}
857
858
	/**
859
	 * @since 2.3
860
	 *
861
	 * @param string $name
862
	 * @param array $parameters
863
	 *
864
	 * @return mixed
865
	 * @throws RuntimeException
866
	 */
867
	public function getExtraneousFunctionFor( $name, array $parameters = array() ) {
868
869
		if ( isset( $this->extraneousFunctions[$name] ) && is_callable( $this->extraneousFunctions[$name] ) ) {
870
			return call_user_func_array( $this->extraneousFunctions[$name], $parameters );
871
		}
872
873
		throw new RuntimeException( "$name is not registered as extraneous function." );
874
	}
875
876
	/**
877
	 * Return a string that displays all error messages as a tooltip, or
878
	 * an empty string if no errors happened.
879
	 *
880
	 * @return string
881
	 */
882 13
	public function getErrorText() {
883 13
		return smwfEncodeMessages( $this->mErrors );
884
	}
885
886
	/**
887
	 * Return an array of error messages, or an empty array
888
	 * if no errors occurred.
889
	 *
890
	 * @return array
891
	 */
892 158
	public function getErrors() {
893 158
		return $this->mErrors;
894
	}
895
896
	/**
897
	 * Check if property is range restricted and, if so, whether the current value is allowed.
898
	 * Creates an error if the value is illegal.
899
	 */
900 188
	protected function checkAllowedValues() {
901 188
		ValueValidatorRegistry::getInstance()->getConstraintValueValidator()->validate( $this );
902 188
	}
903
904
	/**
905
	 * @since 2.4
906
	 *
907
	 * @param string $value
908
	 *
909
	 * @return string
910
	 */
911 36
	protected function convertDoubleWidth( $value ) {
912 36
		return Localizer::convertDoubleWidth( $value );
913
	}
914
915
}
916