From aa61882f3ef6d7b76e7b9b05c995504d1a2b20d1 Mon Sep 17 00:00:00 2001 From: Brian Wolff Date: Sat, 8 Oct 2011 18:40:00 +0000 Subject: [PATCH] Make partial dates in XMP not have the ommitted fields fulled out to 1's (reported by AVRS on irc). Basically, in XMP you can specify partial date (for example 2011-04 for april 2011 with no day). We were extracting that, and fulling out the day to 01 if it wasn't present (My original resoning when writing the code was that the nice localized date functions need a full date, but that's a pretty poor rationale for displaying wrong date). This changes it to just display such year-month things as YYYY:MM. --- includes/media/FormatMetadata.php | 9 ++++ includes/media/XMPValidate.php | 53 +++++++++++++++---- .../includes/media/XMPValidateTest.php | 47 ++++++++++++++++ 3 files changed, 98 insertions(+), 11 deletions(-) create mode 100644 tests/phpunit/includes/media/XMPValidateTest.php diff --git a/includes/media/FormatMetadata.php b/includes/media/FormatMetadata.php index 47fc1adc2d..bd992a214e 100644 --- a/includes/media/FormatMetadata.php +++ b/includes/media/FormatMetadata.php @@ -233,10 +233,19 @@ class FormatMetadata { if ( $val == '0000:00:00 00:00:00' || $val == ' : : : : ' ) { $val = wfMsg( 'exif-unknowndate' ); } elseif ( preg_match( '/^(?:\d{4}):(?:\d\d):(?:\d\d) (?:\d\d):(?:\d\d):(?:\d\d)$/D', $val ) ) { + // Full date. $time = wfTimestamp( TS_MW, $val ); if ( $time && intval( $time ) > 0 ) { $val = $wgLang->timeanddate( $time ); } + } elseif ( preg_match( '/^(?:\d{4}):(?:\d\d):(?:\d\d) (?:\d\d):(?:\d\d)$/D', $val ) ) { + // No second field. Still format the same + // since timeanddate doesn't include seconds anyways, + // but second still available in api + $time = wfTimestamp( TS_MW, $val . ':00' ); + if ( $time && intval( $time ) > 0 ) { + $val = $wgLang->timeanddate( $time ); + } } elseif ( preg_match( '/^(?:\d{4}):(?:\d\d):(?:\d\d)$/D', $val ) ) { // If only the date but not the time is filled in. $time = wfTimestamp( TS_MW, substr( $val, 0, 4 ) diff --git a/includes/media/XMPValidate.php b/includes/media/XMPValidate.php index 0f1d375cbe..600d99deeb 100644 --- a/includes/media/XMPValidate.php +++ b/includes/media/XMPValidate.php @@ -201,10 +201,20 @@ class XMPValidate { } /** - * function to validate date properties, and convert to Exif format. + * function to validate date properties, and convert to (partial) Exif format. + * + * Dates can be one of the following formats: + * YYYY + * YYYY-MM + * YYYY-MM-DD + * YYYY-MM-DDThh:mmTZD + * YYYY-MM-DDThh:mm:ssTZD + * YYYY-MM-DDThh:mm:ss.sTZD * * @param $info Array information about current property * @param &$val Mixed current value to validate. Converts to TS_EXIF as a side-effect. + * in cases where there's only a partial date, it will give things like + * 2011:04. * @param $standalone Boolean if this is a simple property or array */ public static function validateDate( $info, &$val, $standalone ) { @@ -240,25 +250,41 @@ class XMPValidate { $val = null; return; } - //if month, etc unspecified, full out as 01. - $res[2] = isset( $res[2] ) ? $res[2] : '01'; //month - $res[3] = isset( $res[3] ) ? $res[3] : '01'; //day + if ( !isset( $res[4] ) ) { //hour - //just have the year month day - $val = $res[1] . ':' . $res[2] . ':' . $res[3]; + //just have the year month day (if that) + $val = $res[1]; + if ( isset( $res[2] ) ) { + $val .= ':' . $res[2]; + } + if ( isset( $res[3] ) ) { + $val .= ':' . $res[3]; + } return; } - //if hour is set, so is minute or regex above will fail. - //Extra check for empty string necessary due to TZ but no second case. - $res[6] = isset( $res[6] ) && $res[6] != '' ? $res[6] : '00'; if ( !isset( $res[7] ) || $res[7] === 'Z' ) { + //if hour is set, then minute must also be or regex above will fail. $val = $res[1] . ':' . $res[2] . ':' . $res[3] - . ' ' . $res[4] . ':' . $res[5] . ':' . $res[6]; + . ' ' . $res[4] . ':' . $res[5]; + if ( isset( $res[6] ) && $res[6] !== '' ) { + $val .= ':' . $res[6]; + } return; } - //do timezone processing. We've already done the case that tz = Z. + + // Extra check for empty string necessary due to TZ but no second case. + $stripSeconds = false; + if ( !isset( $res[6] ) || $res[6] === '' ) { + $res[6] = '00'; + $stripSeconds = true; + } + + // Do timezone processing. We've already done the case that tz = Z. + + // We know that if we got to this step, year, month day hour and min must be set + // by virtue of regex not failing. $unix = wfTimestamp( TS_UNIX, $res[1] . $res[2] . $res[3] . $res[4] . $res[5] . $res[6] ); $offset = intval( substr( $res[7], 1, 2 ) ) * 60 * 60; @@ -267,6 +293,11 @@ class XMPValidate { $offset = -$offset; } $val = wfTimestamp( TS_EXIF, $unix + $offset ); + + if ( $stripSeconds ) { + // If seconds weren't specified, remove the trailing ':00'. + $val = substr( $val, 0, -3 ); + } } } diff --git a/tests/phpunit/includes/media/XMPValidateTest.php b/tests/phpunit/includes/media/XMPValidateTest.php new file mode 100644 index 0000000000..94ff1dab45 --- /dev/null +++ b/tests/phpunit/includes/media/XMPValidateTest.php @@ -0,0 +1,47 @@ +assertEquals( $expected, $value ); + } + + function providerDate() { + /* For reference valid date formats are: + * YYYY + * YYYY-MM + * YYYY-MM-DD + * YYYY-MM-DDThh:mmTZD + * YYYY-MM-DDThh:mm:ssTZD + * YYYY-MM-DDThh:mm:ss.sTZD + * (Time zone is optional) + */ + return array( + array( '1992', '1992' ), + array( '1992-04', '1992:04' ), + array( '1992-02-01', '1992:02:01' ), + array( '2011-09-29', '2011:09:29' ), + array( '1982-12-15T20:12', '1982:12:15 20:12' ), + array( '1982-12-15T20:12Z', '1982:12:15 20:12' ), + array( '1982-12-15T20:12+02:30', '1982:12:15 22:42' ), + array( '1982-12-15T01:12-02:30', '1982:12:14 22:42' ), + array( '1982-12-15T20:12:11', '1982:12:15 20:12:11' ), + array( '1982-12-15T20:12:11Z', '1982:12:15 20:12:11' ), + array( '1982-12-15T20:12:11+01:10', '1982:12:15 21:22:11' ), + array( '2045-12-15T20:12:11', '2045:12:15 20:12:11' ), + array( '1867-06-01T15:00:00', '1867:06:01 15:00:00' ), + /* some invalid ones */ + array( '2001--12', null ), + array( '2001-5-12', null ), + array( '2001-5-12TZ', null ), + array( '2001-05-12T15', null ), + array( '2001-12T15:13', null ), + ); + + } + +} -- 2.20.1