diff --git a/includes/datavalues/SMW_DV_Time.php b/includes/datavalues/SMW_DV_Time.php index dfc4212def..75e631691a 100644 --- a/includes/datavalues/SMW_DV_Time.php +++ b/includes/datavalues/SMW_DV_Time.php @@ -1,4 +1,7 @@ getDIType() == SMWDataItem::TYPE_TIME ) { - $this->m_dataitem = $dataItem; - $this->m_caption = $this->m_wikivalue = false; - return true; - } else { + + if ( $dataItem->getDIType() !== SMWDataItem::TYPE_TIME ) { return false; } - } - public function getShortWikiText( $linked = null ) { - if ( $this->isValid() ) { - return ( $this->m_caption !== false ) ? $this->m_caption : $this->getPreferredCaption(); - } + $this->m_dataitem = $dataItem; + $this->m_caption = false; + $this->m_wikivalue = false; - // #1074 - return $this->m_caption !== false ? $this->m_caption : ''; + return true; } + /** + * @see SMWDataValue::getShortWikiText + * + * {@inheritDoc} + */ + public function getShortWikiText( $linker = null ) { + return $this->getDataValueFormatter()->format( DataValueFormatter::WIKI_SHORT, $linker ); + } + + /** + * @see SMWDataValue::getShortHTMLText + * + * {@inheritDoc} + */ public function getShortHTMLText( $linker = null ) { - return $this->getShortWikiText( $linker ); // safe in HTML + return $this->getDataValueFormatter()->format( DataValueFormatter::HTML_SHORT, $linker ); } - public function getLongWikiText( $linked = null ) { - return $this->isValid() ? $this->getPreferredCaption() : $this->getErrorText(); + /** + * @see SMWDataValue::getLongWikiText + * + * {@inheritDoc} + */ + public function getLongWikiText( $linker = null ) { + return $this->getDataValueFormatter()->format( DataValueFormatter::WIKI_LONG, $linker ); } + /** + * @see SMWDataValue::getLongHTMLText + * + * {@inheritDoc} + */ public function getLongHTMLText( $linker = null ) { - return $this->getLongWikiText( $linker ); // safe in HTML + return $this->getDataValueFormatter()->format( DataValueFormatter::HTML_LONG, $linker ); } - /// @todo The preferred caption may not be suitable as a wiki value (i.e. not parsable). + /** + * @todo The preferred caption may not be suitable as a wiki value (i.e. not parsable). + * @see SMWDataValue::getLongHTMLText + * + * {@inheritDoc} + */ public function getWikiValue() { - return $this->m_wikivalue ? $this->m_wikivalue : $this->getPreferredCaption(); + return $this->m_wikivalue ? $this->m_wikivalue : $this->getLongWikiText(); } + /** + * @see SMWDataValue::isNumeric + * + * {@inheritDoc} + */ public function isNumeric() { return true; } @@ -643,7 +674,7 @@ public function isNumeric() { * @return mixed typically a number but possibly false */ public function getYear( $calendarmodel = SMWDITime::CM_GREGORIAN ) { - $di = $this->getDataForCalendarModel( $calendarmodel ); + $di = $this->getDataItemForCalendarModel( $calendarmodel ); if ( !is_null( $di ) ) { return $di->getYear(); } else { @@ -660,7 +691,7 @@ public function getYear( $calendarmodel = SMWDITime::CM_GREGORIAN ) { * @return mixed typically a number but possibly anything given as $default */ public function getMonth( $calendarmodel = SMWDITime::CM_GREGORIAN, $default = 1 ) { - $di = $this->getDataForCalendarModel( $calendarmodel ); + $di = $this->getDataItemForCalendarModel( $calendarmodel ); if ( !is_null( $di ) ) { return ( $di->getPrecision() >= SMWDITime::PREC_YM ) ? $di->getMonth() : $default; } else { @@ -677,7 +708,7 @@ public function getMonth( $calendarmodel = SMWDITime::CM_GREGORIAN, $default = 1 * @return mixed typically a number but possibly anything given as $default */ public function getDay( $calendarmodel = SMWDITime::CM_GREGORIAN, $default = 1 ) { - $di = $this->getDataForCalendarModel( $calendarmodel ); + $di = $this->getDataItemForCalendarModel( $calendarmodel ); if ( !is_null( $di ) ) { return ( $di->getPrecision() >= SMWDITime::PREC_YMD ) ? $di->getDay() : $default; } else { @@ -686,21 +717,12 @@ public function getDay( $calendarmodel = SMWDITime::CM_GREGORIAN, $default = 1 ) } /** - * Return the time as a string. The time string has the format HH:MM:SS, - * without any timezone information (see class documentation for details - * on current timezone handling). - * The parameter $default optionally specifies the value returned - * if the date is valid but has no explicitly specified time. It can - * also be set to false to detect this situation. + * @see TimeValueFormatter::getTimeStringFromDataItem + * + * @return */ public function getTimeString( $default = '00:00:00' ) { - if ( $this->m_dataitem->getPrecision() < SMWDITime::PREC_YMDT ) { - return $default; - } else { - return sprintf( "%02d", $this->m_dataitem->getHour() ) . ':' . - sprintf( "%02d", $this->m_dataitem->getMinute() ) . ':' . - sprintf( "%02d", $this->m_dataitem->getSecond() ); - } + return $this->getDataValueFormatter()->getTimeString( $default ); } /** @@ -711,68 +733,25 @@ public function getXMLSchemaDate( $mindefault = true ) { } /** - * Compute a string representation that largely follows the ISO8601 - * standard of representing dates. Large year numbers may have more - * than 4 digits, which is not strictly conforming to the standard. - * The date includes year, month, and day regardless of the input - * precision, but will only include time when specified. - * - * Conforming to the 2000 version of ISO8601, year 1 BC(E) is - * represented as "0000", year 2 BC(E) as "-0001" and so on. + * @see TimeValueFormatter::getISO8601DateFromDataItem * * @param $mindefault boolean determining whether values below the * precision of our input should be completed with minimal or maximal * conceivable values + * * @return string */ public function getISO8601Date( $mindefault = true ) { - $result = ( $this->getYear() > 0 ) ? '' : '-'; - $monthnum = $this->getMonth( SMWDITime::CM_GREGORIAN, ( $mindefault ? 1 : 12 ) ); - $result .= str_pad( $this->getYear(), 4, "0", STR_PAD_LEFT ) . - '-' . str_pad( $monthnum, 2, "0", STR_PAD_LEFT ); - if ( !$mindefault && ( $this->m_dataitem->getPrecision() < SMWDITime::PREC_YMD ) ) { - $maxday = SMWDITime::getDayNumberForMonth( $monthnum, $this->getYear(), SMWDITime::CM_GREGORIAN ); - $result .= '-' . str_pad( $this->getDay( SMWDITime::CM_GREGORIAN, $maxday ), 2, "0", STR_PAD_LEFT ); - } else { - $result .= '-' . str_pad( $this->getDay(), 2, "0", STR_PAD_LEFT ); - } - if ( $this->m_dataitem->getPrecision() == SMWDITime::PREC_YMDT ) { - $result .= 'T' . $this->getTimeString( ( $mindefault ? '00:00:00' : '23:59:59' ) ); - } - return $result; + return $this->getDataValueFormatter()->getISO8601Date( $mindefault ); } /** - * Use MediaWiki's date and time formatting. It can't handle all inputs - * properly, but has superior i18n support. + * @see TimeValueFormatter::getMediaWikiDateFromDataItem * * @return string */ public function getMediaWikiDate() { - global $wgContLang; - - $dataitem = $this->m_dataitem; - $precision = $dataitem->getPrecision(); - - $year = $this->getYear(); - if ( $year < 0 || $year > 9999 ) { - $year = '0000'; - } - $year = str_pad( $year, 4, "0", STR_PAD_LEFT ); - - if ( $precision <= SMWDITime::PREC_Y ) { - return $wgContLang->formatNum( $year, true ); - } - - $month = str_pad( $this->getMonth( SMWDITime::CM_GREGORIAN ), 2, "0", STR_PAD_LEFT ); - $day = str_pad( $this->getDay( SMWDITime::CM_GREGORIAN ), 2, "0", STR_PAD_LEFT ); - - if ( $precision <= SMWDITime::PREC_YMD ) { - return $wgContLang->date( "$year$month$day" . '000000', false, false ); - } - - $time = str_replace( ':', '', $this->getTimeString() ); - return $wgContLang->timeanddate( "$year$month$day$time", false, false ); + return $this->getDataValueFormatter()->getMediaWikiDate(); } /** @@ -784,7 +763,7 @@ public function getMediaWikiDate() { * @param $calendarmodel integer one of SMWDITime::CM_GREGORIAN or SMWDITime::CM_JULIAN * @return SMWDITime */ - protected function getDataForCalendarModel( $calendarmodel ) { + public function getDataItemForCalendarModel( $calendarmodel ) { if ( $this->m_dataitem->getYear() <= self::PREHISTORY ) { return ( $this->m_dataitem->getCalendarModel() == $calendarmodel ) ? $this->m_dataitem : null; } elseif ( $calendarmodel == SMWDITime::CM_GREGORIAN ) { @@ -800,79 +779,4 @@ protected function getDataForCalendarModel( $calendarmodel ) { } } - /** - * Compute a suitable string to display the given date item. - * @note MediaWiki's date functions are not applicable for the range of historic dates we support. - * - * @since 1.6 - * - * @param SMWDITime $dataitem - * - * @return string - * @todo Internationalize the CE and BCE strings. - */ - public function getCaptionFromDataitem( SMWDITime $dataitem ) { - /** - * @var SMWLanguage $smwgContLang - */ - global $smwgContLang; - - if ( $dataitem->getYear() > 0 ) { - $cestring = ''; - $result = number_format( $dataitem->getYear(), 0, '.', '' ) . ( $cestring ? ( ' ' . $cestring ) : '' ); - } else { - $bcestring = 'BC'; - $result = number_format( -( $dataitem->getYear() ), 0, '.', '' ) . ( $bcestring ? ( ' ' . $bcestring ) : '' ); - } - - if ( $dataitem->getPrecision() >= SMWDITime::PREC_YM ) { - $result = $smwgContLang->getMonthLabel( $dataitem->getMonth() ) . " " . $result; - } - - if ( $dataitem->getPrecision() >= SMWDITime::PREC_YMD ) { - $result = $dataitem->getDay() . " " . $result; - } - - if ( $dataitem->getPrecision() >= SMWDITime::PREC_YMDT ) { - $result .= " " . $this->getTimeString(); - } - - return $result; - } - - /** - * Compute a suitable string to display this date, taking into account - * the output format and the preferrable calendar models for the data. - * @note MediaWiki's date functions are not applicable for the range of historic dates we support. - * @return string - */ - protected function getPreferredCaption() { - $year = $this->m_dataitem->getYear(); - $format = strtoupper( $this->m_outformat ); - - if ( $format == 'ISO' || $this->m_outformat == '-' ) { - return $this->getISO8601Date(); - } elseif ( $format == 'MEDIAWIKI' ) { - return $this->getMediaWikiDate(); - } elseif ( $format == 'SORTKEY' ) { - return $this->m_dataitem->getSortKey(); - } elseif ( $year > self::PREHISTORY && $this->m_dataitem->getPrecision() >= SMWDITime::PREC_YM ) { - // Do not convert between Gregorian and Julian if only - // year is given (years largely overlap in history, but - // assuming 1 Jan as the default date, the year number - // would change in conversion). - // Also do not convert calendars in prehistory: not - // meaningful (getDataForCalendarModel may return null). - if ( ( $format == 'JL' ) || - ( $this->m_dataitem->getJD() < self::J1582 - && $format != 'GR' ) ) { - $model = SMWDITime::CM_JULIAN; - } else { - $model = SMWDITime::CM_GREGORIAN; - } - return $this->getCaptionFromDataitem( $this->getDataForCalendarModel( $model ) ); - } else { - return $this->getCaptionFromDataitem( $this->m_dataitem ); - } - } } diff --git a/src/DataValues/ValueFormatterRegistry.php b/src/DataValues/ValueFormatterRegistry.php index f0c4d87731..eb4ca88d9c 100644 --- a/src/DataValues/ValueFormatterRegistry.php +++ b/src/DataValues/ValueFormatterRegistry.php @@ -8,6 +8,7 @@ use SMW\DataValues\ValueFormatters\CodeStringValueFormatter; use SMW\DataValues\ValueFormatters\NoValueFormatter; use SMW\DataValues\ValueFormatters\DataValueFormatter; +use SMW\DataValues\ValueFormatters\TimeValueFormatter; use SMWDataValue as DataValue; /** @@ -100,6 +101,7 @@ private function newDispatchingDataValueFormatter() { // To be checked only after DispatchingDataValueFormatter::addDataValueFormatter did // not match any previous registered DataValueFormatters $dispatchingDataValueFormatter->addDefaultDataValueFormatter( new StringValueFormatter() ); + $dispatchingDataValueFormatter->addDefaultDataValueFormatter( new TimeValueFormatter() ); $dispatchingDataValueFormatter->addDefaultDataValueFormatter( new NoValueFormatter() ); return $dispatchingDataValueFormatter; diff --git a/src/DataValues/ValueFormatters/DataValueFormatter.php b/src/DataValues/ValueFormatters/DataValueFormatter.php index 250c826b13..535d5fc591 100644 --- a/src/DataValues/ValueFormatters/DataValueFormatter.php +++ b/src/DataValues/ValueFormatters/DataValueFormatter.php @@ -90,6 +90,15 @@ public function setDataValue( DataValue $dataValue ) { $this->options = null; } + /** + * @since 2.4 + * + * @return array + */ + public function getErrors() { + return $this->dataValue->getErrors(); + } + /** * @since 2.4 * diff --git a/src/DataValues/ValueFormatters/TimeValueFormatter.php b/src/DataValues/ValueFormatters/TimeValueFormatter.php new file mode 100644 index 0000000000..b80dc4b3e6 --- /dev/null +++ b/src/DataValues/ValueFormatters/TimeValueFormatter.php @@ -0,0 +1,260 @@ +dataValue instanceOf TimeValue ) { + throw new RuntimeException( "The formatter is missing a valid TimeValue object" ); + } + + if ( + $this->dataValue->isValid() && + ( $type === self::WIKI_SHORT || $type === self::HTML_SHORT ) ) { + return ( $this->dataValue->getCaption() !== false ) ? $this->dataValue->getCaption() : $this->getPreferredCaption(); + } + + if ( + $this->dataValue->isValid() && + ( $type === self::WIKI_LONG || $type === self::HTML_LONG ) ) { + return $this->getPreferredCaption(); + } + + // #1074 + return $this->dataValue->getCaption() !== false ? $this->dataValue->getCaption() : ''; + } + + /** + * @private + * + * Compute a string representation that largely follows the ISO8601 standard + * of representing dates. Large year numbers may have more than 4 digits, + * which is not strictly conforming to the standard. The date includes year, + * month, and day regardless of the input precision, but will only include + * time when specified. + * + * Conforming to the 2000 version of ISO8601, year 1 BC(E) is represented + * as "0000", year 2 BC(E) as "-0001" and so on. + * + * @since 2.4 + * + * @param DITime $dataItem + * @param boolean $mindefault determining whether values below the + * precision of our input should be completed with minimal or maximal + * conceivable values + * + * @return string + */ + public function getISO8601Date( $mindefault = true ) { + + $dataItem = $this->dataValue->getDataItemForCalendarModel( DITime::CM_GREGORIAN ); + $precision = $dataItem->getPrecision(); + + $result = $dataItem->getYear() > 0 ? '' : '-'; + $result .= str_pad( $dataItem->getYear(), 4, "0", STR_PAD_LEFT ); + + $monthnum = $precision >= DITime::PREC_YM ? $dataItem->getMonth() : ( $mindefault ? 1 : 12 ); + $result .= '-' . str_pad( $monthnum, 2, "0", STR_PAD_LEFT ); + + $day = $dataItem->getDay(); + + if ( !$mindefault && $precision < DITime::PREC_YMD ) { + $day = DITime::getDayNumberForMonth( $monthnum, $dataItem->getYear(), DITime::CM_GREGORIAN ); + } + + $result .= '-' . str_pad( $day, 2, "0", STR_PAD_LEFT ); + + if ( $precision === DITime::PREC_YMDT ) { + $result .= 'T' . $this->getTimeString( ( $mindefault ? '00:00:00' : '23:59:59' ) ); + } + + return $result; + } + + /** + * @private + * + * Use MediaWiki's date and time formatting. It can't handle all inputs + * properly, but has superior i18n support. + * + * @since 2.4 + * + * @param DITime $dataItem + * + * @return string + */ + public function getMediaWikiDate() { + + $dataItem = $this->dataValue->getDataItemForCalendarModel( DITime::CM_GREGORIAN ); + $precision = $dataItem->getPrecision(); + + $contentLanguage = Localizer::getInstance()->getContentLanguage(); + + $year = $dataItem->getYear(); + + if ( $year < 0 || $year > 9999 ) { + $year = '0000'; + } + + $year = str_pad( $year, 4, "0", STR_PAD_LEFT ); + + if ( $precision <= DITime::PREC_Y ) { + return $contentLanguage->formatNum( $year, true ); + } + + $month = str_pad( $dataItem->getMonth(), 2, "0", STR_PAD_LEFT ); + $day = str_pad( $dataItem->getDay(), 2, "0", STR_PAD_LEFT ); + + if ( $precision <= DITime::PREC_YMD ) { + return $contentLanguage->date( "$year$month$day" . '000000', false, false ); + } + + $time = str_replace( ':', '', $this->getTimeString() ); + + return $contentLanguage->timeanddate( "$year$month$day$time", false, false ); + } + + /** + * @private + * + * @todo Internationalize the CE and BCE strings. + * + * Compute a suitable string to display the given date item. + * + * @note MediaWiki's date functions are not applicable for the range of + * historic dates we support. + * + * @since 2.4 + * + * @param DITime $dataitem + * + * @return string + */ + public function getCaptionFromDataItem( DITime $dataItem ) { + + $extraneousLanguage = Localizer::getInstance()->getExtraneousLanguage(); + + if ( $dataItem->getYear() > 0 ) { + $cestring = ''; + $result = number_format( $dataItem->getYear(), 0, '.', '' ) . ( $cestring ? ( ' ' . $cestring ) : '' ); + } else { + $bcestring = 'BC'; + $result = number_format( -( $dataItem->getYear() ), 0, '.', '' ) . ( $bcestring ? ( ' ' . $bcestring ) : '' ); + } + + if ( $dataItem->getPrecision() >= DITime::PREC_YM ) { + $result = $extraneousLanguage->getMonthLabel( $dataItem->getMonth() ) . " " . $result; + } + + if ( $dataItem->getPrecision() >= DITime::PREC_YMD ) { + $result = $dataItem->getDay() . " " . $result; + } + + if ( $dataItem->getPrecision() >= DITime::PREC_YMDT ) { + $result .= " " . $this->getTimeString(); + } + + return $result; + } + + /** + * @private + * + * Return the time as a string. The time string has the format HH:MM:SS, + * without any timezone information (see class documentation for details + * on current timezone handling). + * The parameter $default optionally specifies the value returned + * if the date is valid but has no explicitly specified time. It can + * also be set to false to detect this situation. + * + * @since 2.4 + * + * @param string $default + * + * @return string + */ + public function getTimeString( $default = '00:00:00' ) { + + $dataItem = $this->dataValue->getDataItemForCalendarModel( DITime::CM_GREGORIAN ); + + if ( $dataItem->getPrecision() < DITime::PREC_YMDT ) { + return $default; + } + + return sprintf( "%02d", $dataItem->getHour() ) . ':' . + sprintf( "%02d", $dataItem->getMinute() ) . ':' . + sprintf( "%02d", $dataItem->getSecond() ); + } + + /** + * Compute a suitable string to display this date, taking into account the + * output format and the preferrable calendar models for the data. + * + * @note MediaWiki's date functions are not applicable for the range + * of historic dates we support. + * + * @return string + */ + protected function getPreferredCaption() { + + $dataItem = $this->dataValue->getDataItem(); + $format = strtoupper( $this->dataValue->getOutputFormat() ); + + if ( $format == 'ISO' || $this->dataValue->getOutputFormat() == '-' ) { + return $this->getISO8601Date(); + } elseif ( $format == 'MEDIAWIKI' ) { + return $this->getMediaWikiDate(); + } elseif ( $format == 'SORTKEY' ) { + return $dataItem->getSortKey(); + } elseif ( $dataItem->getYear() > TimeValue::PREHISTORY && $dataItem->getPrecision() >= DITime::PREC_YM ) { + // Do not convert between Gregorian and Julian if only + // year is given (years largely overlap in history, but + // assuming 1 Jan as the default date, the year number + // would change in conversion). + // Also do not convert calendars in prehistory: not + // meaningful (getDataItemForCalendarModel may return null). + if ( ( $format == 'JL' ) || + ( $dataItem->getJD() < TimeValue::J1582 + && $format != 'GR' ) ) { + $model = DITime::CM_JULIAN; + } else { + $model = DITime::CM_GREGORIAN; + } + return $this->getCaptionFromDataItem( $this->dataValue->getDataItemForCalendarModel( $model ) ); + } + + return $this->getCaptionFromDataItem( $dataItem ); + } + +} diff --git a/src/Localizer.php b/src/Localizer.php index 902ecaeea7..565ffdcf4b 100644 --- a/src/Localizer.php +++ b/src/Localizer.php @@ -76,6 +76,15 @@ public static function getUserLanguage() { return $GLOBALS['wgLang']; } + /** + * @since 2.4 + * + * @return Language + */ + public static function getExtraneousLanguage() { + return $GLOBALS['smwgContLang']; + } + /** * @since 2.1 * diff --git a/tests/phpunit/Integration/ByJsonScript/Fixtures/p-0413.json b/tests/phpunit/Integration/ByJsonScript/Fixtures/p-0413.json index 37a3ec50bb..734e4ec6bf 100644 --- a/tests/phpunit/Integration/ByJsonScript/Fixtures/p-0413.json +++ b/tests/phpunit/Integration/ByJsonScript/Fixtures/p-0413.json @@ -1,5 +1,5 @@ { - "description": "Test in-text annotation for different `_dat` input/output (en)", + "description": "Test in-text annotation for different `_dat` input/output (en, skip virtuoso)", "properties": [ { "name": "Has date", @@ -146,6 +146,20 @@ { "name": "Example/P0413/16a", "contents": "{{#ask: [[Example/P0413/16]] |?Has date |?Has date#- |?Has date#ISO=ISO Date |?Has date#MEDIAWIKI=MW Date }}" + }, + { + "name": "Example/P0413/17", + "contents": "[[Has date::11000 BC]]", + "skip-on": { + "virtuoso": "Virtuoso 6.1 does not support BC/BCE dates" + } + }, + { + "name": "Example/P0413/17a", + "contents": "{{#ask: [[Example/P0413/17]] |?Has date |?Has date#- |?Has date#ISO=ISO Date |?Has date#MEDIAWIKI=MW Date }}", + "skip-on": { + "virtuoso": "Virtuoso 6.1 does not support BC/BCE dates" + } } ], "parser-testcases": [ @@ -595,6 +609,41 @@ "22 February 2000" ] } + }, + { + "about": "#32 Pre-history", + "skip-on": { + "virtuoso": "Virtuoso 6.1 does not support BC/BCE dates" + }, + "subject": "Example/P0413/17", + "store": { + "semantic-data": { + "strict-mode-valuematch": false, + "propertyCount": 3, + "propertyKeys": [ "Has_date", "_SKEY", "_MDAT" ], + "propertyValues": [ "--11000-01-01" ] + } + }, + "expected-output": { + "to-contain": [ + "11000 BC" + ] + } + }, + { + "about": "#33", + "skip-on": { + "virtuoso": "Virtuoso 6.1 does not support BC/BCE dates" + }, + "subject": "Example/P0413/17a", + "expected-output": { + "to-contain": [ + "11000 BC", + "--11000-01-01", + "--11000-01-01", + "0000" + ] + } } ], "settings": { diff --git a/tests/phpunit/Integration/ByJsonScript/README.md b/tests/phpunit/Integration/ByJsonScript/README.md index 089f5a1f71..1917322c06 100644 --- a/tests/phpunit/Integration/ByJsonScript/README.md +++ b/tests/phpunit/Integration/ByJsonScript/README.md @@ -42,7 +42,7 @@ Contains 93 files: * [p-0410.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/ByJsonScript/Fixtures/p-0410.json) Test in-text annotation on `_num`/`_tem`/`_qty` type with denoted precision (`_PREC`) and/or `-p` printout precision marker (#1335, en) * [p-0411.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/ByJsonScript/Fixtures/p-0411.json) Test in-text annotation (and #subobject) using a monolingual property (#1344, en) * [p-0412.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/ByJsonScript/Fixtures/p-0412.json) Test in-text annotation for `_boo` datatype (ja) -* [p-0413.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/ByJsonScript/Fixtures/p-0413.json) Test in-text annotation for different `_dat` input/output (en) +* [p-0413.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/ByJsonScript/Fixtures/p-0413.json) Test in-text annotation for different `_dat` input/output (en, skip virtuoso) * [p-0701.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/ByJsonScript/Fixtures/p-0701.json) Test to create inverted annotation using a #ask/template combination (#711, `import-annotation=true`) * [p-0702.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/ByJsonScript/Fixtures/p-0702.json) Test #ask with `format=table` on inverse property/printrquest (#1270, en) * [p-0901.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/ByJsonScript/Fixtures/p-0901.json) Test #ask on moved redirected subject (#1086) diff --git a/tests/phpunit/JsonTestCaseFileHandler.php b/tests/phpunit/JsonTestCaseFileHandler.php index 6e0290fe27..b366c77537 100644 --- a/tests/phpunit/JsonTestCaseFileHandler.php +++ b/tests/phpunit/JsonTestCaseFileHandler.php @@ -3,7 +3,7 @@ namespace SMW\Tests; use SMW\FileReader; - +use SMW\Localizer; use RuntimeException; /** @@ -165,6 +165,7 @@ public function getSettingsFor( $key ) { if ( ( $key === 'wgContLang' || $key === 'wgLang' ) && isset( $settings[$key] ) ) { \RequestContext::getMain()->setLanguage( $settings[$key] ); + Localizer::getInstance()->clear(); return \Language::factory( $settings[$key] ); } diff --git a/tests/phpunit/Unit/DataValues/ValueFormatters/TimeValueFormatterTest.php b/tests/phpunit/Unit/DataValues/ValueFormatters/TimeValueFormatterTest.php new file mode 100644 index 0000000000..2fa418783b --- /dev/null +++ b/tests/phpunit/Unit/DataValues/ValueFormatters/TimeValueFormatterTest.php @@ -0,0 +1,301 @@ +assertInstanceOf( + '\SMW\DataValues\ValueFormatters\TimeValueFormatter', + new TimeValueFormatter() + ); + } + + public function testIsFormatterForValidation() { + + $timeValue = $this->getMockBuilder( '\SMWTimeValue' ) + ->disableOriginalConstructor() + ->getMock(); + + $instance = new TimeValueFormatter(); + + $this->assertTrue( + $instance->isFormatterFor( $timeValue ) + ); + } + + public function testTryToFormatOnMissingDataValueThrowsException() { + + $instance = new TimeValueFormatter(); + + $this->setExpectedException( 'RuntimeException' ); + $instance->format( TimeValueFormatter::VALUE ); + } + + public function testSetGetOptionValue() { + + $instance = new TimeValueFormatter(); + $instance->setOption( 'Foo', 1001 ); + + $this->assertEquals( + 1001, + $instance->getOptionValueFor( 'Foo' ) + ); + } + + public function testToUseCaptionOutput() { + + $timeValue = new TimeValue( '_dat' ); + $timeValue->setCaption( 'ABC[<>]' ); + + $instance = new TimeValueFormatter( $timeValue ); + + $this->assertEquals( + 'ABC[<>]', + $instance->format( TimeValueFormatter::WIKI_SHORT ) + ); + } + + /** + * @dataProvider timeInputProvider + */ + public function testFormat( $timeUserValue, $type, $format, $linker, $expected ) { + + $timeValue = new TimeValue( '_dat' ); + $timeValue->setUserValue( $timeUserValue ); + $timeValue->setOutputFormat( $format ); + + $instance = new TimeValueFormatter( $timeValue ); + + $this->assertEquals( + $expected, + $instance->format( $type, $linker ) + ); + } + + public function testGetISO8601DateForMinDefault() { + + $timeValue = new TimeValue( '_dat' ); + $timeValue->setUserValue( '2000' ); + + $instance = new TimeValueFormatter( $timeValue ); + + $this->assertEquals( + '2000-01-01', + $instance->getISO8601Date( true ) + ); + + $timeValue = new TimeValue( '_dat' ); + $timeValue->setUserValue( '2000-02-23 12:02' ); + + $instance = new TimeValueFormatter( $timeValue ); + + $this->assertEquals( + '2000-02-23T12:02:00', + $instance->getISO8601Date( true ) + ); + } + + public function testGetISO8601DateForMaxDefault() { + + $timeValue = new TimeValue( '_dat' ); + $timeValue->setUserValue( '2000' ); + + $instance = new TimeValueFormatter( $timeValue ); + + $this->assertEquals( + '2000-12-31', + $instance->getISO8601Date( false ) + ); + + $timeValue = new TimeValue( '_dat' ); + $timeValue->setUserValue( '2000-02-23 12:02' ); + + $instance = new TimeValueFormatter( $timeValue ); + + $this->assertEquals( + '2000-02-23T12:02:00', + $instance->getISO8601Date( false ) + ); + } + + public function testLeapYear() { + + $timeValue = new TimeValue( '_dat' ); + $timeValue->setUserValue( '2016-02-29' ); + + $instance = new TimeValueFormatter( $timeValue ); + + $this->assertEmpty( + $instance->getErrors() + ); + + $this->assertEquals( + '2016-02-29', + $instance->getISO8601Date() + ); + + $timeValue = new TimeValue( '_dat' ); + $timeValue->setUserValue( '2016-02' ); + + $instance = new TimeValueFormatter( $timeValue ); + + $this->assertEquals( + '2016-02-29', + $instance->getISO8601Date( false ) + ); + + $timeValue = new TimeValue( '_dat' ); + $timeValue->setUserValue( '2015-02' ); + + $instance = new TimeValueFormatter( $timeValue ); + + $this->assertEquals( + '2015-02-28', + $instance->getISO8601Date( false ) + ); + } + + public function testInvalidLeapYear() { + + $timeValue = new TimeValue( '_dat' ); + $timeValue->setUserValue( '2015-02-29' ); + + $instance = new TimeValueFormatter( $timeValue ); + + $this->assertNotEmpty( + $instance->getErrors() + ); + } + + public function timeInputProvider() { + + $provider[] = array( + '2000', + TimeValueFormatter::VALUE, + '', + null, + '2000' + ); + + $provider[] = array( + '2000', + TimeValueFormatter::VALUE, + 'ISO', + null, + '2000' + ); + + $provider[] = array( + '2000', + TimeValueFormatter::WIKI_SHORT, + 'ISO', + null, + '2000' + ); + + $provider[] = array( + '2000', + TimeValueFormatter::HTML_SHORT, + 'ISO', + null, + '2000' + ); + + $provider[] = array( + '2000', + TimeValueFormatter::WIKI_LONG, + 'ISO', + null, + '2000-01-01' + ); + + $provider[] = array( + '2000', + TimeValueFormatter::HTML_LONG, + 'ISO', + null, + '2000-01-01' + ); + + $provider[] = array( + '2000', + TimeValueFormatter::WIKI_LONG, + 'MEDIAWIKI', + null, + '2000' + ); + + $provider[] = array( + '2000', + TimeValueFormatter::HTML_LONG, + 'MEDIAWIKI', + null, + '2000' + ); + + $provider[] = array( + '2000-02', + TimeValueFormatter::VALUE, + '', + null, + '2000-02' + ); + + $provider[] = array( + '2000-02', + TimeValueFormatter::VALUE, + 'ISO', + null, + '2000-02' + ); + + $provider[] = array( + '2000-02', + TimeValueFormatter::WIKI_SHORT, + '', + null, + '2000-02' + ); + + $provider[] = array( + '2000-02', + TimeValueFormatter::HTML_SHORT, + 'ISO', + null, + '2000-02' + ); + + $provider[] = array( + '2000-02', + TimeValueFormatter::WIKI_LONG, + 'ISO', + null, + '2000-02-01' + ); + + $provider[] = array( + '2000-02', + TimeValueFormatter::HTML_LONG, + 'ISO', + null, + '2000-02-01' + ); + + return $provider; + } + +}