From 7f563883790307fcfc1caf6cb4df67771dd1cd77 Mon Sep 17 00:00:00 2001 From: Dmitrii Metelkin Date: Fri, 8 Mar 2024 23:20:16 +1100 Subject: [PATCH] issue #36: add support for checkbox custom field --- .../condition/user_custom_profile.php | 113 ++++++++++++++---- .../condition/user_profile.php | 9 +- index.php | 2 +- lang/en/tool_dynamic_cohorts.php | 1 + .../condition/user_custom_profile_test.php | 10 +- 5 files changed, 100 insertions(+), 35 deletions(-) diff --git a/classes/local/tool_dynamic_cohorts/condition/user_custom_profile.php b/classes/local/tool_dynamic_cohorts/condition/user_custom_profile.php index 1abaea3..280e3bc 100644 --- a/classes/local/tool_dynamic_cohorts/condition/user_custom_profile.php +++ b/classes/local/tool_dynamic_cohorts/condition/user_custom_profile.php @@ -16,6 +16,7 @@ namespace tool_dynamic_cohorts\local\tool_dynamic_cohorts\condition; +use coding_exception; use tool_dynamic_cohorts\condition_sql; /** @@ -26,6 +27,7 @@ * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class user_custom_profile extends user_profile { + /** * Field name to store include missing data option, */ @@ -34,7 +36,12 @@ class user_custom_profile extends user_profile { /** * A list of supported custom profile fields. */ - protected const SUPPORTED_CUSTOM_FIELDS = ['text', 'menu']; + protected const SUPPORTED_CUSTOM_FIELDS = ['text', 'menu', 'checkbox']; + + /** + * Value for checkbox field types. + */ + public const FIELD_DATA_TYPE_CHECKBOX = 'checkbox'; /** * Custom field prefix. @@ -51,7 +58,7 @@ public function get_name(): string { } /** - * Returns a list of all fields with extra data (shortname, name, datatype, param1 and type). + * Returns a list of all fields with extra data (shortname, name, datatype and param1). * * @return \stdClass[] */ @@ -70,11 +77,20 @@ protected function get_fields_info(): array { $field = (object)array_intersect_key((array)$customfield->field, ['shortname' => 1, 'name' => 1, 'datatype' => 1, 'param1' => 1]); - if ($field->datatype == self::FIELD_DATA_TYPE_MENU) { - $options = explode("\n", $field->param1); - $field->param1 = array_combine($options, $options); - } else if ($field->datatype == 'text') { - $field->paramtype = PARAM_TEXT; + switch ($field->datatype) { + case self::FIELD_DATA_TYPE_MENU: + $options = explode("\n", $field->param1); + $field->param1 = array_combine($options, $options); + break; + case self::FIELD_DATA_TYPE_TEXT: + $field->paramtype = PARAM_TEXT; + break; + case self::FIELD_DATA_TYPE_CHECKBOX: + $field->param1 = array_combine([0, 1], [get_string('no'), get_string('yes')]); + break; + + default: + throw new coding_exception('Invalid field type ' . $field->datatype); } $shortname = self::FIELD_PREFIX . $field->shortname; @@ -90,7 +106,31 @@ protected function get_fields_info(): array { * @param \MoodleQuickForm $mform */ public function config_form_add(\MoodleQuickForm $mform): void { - parent::config_form_add($mform); + $options = [0 => get_string('select')]; + + $fields = $this->get_fields_info(); + foreach ($fields as $shortname => $field) { + $options[$shortname] = $field->name; + } + + $group = []; + $group[] = $mform->createElement('select', self::FIELD_NAME, '', $options); + + foreach ($fields as $shortname => $field) { + switch ($field->datatype) { + case self::FIELD_DATA_TYPE_TEXT: + $this->add_text_field($mform, $group, $field, $shortname); + break; + case self::FIELD_DATA_TYPE_MENU: + $this->add_menu_field($mform, $group, $field, $shortname); + break; + case self::FIELD_DATA_TYPE_CHECKBOX: + $this->add_checkbox_field($mform, $group, $field, $shortname); + break; + } + } + + $mform->addGroup($group, 'profilefieldgroup', get_string('profilefield', 'tool_dynamic_cohorts'), '', false); $mform->addElement( 'checkbox', @@ -102,6 +142,23 @@ public function config_form_add(\MoodleQuickForm $mform): void { $mform->addHelpButton(self::INCLUDE_MISSING_DATA_FIELD_NAME, self::INCLUDE_MISSING_DATA_FIELD_NAME, 'tool_dynamic_cohorts'); } + /** + * Adds a check box field to the form. + * + * @param \MoodleQuickForm $mform Form to add the field to. + * @param array $group A group to add the field to. + * @param \stdClass $field Field info. + * @param string $shortname A field shortname. + */ + protected function add_checkbox_field(\MoodleQuickForm $mform, array &$group, \stdClass $field, string $shortname): void { + $options = (array) $field->param1; + + $elements = []; + $elements[] = $mform->createElement('hidden', $shortname . '_operator', self::TEXT_IS_EQUAL_TO); + $elements[] = $mform->createElement('select', $shortname . '_value', $field->name, $options); + $group[] = $mform->createElement('group', $shortname, '', $elements, '', false); + $mform->hideIf($shortname, self::FIELD_NAME, 'neq', $shortname); + } /** * Gets required config data from submitted condition form data. * @@ -121,24 +178,7 @@ public static function retrieve_config_data(\stdClass $formdata): array { * @return bool */ protected function should_include_missing_data(): bool { - if (in_array($this->get_operator_value(), $this->missing_data_operators())) { - return !empty($this->get_config_data()[self::INCLUDE_MISSING_DATA_FIELD_NAME]); - } - - return false; - } - - /** - * A list of operators that getting missing data does make sense for. - * - * @return array - */ - protected function missing_data_operators(): array { - return [ - self::TEXT_DOES_NOT_CONTAIN, - self::TEXT_IS_NOT_EQUAL_TO, - self::TEXT_IS_EMPTY, - ]; + return !empty($this->get_config_data()[self::INCLUDE_MISSING_DATA_FIELD_NAME]); } /** @@ -157,6 +197,7 @@ public function get_sql(): condition_sql { case self::FIELD_DATA_TYPE_TEXT: $result = $this->get_text_sql_data($ud, 'data'); break; + case self::FIELD_DATA_TYPE_CHECKBOX: case self::FIELD_DATA_TYPE_MENU: $result = $this->get_menu_sql_data($ud, 'data'); break; @@ -191,6 +232,26 @@ public function get_sql(): condition_sql { return $result; } + /** + * Returns a value of the configured field. + * + * @return string|null + */ + protected function get_field_value(): ?string { + $fieldvalue = parent::get_field_value(); + + // A special case for checkbox field. + $fieldname = $this->get_field_name(); + if (!empty($fieldname) && !empty($this->get_fields_info()[$fieldname])) { + $datatype = $this->get_fields_info()[$fieldname]->datatype; + if ($datatype == self::FIELD_DATA_TYPE_CHECKBOX) { + $fieldvalue = empty($fieldvalue) ? get_string('no') : get_string('yes'); + } + } + + return $fieldvalue; + } + /** * Human-readable description of the configured condition. * diff --git a/classes/local/tool_dynamic_cohorts/condition/user_profile.php b/classes/local/tool_dynamic_cohorts/condition/user_profile.php index dbdaaa2..d8df57a 100644 --- a/classes/local/tool_dynamic_cohorts/condition/user_profile.php +++ b/classes/local/tool_dynamic_cohorts/condition/user_profile.php @@ -20,6 +20,7 @@ use tool_dynamic_cohorts\condition_sql; use core_user; use core_plugin_manager; +use coding_exception; /** * Condition using standard user profile. @@ -31,7 +32,7 @@ class user_profile extends condition_base { /** - * Base field nname. + * Base field name. */ public const FIELD_NAME = 'profilefield'; @@ -121,9 +122,11 @@ public function config_form_add(\MoodleQuickForm $mform): void { case self::FIELD_DATA_TYPE_TEXT: $this->add_text_field($mform, $group, $field, $shortname); break; - case self::FIELD_DATA_TYPE_MENU: + case self::FIELD_DATA_TYPE_MENU: $this->add_menu_field($mform, $group, $field, $shortname); break; + default: + throw new coding_exception('Invalid field type ' . $field->datatype); } } @@ -349,7 +352,7 @@ protected function get_operator_text(string $fielddatatype): string { } /** - * Human readable description of the configured condition. + * Human-readable description of the configured condition. * * @return string */ diff --git a/index.php b/index.php index ca0c743..091d199 100644 --- a/index.php +++ b/index.php @@ -36,7 +36,7 @@ $editurl = new moodle_url('/admin/tool/dynamic_cohorts/edit.php'); foreach (rule::get_records() as $rule) { - if ($rule->is_broken(true)) { + if ($rule->is_broken()) { notification::warning(get_string('brokenruleswarning', 'tool_dynamic_cohorts')); break; } diff --git a/lang/en/tool_dynamic_cohorts.php b/lang/en/tool_dynamic_cohorts.php index 68cacc1..0c47fd7 100644 --- a/lang/en/tool_dynamic_cohorts.php +++ b/lang/en/tool_dynamic_cohorts.php @@ -68,6 +68,7 @@ $string['event:ruledeleted'] = 'Rule deleted'; $string['includingmissingdatadesc'] = '(including users with missing data)'; $string['includeusersmissingdata'] = 'include users with missing data'; +$string['include_missing_data'] = 'Include users with missing data.'; $string['include_missing_data_help'] = 'Some users may not have a custom field data set yet. This option includes those user in the final result.'; $string['invalidfieldvalue'] = 'Invalid field value'; $string['ismemberof'] = 'is member of'; diff --git a/tests/local/tool_dynamic_cohorts/condition/user_custom_profile_test.php b/tests/local/tool_dynamic_cohorts/condition/user_custom_profile_test.php index 485a66f..564297d 100644 --- a/tests/local/tool_dynamic_cohorts/condition/user_custom_profile_test.php +++ b/tests/local/tool_dynamic_cohorts/condition/user_custom_profile_test.php @@ -150,14 +150,14 @@ public function test_set_and_get_configdata() { */ public function config_description_data_provider(): array { return [ - [user_profile::TEXT_CONTAINS, 'Test field1 contains 123', false], + [user_profile::TEXT_CONTAINS, 'Test field1 contains 123', true], [user_profile::TEXT_DOES_NOT_CONTAIN, 'Test field1 doesn\'t contain 123', true], - [user_profile::TEXT_IS_EQUAL_TO, 'Test field1 is equal to 123', false], + [user_profile::TEXT_IS_EQUAL_TO, 'Test field1 is equal to 123', true], [user_profile::TEXT_IS_NOT_EQUAL_TO, 'Test field1 isn\'t equal to 123', true], - [user_profile::TEXT_STARTS_WITH, 'Test field1 starts with 123', false], - [user_profile::TEXT_ENDS_WITH, 'Test field1 ends with 123', false], + [user_profile::TEXT_STARTS_WITH, 'Test field1 starts with 123', true], + [user_profile::TEXT_ENDS_WITH, 'Test field1 ends with 123', true], [user_profile::TEXT_IS_EMPTY, 'Test field1 is empty', true], - [user_profile::TEXT_IS_NOT_EMPTY, 'Test field1 is not empty', false], + [user_profile::TEXT_IS_NOT_EMPTY, 'Test field1 is not empty', true], ]; }