Passed
Pull Request — master (#49)
by no
04:29 queued 01:10
created

TimeFormatter::getFormattedCalendarModel()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 9
ccs 0
cts 5
cp 0
rs 9.6666
cc 2
eloc 5
nc 2
nop 1
crap 6
1
<?php
2
3
namespace ValueFormatters;
4
5
use DataValues\TimeValue;
6
use InvalidArgumentException;
7
8
/**
9
 * Basic plain text formatter for TimeValue objects that either delegates formatting to an other
10
 * formatter given via self::OPT_TIME_ISO_FORMATTER or outputs the timestamp in simple YMD-ordered
11
 * fallback formats, resembling ISO 8601.
12
 *
13
 * @since 0.1
14
 *
15
 * @license GPL-2.0+
16
 * @author H. Snater < [email protected] >
17
 * @author Thiemo Mättig
18
 */
19
class TimeFormatter extends ValueFormatterBase {
20
21
	/**
22
	 * @deprecated since 0.7.1, use TimeValue::CALENDAR_GREGORIAN instead
23
	 */
24
	const CALENDAR_GREGORIAN = TimeValue::CALENDAR_GREGORIAN;
25
26
	/**
27
	 * @deprecated since 0.7.1, use TimeValue::CALENDAR_JULIAN instead
28
	 */
29
	const CALENDAR_JULIAN = TimeValue::CALENDAR_JULIAN;
30
31
	/**
32
	 * Option to localize calendar models. Must contain an array mapping known calendar model URIs
33
	 * to localized calendar model names.
34
	 */
35
	const OPT_CALENDARNAMES = 'calendars';
36
37
	/**
38
	 * Option for a custom timestamp formatter. Must contain an instance of a ValueFormatter
39
	 * subclass, capable of formatting TimeValue objects. The output of the custom formatter is
40
	 * threaded as plain text and passed through.
41
	 */
42
	const OPT_TIME_ISO_FORMATTER = 'time iso formatter';
43
44
	/**
45
	 * @see ValueFormatterBase::__construct
46
	 *
47
	 * @param FormatterOptions|null $options
48
	 */
49 20
	public function __construct( FormatterOptions $options = null ) {
50 20
		parent::__construct( $options );
51
52
		// A non-localized default is still better than showing full concept URIs.
53 20
		$this->defaultOption( self::OPT_CALENDARNAMES, array(
54 20
			TimeValue::CALENDAR_GREGORIAN => 'Gregorian',
55 20
			TimeValue::CALENDAR_JULIAN => 'Julian',
56
		) );
57 20
		$this->defaultOption( self::OPT_TIME_ISO_FORMATTER, null );
58 20
	}
59
60
	/**
61
	 * @see ValueFormatter::format
62
	 *
63
	 * @param TimeValue $value
64
	 *
65
	 * @throws InvalidArgumentException
66
	 * @return string Plain text
67
	 */
68 20
	public function format( $value ) {
69 20
		if ( !( $value instanceof TimeValue ) ) {
70
			throw new InvalidArgumentException( 'Data value type mismatch. Expected a TimeValue.' );
71
		}
72
73 20
		$formatted = $this->getFormattedTimestamp( $value );
74
		// FIXME: Temporarily disabled.
75
		// $formatted .= ' (' . $this->getFormattedCalendarModel( $value->getCalendarModel() ) . ')';
76 20
		return $formatted;
77
	}
78
79
	/**
80
	 * @param TimeValue $value
81
	 *
82
	 * @return string Plain text
83
	 */
84 20
	private function getFormattedTimestamp( TimeValue $value ) {
85 20
		$formatter = $this->getOption( self::OPT_TIME_ISO_FORMATTER );
86
87 20
		if ( $formatter instanceof ValueFormatter ) {
88 1
			return $formatter->format( $value );
89
		}
90
91 19
		if ( !preg_match(
92
			// Loose check for ISO-like strings, as used in Gregorian and Julian time values.
93 19
			'/^([-+]?)(\d+)-(\d+)-(\d+)(?:T(\d+):(\d+)(?::(\d+))?)?Z?$/i',
94 19
			$value->getTime(),
95 19
			$matches
96
		) ) {
97
			return $value->getTime();
98
		}
99
100 19
		list( , $sign, $year, $month, $day, $hour, $minute, $second ) = $matches;
101
102
		// Actual MINUS SIGN (U+2212) instead of HYPHEN-MINUS (U+002D)
103 19
		$sign = $sign === '-' ? "\xE2\x88\x92" : '';
104
105
		// Warning, never cast the year to integer to not run into 32-bit integer overflows!
106 19
		$year = ltrim( $year, '0' );
107
108 19
		if ( $value->getPrecision() <= TimeValue::PRECISION_YEAR ) {
109 3
			return sprintf( '%s%04s', $sign, $year );
110
		}
111
112 16
		switch ( $value->getPrecision() ) {
113 16
			case TimeValue::PRECISION_MONTH:
114 1
				return sprintf(
115 1
					'%s%04s-%02s',
116 1
					$sign, $year, $month
117
				);
118 15
			case TimeValue::PRECISION_DAY:
119 12
				return sprintf(
120 12
					'%s%04s-%02s-%02s',
121 12
					$sign, $year, $month, $day
122
				);
123 3
			case TimeValue::PRECISION_HOUR:
124 1
				return sprintf(
125 1
					'%s%04s-%02s-%02sT%02s',
126 1
					$sign, $year, $month, $day, $hour
127
				);
128 2
			case TimeValue::PRECISION_MINUTE:
129 1
				return sprintf(
130 1
					'%s%04s-%02s-%02sT%02s:%02s',
131 1
					$sign, $year, $month, $day, $hour, $minute
132
				);
133
			default:
134 1
				return sprintf(
135 1
					'%s%04s-%02s-%02sT%02s:%02s:%02s',
136 1
					$sign, $year, $month, $day, $hour, $minute, $second
137
				);
138
		}
139
	}
140
141
	/**
142
	 * @param string $calendarModel
143
	 *
144
	 * @return string Plain text
145
	 */
146
	private function getFormattedCalendarModel( $calendarModel ) {
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
147
		$calendarNames = $this->getOption( self::OPT_CALENDARNAMES );
148
149
		if ( array_key_exists( $calendarModel, $calendarNames ) ) {
150
			return $calendarNames[$calendarModel];
151
		}
152
153
		return $calendarModel;
154
	}
155
156
}
157