Completed
Push — master ( b51007...cd2f8d )
by mw
37:59 queued 02:53
created

TimeValueFormatter::getCaptionFromDataItem()   D

Complexity

Conditions 9
Paths 96

Size

Total Lines 35
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 9

Importance

Changes 3
Bugs 0 Features 1
Metric Value
dl 0
loc 35
ccs 18
cts 18
cp 1
rs 4.909
c 3
b 0
f 1
cc 9
eloc 17
nc 96
nop 1
crap 9
1
<?php
2
3
namespace SMW\DataValues\ValueFormatters;
4
5
use SMW\Localizer;
6
use SMW\IntlTimeFormatter;
7
use SMWDataValue as DataValue;
8
use SMWTimeValue as TimeValue;
9
use SMWDITime as DITime;
10
use RuntimeException;
11
12
/**
13
 * @license GNU GPL v2+
14
 * @since 2.4
15
 *
16
 * @author mwjames
17
 * @author Markus Krötzsch
18
 * @author Fabian Howahl
19
 * @author Terry A. Hurlbut
20
 */
21
class TimeValueFormatter extends DataValueFormatter {
22
23
	/**
24
	 * @since 2.4
25
	 *
26
	 * {@inheritDoc}
27
	 */
28 45
	public function isFormatterFor( DataValue $dataValue ) {
29 45
		return $dataValue instanceOf TimeValue;
30
	}
31
32
	/**
33
	 * @since 2.4
34
	 *
35
	 * {@inheritDoc}
36
	 */
37 39
	public function format( $type, $linker = null ) {
38
39 39
		if ( !$this->dataValue instanceOf TimeValue ) {
40 1
			throw new RuntimeException( "The formatter is missing a valid TimeValue object" );
41
		}
42
43
		if (
44 38
			$this->dataValue->isValid() &&
45 38
			( $type === self::WIKI_SHORT || $type === self::HTML_SHORT ) ) {
46 22
			return ( $this->dataValue->getCaption() !== false ) ? $this->dataValue->getCaption() : $this->getPreferredCaption();
47
		}
48
49
		if (
50 18
			$this->dataValue->isValid() &&
51 18
			( $type === self::WIKI_LONG || $type === self::HTML_LONG ) ) {
52 12
			return $this->getPreferredCaption();
53
		}
54
55
		// #1074
56 6
		return $this->dataValue->getCaption() !== false ? $this->dataValue->getCaption() : '';
57
	}
58
59
	/**
60
	 * @private
61
	 *
62
	 * Compute a string representation that largely follows the ISO8601 standard
63
	 * of representing dates. Large year numbers may have more than 4 digits,
64
	 * which is not strictly conforming to the standard. The date includes year,
65
	 * month, and day regardless of the input precision, but will only include
66
	 * time when specified.
67
	 *
68
	 * Conforming to the 2000 version of ISO8601, year 1 BC(E) is represented
69
	 * as "0000", year 2 BC(E) as "-0001" and so on.
70
	 *
71
	 * @since 2.4
72
	 *
73
	 * @param DITime $dataItem
0 ignored issues
show
Bug introduced by
There is no parameter named $dataItem. 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...
74
	 * @param boolean $mindefault determining whether values below the
75
	 * precision of our input should be completed with minimal or maximal
76
	 * conceivable values
77
	 *
78
	 * @return string
79
	 */
80 34
	public function getISO8601Date( $mindefault = true ) {
81
82 34
		$dataItem = $this->dataValue->getDataItemForCalendarModel( DITime::CM_GREGORIAN );
0 ignored issues
show
Bug introduced by
The method getDataItemForCalendarModel() does not exist on SMWDataValue. Did you maybe mean getDataItem()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
83 34
		$precision = $dataItem->getPrecision();
84
85 34
		$result = $dataItem->getYear() > 0 ? '' : '-';
86 34
		$result .= str_pad( $dataItem->getYear(), 4, "0", STR_PAD_LEFT );
87
88 34
		$monthnum = $precision >= DITime::PREC_YM ? $dataItem->getMonth() : ( $mindefault ? 1 : 12 );
89 34
		$result .= '-' . str_pad( $monthnum, 2, "0", STR_PAD_LEFT );
90
91 34
		$day = $dataItem->getDay();
92
93 34
		if ( !$mindefault && $precision < DITime::PREC_YMD ) {
94 2
			$day = DITime::getDayNumberForMonth( $monthnum, $dataItem->getYear(), DITime::CM_GREGORIAN );
95 2
		}
96
97 34
		$result .= '-' . str_pad( $day, 2, "0", STR_PAD_LEFT );
98
99 34
		if ( $precision === DITime::PREC_YMDT ) {
100 29
			$result .= 'T' . $this->getTimeString( ( $mindefault ? '00:00:00' : '23:59:59' ) );
101 29
		}
102
103 34
		return $result;
104
	}
105
106
	/**
107
	 * @private
108
	 *
109
	 * Use MediaWiki's date and time formatting. It can't handle all inputs
110
	 * properly, but has superior i18n support.
111
	 *
112
	 * @since 2.4
113
	 *
114
	 * @param DITime $dataItem
0 ignored issues
show
Bug introduced by
There is no parameter named $dataItem. 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...
115
	 *
116
	 * @return string
117
	 */
118 4
	public function getMediaWikiDate() {
119
120 4
		$dataItem = $this->dataValue->getDataItemForCalendarModel( DITime::CM_GREGORIAN );
0 ignored issues
show
Bug introduced by
The method getDataItemForCalendarModel() does not exist on SMWDataValue. Did you maybe mean getDataItem()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
121 4
		$precision = $dataItem->getPrecision();
122
123 4
		$contentLanguage = Localizer::getInstance()->getContentLanguage();
124
125 4
		$year = $dataItem->getYear();
126
127 4
		if ( $year < 0 || $year > 9999 ) {
128 1
			$year = '0000';
129 1
		}
130
131 4
		$year = str_pad( $year, 4, "0", STR_PAD_LEFT );
132
133 4
		if ( $precision <= DITime::PREC_Y ) {
134 3
			return $contentLanguage->formatNum( $year, true );
135
		}
136
137 2
		$month = str_pad( $dataItem->getMonth(), 2, "0", STR_PAD_LEFT );
138 2
		$day = str_pad( $dataItem->getDay(), 2, "0", STR_PAD_LEFT );
139
140 2
		if ( $precision <= DITime::PREC_YMD ) {
141 2
			return $contentLanguage->date( "$year$month$day" . '000000', false, false );
142
		}
143
144 2
		$time = str_replace( ':', '', $this->getTimeString() );
145
146 2
		return $contentLanguage->timeanddate( "$year$month$day$time", false, false );
147
	}
148
149
	/**
150
	 * @private
151
	 *
152
	 * @todo Internationalize the CE and BCE strings.
153
	 *
154
	 * Compute a suitable string to display the given date item.
155
	 *
156
	 * @note MediaWiki's date functions are not applicable for the range of
157
	 * historic dates we support.
158
	 *
159
	 * @since 2.4
160
	 *
161
	 * @param DITime $dataitem
0 ignored issues
show
Documentation introduced by
There is no parameter named $dataitem. Did you maybe mean $dataItem?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

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

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

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

Loading history...
162
	 *
163
	 * @return string
164
	 */
165 10
	public function getCaptionFromDataItem( DITime $dataItem ) {
166
167 10
		$extraneousLanguage = Localizer::getInstance()->getExtraneousLanguage();
168
169 10
		// https://en.wikipedia.org/wiki/Anno_Domini
170 10
		// "...placing the "AD" abbreviation before the year number ... BC is
171 10
		// placed after the year number (for example: AD 2016, but 68 BC)..."
172 10
		// Chicago Manual of Style 2010, pp. 476–7; Goldstein 2007, p. 6.
173 2
174 2
		if ( $dataItem->getYear() > 0 ) {
175
			$cestring = $dataItem->getEra() > 0 ? 'AD' : '';
176
			$result = ( $cestring ? ( $cestring . ' ' ) : '' ) . number_format( $dataItem->getYear(), 0, '.', '' );
177 10
		} else {
178 10
			$bcestring = 'BC';
179 10
			$result = number_format( -( $dataItem->getYear() ), 0, '.', '' ) . ( $bcestring ? ( ' ' . $bcestring ) : '' );
180
		}
181 10
182 10
		if ( $dataItem->getPrecision() >= DITime::PREC_YM ) {
183 10
			$result = $extraneousLanguage->getMonthLabel( $dataItem->getMonth() ) . " " . $result;
184
		}
185 10
186 8
		if ( $dataItem->getPrecision() >= DITime::PREC_YMD ) {
187 8
			$result = $dataItem->getDay() . " " . $result;
188
		}
189 10
190
		if ( $dataItem->getPrecision() >= DITime::PREC_YMDT ) {
191
			$result .= " " . $this->getTimeString();
192
		}
193
194
		if ( $dataItem->getCalendarModel() !== DITime::CM_GREGORIAN ) {
195
			$result .= " " . $dataItem->getCalendarModelLiteral();
196
		}
197
198
		return $result;
199
	}
200
201
	/**
202
	 * @private
203
	 *
204
	 * Return the time as a string. The time string has the format HH:MM:SS,
205
	 * without any timezone information (see class documentation for details
206
	 * on current timezone handling).
207
	 * The parameter $default optionally specifies the value returned
208 34
	 * if the date is valid but has no explicitly specified time. It can
209
	 * also be set to false to detect this situation.
210 34
	 *
211
	 * @since  2.4
212 34
	 *
213
	 * @param string $default
214
	 *
215
	 * @return string
216 34
	 */
217 34
	public function getTimeString( $default = '00:00:00' ) {
218 34
219
		$dataItem = $this->dataValue->getDataItemForCalendarModel( DITime::CM_GREGORIAN );
0 ignored issues
show
Bug introduced by
The method getDataItemForCalendarModel() does not exist on SMWDataValue. Did you maybe mean getDataItem()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
220
221
		if ( $dataItem->getPrecision() < DITime::PREC_YMDT ) {
222
			return $default;
223
		}
224
225
		return sprintf( "%02d", $dataItem->getHour() ) . ':' .
226
		       sprintf( "%02d", $dataItem->getMinute() ) . ':' .
227
		       sprintf( "%02d", $dataItem->getSecond() );
228 1
	}
229
230
	/**
231
	 * @since 2.4
232
	 *
233 1
	 * @param  DITime|null $dataItem
234 1
	 *
235 1
	 * @return string
236 1
	 */
237
	public function getCaptionFromFreeFormat( DITime $dataItem = null ) {
238 1
239 1
		// Prehistory dates are not supported when using this output format
240
		// Only match options encapsulated by [ ... ]
241
		if (
242
			$dataItem !== null &&
243 1
			$dataItem->getYear() > DITime::PREHISTORY &&
244
			preg_match("/\[([^\]]*)\]/", $this->dataValue->getOutputFormat(), $matches ) ) {
245
			$intlTimeFormatter = new IntlTimeFormatter( $dataItem );
246
247
			if ( ( $caption = $intlTimeFormatter->format( $matches[1] ) ) !== false ) {
248
				return $caption;
249
			}
250
		}
251
252
		return $this->getISO8601Date();
253
	}
254
255 17
	/**
256
	 * Compute a suitable string to display this date, taking into account the
257 17
	 * output format and the preferrable calendar models for the data.
258 17
	 *
259
	 * @note MediaWiki's date functions are not applicable for the range
260 17
	 * of historic dates we support.
261 6
	 *
262 13
	 * @return string
263 3
	 */
264 11
	protected function getPreferredCaption() {
265
266 11
		$dataItem = $this->dataValue->getDataItem();
267 1
		$format = strtoupper( $this->dataValue->getOutputFormat() );
268
269
		if ( $format == 'ISO' || $this->dataValue->getOutputFormat() == '-' ) {
270
			return $this->getISO8601Date();
271 11
		} elseif ( $format == 'MEDIAWIKI' ) {
272
			return $this->getMediaWikiDate();
273
		} elseif ( $format == 'SORTKEY' ) {
274 11
			return $dataItem->getSortKey();
275 11
		} elseif ( $format == 'JD' ) {
276 3
			return $dataItem->getJD();
277
		}
278 3
279 11
		// Does the formatting require calendar conversion?
280
		$model = $dataItem->getCalendarModel();
281
282 11
		if (
283 1
			( strpos( $format, 'JL' ) !== false ) ||
284 10
			( $dataItem->getJD() < TimeValue::J1582 && strpos( $format, 'GR' ) === false ) ) {
285
			$model = DITime::CM_JULIAN;
286
		} elseif ( strpos( $format, 'GR' ) !== false ) {
287
			$model = DITime::CM_GREGORIAN;
288
		}
289
290
		if ( strpos( $format, '-F[' ) !== false ) {
291 10
			return $this->getCaptionFromFreeFormat( $this->dataValue->getDataItemForCalendarModel( $model ) );
0 ignored issues
show
Bug introduced by
The method getDataItemForCalendarModel() does not exist on SMWDataValue. Did you maybe mean getDataItem()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
292
		} elseif ( $dataItem->getYear() > TimeValue::PREHISTORY && $dataItem->getPrecision() >= DITime::PREC_YM ) {
293
			// Do not convert between Gregorian and Julian if only
294 4
			// year is given (years largely overlap in history, but
295
			// assuming 1 Jan as the default date, the year number
296
			// would change in conversion).
297
			// Also do not convert calendars in prehistory: not
298
			// meaningful (getDataItemForCalendarModel may return null).
299
			return $this->getCaptionFromDataItem( $this->dataValue->getDataItemForCalendarModel( $model ) );
0 ignored issues
show
Bug introduced by
The method getDataItemForCalendarModel() does not exist on SMWDataValue. Did you maybe mean getDataItem()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
300
		}
301
302
		return $this->getCaptionFromDataItem( $dataItem );
0 ignored issues
show
Compatibility introduced by
$dataItem of type object<SMWDataItem> is not a sub-type of object<SMWDITime>. It seems like you assume a child class of the class SMWDataItem to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
303
	}
304
305
}
306