From c312cc11bfce0fbb12b90ad23e9fb06ac18a1a7c Mon Sep 17 00:00:00 2001 From: Alex Pott Date: Thu, 30 Mar 2023 21:53:52 +0100 Subject: [PATCH] Issue #3343755 by kim.pepper, catch, smustgrave, longwave: Simplify TimeZoneFormHelper --- .../Core/Datetime/TimeZoneFormHelper.php | 61 +++++++++++-------- .../FieldFormatter/TimestampFormatter.php | 2 +- .../Core/Installer/Form/SiteConfigureForm.php | 2 +- .../FieldFormatter/DateTimeFormatterBase.php | 2 +- core/modules/system/src/Form/RegionalForm.php | 2 +- core/modules/system/system.module | 4 +- .../System/SystemFunctionsLegacyTest.php | 2 +- core/modules/user/src/AccountForm.php | 2 +- .../views/src/Plugin/views/field/Date.php | 2 +- .../Core/Datetime/TimeZoneFormHelperTest.php | 27 +++++--- 10 files changed, 63 insertions(+), 43 deletions(-) diff --git a/core/lib/Drupal/Core/Datetime/TimeZoneFormHelper.php b/core/lib/Drupal/Core/Datetime/TimeZoneFormHelper.php index 3be2148b7ba..e79d6cbe1a7 100644 --- a/core/lib/Drupal/Core/Datetime/TimeZoneFormHelper.php +++ b/core/lib/Drupal/Core/Datetime/TimeZoneFormHelper.php @@ -18,15 +18,13 @@ class TimeZoneFormHelper { * * @param bool $blank * (optional) If TRUE, prepend an empty time zone option to the array. - * @param bool $grouped - * (optional) Whether the timezones should be grouped by region. * * @return array * An array or nested array containing time zones, keyed by the system name. * The keys are valid time zone identifiers provided by * \DateTimeZone::listIdentifiers() */ - public static function getOptionsList(bool $blank = FALSE, bool $grouped = FALSE): array { + public static function getOptionsList(bool $blank = FALSE): array { $zonelist = \DateTimeZone::listIdentifiers(); $zones = $blank ? ['' => new TranslatableMarkup('- None selected -')] : []; foreach ($zonelist as $zone) { @@ -34,29 +32,44 @@ class TimeZoneFormHelper { } // Sort the translated time zones alphabetically. asort($zones); - if ($grouped) { - $grouped_zones = []; - foreach ($zones as $key => $value) { - $split = explode('/', $value); - $city = array_pop($split); - $region = array_shift($split); - if (!empty($region)) { - $grouped_zones[$region][$key] = empty($split) ? $city : $city . ' (' . implode('/', $split) . ')'; - } - else { - $grouped_zones[$key] = $value; - } - } - foreach ($grouped_zones as $key => $value) { - if (is_array($grouped_zones[$key])) { - asort($grouped_zones[$key]); - } - } - $zones = $grouped_zones; - } - return $zones; + } + /** + * Generate an array of time zones names grouped by region. + * + * This method retrieves the list of IANA time zones names that PHP is + * configured to use, for display to users. It does not return the backward + * compatible names (i.e., the ones defined in the back-zone file). + * + * @param bool $blank + * (optional) If TRUE, prepend an empty time zone option to the array. + * + * @return array + * An nested array containing time zones, keyed by the system name. The keys + * are valid time zone identifiers provided by + * \DateTimeZone::listIdentifiers() + */ + public static function getOptionsListByRegion(bool $blank = FALSE): array { + $zones = static::getOptionsList($blank); + $grouped_zones = []; + foreach ($zones as $key => $value) { + $split = explode('/', $value); + $city = array_pop($split); + $region = array_shift($split); + if (!empty($region)) { + $grouped_zones[$region][$key] = empty($split) ? $city : $city . ' (' . implode('/', $split) . ')'; + } + else { + $grouped_zones[$key] = $value; + } + } + foreach ($grouped_zones as $key => $value) { + if (is_array($grouped_zones[$key])) { + asort($grouped_zones[$key]); + } + } + return $grouped_zones; } } diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampFormatter.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampFormatter.php index 85ea67c8c33..19b1397de46 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampFormatter.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampFormatter.php @@ -201,7 +201,7 @@ class TimestampFormatter extends FormatterBase { $form['timezone'] = [ '#type' => 'select', '#title' => $this->t('Time zone'), - '#options' => ['' => $this->t('- Default site/user time zone -')] + TimeZoneFormHelper::getOptionsList(FALSE, TRUE), + '#options' => ['' => $this->t('- Default site/user time zone -')] + TimeZoneFormHelper::getOptionsListByRegion(), '#default_value' => $this->getSetting('timezone'), ]; diff --git a/core/lib/Drupal/Core/Installer/Form/SiteConfigureForm.php b/core/lib/Drupal/Core/Installer/Form/SiteConfigureForm.php index 42a57221ef7..a8f98d3cc4d 100644 --- a/core/lib/Drupal/Core/Installer/Form/SiteConfigureForm.php +++ b/core/lib/Drupal/Core/Installer/Form/SiteConfigureForm.php @@ -208,7 +208,7 @@ class SiteConfigureForm extends ConfigFormBase { '#type' => 'select', '#title' => $this->t('Default time zone'), '#default_value' => $default_timezone, - '#options' => TimeZoneFormHelper::getOptionsList(FALSE, TRUE), + '#options' => TimeZoneFormHelper::getOptionsListByRegion(), '#weight' => 5, '#attributes' => ['class' => ['timezone-detect']], '#access' => empty($install_state['config_install_path']), diff --git a/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeFormatterBase.php b/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeFormatterBase.php index 52d060febe8..73435402284 100644 --- a/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeFormatterBase.php +++ b/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeFormatterBase.php @@ -98,7 +98,7 @@ abstract class DateTimeFormatterBase extends FormatterBase { '#type' => 'select', '#title' => $this->t('Time zone override'), '#description' => $this->t('The time zone selected here will always be used'), - '#options' => TimeZoneFormHelper::getOptionsList(TRUE, TRUE), + '#options' => TimeZoneFormHelper::getOptionsListByRegion(TRUE), '#default_value' => $this->getSetting('timezone_override'), ]; diff --git a/core/modules/system/src/Form/RegionalForm.php b/core/modules/system/src/Form/RegionalForm.php index 25d2e20ff08..f2028ec3fb5 100644 --- a/core/modules/system/src/Form/RegionalForm.php +++ b/core/modules/system/src/Form/RegionalForm.php @@ -68,7 +68,7 @@ class RegionalForm extends ConfigFormBase { $system_date = $this->config('system.date'); // Date settings: - $zones = TimeZoneFormHelper::getOptionsList(FALSE, TRUE); + $zones = TimeZoneFormHelper::getOptionsListByRegion(); $form['locale'] = [ '#type' => 'details', diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 5372aa4322f..c821d3b2bfc 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -1114,8 +1114,8 @@ function system_mail($key, &$message, $params) { * @see https://www.drupal.org/node/3023528 */ function system_time_zones($blank = NULL, $grouped = FALSE) { - @trigger_error(__METHOD__ . '() is deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. This function is no longer used in Drupal core. Use \Drupal\Core\Datetime\TimeZoneFormHelper::getOptionsList() or \DateTimeZone::listIdentifiers() instead. See https://www.drupal.org/node/3023528', E_USER_DEPRECATED); - return TimeZoneFormHelper::getOptionsList((bool) $blank, $grouped); + @trigger_error(__METHOD__ . '() is deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. This function is no longer used in Drupal core. Use \Drupal\Core\Datetime\TimeZoneFormHelper::getOptionsList(), \Drupal\Core\Datetime\TimeZoneFormHelper::getOptionsListByRegion() or \DateTimeZone::listIdentifiers() instead. See https://www.drupal.org/node/3023528', E_USER_DEPRECATED); + return $grouped ? TimeZoneFormHelper::getOptionsListByRegion((bool) $blank) : TimeZoneFormHelper::getOptionsList((bool) $blank); } /** diff --git a/core/modules/system/tests/src/Kernel/System/SystemFunctionsLegacyTest.php b/core/modules/system/tests/src/Kernel/System/SystemFunctionsLegacyTest.php index 5316186aec5..1d26bd50f40 100644 --- a/core/modules/system/tests/src/Kernel/System/SystemFunctionsLegacyTest.php +++ b/core/modules/system/tests/src/Kernel/System/SystemFunctionsLegacyTest.php @@ -23,7 +23,7 @@ class SystemFunctionsLegacyTest extends KernelTestBase { * @covers ::system_time_zones */ public function testSystemTimeZones() { - $this->expectDeprecation('system_time_zones() is deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. This function is no longer used in Drupal core. Use \Drupal\Core\Datetime\TimeZoneFormHelper::getOptionsList() or \DateTimeZone::listIdentifiers() instead. See https://www.drupal.org/node/3023528'); + $this->expectDeprecation('system_time_zones() is deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. This function is no longer used in Drupal core. Use \Drupal\Core\Datetime\TimeZoneFormHelper::getOptionsList(), \Drupal\Core\Datetime\TimeZoneFormHelper::getOptionsListByRegion() or \DateTimeZone::listIdentifiers() instead. See https://www.drupal.org/node/3023528'); system_time_zones(); } diff --git a/core/modules/user/src/AccountForm.php b/core/modules/user/src/AccountForm.php index c553cbf0349..1cbd8704c1c 100644 --- a/core/modules/user/src/AccountForm.php +++ b/core/modules/user/src/AccountForm.php @@ -297,7 +297,7 @@ abstract class AccountForm extends ContentEntityForm implements TrustedCallbackI '#type' => 'select', '#title' => $this->t('Time zone'), '#default_value' => $account->getTimezone() ?: $system_date_config->get('timezone.default'), - '#options' => TimeZoneFormHelper::getOptionsList($account->id() != $user->id(), TRUE), + '#options' => TimeZoneFormHelper::getOptionsListByRegion($account->id() != $user->id()), '#description' => $this->t('Select the desired local time and time zone. Dates and times throughout this site will be displayed using this time zone.'), ]; diff --git a/core/modules/views/src/Plugin/views/field/Date.php b/core/modules/views/src/Plugin/views/field/Date.php index 80008a8baf1..5c8c3df2370 100644 --- a/core/modules/views/src/Plugin/views/field/Date.php +++ b/core/modules/views/src/Plugin/views/field/Date.php @@ -120,7 +120,7 @@ class Date extends FieldPluginBase { '#type' => 'select', '#title' => $this->t('Timezone'), '#description' => $this->t('Timezone to be used for date output.'), - '#options' => ['' => $this->t('- Default site/user timezone -')] + TimeZoneFormHelper::getOptionsList(FALSE, TRUE), + '#options' => ['' => $this->t('- Default site/user timezone -')] + TimeZoneFormHelper::getOptionsListByRegion(), '#default_value' => $this->options['timezone'], ]; foreach (array_merge(['custom'], array_keys($date_formats)) as $timezone_date_formats) { diff --git a/core/tests/Drupal/Tests/Core/Datetime/TimeZoneFormHelperTest.php b/core/tests/Drupal/Tests/Core/Datetime/TimeZoneFormHelperTest.php index 3f78db5ba42..72a0f74ae20 100644 --- a/core/tests/Drupal/Tests/Core/Datetime/TimeZoneFormHelperTest.php +++ b/core/tests/Drupal/Tests/Core/Datetime/TimeZoneFormHelperTest.php @@ -25,6 +25,7 @@ class TimeZoneFormHelperTest extends UnitTestCase { /** * @covers ::getOptionsList + * @covers ::getOptionsListByRegion */ public function testGetList(): void { // Test the default parameters for getOptionsList(). @@ -33,8 +34,23 @@ class TimeZoneFormHelperTest extends UnitTestCase { $this->assertArrayHasKey('Africa/Dar_es_Salaam', $result); $this->assertEquals('Africa/Dar es Salaam', $result['Africa/Dar_es_Salaam']); + // Test that the ungrouped and grouped results have the same number of + // items. + $ungrouped_count = count(TimeZoneFormHelper::getOptionsList()); + $grouped_result = TimeZoneFormHelper::getOptionsListByRegion(); + $grouped_count = 0; + array_walk_recursive($grouped_result, function () use (&$grouped_count) { + $grouped_count++; + }); + $this->assertEquals($ungrouped_count, $grouped_count); + } + + /** + * @covers ::getOptionsListByRegion + */ + public function testGetGroupedList(): void { // Tests time zone grouping. - $result = TimeZoneFormHelper::getOptionsList(FALSE, TRUE); + $result = TimeZoneFormHelper::getOptionsListByRegion(); // Check a two-level time zone. $this->assertIsArray($result); @@ -59,15 +75,6 @@ class TimeZoneFormHelperTest extends UnitTestCase { // results array. $this->assertArrayNotHasKey('America/Indiana/Indianapolis', $result); - // Test that the ungrouped and grouped results have the same number of - // items. - $ungrouped_count = count(TimeZoneFormHelper::getOptionsList()); - $grouped_result = TimeZoneFormHelper::getOptionsList(FALSE, TRUE); - $grouped_count = 0; - array_walk_recursive($grouped_result, function () use (&$grouped_count) { - $grouped_count++; - }); - $this->assertEquals($ungrouped_count, $grouped_count); } }