diff --git a/admin/settings/location.php b/admin/settings/location.php index 85d58388ba7..5a4cc9010c8 100644 --- a/admin/settings/location.php +++ b/admin/settings/location.php @@ -49,8 +49,8 @@ if ($hassiteconfig) { $temp->add(new admin_setting_configtext('googlemapkey3', new lang_string('googlemapkey3', 'core_admin'), new lang_string('googlemapkey3_help', 'core_admin'), '', PARAM_RAW, 60)); - $temp->add(new admin_setting_configtext('allcountrycodes', new lang_string('allcountrycodes', 'core_admin'), - new lang_string('configallcountrycodes', 'core_admin'), '', '/^(?:\w+(?:,\w+)*)?$/')); + $temp->add(new admin_setting_countrycodes('allcountrycodes', new lang_string('allcountrycodes', 'core_admin'), + new lang_string('configallcountrycodes', 'core_admin'))); } $ADMIN->add('location', $temp); diff --git a/admin/tests/behat/invalid_allcountrycodes.feature b/admin/tests/behat/invalid_allcountrycodes.feature new file mode 100644 index 00000000000..399712f45e1 --- /dev/null +++ b/admin/tests/behat/invalid_allcountrycodes.feature @@ -0,0 +1,29 @@ +@core @core_admin +Feature: Administrator is warned and when trying to set invalid allcountrycodes value. + In order to avoid misconfiguration of the country selector fields + As an admin + I want to be warned when I try to set an invalid country code in the allcountrycodes field + + Scenario: Attempting to set allcountrycodes field with valid country codes + Given I log in as "admin" + And I navigate to "Location > Location settings" in site administration + When I set the following administration settings values: + | All country codes | CZ,BE,GB,ES | + Then I should not see "Invalid country code" + + Scenario: Attempting to set allcountrycodes field with invalid country code + Given I log in as "admin" + And I navigate to "Location > Location settings" in site administration + When I set the following administration settings values: + | All country codes | CZ,BE,FOOBAR,GB,ES | + Then I should see "Invalid country code: FOOBAR" + + Scenario: Attempting to unset allcountrycodes field + Given I log in as "admin" + And I navigate to "Location > Location settings" in site administration + And I set the following administration settings values: + | All country codes | CZ,BE,GB,ES | + And I navigate to "Location > Location settings" in site administration + When I set the following administration settings values: + | All country codes | | + Then I should not see "Invalid country code" diff --git a/lang/en/error.php b/lang/en/error.php index e41176cdbd1..21416150fc3 100644 --- a/lang/en/error.php +++ b/lang/en/error.php @@ -324,6 +324,7 @@ $string['invalidcourselevel'] = 'Incorrect context level'; $string['invalidcourseformat'] = 'Invalid course format'; $string['invalidcoursemodule'] = 'Invalid course module ID'; $string['invalidcoursenameshort'] = 'Invalid short course name'; +$string['invalidcountrycode'] = 'Invalid country code: {$a}'; $string['invaliddata'] = 'Data submitted is invalid'; $string['invaliddatarootpermissions'] = 'Invalid permissions detected when trying to create a directory. Turn debugging on for further details.'; $string['invaliddevicetype'] = 'Invalid device type'; diff --git a/lib/adminlib.php b/lib/adminlib.php index 9b7445d6b80..29889c777c0 100644 --- a/lib/adminlib.php +++ b/lib/adminlib.php @@ -4901,6 +4901,66 @@ class admin_setting_langlist extends admin_setting_configtext { } +/** + * Allows to specify comma separated list of known country codes. + * + * This is a simple subclass of the plain input text field with added validation so that all the codes are actually + * known codes. + * + * @package core + * @category admin + * @copyright 2020 David Mudrák + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class admin_setting_countrycodes extends admin_setting_configtext { + + /** + * Construct the instance of the setting. + * + * @param string $name Name of the admin setting such as 'allcountrycodes' or 'myplugin/countries'. + * @param lang_string|string $visiblename Language string with the field label text. + * @param lang_string|string $description Language string with the field description text. + * @param string $defaultsetting Default value of the setting. + * @param int $size Input text field size. + */ + public function __construct($name, $visiblename, $description, $defaultsetting = '', $size = null) { + parent::__construct($name, $visiblename, $description, $defaultsetting, '/^(?:\w+(?:,\w+)*)?$/', $size); + } + + /** + * Validate the setting value before storing it. + * + * The value is first validated through custom regex so that it is a word consisting of letters, numbers or underscore; or + * a comma separated list of such words. + * + * @param string $data Value inserted into the setting field. + * @return bool|string True if the value is OK, error string otherwise. + */ + public function validate($data) { + + $parentcheck = parent::validate($data); + + if ($parentcheck !== true) { + return $parentcheck; + } + + if ($data === '') { + return true; + } + + $allcountries = get_string_manager()->get_list_of_countries(true); + + foreach (explode(',', $data) as $code) { + if (!isset($allcountries[$code])) { + return get_string('invalidcountrycode', 'core_error', $code); + } + } + + return true; + } +} + + /** * Selection of one of the recognised countries using the list * returned by {@link get_list_of_countries()}.