diff --git a/.horde.yml b/.horde.yml index 3eec9ef..c518014 100644 --- a/.horde.yml +++ b/.horde.yml @@ -10,7 +10,7 @@ authors: - name: Dmitry Petrov user: dpetrov - email: '' + email: active: true role: lead - @@ -38,10 +38,10 @@ authors: active: false role: lead version: - release: 3.0.0-beta8 + release: 3.0.0-RC1 api: 3.0.0alpha1 state: - release: beta + release: RC api: alpha license: identifier: LGPL-2.1-only diff --git a/composer.json b/composer.json index 5e8f225..e4019d5 100644 --- a/composer.json +++ b/composer.json @@ -5,6 +5,20 @@ "homepage": "https://www.horde.org/libraries/Horde_Form", "license": "LGPL-2.1-only", "authors": [ + { + "name": "Dmitry Petrov", + "role": "lead" + }, + { + "name": "Torben Dannhauber", + "email": "torben@dannhauer.de", + "role": "releasemanager" + }, + { + "name": "Ralf Lang", + "email": "ralf.lang@ralf-lang.de", + "role": "contributor" + }, { "name": "Jan Schneider", "email": "jan@horde.org", @@ -21,7 +35,7 @@ "validation", "crud" ], - "time": "2026-04-13", + "time": "2026-05-18", "repositories": [], "require": { "php": "^7.4 || ^8", diff --git a/doc/changelog.yml b/doc/changelog.yml index ee9caa6..b765697 100644 --- a/doc/changelog.yml +++ b/doc/changelog.yml @@ -271,6 +271,41 @@ Original version string was 3.0.0alpha1 [mjr] SECURITY: Prevent ability to specify temporary filename (CVE-2020-8866, Reported By: Andrea Cardaci working with Trend Micro Zero Day Initiative). |+ +3.0.0-RC1: + api: 3.0.0-RC1 + state: + release: RC + api: RC + date: 2026-05-18 + license: + identifier: LGPL-2.1-only + uri: https://spdx.org/licenses/LGPL-2.1-only.html + notes: |- + fix: Allow Horde\Util\Variables class in isValid() method + fix: Add Delegators - 866aa1af commit "Refactor variable method calls in Html.php" broke trean config menu + feat: add __call magic method to delegate undefined methods to $type + fix(v3): Reproduce legacy type names in getTypeName() + refactor: Improve createVariable() logic + fix: Make unused $info parameter in Horde_Form_Variable::getInfo() optional + Fix prompt check and update getInfo call + Merge pull request #26 from horde6/FRAMEWORK_6_0 + refactor: use getFieldParts() in _getInfoFromVariables() + refactor: simplify _getUpload and getUploadedFileType() - use getFieldParts() instead of getArrayParts() in 'image' type - utilize extra parameter in getElement/setElement to simplify the code - make getUploadedFileType() static + refactor: use array_splice in removeVariable() + fix: initialize $_img variable + refactor(Form): modernise _currentSection handling and variable insertion + Initialize _img property to null + Merge pull request #24 from horde6/V3 + feat: Implement transitional support to V3 classes + docs: Add an "old-style entrypoint" and a PSR controller demonstrating all form types + test: Add regression test against the File behaviour change + fix: Restore original behavior of getInfo() for 'file" variable type + chore: Add Dmitry as the primary maintainer + fix: Type safety issue in PHP 8.5 + docs: Add V3 UPGRADING.md which supersedes the previous migration guide + docs: Reference CSS for the V3 form model + test: Add test cases for V3 FieldGroups (replacing nested forms) + feat: Flesh out V3 forms and migrations 2.0.19: api: 1.1.0 state: diff --git a/lib/Horde/Form/Type.php b/lib/Horde/Form/Type.php index 0200365..ff9c436 100644 --- a/lib/Horde/Form/Type.php +++ b/lib/Horde/Form/Type.php @@ -12,11 +12,11 @@ * @package Form */ +use Horde\Date\Format; use Horde\Date\FormatterInterface; +use Horde\Date\Formatter\IcuFormatter; use Horde\Util\ArrayUtils; -use function PHP81_BC\strftime; - /** * Horde_Form_Type Class * @@ -3099,8 +3099,8 @@ public function getFormattedTime($timestamp, $format = null, $showago = true) $locale = $this->_resolveLocale(); $formatted = $this->_formatter->format($timestamp, $format, $locale, $this->_timezone); } else { - // strftime mode (default, backward compatible) - $formatted = strftime($format, $timestamp); + // ICU format mode (default) + $formatted = Format::formatDate($timestamp, $format, $GLOBALS['language'] ?? 'en_US'); } return $formatted . ($showago ? Horde_Form_Type_date::getAgo($timestamp) : ''); } else { @@ -3598,8 +3598,8 @@ public function formatDate($date) $locale = $this->_resolveLocale(); return $date->format($this->_format_out, $this->_formatter, $locale); } else { - // strftime mode (default) - return $date->strftime($this->_format_out); + // ICU format mode (default) + return $date->format($this->_format_out, new IcuFormatter(), $GLOBALS['language'] ?? 'en_US'); } } @@ -3688,8 +3688,8 @@ public function _validateAndFormat($value, $var) // Formatter mode return $date->format($this->_format_in, $this->_formatter, $this->_locale); } else { - // strftime mode - return $date->strftime($this->_format_in); + // ICU format mode + return $date->format($this->_format_in, new IcuFormatter(), $GLOBALS['language'] ?? 'en_US'); } } } @@ -3827,7 +3827,7 @@ private function _getInfo($value) if ($this->getProperty('format_in') === null) { $info = $date->timestamp(); } else { - $info = $date->strftime($this->getProperty('format_in')); + $info = $date->format($this->getProperty('format_in'), new IcuFormatter(), $GLOBALS['language'] ?? 'en_US'); } return $info; } diff --git a/src/V3/DateVariable.php b/src/V3/DateVariable.php index 928ce67..78178f1 100644 --- a/src/V3/DateVariable.php +++ b/src/V3/DateVariable.php @@ -2,6 +2,7 @@ namespace Horde\Form\V3; +use Horde\Date\Format; use Horde\Util\Variables; use Horde_Variables; use Horde_Date; @@ -11,7 +12,7 @@ /** * DateVariable type for date input fields. * - * @property string $format The date format string + * @property string $format The ICU date format pattern * * PSR-4 implementation. @@ -26,13 +27,13 @@ class DateVariable extends BaseVariable * Initialize a date field. * * @param array $params Variable arguments: - * - $params[0]: string $format - The date format string (default: '%a %d %B') + * - $params[0]: string $format - ICU date format pattern (default: 'EEE dd MMMM') * * @api */ public function init(...$params) { - $this->_format = $params[0] ?? '%a %d %B'; + $this->_format = $params[0] ?? 'EEE dd MMMM'; } protected function isValid(Horde_Variables|array $vars, $value): bool @@ -97,7 +98,7 @@ public function getFormattedTime($timestamp, $format = null, $showago = true) $format = $this->_format; } - return strftime($format, $timestamp) . ($showago ? $this::getAgo($timestamp) : ''); + return Format::formatDate($timestamp, $format, $GLOBALS['language'] ?? 'en_US') . ($showago ? $this::getAgo($timestamp) : ''); } /** diff --git a/src/V3/DatetimeVariable.php b/src/V3/DatetimeVariable.php index 1b18cc2..60a6619 100644 --- a/src/V3/DatetimeVariable.php +++ b/src/V3/DatetimeVariable.php @@ -2,6 +2,7 @@ namespace Horde\Form\V3; +use Horde\Date\Formatter\IcuFormatter; use Horde\Util\Variables; use Horde_Variables; use Horde_Form_Translation; @@ -12,8 +13,8 @@ * @property int $start_year The first available year for input * @property int $end_year The last available year for input * @property bool $picker Do we show the DHTML calendar - * @property string|null $format_in The format to use when sending the date for storage - * @property string $format_out The format to use when displaying the date + * @property string|null $format_in The ICU format to use when sending the date for storage + * @property string $format_out The ICU format to use when displaying the date * @property bool $show_seconds Include a form input for seconds * @@ -33,8 +34,8 @@ class DatetimeVariable extends BaseVariable * - $params[0]: int $start_year - The first available year for input (default: '') * - $params[1]: int $end_year - The last available year for input (default: '') * - $params[2]: bool $picker - Do we show the DHTML calendar (default: true) - * - $params[3]: string|null $format_in - The format to use when sending the date for storage. Defaults to Unix epoch. Similar to the strftime() function. (default: null) - * - $params[4]: string $format_out - The format to use when displaying the date. Similar to the strftime() function. (default: '%x') + * - $params[3]: string|null $format_in - ICU format for storage. Defaults to Unix epoch. (default: null) + * - $params[4]: string $format_out - ICU format for display (default: 'short') * - $params[5]: bool $show_seconds - Include a form input for seconds (default: false) * * @api @@ -45,7 +46,7 @@ public function init(...$params) $end_year = $params[1] ?? ''; $picker = $params[2] ?? true; $format_in = $params[3] ?? null; - $format_out = $params[4] ?? '%x'; + $format_out = $params[4] ?? 'short'; $show_seconds = $params[5] ?? false; $this->_mdy = new MonthdayyearVariable('', '', true); @@ -100,7 +101,7 @@ private function _getInfo($value) if ($this->getProperty('format_in') === null) { $info = $date->timestamp(); } else { - $info = $date->strftime($this->getProperty('format_in')); + $info = $date->format($this->getProperty('format_in'), new IcuFormatter(), $GLOBALS['language'] ?? 'en_US'); } return $info; diff --git a/src/V3/MonthdayyearVariable.php b/src/V3/MonthdayyearVariable.php index 0828576..85ce633 100644 --- a/src/V3/MonthdayyearVariable.php +++ b/src/V3/MonthdayyearVariable.php @@ -2,6 +2,7 @@ namespace Horde\Form\V3; +use Horde\Date\Formatter\IcuFormatter; use Horde\Util\Variables; use Horde_Variables; use Horde_Date; @@ -13,8 +14,8 @@ * @property int $start_year The first available year for input * @property int $end_year The last available year for input * @property bool $picker Do we show the DHTML calendar - * @property string|null $format_in The format to use when sending the date for storage - * @property string $format_out The format to use when displaying the date + * @property string|null $format_in The ICU format to use when sending the date for storage + * @property string $format_out The ICU format to use when displaying the date * * PSR-4 implementation. @@ -27,7 +28,7 @@ class MonthdayyearVariable extends BaseVariable public $_end_year; public $_picker; public $_format_in = null; - public $_format_out = '%x'; + public $_format_out = 'short'; /** * Initialize a date selection field. @@ -36,8 +37,8 @@ class MonthdayyearVariable extends BaseVariable * - $params[0]: int $start_year - The first available year for input (default: current year) * - $params[1]: int $end_year - The last available year for input (default: current year + 10) * - $params[2]: bool $picker - Do we show the DHTML calendar (default: true) - * - $params[3]: string|null $format_in - The format to use when sending the date for storage. Defaults to Unix epoch. Similar to the strftime() function. (default: null) - * - $params[4]: string $format_out - The format to use when displaying the date. Similar to the strftime() function. (default: '%x') + * - $params[3]: string|null $format_in - ICU format for storage. Defaults to Unix epoch. (default: null) + * - $params[4]: string $format_out - ICU format for display (default: 'short') * * @api */ @@ -47,7 +48,7 @@ public function init(...$params) $end_year = $params[1] ?? ''; $picker = $params[2] ?? true; $format_in = $params[3] ?? null; - $format_out = $params[4] ?? '%x'; + $format_out = $params[4] ?? 'short'; if (empty($start_year)) { $start_year = date('Y'); @@ -211,7 +212,7 @@ public function formatDate($date) $date = $this->getDateOb($date); } - return $date->strftime($this->_format_out); + return $date->format($this->_format_out, new IcuFormatter(), $GLOBALS['language'] ?? 'en_US'); } /** @@ -246,7 +247,7 @@ public function _validateAndFormat($value) return $date->timestamp(); } - return $date->strftime($this->_format_in); + return $date->format($this->_format_in, new IcuFormatter(), $GLOBALS['language'] ?? 'en_US'); } /** diff --git a/var/config/horde/registry.d/00-horde.php b/var/config/horde/registry.d/00-horde.php new file mode 100644 index 0000000..d6c21af --- /dev/null +++ b/var/config/horde/registry.d/00-horde.php @@ -0,0 +1,11 @@ +