From ae66eba0aa78bce6a07f39ae5f205f453c03e9db Mon Sep 17 00:00:00 2001 From: Matthias Schmidt Date: Sun, 30 Jun 2019 14:01:25 +0200 Subject: [PATCH] Add support for earliest/latest date in DateFormField See #2309 --- com.woltlab.wcf/templates/__dateFormField.tpl | 2 + .../files/acp/templates/__dateFormField.tpl | 2 + .../builder/field/DateFormField.class.php | 193 +++++++++++++++++- wcfsetup/install/lang/de.xml | 2 + wcfsetup/install/lang/en.xml | 2 + 5 files changed, 190 insertions(+), 11 deletions(-) diff --git a/com.woltlab.wcf/templates/__dateFormField.tpl b/com.woltlab.wcf/templates/__dateFormField.tpl index ec69fd6e55..3fe9d8d6be 100644 --- a/com.woltlab.wcf/templates/__dateFormField.tpl +++ b/com.woltlab.wcf/templates/__dateFormField.tpl @@ -9,6 +9,8 @@ *}{if $field->isAutofocused()} autofocus{/if}{* *}{if $field->isRequired()} required{/if}{* *}{if $field->isImmutable()} disabled{/if}{* + *}{if $field->getEarliestDate() !== null} min="{$dateFormFieldEarliestDate}"{/if}{* + *}{if $field->getLatestDate() !== null} max="{$dateFormFieldLatestDate}"{/if}{* *}> {include file='__formFieldFooter'} diff --git a/wcfsetup/install/files/acp/templates/__dateFormField.tpl b/wcfsetup/install/files/acp/templates/__dateFormField.tpl index ec69fd6e55..3fe9d8d6be 100644 --- a/wcfsetup/install/files/acp/templates/__dateFormField.tpl +++ b/wcfsetup/install/files/acp/templates/__dateFormField.tpl @@ -9,6 +9,8 @@ *}{if $field->isAutofocused()} autofocus{/if}{* *}{if $field->isRequired()} required{/if}{* *}{if $field->isImmutable()} disabled{/if}{* + *}{if $field->getEarliestDate() !== null} min="{$dateFormFieldEarliestDate}"{/if}{* + *}{if $field->getLatestDate() !== null} max="{$dateFormFieldLatestDate}"{/if}{* *}> {include file='__formFieldFooter'} diff --git a/wcfsetup/install/files/lib/system/form/builder/field/DateFormField.class.php b/wcfsetup/install/files/lib/system/form/builder/field/DateFormField.class.php index 84dcbd2363..6e1398477b 100644 --- a/wcfsetup/install/files/lib/system/form/builder/field/DateFormField.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/field/DateFormField.class.php @@ -1,10 +1,11 @@ earliestDate = $earliestDate; + + if ($this->earliestDate !== null) { + $earliestDateTime = \DateTime::createFromFormat($this->getSaveValueFormat(), $this->earliestDate); + if ($earliestDateTime === false) { + throw new \InvalidArgumentException("Earliest date '{$this->earliestDate}' does not have save value format '{$this->getSaveValueFormat()}'."); + } + + if ($this->getLatestDate() !== null) { + $latestDateTime = \DateTime::createFromFormat($this->getSaveValueFormat(), $this->getLatestDate()); + + if ($latestDateTime < $earliestDateTime) { + throw new \InvalidArgumentException("Earliest date '{$this->earliestDate}' cannot be later than latest date '{$this->getLatestDate()}'."); + } + } + } + + return $this; + } + + /** + * Returns the earliest valid date in `DateFormField::getSaveValueFormat()` format. + * + * If no earliest valid date has been set, `null` is returned. + * + * @return null|string|int + */ + public function getEarliestDate() { + return $this->earliestDate; + } + + /** + * @inheritDoc + */ + public function getHtmlVariables() { + // the date picker JavaScript code requires the `min` and `max` value to have a + // specific format which is easier to create in PHP than in the template itself + + $format = static::DATE_FORMAT; + if ($this->supportsTime()) { + $format = static::TIME_FORMAT; + } + + $formattedEarliestDate = ''; + if ($this->getEarliestDate() !== null) { + $formattedEarliestDate = \DateTime::createFromFormat( + $this->getSaveValueFormat(), + $this->getEarliestDate() + )->format($format); + } + + $formattedLatestDate = ''; + if ($this->getLatestDate() !== null) { + $formattedLatestDate = \DateTime::createFromFormat( + $this->getSaveValueFormat(), + $this->getLatestDate() + )->format($format); + } + + return [ + 'dateFormFieldEarliestDate' => $formattedEarliestDate, + 'dateFormFieldLatestDate' => $formattedLatestDate + ]; + } + + /** + * Returns the latest valid date in `DateFormField::getSaveValueFormat()` format. + * + * If no latest valid date has been set, `null` is returned. + * + * @return null|string|int + */ + public function getLatestDate() { + return $this->latestDate; + } + /** * Returns the type of the returned save value. * @@ -62,10 +164,10 @@ class DateFormField extends AbstractFormField implements IAutoFocusFormField, II */ protected function getValueDateTimeObject() { if ($this->supportsTime()) { - $dateTime = \DateTime::createFromFormat('Y-m-d\TH:i:sP', $this->getValue()); + $dateTime = \DateTime::createFromFormat(static::TIME_FORMAT, $this->getValue()); } else { - $dateTime = \DateTime::createFromFormat('Y-m-d', $this->getValue()); + $dateTime = \DateTime::createFromFormat(static::DATE_FORMAT, $this->getValue()); } if ($dateTime === false) { @@ -91,6 +193,35 @@ class DateFormField extends AbstractFormField implements IAutoFocusFormField, II return $this->getValueDateTimeObject()->format($this->getSaveValueFormat()); } + /** + * Sets the latest valid date in `DateFormField::$saveValueFormat` format and returns this + * field. If `null` is given, the previously set latest valid date is unset. + * + * @param null|string|int $latestDate + * @return static + */ + public function latestDate($latestDate = null) { + $this->latestDate = $latestDate; + + if ($this->latestDate !== null) { + $latestDateTime = \DateTime::createFromFormat($this->getSaveValueFormat(), $this->latestDate); + + if ($latestDateTime === false) { + throw new \InvalidArgumentException("Latest date '{$this->latestDate}' does not have save value format '{$this->getSaveValueFormat()}'."); + } + + if ($this->getEarliestDate() !== null) { + $earliestDateTime = \DateTime::createFromFormat($this->getSaveValueFormat(), $this->getEarliestDate()); + + if ($latestDateTime < $earliestDateTime) { + throw new \InvalidArgumentException("Latest date '{$this->latestDate}' cannot be earlier than earliest date '{$this->getEarliestDate()}'."); + } + } + } + + return $this; + } + /** * @inheritDoc */ @@ -117,13 +248,6 @@ class DateFormField extends AbstractFormField implements IAutoFocusFormField, II throw new \BadMethodCallException("Save value type has already been set."); } - try { - \DateTime::createFromFormat($saveValueFormat, TIME_NOW); - } - catch (\Exception $e) { - throw new \InvalidArgumentException("Invalid date time format '{$saveValueFormat}'.", 0, $e); - } - $this->saveValueFormat = $saveValueFormat; return $this; @@ -161,12 +285,59 @@ class DateFormField extends AbstractFormField implements IAutoFocusFormField, II } } else { - if ($this->getValueDateTimeObject() === null) { + $dateTime = $this->getValueDateTimeObject(); + if ($dateTime === null) { $this->addValidationError(new FormFieldValidationError( 'format', 'wcf.form.field.date.error.format' )); } + else if ($this->getEarliestDate() !== null) { + $earliestDateTime = \DateTime::createFromFormat($this->getSaveValueFormat(), $this->getEarliestDate()); + + if ($dateTime < $earliestDateTime) { + $format = DateUtil::DATE_FORMAT; + if ($this->supportsTime()) { + $format = str_replace( + ['%date%', '%time%'], + [ + WCF::getLanguage()->get(DateUtil::DATE_FORMAT), + WCF::getLanguage()->get(DateUtil::TIME_FORMAT) + ], + WCF::getLanguage()->get('wcf.date.dateTimeFormat') + ); + } + + $this->addValidationError(new FormFieldValidationError( + 'minimum', + 'wcf.form.field.date.error.earliestDate', + ['earliestDate' => DateUtil::format($earliestDateTime, $format)] + )); + } + } + else if ($this->getLatestDate() !== null) { + $latestDateTime = \DateTime::createFromFormat($this->getSaveValueFormat(), $this->getLatestDate()); + + if ($dateTime > $latestDateTime) { + $format = DateUtil::DATE_FORMAT; + if ($this->supportsTime()) { + $format = str_replace( + ['%date%', '%time%'], + [ + WCF::getLanguage()->get(DateUtil::DATE_FORMAT), + WCF::getLanguage()->get(DateUtil::TIME_FORMAT) + ], + WCF::getLanguage()->get('wcf.date.dateTimeFormat') + ); + } + + $this->addValidationError(new FormFieldValidationError( + 'minimum', + 'wcf.form.field.date.error.latestDate', + ['latestDateTime' => DateUtil::format($latestDateTime, $format)] + )); + } + } } } diff --git a/wcfsetup/install/lang/de.xml b/wcfsetup/install/lang/de.xml index 42c82e02ed..6aac3554b1 100644 --- a/wcfsetup/install/lang/de.xml +++ b/wcfsetup/install/lang/de.xml @@ -3908,6 +3908,8 @@ Dateianhänge: + + diff --git a/wcfsetup/install/lang/en.xml b/wcfsetup/install/lang/en.xml index a0a0281b5f..5a84208943 100644 --- a/wcfsetup/install/lang/en.xml +++ b/wcfsetup/install/lang/en.xml @@ -3854,6 +3854,8 @@ Attachments: + + -- 2.20.1