mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
API HTML5 date/time fields, remove member prefs (fixes #6626)
This commit is contained in:
parent
ac6d4f3038
commit
326aa37ea4
@ -40,19 +40,19 @@ A custom date format for a [api:DateField] can be provided through `setDateForma
|
||||
DateField::create('MyDate')->setDateFormat('dd-MM-yyyy');
|
||||
|
||||
<div class="info" markdown="1">
|
||||
The formats are based on [CLDR format](http://userguide.icu-project.org/formatparse/datetime).
|
||||
The formats are based on [ICU format](http://www.icu-project.org/apiref/icu4c/classSimpleDateFormat.html#details).
|
||||
</div>
|
||||
|
||||
|
||||
## Min and Max Dates
|
||||
|
||||
Sets the minimum and maximum allowed date values using the `min` and `max` configuration settings (in ISO format or
|
||||
strtotime()).
|
||||
`strtotime()`).
|
||||
|
||||
:::php
|
||||
DateField::create('MyDate')
|
||||
->setMinDate('-7 days')
|
||||
->setMaxDate'2012-12-31')
|
||||
->setMaxDate('2012-12-31')
|
||||
|
||||
## Separate Day / Month / Year Fields
|
||||
|
||||
@ -66,33 +66,21 @@ HTML5 placeholders 'day', 'month' and 'year' are enabled by default.
|
||||
Any custom date format settings will be ignored.
|
||||
</div>
|
||||
|
||||
## Calendar Picker
|
||||
## Date Picker and HTML5 support
|
||||
|
||||
The following setting will add a Calendar to a single DateField, using the jQuery UI DatePicker widget.
|
||||
The field can be used as a [HTML5 input date type](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date)
|
||||
(with `type=date`) by calling `setHTML5(true)`.
|
||||
|
||||
:::php
|
||||
DateField::create('MyDate')
|
||||
->setShowCalendar(true);
|
||||
->setHTML5(true);
|
||||
|
||||
The jQuery date picker will support most custom locale formats (if left as default).
|
||||
If setting an explicit date format via setDateFormat() then the below table of supported
|
||||
characters should be used.
|
||||
In browsers [supporting HTML5 date inputs](caniuse.com/#feat=input-datetime),
|
||||
this will cause a localised date picker to appear for users.
|
||||
In this mode, the field will be forced to present and save ISO 8601 date formats (`y-MM-dd`),
|
||||
since the browser takes care of converting to/from a localised presentation.
|
||||
|
||||
It is recommended to use numeric format, as `MMM` or `MMMM` month names may not always pass validation.
|
||||
|
||||
Constant | xxxxx
|
||||
-------- | -----
|
||||
d | numeric day of the month (without leading zero)
|
||||
dd | numeric day of the month (with leading zero)
|
||||
EEE | dayname, abbreviated
|
||||
EEEE | dayname
|
||||
M | numeric month of the year (without leading zero)
|
||||
MM | numeric month of the year (with leading zero)
|
||||
MMM | monthname, abbreviated
|
||||
MMMM | monthname
|
||||
y | year (4 digits)
|
||||
yy | year (2 digits)
|
||||
yyyy | year (4 digits)
|
||||
Browsers without support receive an `<input type=text>` based polyfill.
|
||||
|
||||
## Formatting Hints
|
||||
|
||||
|
@ -71,18 +71,24 @@ and default alignment of paragraphs and tables to browsers.
|
||||
|
||||
### Date and time formats
|
||||
|
||||
Formats can be set globally in the i18n class. These settings are currently only picked up by the CMS, you'll need
|
||||
to write your own logic for any frontend output.
|
||||
Formats can be set globally in the i18n class.
|
||||
You can use these settings for your own view logic.
|
||||
|
||||
:::php
|
||||
Config::inst()->update('i18n', 'date_format', 'dd.MM.YYYY');
|
||||
Config::inst()->update('i18n', 'time_format', 'HH:mm');
|
||||
|
||||
Most localization routines in SilverStripe use the [Zend_Date API](http://framework.zend.com/manual/1.12/en/zend.date.overview.html).
|
||||
This means all formats are defined in
|
||||
[ISO date format](http://framework.zend.com/manual/1.12/en/zend.date.constants.html),
|
||||
Localization in SilverStripe uses PHP's [intl extension](http://php.net/intl).
|
||||
Formats for it's [IntlDateFormatter](http://php.net/manual/en/class.intldateformatter.php)
|
||||
are defined in [ICU format](http://www.icu-project.org/apiref/icu4c/classSimpleDateFormat.html#details),
|
||||
not PHP's built-in [date()](http://nz.php.net/manual/en/function.date.php).
|
||||
|
||||
These settings are not used for CMS presentation.
|
||||
Users can choose their own locale, which determines the date format
|
||||
that gets presented to them. Currently this is a mix of PHP defaults (for readonly `DateField` and `TimeField`),
|
||||
browser defaults (for `DateField` on browsers supporting HTML5), and [Moment.JS](http://momentjs.com/)
|
||||
client-side logic (for `DateField` polyfills and other readonly dates and times).
|
||||
|
||||
### Language Names
|
||||
|
||||
SilverStripe comes with a built-in list of common languages, listed by locale and region.
|
||||
|
@ -398,6 +398,18 @@ In templates this can also be invoked as below:
|
||||
<%t MyObject.PLURALS 'An item|{count} items' count=$Count %>
|
||||
|
||||
|
||||
#### Removed Member.DateFormat and Member.TimeFormat database settings
|
||||
|
||||
We're using [native HTML5 date and time pickers](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date)
|
||||
in `DateField` and `TimeField` now ([discussion](https://github.com/silverstripe/silverstripe-framework/issues/6626)),
|
||||
where the browser localises the output based on the browser/system preferences.
|
||||
In this context it no longer makes sense to give users control over their own
|
||||
date and time formats in their CMS profile.
|
||||
|
||||
`Member->getDateFormat()` and `Member->getTimeFormat()` still exist, and default to
|
||||
the [IntlDateFormatter defaults](http://php.net/manual/en/class.intldateformatter.php) for the selected locale.
|
||||
|
||||
|
||||
#### New asset storage mechanism
|
||||
|
||||
File system has been abstracted into an abstract interface. By default, the out of the box filesystem
|
||||
@ -1495,19 +1507,27 @@ New `DatetimeField` methods replace `getConfig()` / `setConfig()`:
|
||||
|
||||
New `DateField` methods replace `getConfig()` / `setConfig()`:
|
||||
|
||||
* `getShowCalendar()` / `setShowCalendar()`
|
||||
* `getDateFormat()` / `setShowCalendar()`
|
||||
* `getDateFormat()` / `setDateFormat()`
|
||||
* `getMinDate()` / `setMinDate()`
|
||||
* `getMaxDate()` / `setMaxDate()`
|
||||
* `getPlaceholders()` / `setPlaceholders()`
|
||||
* `getClientLocale` / `setClientLocale`
|
||||
* `getLocale()` / `setLocale()`
|
||||
* option `dmyfields` is now superceded with an `SeparatedDateField` class
|
||||
|
||||
The `DateField` has changed behavior:
|
||||
|
||||
* `DateField` no longer provides a jQuery UI date picker,
|
||||
and uses [HTML5 date pickers](https://www.wufoo.com/html5/types/4-date.html) instead.
|
||||
Use `setUseHTML()` to activate this mode (instead of `setConfig('showcalendar', true)`).
|
||||
* `DateField` provides an optional polyfill for
|
||||
[browsers without HTML5 date picker support](http://caniuse.com/#feat=input-datetime)
|
||||
* The `dmyfields` option is now superceded with an `SeparatedDateField` class.
|
||||
* `getPlaceholders()` / `setPlaceholders()` moved to a new `SeparatedDateField` class
|
||||
* `getClientLocale` / `setClientLocale` have been removed (handled by `DateField->locale` and browser settings)
|
||||
|
||||
New `TimeField` methods replace `getConfig()` / `setConfig()`
|
||||
|
||||
* `getTimeFormat()` / `setTimeFormat()`
|
||||
* `getLocale()` / `setLocale()`
|
||||
* `getClientConfig()` has been removed (in favour of `setHTML5()`)
|
||||
|
||||
#### <a name="overview-template-removed"></a>Template and Form Removed API
|
||||
|
||||
|
@ -115,25 +115,27 @@ class DateField extends TextField
|
||||
protected $rawValue = null;
|
||||
|
||||
/**
|
||||
* Check if calendar should be shown on the frontend
|
||||
* Use HTML5-based input fields (and force ISO 8601 date formats).
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $html5 = false;
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function getShowCalendar()
|
||||
public function getHTML5()
|
||||
{
|
||||
return $this->showCalendar;
|
||||
return $this->html5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if calendar should be shown on the frontend.
|
||||
* @internal WARNING: Experimental and volatile API.
|
||||
*
|
||||
* @param bool $show
|
||||
* @param boolean $bool
|
||||
* @return $this
|
||||
*/
|
||||
public function setShowCalendar($show)
|
||||
public function setHTML5($bool)
|
||||
{
|
||||
$this->showCalendar = $show;
|
||||
$this->html5 = $bool;
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -209,6 +211,7 @@ class DateField extends TextField
|
||||
/**
|
||||
* Get date formatter with the standard locale / date format
|
||||
*
|
||||
* @throws \LogicException
|
||||
* @return IntlDateFormatter
|
||||
*/
|
||||
protected function getFormatter()
|
||||
@ -219,8 +222,20 @@ class DateField extends TextField
|
||||
IntlDateFormatter::NONE
|
||||
);
|
||||
|
||||
$isoFormat = 'y-MM-dd';
|
||||
|
||||
if ($this->dateFormat && $this->getHTML5() && $this->dateFormat !== $isoFormat) {
|
||||
throw new \LogicException(sprintf(
|
||||
'Can\'t use a custom dateFormat value with $html5=true (needs to be %s)',
|
||||
$isoFormat
|
||||
));
|
||||
}
|
||||
|
||||
if ($this->getHTML5()) {
|
||||
// Browsers expect ISO 8601 dates, localisation is handled on the client
|
||||
$formatter->setPattern($isoFormat);
|
||||
} elseif ($this->dateFormat) {
|
||||
// Don't invoke getDateFormat() directly to avoid infinite loop
|
||||
if ($this->dateFormat) {
|
||||
$ok = $formatter->setPattern($this->dateFormat);
|
||||
if (!$ok) {
|
||||
throw new InvalidArgumentException("Invalid date format {$this->dateFormat}");
|
||||
@ -236,59 +251,38 @@ class DateField extends TextField
|
||||
*/
|
||||
protected function getISO8601Formatter()
|
||||
{
|
||||
$locale = i18n::config()->uninherited('default_locale');
|
||||
$formatter = IntlDateFormatter::create(
|
||||
i18n::config()->uninherited('default_locale'),
|
||||
IntlDateFormatter::MEDIUM,
|
||||
IntlDateFormatter::NONE
|
||||
);
|
||||
$formatter->setLenient(false);
|
||||
// CLDR iso8601 date.
|
||||
// CLDR ISO 8601 date.
|
||||
$formatter->setPattern('y-MM-dd');
|
||||
return $formatter;
|
||||
}
|
||||
|
||||
public function FieldHolder($properties = array())
|
||||
{
|
||||
return $this->renderWithClientView(function () use ($properties) {
|
||||
if ($this->getHTML5()) {
|
||||
// Browsers expect ISO 8601 dates, localisation is handled on the client
|
||||
$this->setDateFormat('y-MM-dd');
|
||||
}
|
||||
|
||||
return parent::FieldHolder($properties);
|
||||
});
|
||||
}
|
||||
|
||||
public function SmallFieldHolder($properties = array())
|
||||
{
|
||||
return $this->renderWithClientView(function () use ($properties) {
|
||||
return parent::SmallFieldHolder($properties);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate field with client view enabled
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return string
|
||||
*/
|
||||
protected function renderWithClientView($callback)
|
||||
{
|
||||
$clientView = null;
|
||||
if ($this->getShowCalendar()) {
|
||||
$clientView = $this->getClientView();
|
||||
$clientView->onBeforeRender();
|
||||
}
|
||||
$html = $callback();
|
||||
if ($clientView) {
|
||||
$html = $clientView->onAfterRender($html);
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
|
||||
public function getAttributes()
|
||||
{
|
||||
$attributes = parent::getAttributes();
|
||||
|
||||
// Merge with client config
|
||||
$config = $this->getClientConfig();
|
||||
foreach ($config as $key => $value) {
|
||||
$attributes["data-{$key}"] = $value;
|
||||
$attributes['lang'] = i18n::convert_rfc1766($this->getLocale());
|
||||
|
||||
if ($this->getHTML5()) {
|
||||
$attributes['type'] = 'date';
|
||||
$attributes['min'] = $this->getMinDate();
|
||||
$attributes['max'] = $this->getMaxDate();
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
@ -438,29 +432,6 @@ class DateField extends TextField
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get locale code for client-side. Will default to getLocale() if omitted.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getClientLocale()
|
||||
{
|
||||
if ($this->clientLocale) {
|
||||
return $this->clientLocale;
|
||||
}
|
||||
return $this->getLocale();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $clientLocale
|
||||
* @return DateField
|
||||
*/
|
||||
public function setClientLocale($clientLocale)
|
||||
{
|
||||
$this->clientLocale = $clientLocale;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSchemaValidation()
|
||||
{
|
||||
$rules = parent::getSchemaValidation();
|
||||
@ -504,35 +475,6 @@ class DateField extends TextField
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get client data properties for this field
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getClientConfig()
|
||||
{
|
||||
$view = $this->getClientView();
|
||||
$config = [
|
||||
'showcalendar' => $this->getShowCalendar() ? 'true' : null,
|
||||
'date-format' => $view->getDateFormat(), // https://api.jqueryui.com/datepicker/#option-dateFormat
|
||||
'locale' => $view->getLocale(),
|
||||
];
|
||||
|
||||
// Format min/maxDate in format expected by jquery datepicker
|
||||
$min = $this->getMinDate();
|
||||
if ($min) {
|
||||
// https://api.jqueryui.com/datepicker/#option-minDate
|
||||
$config['min-date'] = $this->iso8601ToLocalised($min);
|
||||
}
|
||||
$max = $this->getMaxDate();
|
||||
if ($max) {
|
||||
// https://api.jqueryui.com/datepicker/#option-maxDate
|
||||
$config['max-date'] = $this->iso8601ToLocalised($max);
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert date localised in the current locale to ISO 8601 date
|
||||
*
|
||||
@ -599,11 +541,4 @@ class DateField extends TextField
|
||||
return $formatter->format($timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DateField_View_JQuery
|
||||
*/
|
||||
protected function getClientView()
|
||||
{
|
||||
return DateField_View_JQuery::create($this);
|
||||
}
|
||||
}
|
||||
|
@ -1,197 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Forms;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Core\Config\Configurable;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
use SilverStripe\i18n\i18n;
|
||||
use SilverStripe\View\Requirements;
|
||||
|
||||
/**
|
||||
* Preliminary API to separate optional view properties
|
||||
* like calendar popups from the actual datefield logic.
|
||||
*
|
||||
* Caution: This API is highly volatile, and might change without prior deprecation.
|
||||
*/
|
||||
class DateField_View_JQuery
|
||||
{
|
||||
use Injectable;
|
||||
use Configurable;
|
||||
|
||||
/**
|
||||
* @var DateField
|
||||
*/
|
||||
protected $field;
|
||||
|
||||
/**
|
||||
* @var array Maps values from {@link i18n::$all_locales} to
|
||||
* localizations existing in jQuery UI.
|
||||
*/
|
||||
private static $locale_map = array(
|
||||
'en_GB' => 'en-GB',
|
||||
'en_US' => 'en',
|
||||
'en_NZ' => 'en-GB',
|
||||
'fr_CH' => 'fr',
|
||||
'pt_BR' => 'pt-BR',
|
||||
'sr_SR' => 'sr-SR',
|
||||
'zh_CN' => 'zh-CN',
|
||||
'zh_HK' => 'zh-HK',
|
||||
'zh_TW' => 'zh-TW',
|
||||
);
|
||||
|
||||
/**
|
||||
* @param DateField $field
|
||||
*/
|
||||
public function __construct($field)
|
||||
{
|
||||
$this->field = $field;
|
||||
|
||||
// Health check
|
||||
if (!$this->localePath('en')) {
|
||||
throw new InvalidArgumentException("Missing jquery config");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DateField
|
||||
*/
|
||||
public function getField()
|
||||
{
|
||||
return $this->field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get path to localisation file for a given locale, if it exists
|
||||
*
|
||||
* @param string $lang
|
||||
* @return string Relative path to file, or null if it isn't available
|
||||
*/
|
||||
protected function localePath($lang)
|
||||
{
|
||||
$path = ADMIN_THIRDPARTY_DIR . "/jquery-ui/datepicker/i18n/jquery.ui.datepicker-{$lang}.js";
|
||||
if (file_exists(BASE_PATH . '/' . $path)) {
|
||||
return $path;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function onBeforeRender()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param String $html
|
||||
* @return string
|
||||
*/
|
||||
public function onAfterRender($html)
|
||||
{
|
||||
if ($this->getField()->getShowCalendar()) {
|
||||
// Load config for this locale if available
|
||||
$locale = $this->getLocale();
|
||||
$localeFile = $this->localePath($locale);
|
||||
if ($localeFile) {
|
||||
Requirements::javascript($localeFile);
|
||||
}
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines which language to use for jQuery UI, which
|
||||
* can be different from the value set in i18n.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLocale()
|
||||
{
|
||||
$locale = $this->getField()->getClientLocale();
|
||||
|
||||
// Check standard mappings
|
||||
$map = Config::inst()->get(__CLASS__, 'locale_map');
|
||||
if (array_key_exists($locale, $map)) {
|
||||
return $map[$locale];
|
||||
}
|
||||
|
||||
// Fall back to default lang (meaning "en_US" turns into "en")
|
||||
return i18n::getData()->langFromLocale($locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert iso to jquery UI date format.
|
||||
* Needs to be consistent with Zend formatting, otherwise validation will fail.
|
||||
* Removes all time settings like hour/minute/second from the format.
|
||||
* See http://docs.jquery.com/UI/Datepicker/formatDate
|
||||
* From http://userguide.icu-project.org/formatparse/datetime
|
||||
*
|
||||
* @param string $format
|
||||
* @return string
|
||||
*/
|
||||
public static function convert_iso_to_jquery_format($format)
|
||||
{
|
||||
$convert = array(
|
||||
'/([^d])d([^d])/' => '$1d$2',
|
||||
'/^d([^d])/' => 'd$1',
|
||||
'/([^d])d$/' => '$1d',
|
||||
'/dd/' => 'dd',
|
||||
'/SS/' => '',
|
||||
'/eee/' => 'd',
|
||||
'/e/' => 'N',
|
||||
'/D/' => '',
|
||||
'/EEEE/' => 'DD',
|
||||
'/EEE/' => 'D',
|
||||
'/w/' => '',
|
||||
// make single "M" lowercase
|
||||
'/([^M])M([^M])/' => '$1m$2',
|
||||
// make single "M" at start of line lowercase
|
||||
'/^M([^M])/' => 'm$1',
|
||||
// make single "M" at end of line lowercase
|
||||
'/([^M])M$/' => '$1m',
|
||||
// match exactly three capital Ms not preceeded or followed by an M
|
||||
'/(?<!M)MMM(?!M)/' => 'M',
|
||||
// match exactly two capital Ms not preceeded or followed by an M
|
||||
'/(?<!M)MM(?!M)/' => 'mm',
|
||||
// match four capital Ms (maximum allowed)
|
||||
'/MMMM/' => 'MM',
|
||||
'/l/' => '',
|
||||
'/YYYY/' => 'yy',
|
||||
'/yyyy/' => 'yy',
|
||||
// See http://open.silverstripe.org/ticket/7669
|
||||
'/y{1,3}/' => 'yy',
|
||||
'/a/' => '',
|
||||
'/B/' => '',
|
||||
'/hh/' => '',
|
||||
'/h/' => '',
|
||||
'/([^H])H([^H])/' => '',
|
||||
'/^H([^H])/' => '',
|
||||
'/([^H])H$/' => '',
|
||||
'/HH/' => '',
|
||||
// '/mm/' => '',
|
||||
'/ss/' => '',
|
||||
'/zzzz/' => '',
|
||||
'/I/' => '',
|
||||
'/ZZZZ/' => '',
|
||||
'/Z/' => '',
|
||||
'/z/' => '',
|
||||
'/X/' => '',
|
||||
'/r/' => '',
|
||||
'/U/' => '',
|
||||
);
|
||||
$patterns = array_keys($convert);
|
||||
$replacements = array_values($convert);
|
||||
|
||||
return preg_replace($patterns, $replacements, $format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get client date format
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDateFormat()
|
||||
{
|
||||
return static::convert_iso_to_jquery_format($this->getField()->getDateFormat());
|
||||
}
|
||||
}
|
@ -13,6 +13,10 @@ use SilverStripe\i18n\i18n;
|
||||
* If you want to save into {@link Date} or {@link Time} columns,
|
||||
* please instanciate the fields separately.
|
||||
*
|
||||
* This field does not implement the <input type="datetime-local"> HTML5 field,
|
||||
* but can use date and time HTML5 inputs separately (through {@link DateField->setHTML5()}
|
||||
* and {@link TimeField->setHTML5()}.
|
||||
*
|
||||
* # Configuration
|
||||
*
|
||||
* Individual options are configured either on the DatetimeField, or on individual
|
||||
|
@ -57,6 +57,31 @@ class TimeField extends TextField
|
||||
*/
|
||||
protected $timezone = null;
|
||||
|
||||
/**
|
||||
* Use HTML5-based input fields (and force ISO 8601 date formats).
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $html5 = false;
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function getHTML5()
|
||||
{
|
||||
return $this->html5;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $bool
|
||||
* @return $this
|
||||
*/
|
||||
public function setHTML5($bool)
|
||||
{
|
||||
$this->html5 = $bool;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get time format in CLDR standard format
|
||||
*
|
||||
@ -140,8 +165,20 @@ class TimeField extends TextField
|
||||
$this->getTimezone()
|
||||
);
|
||||
|
||||
// Don't invoke getDateFormat() directly to avoid infinite loop
|
||||
if ($this->timeFormat) {
|
||||
$isoFormat = 'HH:mm:ss';
|
||||
|
||||
if ($this->timeFormat && $this->getHTML5() && $this->timeFormat !== $isoFormat) {
|
||||
throw new \LogicException(sprintf(
|
||||
'Can\'t use a custom timeFormat value with $html5=true (needs to be %s)',
|
||||
$isoFormat
|
||||
));
|
||||
}
|
||||
|
||||
if ($this->getHTML5()) {
|
||||
// Browsers expect ISO 8601 times, localisation is handled on the client
|
||||
$formatter->setPattern($isoFormat);
|
||||
// Don't invoke getTimeFormat() directly to avoid infinite loop
|
||||
} elseif ($this->timeFormat) {
|
||||
$ok = $formatter->setPattern($this->timeFormat);
|
||||
if (!$ok) {
|
||||
throw new InvalidArgumentException("Invalid time format {$this->timeFormat}");
|
||||
@ -164,35 +201,21 @@ class TimeField extends TextField
|
||||
date_default_timezone_get() // Default to server timezone
|
||||
);
|
||||
$formatter->setLenient(false);
|
||||
// CLDR iso8601 time
|
||||
// ISO 8601 time
|
||||
// Note we omit timezone from this format, and we assume server TZ always.
|
||||
$formatter->setPattern('HH:mm:ss');
|
||||
return $formatter;
|
||||
}
|
||||
|
||||
public function getAttribute($name)
|
||||
public function getAttributes()
|
||||
{
|
||||
$attributes = parent::getAttributes();
|
||||
|
||||
// Merge with client config
|
||||
$config = $this->getClientConfig();
|
||||
foreach ($config as $key => $value) {
|
||||
$attributes["data-{$key}"] = $value;
|
||||
}
|
||||
return $attributes;
|
||||
if ($this->getHTML5()) {
|
||||
$attributes['type'] = 'time';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get client config options for this field
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getClientConfig()
|
||||
{
|
||||
return [
|
||||
// @todo - Support javascript time picker
|
||||
'timeformat' => $this->getTimeFormat(),
|
||||
];
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
public function Type()
|
||||
@ -337,9 +360,19 @@ class TimeField extends TextField
|
||||
$fromFormatter = $this->getFormatter();
|
||||
$toFormatter = $this->getISO8601Formatter();
|
||||
$timestamp = $fromFormatter->parse($time);
|
||||
|
||||
// Try to parse time without seconds, since that's a valid HTML5 submission format
|
||||
// See https://html.spec.whatwg.org/multipage/infrastructure.html#times
|
||||
if ($timestamp === false && $this->setHTML5(true)) {
|
||||
$fromFormatter->setPattern('HH:mm');
|
||||
$timestamp = $fromFormatter->parse($time);
|
||||
}
|
||||
|
||||
// If timestamp still can't be detected, we've got an invalid time
|
||||
if ($timestamp === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $toFormatter->format($timestamp);
|
||||
}
|
||||
|
||||
|
@ -512,17 +512,7 @@ class DBDate extends DBField
|
||||
public function scaffoldFormField($title = null, $params = null)
|
||||
{
|
||||
$field = DateField::create($this->name, $title);
|
||||
$format = $field->getDateFormat();
|
||||
|
||||
// Show formatting hints for better usability
|
||||
$now = DBDatetime::now()->Format($format);
|
||||
$field->setDescription(_t(
|
||||
'FormField.EXAMPLE',
|
||||
'e.g. {format}',
|
||||
'Example format',
|
||||
[ 'format' => $now ]
|
||||
));
|
||||
$field->setAttribute('placeholder', $format);
|
||||
$field->setHTML5(true);
|
||||
|
||||
return $field;
|
||||
}
|
||||
|
@ -142,17 +142,8 @@ class DBTime extends DBField
|
||||
public function scaffoldFormField($title = null, $params = null)
|
||||
{
|
||||
$field = TimeField::create($this->name, $title);
|
||||
$format = $field->getTimeFormat();
|
||||
$field->setHTML5(true);
|
||||
|
||||
// Show formatting hints for better usability
|
||||
$now = DBDatetime::now()->Format($format);
|
||||
$field->setDescription(_t(
|
||||
'FormField.Example',
|
||||
'e.g. {format}',
|
||||
'Example format',
|
||||
[ 'format' => $now ]
|
||||
));
|
||||
$field->setAttribute('placeholder', $format);
|
||||
return $field;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,6 @@ use SilverStripe\Forms\DropdownField;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Forms\HTMLEditor\HTMLEditorConfig;
|
||||
use SilverStripe\Forms\ListboxField;
|
||||
use SilverStripe\Forms\MemberDatetimeOptionsetField;
|
||||
use SilverStripe\i18n\i18n;
|
||||
use SilverStripe\MSSQL\MSSQLDatabase;
|
||||
use SilverStripe\ORM\ArrayList;
|
||||
@ -81,9 +80,6 @@ class Member extends DataObject implements TemplateGlobalProvider
|
||||
'Locale' => 'Varchar(6)',
|
||||
// handled in registerFailedLogin(), only used if $lock_out_after_incorrect_logins is set
|
||||
'FailedLoginCount' => 'Int',
|
||||
// In ISO format
|
||||
'DateFormat' => 'Varchar(30)',
|
||||
'TimeFormat' => 'Varchar(30)',
|
||||
);
|
||||
|
||||
private static $belongs_many_many = array(
|
||||
@ -1315,20 +1311,17 @@ class Member extends DataObject implements TemplateGlobalProvider
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the default getter for DateFormat so the
|
||||
* default format for the user's locale is used
|
||||
* if the user has not defined their own.
|
||||
* Return the date format based on the user's chosen locale,
|
||||
* falling back to the default format defined by the {@link i18n.get_locale()} setting.
|
||||
*
|
||||
* @return string ISO date format
|
||||
*/
|
||||
public function getDateFormat()
|
||||
{
|
||||
$format = $this->getField('DateFormat');
|
||||
if ($format) {
|
||||
$format = $this->getDefaultDateFormat();
|
||||
$this->extend('updateDateFormat', $format);
|
||||
return $format;
|
||||
}
|
||||
return $this->getDefaultDateFormat();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user locale
|
||||
@ -1343,19 +1336,17 @@ class Member extends DataObject implements TemplateGlobalProvider
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the default getter for TimeFormat so the
|
||||
* default format for the user's locale is used
|
||||
* if the user has not defined their own.
|
||||
* Return the time format based on the user's chosen locale,
|
||||
* falling back to the default format defined by the {@link i18n.get_locale()} setting.
|
||||
*
|
||||
* @return string ISO date format
|
||||
*/
|
||||
public function getTimeFormat()
|
||||
{
|
||||
$timeFormat = $this->getField('TimeFormat');
|
||||
if ($timeFormat) {
|
||||
return $timeFormat;
|
||||
}
|
||||
return $this->getDefaultTimeFormat();
|
||||
$format = $this->getDefaultTimeFormat();
|
||||
$this->extend('updateTimeFormat', $format);
|
||||
|
||||
return $format;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
@ -1592,61 +1583,11 @@ class Member extends DataObject implements TemplateGlobalProvider
|
||||
if ($permissionsTab) {
|
||||
$permissionsTab->addExtraClass('readonly');
|
||||
}
|
||||
|
||||
// Date format selecter
|
||||
$mainFields->push(
|
||||
$dateFormatField = new MemberDatetimeOptionsetField(
|
||||
'DateFormat',
|
||||
$this->fieldLabel('DateFormat'),
|
||||
$this->getDateFormats()
|
||||
)
|
||||
);
|
||||
$formatClass = get_class($dateFormatField);
|
||||
$dateFormatField->setValue($this->DateFormat);
|
||||
$dateTemplate = SSViewer::get_templates_by_class($formatClass, '_description_date', $formatClass);
|
||||
$dateFormatField->setDescriptionTemplate($dateTemplate);
|
||||
|
||||
// Time format selector
|
||||
$mainFields->push(
|
||||
$timeFormatField = new MemberDatetimeOptionsetField(
|
||||
'TimeFormat',
|
||||
$this->fieldLabel('TimeFormat'),
|
||||
$this->getTimeFormats()
|
||||
)
|
||||
);
|
||||
$timeFormatField->setValue($this->TimeFormat);
|
||||
$timeTemplate = SSViewer::get_templates_by_class($formatClass, '_description_time', $formatClass);
|
||||
$timeFormatField->setDescriptionTemplate($timeTemplate);
|
||||
});
|
||||
|
||||
return parent::getCMSFields();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of date formats with example values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getDateFormats()
|
||||
{
|
||||
$defaultDateFormat = $this->getDefaultDateFormat();
|
||||
$formats = [
|
||||
'MMM d, y' => null,
|
||||
'yyyy/MM/dd' => null,
|
||||
'MM/dd/y' => null,
|
||||
'dd/MM/y' => null,
|
||||
];
|
||||
unset($formats[$defaultDateFormat]);
|
||||
$formats[$defaultDateFormat] = null;
|
||||
// Fill in each format with example
|
||||
foreach (array_keys($formats) as $format) {
|
||||
$formats[$format] = DBDatetime::now()->Format($format);
|
||||
}
|
||||
// Mark default format
|
||||
$formats[$defaultDateFormat] .= sprintf(' (%s)', _t('Member.DefaultDateTime', 'default'));
|
||||
return $formats;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
@ -1674,30 +1615,6 @@ class Member extends DataObject implements TemplateGlobalProvider
|
||||
return $defaultTimeFormat;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get list of date formats with example values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getTimeFormats()
|
||||
{
|
||||
$defaultTimeFormat = $this->getDefaultTimeFormat();
|
||||
$formats = [
|
||||
'h:mm a' => null,
|
||||
'H:mm' => null,
|
||||
];
|
||||
unset($formats[$defaultTimeFormat]);
|
||||
$formats[$defaultTimeFormat] = null;
|
||||
// Fill in each format with example
|
||||
foreach (array_keys($formats) as $format) {
|
||||
$formats[$format] = DBDatetime::now()->Format($format);
|
||||
}
|
||||
// Mark default format
|
||||
$formats[$defaultTimeFormat] .= sprintf(' (%s)', _t('Member.DefaultDateTime', 'default'));
|
||||
return $formats;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $includerelations Indicate if the labels returned include relation fields
|
||||
* @return array
|
||||
@ -1714,8 +1631,6 @@ class Member extends DataObject implements TemplateGlobalProvider
|
||||
$labels['PasswordExpiry'] = _t('Member.db_PasswordExpiry', 'Password Expiry Date', 'Password expiry date');
|
||||
$labels['LockedOutUntil'] = _t('Member.db_LockedOutUntil', 'Locked out until', 'Security related date');
|
||||
$labels['Locale'] = _t('Member.db_Locale', 'Interface Locale');
|
||||
$labels['DateFormat'] = _t('Member.DATEFORMAT', 'Date format');
|
||||
$labels['TimeFormat'] = _t('Member.TIMEFORMAT', 'Time format');
|
||||
if ($includerelations) {
|
||||
$labels['Groups'] = _t(
|
||||
'Member.belongs_many_many_Groups',
|
||||
|
@ -85,12 +85,20 @@ class i18n implements TemplateGlobalProvider
|
||||
private static $default_locale = 'en_US';
|
||||
|
||||
/**
|
||||
* System-wide date format. Will be overruled for CMS UI display
|
||||
* by the format defaults inferred from the browser as well as
|
||||
* any user-specific locale preferences.
|
||||
*
|
||||
* @config
|
||||
* @var string
|
||||
*/
|
||||
private static $date_format = 'yyyy-MM-dd';
|
||||
|
||||
/**
|
||||
* System-wide time format. Will be overruled for CMS UI display
|
||||
* by the format defaults inferred from the browser as well as
|
||||
* any user-specific locale preferences.
|
||||
*
|
||||
* @config
|
||||
* @var string
|
||||
*/
|
||||
|
@ -259,4 +259,16 @@ class DateFieldTest extends SapphireTest
|
||||
"Even if input value hasn't got leading 0's in it we still get the correct data value"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
*/
|
||||
public function testHtml5WithCustomFormatThrowsException()
|
||||
{
|
||||
$dateField = new DateField('Date', 'Date');
|
||||
$dateField->setValue('2010-03-31');
|
||||
$dateField->setHTML5(true);
|
||||
$dateField->setDateFormat('d/M/y');
|
||||
$dateField->Value();
|
||||
}
|
||||
}
|
||||
|
@ -1,47 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Forms\Tests;
|
||||
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\Forms\DateField_View_JQuery;
|
||||
|
||||
class DateFieldViewJQueryTest extends SapphireTest
|
||||
{
|
||||
|
||||
public function testConvert()
|
||||
{
|
||||
$this->assertEquals(
|
||||
'M d, yy',
|
||||
DateField_View_JQuery::convert_iso_to_jquery_format('MMM d, yyyy')
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
'd/mm/yy',
|
||||
DateField_View_JQuery::convert_iso_to_jquery_format('d/MM/yyyy')
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
'dd.m.yy',
|
||||
DateField_View_JQuery::convert_iso_to_jquery_format('dd.M.yyyy'),
|
||||
'Month, no leading zero'
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
'dd.mm.yy',
|
||||
DateField_View_JQuery::convert_iso_to_jquery_format('dd.MM.yyyy'),
|
||||
'Month, two digit'
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
'dd.M.yy',
|
||||
DateField_View_JQuery::convert_iso_to_jquery_format('dd.MMM.yyyy'),
|
||||
'Abbreviated month name'
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
'dd.MM.yy',
|
||||
DateField_View_JQuery::convert_iso_to_jquery_format('dd.MMMM.yyyy'),
|
||||
'Full month name'
|
||||
);
|
||||
}
|
||||
}
|
@ -1,177 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Forms\Tests;
|
||||
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Dev\CSSContentParser;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\Forms\MemberDatetimeOptionsetField;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Forms\Form;
|
||||
use SilverStripe\Forms\RequiredFields;
|
||||
use SilverStripe\i18n\i18n;
|
||||
use SilverStripe\ORM\FieldType\DBDatetime;
|
||||
use SilverStripe\Security\Member;
|
||||
|
||||
class MemberDatetimeOptionsetFieldTest extends SapphireTest
|
||||
{
|
||||
protected static $fixture_file = 'MemberDatetimeOptionsetFieldTest.yml';
|
||||
|
||||
/**
|
||||
* @param Member $member
|
||||
* @return MemberDatetimeOptionsetField
|
||||
*/
|
||||
protected function createDateFormatFieldForMember($member)
|
||||
{
|
||||
$defaultDateFormat = $member->getDefaultDateFormat();
|
||||
$dateFormatMap = array(
|
||||
'yyyy-MM-dd' => DBDatetime::now()->Format('yyyy-MM-dd'),
|
||||
'yyyy/MM/dd' => DBDatetime::now()->Format('yyyy/MM/dd'),
|
||||
'MM/dd/yyyy' => DBDatetime::now()->Format('MM/dd/yyyy'),
|
||||
'dd/MM/yyyy' => DBDatetime::now()->Format('dd/MM/yyyy'),
|
||||
);
|
||||
$dateFormatMap[$defaultDateFormat] = DBDatetime::now()->Format($defaultDateFormat) . ' (default)';
|
||||
$field = new MemberDatetimeOptionsetField(
|
||||
'DateFormat',
|
||||
'Date format',
|
||||
$dateFormatMap
|
||||
);
|
||||
$field->setValue($member->getDateFormat());
|
||||
return $field;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Member $member
|
||||
* @return MemberDatetimeOptionsetField
|
||||
*/
|
||||
protected function createTimeFormatFieldForMember($member)
|
||||
{
|
||||
$defaultTimeFormat = $member->getDefaultTimeFormat();
|
||||
$timeFormatMap = array(
|
||||
'h:mm a' => DBDatetime::now()->Format('h:mm a'),
|
||||
'H:mm' => DBDatetime::now()->Format('H:mm'),
|
||||
);
|
||||
$timeFormatMap[$defaultTimeFormat] = DBDatetime::now()->Format($defaultTimeFormat) . ' (default)';
|
||||
$field = new MemberDatetimeOptionsetField(
|
||||
'TimeFormat',
|
||||
'Time format',
|
||||
$timeFormatMap
|
||||
);
|
||||
$field->setValue($member->getTimeFormat());
|
||||
return $field;
|
||||
}
|
||||
|
||||
public function testDateFormatDefaultCheckedInFormField()
|
||||
{
|
||||
/** @var Member $member */
|
||||
$member = $this->objFromFixture(Member::class, 'noformatmember');
|
||||
$field = $this->createDateFormatFieldForMember($member);
|
||||
/** @skipUpgrade */
|
||||
$field->setForm(
|
||||
new Form(
|
||||
new Controller(),
|
||||
'Form',
|
||||
new FieldList(),
|
||||
new FieldList()
|
||||
)
|
||||
); // fake form
|
||||
// `MMM d, y` is default format for default locale (en_US)
|
||||
$parser = new CSSContentParser($field->Field());
|
||||
$xmlArr = $parser->getBySelector('#Form_Form_DateFormat_MMM_d_y');
|
||||
$this->assertEquals('checked', (string) $xmlArr[0]['checked']);
|
||||
}
|
||||
|
||||
public function testTimeFormatDefaultCheckedInFormField()
|
||||
{
|
||||
/** @var Member $member */
|
||||
$member = $this->objFromFixture(Member::class, 'noformatmember');
|
||||
$field = $this->createTimeFormatFieldForMember($member);
|
||||
/** @skipUpgrade */
|
||||
$field->setForm(
|
||||
new Form(
|
||||
new Controller(),
|
||||
'Form',
|
||||
new FieldList(),
|
||||
new FieldList()
|
||||
)
|
||||
); // fake form
|
||||
// `h:mm:ss a` is the default for en_US locale
|
||||
$parser = new CSSContentParser($field->Field());
|
||||
$xmlArr = $parser->getBySelector('#Form_Form_TimeFormat_h:mm:ss_a');
|
||||
$this->assertEquals('checked', (string) $xmlArr[0]['checked']);
|
||||
}
|
||||
|
||||
public function testDateFormatChosenIsCheckedInFormField()
|
||||
{
|
||||
/** @var Member $member */
|
||||
$member = $this->objFromFixture(Member::class, 'noformatmember');
|
||||
$member->setField('DateFormat', 'MM/dd/yyyy');
|
||||
$field = $this->createDateFormatFieldForMember($member);
|
||||
/** @skipUpgrade */
|
||||
$field->setForm(
|
||||
new Form(
|
||||
new Controller(),
|
||||
'Form',
|
||||
new FieldList(),
|
||||
new FieldList()
|
||||
)
|
||||
); // fake form
|
||||
$parser = new CSSContentParser($field->Field());
|
||||
$xmlArr = $parser->getBySelector('#Form_Form_DateFormat_MM_dd_yyyy');
|
||||
$this->assertEquals('checked', (string) $xmlArr[0]['checked']);
|
||||
}
|
||||
|
||||
public function testDateFormatCustomFormatAppearsInCustomInputInField()
|
||||
{
|
||||
/** @var Member $member */
|
||||
$member = $this->objFromFixture(Member::class, 'noformatmember');
|
||||
$member->setField('DateFormat', 'dd MM yy');
|
||||
$field = $this->createDateFormatFieldForMember($member);
|
||||
/** @skipUpgrade */
|
||||
$field->setForm(
|
||||
new Form(
|
||||
new Controller(),
|
||||
'Form',
|
||||
new FieldList(),
|
||||
new FieldList()
|
||||
)
|
||||
); // fake form
|
||||
$parser = new CSSContentParser($field->Field());
|
||||
$xmlInputArr = $parser->getBySelector('.valcustom input');
|
||||
$this->assertEquals('checked', (string) $xmlInputArr[0]['checked']);
|
||||
$this->assertEquals('dd MM yy', (string) $xmlInputArr[1]['value']);
|
||||
}
|
||||
|
||||
public function testDateFormValid()
|
||||
{
|
||||
$field = new MemberDatetimeOptionsetField('DateFormat', 'DateFormat');
|
||||
$validator = new RequiredFields();
|
||||
$this->assertTrue($field->validate($validator));
|
||||
$field->setSubmittedValue([
|
||||
'Options' => '__custom__',
|
||||
'Custom' => 'dd MM yyyy'
|
||||
]);
|
||||
$this->assertTrue($field->validate($validator));
|
||||
$field->setSubmittedValue([
|
||||
'Options' => '__custom__',
|
||||
'Custom' => 'sdfdsfdfd1244'
|
||||
]);
|
||||
// @todo - Be less forgiving of invalid CLDR date format strings
|
||||
$this->assertTrue($field->validate($validator));
|
||||
}
|
||||
|
||||
public function testDescriptionTemplate()
|
||||
{
|
||||
$field = new MemberDatetimeOptionsetField('DateFormat', 'DateFormat');
|
||||
|
||||
$this->assertEmpty($field->getDescription());
|
||||
|
||||
$field->setDescription('Test description');
|
||||
$this->assertEquals('Test description', $field->getDescription());
|
||||
|
||||
$field->setDescriptionTemplate(get_class($field).'_description_time');
|
||||
$this->assertNotEmpty($field->getDescription());
|
||||
$this->assertNotEquals('Test description', $field->getDescription());
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
SilverStripe\Security\Member:
|
||||
noformatmember:
|
||||
Email: noformat@test.com
|
||||
delocalemember:
|
||||
Email: delocalemember@test.com
|
||||
Locale: de_DE
|
@ -40,6 +40,17 @@ class TimeFieldTest extends SapphireTest
|
||||
$this->assertFalse($f->validate(new RequiredFields()));
|
||||
}
|
||||
|
||||
public function testValidateLenientWithHtml5()
|
||||
{
|
||||
$f = new TimeField('Time', 'Time', '23:59:59');
|
||||
$f->setHTML5(true);
|
||||
$this->assertTrue($f->validate(new RequiredFields()));
|
||||
|
||||
$f = new TimeField('Time', 'Time', '23:59'); // leave out seconds
|
||||
$f->setHTML5(true);
|
||||
$this->assertTrue($f->validate(new RequiredFields()));
|
||||
}
|
||||
|
||||
public function testSetLocale()
|
||||
{
|
||||
// should get en_NZ by default through setUp()
|
||||
@ -123,4 +134,24 @@ class TimeFieldTest extends SapphireTest
|
||||
$f->setValue('03:59:00');
|
||||
$this->assertEquals($f->dataValue(), '03:59:00');
|
||||
}
|
||||
|
||||
public function testLenientSubmissionParseWithoutSecondsOnHtml5()
|
||||
{
|
||||
$f = new TimeField('Time', 'Time');
|
||||
$f->setHTML5(true);
|
||||
$f->setSubmittedValue('23:59');
|
||||
$this->assertEquals($f->Value(), '23:59:00');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
*/
|
||||
public function testHtml5WithCustomFormatThrowsException()
|
||||
{
|
||||
$f = new TimeField('Time', 'Time');
|
||||
$f->setValue('15:59:00');
|
||||
$f->setHTML5(true);
|
||||
$f->setTimeFormat('mm:HH');
|
||||
$f->Value();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user