API rename

This commit is contained in:
Ingo Schommer 2017-04-27 11:53:43 +12:00
parent 9b41350f64
commit de8abe1167
4 changed files with 126 additions and 88 deletions

View File

@ -194,7 +194,7 @@ class DateField extends TextField
} }
// Get from locale // Get from locale
return $this->getFormatter()->getPattern(); return $this->getFrontendFormatter()->getPattern();
} }
/** /**
@ -217,7 +217,7 @@ class DateField extends TextField
* @throws \LogicException * @throws \LogicException
* @return IntlDateFormatter * @return IntlDateFormatter
*/ */
protected function getFormatter() protected function getFrontendFormatter()
{ {
if ($this->getHTML5() && $this->dateFormat && $this->dateFormat !== DBDate::ISO_DATE) { if ($this->getHTML5() && $this->dateFormat && $this->dateFormat !== DBDate::ISO_DATE) {
throw new \LogicException( throw new \LogicException(
@ -261,7 +261,7 @@ class DateField extends TextField
* *
* @return IntlDateFormatter * @return IntlDateFormatter
*/ */
protected function getISO8601Formatter() protected function getInternalFormatter()
{ {
$locale = i18n::config()->uninherited('default_locale'); $locale = i18n::config()->uninherited('default_locale');
$formatter = IntlDateFormatter::create( $formatter = IntlDateFormatter::create(
@ -327,10 +327,19 @@ class DateField extends TextField
} }
// Parse from submitted value // Parse from submitted value
$this->value = $this->localisedToISO8601($value); $this->value = $this->frontendToInternal($value);
return $this; return $this;
} }
/**
* Assign value based on {@link $datetimeFormat}, which might be localised.
*
* When $html5=true, assign value from ISO 8601 string.
*
* @param mixed $value
* @param mixed $data
* @return $this
*/
public function setValue($value, $data = null) public function setValue($value, $data = null)
{ {
// Save raw value for later validation // Save raw value for later validation
@ -343,13 +352,13 @@ class DateField extends TextField
} }
// Re-run through formatter to tidy up (e.g. remove time component) // Re-run through formatter to tidy up (e.g. remove time component)
$this->value = $this->tidyISO8601($value); $this->value = $this->tidyInternal($value);
return $this; return $this;
} }
public function Value() public function Value()
{ {
return $this->iso8601ToLocalised($this->value); return $this->internalToFrontend($this->value);
} }
public function performReadonlyTransformation() public function performReadonlyTransformation()
@ -394,7 +403,7 @@ class DateField extends TextField
_t( _t(
'DateField.VALIDDATEMINDATE', 'DateField.VALIDDATEMINDATE',
"Your date has to be newer or matching the minimum allowed date ({date})", "Your date has to be newer or matching the minimum allowed date ({date})",
['date' => $this->iso8601ToLocalised($min)] ['date' => $this->internalToFrontend($min)]
) )
); );
return false; return false;
@ -411,7 +420,7 @@ class DateField extends TextField
_t( _t(
'DateField.VALIDDATEMAXDATE', 'DateField.VALIDDATEMAXDATE',
"Your date has to be older or matching the maximum allowed date ({date})", "Your date has to be older or matching the maximum allowed date ({date})",
['date' => $this->iso8601ToLocalised($max)] ['date' => $this->internalToFrontend($max)]
) )
); );
return false; return false;
@ -466,7 +475,7 @@ class DateField extends TextField
*/ */
public function setMinDate($minDate) public function setMinDate($minDate)
{ {
$this->minDate = $this->tidyISO8601($minDate); $this->minDate = $this->tidyInternal($minDate);
return $this; return $this;
} }
@ -484,23 +493,24 @@ class DateField extends TextField
*/ */
public function setMaxDate($maxDate) public function setMaxDate($maxDate)
{ {
$this->maxDate = $this->tidyISO8601($maxDate); $this->maxDate = $this->tidyInternal($maxDate);
return $this; return $this;
} }
/** /**
* Convert date localised in the current locale to ISO 8601 date * Convert frontend date to the internal representation (ISO 8601).
* The frontend date is also in ISO 8601 when $html5=true.
* *
* @param string $date * @param string $date
* @return string The formatted date, or null if not a valid date * @return string The formatted date, or null if not a valid date
*/ */
public function localisedToISO8601($date) protected function frontendToInternal($date)
{ {
if (!$date) { if (!$date) {
return null; return null;
} }
$fromFormatter = $this->getFormatter(); $fromFormatter = $this->getFrontendFormatter();
$toFormatter = $this->getISO8601Formatter(); $toFormatter = $this->getInternalFormatter();
$timestamp = $fromFormatter->parse($date); $timestamp = $fromFormatter->parse($date);
if ($timestamp === false) { if ($timestamp === false) {
return null; return null;
@ -509,20 +519,21 @@ class DateField extends TextField
} }
/** /**
* Convert an ISO 8601 localised date into the format specified by the * Convert the internal date representation (ISO 8601) to a format used by the frontend,
* current date format. * as defined by {@link $dateFormat}. With $html5=true, the frontend date will also be
* in ISO 8601.
* *
* @param string $date * @param string $date
* @return string The formatted date, or null if not a valid date * @return string The formatted date, or null if not a valid date
*/ */
public function iso8601ToLocalised($date) protected function internalToFrontend($date)
{ {
$date = $this->tidyISO8601($date); $date = $this->tidyInternal($date);
if (!$date) { if (!$date) {
return null; return null;
} }
$fromFormatter = $this->getISO8601Formatter(); $fromFormatter = $this->getInternalFormatter();
$toFormatter = $this->getFormatter(); $toFormatter = $this->getFrontendFormatter();
$timestamp = $fromFormatter->parse($date); $timestamp = $fromFormatter->parse($date);
if ($timestamp === false) { if ($timestamp === false) {
return null; return null;
@ -531,18 +542,19 @@ class DateField extends TextField
} }
/** /**
* Tidy up iso8601-ish date, or approximation * Tidy up the internal date representation (ISO 8601),
* and fall back to strtotime() if there's parsing errors.
* *
* @param string $date Date in iso8601 or approximate form * @param string $date Date in ISO 8601 or approximate form
* @return string iso8601 date, or null if not valid * @return string ISO 8601 date, or null if not valid
*/ */
public function tidyISO8601($date) protected function tidyInternal($date)
{ {
if (!$date) { if (!$date) {
return null; return null;
} }
// Re-run through formatter to tidy up (e.g. remove time component) // Re-run through formatter to tidy up (e.g. remove time component)
$formatter = $this->getISO8601Formatter(); $formatter = $this->getInternalFormatter();
$timestamp = $formatter->parse($date); $timestamp = $formatter->parse($date);
if ($timestamp === false) { if ($timestamp === false) {
// Fallback to strtotime // Fallback to strtotime

View File

@ -156,25 +156,25 @@ class DatetimeField extends TextField
} }
// Parse from submitted value // Parse from submitted value
$this->value = $this->localisedToISO8601($value); $this->value = $this->frontendToInternal($value);
return $this; return $this;
} }
/** /**
* Convert date localised in the current locale to ISO 8601 date. * Convert frontend date to the internal representation (ISO 8601).
* Note that "localised" could also mean ISO format when $html5=true. * The frontend date is also in ISO 8601 when $html5=true.
* *
* @param string $datetime * @param string $datetime
* @return string The formatted date, or null if not a valid date * @return string The formatted date, or null if not a valid date
*/ */
public function localisedToISO8601($datetime) public function frontendToInternal($datetime)
{ {
if (!$datetime) { if (!$datetime) {
return null; return null;
} }
$fromFormatter = $this->getFormatter(); $fromFormatter = $this->getFrontendFormatter();
$toFormatter = $this->getISO8601Formatter(); $toFormatter = $this->getInternalFormatter();
// Try to parse time with seconds // Try to parse time with seconds
$timestamp = $fromFormatter->parse($datetime); $timestamp = $fromFormatter->parse($datetime);
@ -198,7 +198,7 @@ class DatetimeField extends TextField
* @throws \LogicException * @throws \LogicException
* @return IntlDateFormatter * @return IntlDateFormatter
*/ */
protected function getFormatter() protected function getFrontendFormatter()
{ {
if ($this->getHTML5() && $this->datetimeFormat && $this->datetimeFormat !== DBDatetime::ISO_DATETIME_NORMALISED) { if ($this->getHTML5() && $this->datetimeFormat && $this->datetimeFormat !== DBDatetime::ISO_DATETIME_NORMALISED) {
throw new \LogicException( throw new \LogicException(
@ -254,7 +254,7 @@ class DatetimeField extends TextField
} }
// Get from locale // Get from locale
return $this->getFormatter()->getPattern(); return $this->getFrontendFormatter()->getPattern();
} }
/** /**
@ -285,7 +285,7 @@ class DatetimeField extends TextField
} }
// Build new formatter with the altered timezone // Build new formatter with the altered timezone
$formatter = clone $this->getISO8601Formatter(); $formatter = clone $this->getInternalFormatter();
$formatter->setTimeZone($timezone); $formatter->setTimeZone($timezone);
// ISO8601 date with a standard "T" separator (W3C standard). // ISO8601 date with a standard "T" separator (W3C standard).
@ -300,7 +300,7 @@ class DatetimeField extends TextField
* *
* @return IntlDateFormatter * @return IntlDateFormatter
*/ */
protected function getISO8601Formatter() protected function getInternalFormatter()
{ {
$formatter = IntlDateFormatter::create( $formatter = IntlDateFormatter::create(
i18n::config()->uninherited('default_locale'), i18n::config()->uninherited('default_locale'),
@ -311,14 +311,13 @@ class DatetimeField extends TextField
$formatter->setLenient(false); $formatter->setLenient(false);
// Note we omit timezone from this format, and we always assume server TZ // Note we omit timezone from this format, and we always assume server TZ
// ISO8601 date with a standard "T" separator (W3C standard).
$formatter->setPattern(DBDatetime::ISO_DATETIME_NORMALISED); $formatter->setPattern(DBDatetime::ISO_DATETIME_NORMALISED);
return $formatter; return $formatter;
} }
/** /**
* Assign value based on {@link $datetimeFormat}. * Assign value based on {@link $datetimeFormat}, which might be localised.
* *
* When $html5=true, assign value from ISO 8601 normalised string (with a "T" separator). * When $html5=true, assign value from ISO 8601 normalised string (with a "T" separator).
* Falls back to an ISO 8601 string (with a whitespace separator). * Falls back to an ISO 8601 string (with a whitespace separator).
@ -340,14 +339,14 @@ class DatetimeField extends TextField
// Validate iso 8601 date // Validate iso 8601 date
// If invalid, assign for later validation failure // If invalid, assign for later validation failure
$isoFormatter = $this->getISO8601Formatter(); $internalFormatter = $this->getInternalFormatter();
$timestamp = $isoFormatter->parse($value); $timestamp = $internalFormatter->parse($value);
// Retry without "T" separator // Retry without "T" separator
if (!$timestamp) { if (!$timestamp) {
$isoFallbackFormatter = $this->getISO8601Formatter(); $fallbackFormatter = $this->getInternalFormatter();
$isoFallbackFormatter->setPattern(DBDatetime::ISO_DATETIME); $fallbackFormatter->setPattern(DBDatetime::ISO_DATETIME);
$timestamp = $isoFallbackFormatter->parse($value); $timestamp = $fallbackFormatter->parse($value);
} }
if ($timestamp === false) { if ($timestamp === false) {
@ -355,7 +354,7 @@ class DatetimeField extends TextField
} }
// Cleanup date // Cleanup date
$value = $isoFormatter->format($timestamp); $value = $internalFormatter->format($timestamp);
// Save value // Save value
$this->value = $value; $this->value = $value;
@ -363,14 +362,27 @@ class DatetimeField extends TextField
return $this; return $this;
} }
/**
* Returns the frontend representation of the field value,
* according to the defined {@link dateFormat}.
* With $html5=true, this will be in ISO 8601 format.
*
* @return string
*/
public function Value() public function Value()
{ {
return $this->iso8601ToLocalised($this->value); return $this->internalToFrontend($this->value);
} }
/**
* Returns the field value in the internal representation (ISO 8601),
* suitable for insertion into the data object.
*
* @return string
*/
public function dataValue() public function dataValue()
{ {
return $this->iso8601ToDataValue($this->value); return $this->internalToDataValue($this->value);
} }
/** /**
@ -379,10 +391,10 @@ class DatetimeField extends TextField
* @param string $datetime * @param string $datetime
* @return string The formatted date and time, or null if not a valid date and time * @return string The formatted date and time, or null if not a valid date and time
*/ */
public function iso8601ToDataValue($datetime) public function internalToDataValue($datetime)
{ {
$fromFormatter = $this->getISO8601Formatter(); $fromFormatter = $this->getInternalFormatter();
$toFormatter = $this->getFormatter(); $toFormatter = $this->getFrontendFormatter();
// Set default timezone (avoid shifting data values into user timezone) // Set default timezone (avoid shifting data values into user timezone)
$toFormatter->setTimezone(date_default_timezone_get()); $toFormatter->setTimezone(date_default_timezone_get());
@ -398,19 +410,21 @@ class DatetimeField extends TextField
} }
/** /**
* Convert an ISO 8601 localised datetime into the format specified by the current format. * Convert the internal date representation (ISO 8601) to a format used by the frontend,
* as defined by {@link $dateFormat}. With $html5=true, the frontend date will also be
* in ISO 8601.
* *
* @param string $datetime * @param string $datetime
* @return string The formatted date and time, or null if not a valid date and time * @return string The formatted date and time, or null if not a valid date and time
*/ */
public function iso8601ToLocalised($datetime) public function internalToFrontend($datetime)
{ {
$datetime = $this->tidyISO8601($datetime); $datetime = $this->tidyInternal($datetime);
if (!$datetime) { if (!$datetime) {
return null; return null;
} }
$fromFormatter = $this->getISO8601Formatter(); $fromFormatter = $this->getInternalFormatter();
$toFormatter = $this->getFormatter(); $toFormatter = $this->getFrontendFormatter();
$timestamp = $fromFormatter->parse($datetime); $timestamp = $fromFormatter->parse($datetime);
if ($timestamp === false) { if ($timestamp === false) {
return null; return null;
@ -420,18 +434,19 @@ class DatetimeField extends TextField
} }
/** /**
* Tidy up iso8601-ish date, or approximation * Tidy up the internal date representation (ISO 8601),
* and fall back to strtotime() if there's parsing errors.
* *
* @param string $date Date in ISO 8601 or approximate form * @param string $date Date in ISO 8601 or approximate form
* @return string iso8601 date, or null if not valid * @return string ISO 8601 date, or null if not valid
*/ */
public function tidyISO8601($datetime) public function tidyInternal($datetime)
{ {
if (!$datetime) { if (!$datetime) {
return null; return null;
} }
// Re-run through formatter to tidy up (e.g. remove time component) // Re-run through formatter to tidy up (e.g. remove time component)
$formatter = $this->getISO8601Formatter(); $formatter = $this->getInternalFormatter();
$timestamp = $formatter->parse($datetime); $timestamp = $formatter->parse($datetime);
if ($timestamp === false) { if ($timestamp === false) {
// Fallback to strtotime // Fallback to strtotime
@ -559,7 +574,7 @@ class DatetimeField extends TextField
*/ */
public function setMinDatetime($minDatetime) public function setMinDatetime($minDatetime)
{ {
$this->minDatetime = $this->tidyISO8601($minDatetime); $this->minDatetime = $this->tidyInternal($minDatetime);
return $this; return $this;
} }
@ -577,7 +592,7 @@ class DatetimeField extends TextField
*/ */
public function setMaxDatetime($maxDatetime) public function setMaxDatetime($maxDatetime)
{ {
$this->maxDatetime = $this->tidyISO8601($maxDatetime); $this->maxDatetime = $this->tidyInternal($maxDatetime);
return $this; return $this;
} }
@ -615,7 +630,7 @@ class DatetimeField extends TextField
_t( _t(
'DatetimeField.VALIDDATETIMEMINDATE', 'DatetimeField.VALIDDATETIMEMINDATE',
"Your date has to be newer or matching the minimum allowed date and time ({datetime})", "Your date has to be newer or matching the minimum allowed date and time ({datetime})",
['datetime' => $this->iso8601ToLocalised($min)] ['datetime' => $this->internalToFrontend($min)]
) )
); );
return false; return false;
@ -632,7 +647,7 @@ class DatetimeField extends TextField
_t( _t(
'DatetimeField.VALIDDATEMAXDATETIME', 'DatetimeField.VALIDDATEMAXDATETIME',
"Your date has to be older or matching the maximum allowed date and time ({datetime})", "Your date has to be older or matching the maximum allowed date and time ({datetime})",
['datetime' => $this->iso8601ToLocalised($max)] ['datetime' => $this->internalToFrontend($max)]
) )
); );
return false; return false;

View File

@ -103,7 +103,7 @@ class TimeField extends TextField
} }
// Get from locale // Get from locale
return $this->getFormatter()->getPattern(); return $this->getFrontendFormatter()->getPattern();
} }
/** /**
@ -159,7 +159,7 @@ class TimeField extends TextField
* *
* @return IntlDateFormatter * @return IntlDateFormatter
*/ */
protected function getFormatter() protected function getFrontendFormatter()
{ {
if ($this->getHTML5() && $this->timeFormat && $this->timeFormat !== DBTime::ISO_TIME) { if ($this->getHTML5() && $this->timeFormat && $this->timeFormat !== DBTime::ISO_TIME) {
throw new \LogicException( throw new \LogicException(
@ -204,7 +204,7 @@ class TimeField extends TextField
* *
* @return IntlDateFormatter * @return IntlDateFormatter
*/ */
protected function getISO8601Formatter() protected function getInternalFormatter()
{ {
$formatter = IntlDateFormatter::create( $formatter = IntlDateFormatter::create(
i18n::config()->uninherited('default_locale'), i18n::config()->uninherited('default_locale'),
@ -260,7 +260,7 @@ class TimeField extends TextField
$this->rawValue = $value; $this->rawValue = $value;
// Parse from submitted value // Parse from submitted value
$this->value = $this->localisedToISO8601($value); $this->value = $this->frontendToInternal($value);
return $this; return $this;
} }
@ -283,13 +283,13 @@ class TimeField extends TextField
} }
// Re-run through formatter to tidy up (e.g. remove date component) // Re-run through formatter to tidy up (e.g. remove date component)
$this->value = $this->tidyISO8601($value); $this->value = $this->tidyInternal($value);
return $this; return $this;
} }
public function Value() public function Value()
{ {
$localised = $this->iso8601ToLocalised($this->value); $localised = $this->internalToFrontend($this->value);
if ($localised) { if ($localised) {
return $localised; return $localised;
} }
@ -305,7 +305,7 @@ class TimeField extends TextField
*/ */
public function getMidnight() public function getMidnight()
{ {
$formatter = $this->getFormatter(); $formatter = $this->getFrontendFormatter();
$timestamp = $this->withTimezone($this->getTimezone(), function () { $timestamp = $this->withTimezone($this->getTimezone(), function () {
return strtotime('midnight'); return strtotime('midnight');
}); });
@ -375,18 +375,19 @@ class TimeField extends TextField
} }
/** /**
* Convert time localised in the current locale to ISO 8601 time * Convert frontend time to the internal representation (ISO 8601).
* The frontend time is also in ISO 8601 when $html5=true.
* *
* @param string $time * @param string $time
* @return string The formatted time, or null if not a valid time * @return string The formatted time, or null if not a valid time
*/ */
public function localisedToISO8601($time) protected function frontendToInternal($time)
{ {
if (!$time) { if (!$time) {
return null; return null;
} }
$fromFormatter = $this->getFormatter(); $fromFormatter = $this->getFrontendFormatter();
$toFormatter = $this->getISO8601Formatter(); $toFormatter = $this->getInternalFormatter();
$timestamp = $fromFormatter->parse($time); $timestamp = $fromFormatter->parse($time);
// Try to parse time without seconds, since that's a valid HTML5 submission format // Try to parse time without seconds, since that's a valid HTML5 submission format
@ -405,19 +406,21 @@ class TimeField extends TextField
} }
/** /**
* Format iso time to localised form * Convert the internal time representation (ISO 8601) to a format used by the frontend,
* as defined by {@link $timeFormat}. With $html5=true, the frontend time will also be
* in ISO 8601.
* *
* @param string $time * @param string $time
* @return string * @return string
*/ */
public function iso8601ToLocalised($time) protected function internalToFrontend($time)
{ {
$time = $this->tidyISO8601($time); $time = $this->tidyInternal($time);
if (!$time) { if (!$time) {
return null; return null;
} }
$fromFormatter = $this->getISO8601Formatter(); $fromFormatter = $this->getInternalFormatter();
$toFormatter = $this->getFormatter(); $toFormatter = $this->getFrontendFormatter();
$timestamp = $fromFormatter->parse($time); $timestamp = $fromFormatter->parse($time);
if ($timestamp === false) { if ($timestamp === false) {
return null; return null;
@ -428,18 +431,19 @@ class TimeField extends TextField
/** /**
* Tidy up iso8601-ish time, or approximation * Tidy up the internal time representation (ISO 8601),
* and fall back to strtotime() if there's parsing errors.
* *
* @param string $time Time in iso8601 or approximate form * @param string $time Time in ISO 8601 or approximate form
* @return string iso8601 time, or null if not valid * @return string ISO 8601 time, or null if not valid
*/ */
public function tidyISO8601($time) protected function tidyInternal($time)
{ {
if (!$time) { if (!$time) {
return null; return null;
} }
// Re-run through formatter to tidy up (e.g. remove date component) // Re-run through formatter to tidy up (e.g. remove date component)
$formatter = $this->getISO8601Formatter(); $formatter = $this->getInternalFormatter();
$timestamp = $formatter->parse($time); $timestamp = $formatter->parse($time);
if ($timestamp === false) { if ($timestamp === false) {
// Fallback to strtotime // Fallback to strtotime

View File

@ -94,15 +94,22 @@ class DateFieldTest extends SapphireTest
$this->assertEquals('2003-03-29', $f->dataValue()); $this->assertEquals('2003-03-29', $f->dataValue());
} }
public function testTidyISO8601() public function testSetValue()
{ {
$f = new DateField('Date', 'Date'); $f = (new DateField('Date', 'Date'))->setValue('notadate');
$this->assertEquals(null, $f->tidyISO8601('notadate')); $this->assertNull($f->Value(), 'Invalid input ignored');
$this->assertEquals('2011-01-31', $f->tidyISO8601('-1 day'));
$this->assertEquals(null, $f->tidyISO8601('29/03/2003')); $f = (new DateField('Date', 'Date'))->setValue('-1 day');
$this->assertEquals($f->Value(), '2011-01-31', 'Relative dates accepted');
$f = (new DateField('Date', 'Date'))->setValue('2011-01-31');
$this->assertEquals($f->Value(), '2011-01-31', 'ISO format accepted');
$f = (new DateField('Date', 'Date'))->setValue('2011-01-31 23:59:59');
$this->assertEquals($f->Value(), '2011-01-31', 'ISO format with time accepted');
} }
public function testSetValueWithDateString() public function testSetValueWithLocalisedDateString()
{ {
$f = new DateField('Date', 'Date'); $f = new DateField('Date', 'Date');
$f->setHTML5(false); $f->setHTML5(false);