Skip to content

Commit

Permalink
Merge pull request #72 from catalyst/issue40
Browse files Browse the repository at this point in the history
issue #40: add support for date field
  • Loading branch information
dmitriim authored Apr 2, 2024
2 parents 227ffa3 + 9551126 commit 9fc4f7d
Show file tree
Hide file tree
Showing 9 changed files with 257 additions and 72 deletions.
20 changes: 20 additions & 0 deletions classes/condition_base.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ abstract class condition_base {
*/
public const FIELD_DATA_TYPE_CHECKBOX = 'checkbox';

/**
* Value for date field types.
*/
public const FIELD_DATA_TYPE_DATE = 'date';

/**
* Value for date field types.
*/
public const FIELD_DATA_TYPE_DATETIME = 'datetime';

/**
* Value for operator text contains.
*/
Expand Down Expand Up @@ -85,6 +95,16 @@ abstract class condition_base {
*/
public const TEXT_IS_NOT_EQUAL_TO = 8;

/**
* Value for operator date is after.
*/
public const DATE_IS_AFTER = 1;

/**
* Value for operator date is before.
*/
public const DATE_IS_BEFORE = 2;

/**
* Condition persistent object.
*
Expand Down
39 changes: 11 additions & 28 deletions classes/local/tool_dynamic_cohorts/condition/cohort_field.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ protected function get_cohort_operators(): array {
* @return array
*/
protected function get_supported_custom_fields(): array {
return [self::FIELD_DATA_TYPE_TEXT, self::FIELD_DATA_TYPE_SELECT, self::FIELD_DATA_TYPE_CHECKBOX];
return [self::FIELD_DATA_TYPE_TEXT, self::FIELD_DATA_TYPE_SELECT,
self::FIELD_DATA_TYPE_CHECKBOX, self::FIELD_DATA_TYPE_DATE];
}

/**
Expand Down Expand Up @@ -154,6 +155,9 @@ protected function get_fields_info(): array {
case self::FIELD_DATA_TYPE_CHECKBOX:
$fields[$shortname]->param1 = array_combine([0, 1], [get_string('no'), get_string('yes')]);
break;
case self::FIELD_DATA_TYPE_DATE:
$fields[$shortname]->paramtype = PARAM_INT;
break;
default:
throw new coding_exception('Invalid field type ' . $fields[$shortname]->datatype);
}
Expand Down Expand Up @@ -217,6 +221,9 @@ public function config_form_add(\MoodleQuickForm $mform): void {
case self::FIELD_DATA_TYPE_CHECKBOX:
$this->add_checkbox_field($mform, $group, $field, $shortname);
break;
case self::FIELD_DATA_TYPE_DATE:
$this->add_date_field($mform, $group, $field, $shortname);
break;
default:
throw new coding_exception('Invalid field type ' . $field->datatype);
}
Expand Down Expand Up @@ -244,33 +251,6 @@ public function config_form_add(\MoodleQuickForm $mform): void {
}
}

/**
* Validate config form elements.
*
* @param array $data Data to validate.
* @return array
*/
public function config_form_validate(array $data): array {
$errors = [];

$fields = $this->get_fields_info();
if (empty($data[static::get_form_field()]) || !isset($fields[$data[static::get_form_field()]])) {
$errors['fieldgroup'] = get_string('pleaseselectfield', 'tool_dynamic_cohorts');
}

$fieldvalue = $data[static::get_form_field()] . '_value';
$operator = $data[static::get_form_field()] . '_operator';
$datatype = $fields[$data[static::get_form_field()]]->datatype ?? '';

if (empty($data[$fieldvalue])) {
if ($datatype == 'text' && !in_array($data[$operator], [self::TEXT_IS_EMPTY, self::TEXT_IS_NOT_EMPTY])) {
$errors['fieldgroup'] = get_string('invalidfieldvalue', 'tool_dynamic_cohorts');
}
}

return $errors;
}

/**
* Gets required config data from submitted condition form data.
*
Expand Down Expand Up @@ -405,6 +385,9 @@ public function get_sql(): condition_sql {
case self::FIELD_DATA_TYPE_SELECT:
$fieldsqldata = $this->get_menu_sql($fieldstable, $dbcolumn);
break;
case self::FIELD_DATA_TYPE_DATE:
$fieldsqldata = $this->get_date_sql($fieldstable, $dbcolumn);
break;
default:
throw new coding_exception('Invalid field type ' . $datatype);
}
Expand Down
126 changes: 117 additions & 9 deletions classes/local/tool_dynamic_cohorts/condition/fields_trait.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,20 @@ protected function get_menu_operators(): array {
];
}

/**
* Gets a list of comparison operators for date fields.
*
* @return array A list of operators.
*/
protected function get_date_operators(): array {
return [
self::DATE_IS_AFTER => get_string('isafter', 'tool_dynamic_cohorts'),
self::DATE_IS_BEFORE => get_string('isbefore', 'tool_dynamic_cohorts'),
self::TEXT_IS_EMPTY => get_string('isempty', 'filters'),
self::TEXT_IS_NOT_EMPTY => get_string('isnotempty', 'tool_dynamic_cohorts'),
];
}

/**
* Returns a field name for the configured field.
*
Expand Down Expand Up @@ -109,7 +123,9 @@ protected function get_field_value_text(): ?string {
case self::FIELD_DATA_TYPE_CHECKBOX:
$fieldvalue = $fieldinfo[$fieldname]->param1[$fieldvalue];
break;

case self::FIELD_DATA_TYPE_DATE:
case self::FIELD_DATA_TYPE_DATETIME:
$fieldvalue = userdate($fieldvalue);
}
}

Expand All @@ -136,15 +152,16 @@ protected function get_operator_value(): int {
* @return string
*/
protected function get_operator_text(string $fielddatatype): string {
if ($fielddatatype == self::FIELD_DATA_TYPE_TEXT) {
return $this->get_text_operators()[$this->get_operator_value()];
}

if ($fielddatatype == self::FIELD_DATA_TYPE_MENU) {
return $this->get_menu_operators()[$this->get_operator_value()];
switch ($fielddatatype) {
case self::FIELD_DATA_TYPE_MENU:
case self::FIELD_DATA_TYPE_SELECT:
return $this->get_menu_operators()[$this->get_operator_value()];
case self::FIELD_DATA_TYPE_DATETIME:
case self::FIELD_DATA_TYPE_DATE:
return $this->get_date_operators()[$this->get_operator_value()];
default:
return $this->get_text_operators()[$this->get_operator_value()];
}

return $this->get_text_operators()[$this->get_operator_value()];
}

/**
Expand Down Expand Up @@ -205,6 +222,57 @@ protected function add_checkbox_field(\MoodleQuickForm $mform, array &$group, \s
$mform->hideIf($shortname, self::get_form_field(), 'neq', $shortname);
}

/**
* Adds a date 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_date_field(\MoodleQuickForm $mform, array &$group, \stdClass $field, string $shortname): void {
$elements = [];
$elements[] = $mform->createElement('select', $shortname . '_operator', null, $this->get_date_operators());

$elements[] = $mform->createElement('date_time_selector', $shortname . '_value');
$mform->setDefault($shortname . '_value', usergetmidnight(time()));
$mform->hideIf($shortname . '_value', $shortname . '_operator', 'in', self::TEXT_IS_EMPTY . '|' . self::TEXT_IS_NOT_EMPTY);

$group[] = $mform->createElement('group', $shortname, '', $elements, '', false);

$mform->hideIf($shortname . '_operator', static::get_form_field(), 'neq', $shortname);
$mform->hideIf($shortname . '_value', static::get_form_field(), 'neq', $shortname);
$mform->hideIf($shortname . '_value1', static::get_form_field(), 'neq', $shortname);
$mform->hideIf($shortname, static::get_form_field(), 'neq', $shortname);
}

/**
* Validate config form elements.
*
* @param array $data Data to validate.
* @return array
*/
public function config_form_validate(array $data): array {
$errors = [];

$fields = $this->get_fields_info();
if (empty($data[static::get_form_field()]) || !isset($fields[$data[static::get_form_field()]])) {
$errors['fieldgroup'] = get_string('pleaseselectfield', 'tool_dynamic_cohorts');
}

$fieldvalue = $data[static::get_form_field()] . '_value';
$operator = $data[static::get_form_field()] . '_operator';
$datatype = $fields[$data[static::get_form_field()]]->datatype ?? '';

if (empty($data[$fieldvalue])) {
if ($datatype == 'text' && !in_array($data[$operator], [self::TEXT_IS_EMPTY, self::TEXT_IS_NOT_EMPTY])) {
$errors['fieldgroup'] = get_string('invalidfieldvalue', 'tool_dynamic_cohorts');
}
}

return $errors;
}

/**
* Get SQl data for text type fields.
*
Expand Down Expand Up @@ -303,4 +371,44 @@ protected function get_menu_sql(string $tablealias, string $fieldname): conditio

return new condition_sql('', $where, $params);
}

/**
* Get SQL data for date type fields.
*
* @param string $tablealias Alias for a table.
* @param string $fieldname Field name.
* @return condition_sql
*/
protected function get_date_sql(string $tablealias, string $fieldname): condition_sql {
$fieldvalue = $this->get_field_value();
$operatorvalue = $this->get_operator_value();

if ($this->is_broken()) {
return new condition_sql('', '', []);
}

$param = condition_sql::generate_param_alias();
switch ($operatorvalue) {
case self::TEXT_IS_EMPTY:
$where = "$tablealias.$fieldname = :$param OR $tablealias.$fieldname IS NULL";
$params[$param] = 0;
break;
case self::TEXT_IS_NOT_EMPTY:
$where = "$tablealias.$fieldname <> :$param";
$params[$param] = (int) $fieldvalue;
break;
case self::DATE_IS_BEFORE:
$where = "$tablealias.$fieldname <= :$param";
$params[$param] = (int) $fieldvalue;
break;
case self::DATE_IS_AFTER:
$where = "$tablealias.$fieldname >= :$param";
$params[$param] = (int) $fieldvalue;
break;
default:
return new condition_sql('', '', []);
}

return new condition_sql('', $where, $params);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ public function get_name(): string {
* @return array
*/
protected function get_supported_custom_fields(): array {
return [self::FIELD_DATA_TYPE_TEXT, self::FIELD_DATA_TYPE_MENU, self::FIELD_DATA_TYPE_CHECKBOX];
return [self::FIELD_DATA_TYPE_TEXT, self::FIELD_DATA_TYPE_MENU,
self::FIELD_DATA_TYPE_CHECKBOX, self::FIELD_DATA_TYPE_DATETIME];
}

/**
Expand Down Expand Up @@ -87,6 +88,9 @@ protected function get_fields_info(): array {
case self::FIELD_DATA_TYPE_CHECKBOX:
$field->param1 = array_combine([0, 1], [get_string('no'), get_string('yes')]);
break;
case self::FIELD_DATA_TYPE_DATETIME:
$field->paramtype = PARAM_INT;
break;
default:
throw new coding_exception('Invalid field type ' . $field->datatype);
}
Expand Down Expand Up @@ -119,16 +123,19 @@ 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;
case self::FIELD_DATA_TYPE_CHECKBOX:
case self::FIELD_DATA_TYPE_CHECKBOX:
$this->add_checkbox_field($mform, $group, $field, $shortname);
break;
case self::FIELD_DATA_TYPE_DATETIME:
$this->add_date_field($mform, $group, $field, $shortname);
break;
}
}

$mform->addGroup($group, 'profilefieldgroup', get_string('profilefield', 'tool_dynamic_cohorts'), '', false);
$mform->addGroup($group, 'fieldgroup', get_string('profilefield', 'tool_dynamic_cohorts'), '', false);

$mform->addElement(
'checkbox',
Expand Down Expand Up @@ -182,6 +189,9 @@ public function get_sql(): condition_sql {
case self::FIELD_DATA_TYPE_MENU:
$result = $this->get_menu_sql($ud, 'data');
break;
case self::FIELD_DATA_TYPE_DATETIME:
$result = $this->get_date_sql($ud, 'data');
break;
}

if (!empty($result->get_params())) {
Expand Down
31 changes: 3 additions & 28 deletions classes/local/tool_dynamic_cohorts/condition/user_profile.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,39 +84,14 @@ public function config_form_add(\MoodleQuickForm $mform): void {
case self::FIELD_DATA_TYPE_CHECKBOX:
$this->add_checkbox_field($mform, $group, $field, $shortname);
break;
case self::FIELD_DATA_TYPE_DATE:
$this->add_date_field($mform, $group, $field, $shortname);
default:
throw new coding_exception('Invalid field type ' . $field->datatype);
}
}

$mform->addGroup($group, 'profilefieldgroup', get_string('profilefield', 'tool_dynamic_cohorts'), '', false);
}

/**
* Validate config form elements.
*
* @param array $data Data to validate.
* @return array
*/
public function config_form_validate(array $data): array {
$errors = [];

$fields = $this->get_fields_info();
if (empty($data[static::get_form_field()]) || !isset($fields[$data[static::get_form_field()]])) {
$errors['profilefieldgroup'] = get_string('pleaseselectfield', 'tool_dynamic_cohorts');
}

$fieldvalue = $data[static::get_form_field()] . '_value';
$operator = $data[static::get_form_field()] . '_operator';
$datatype = $fields[$data[static::get_form_field()]]->datatype ?? '';

if (empty($data[$fieldvalue])) {
if ($datatype == 'text' && !in_array($data[$operator], [self::TEXT_IS_EMPTY, self::TEXT_IS_NOT_EMPTY])) {
$errors['profilefieldgroup'] = get_string('invalidfieldvalue', 'tool_dynamic_cohorts');
}
}

return $errors;
$mform->addGroup($group, 'fieldgroup', get_string('profilefield', 'tool_dynamic_cohorts'), '', false);
}

/**
Expand Down
2 changes: 2 additions & 0 deletions lang/en/tool_dynamic_cohorts.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@
$string['ismemberof'] = 'is member of';
$string['isnotmemberof'] = 'is not member of';
$string['isnotempty'] = 'is not empty';
$string['isafter'] = 'is after';
$string['isbefore'] = 'is before';
$string['logical_operator'] = 'Logical operator';
$string['logical_operator_help'] = 'A logical operator to be applied to conditions for this rule. Operator "AND" means a user has to match all conditions to be added to a cohort. "OR" means a user has to match any of conditions to be added to a cohort.';
$string['managerules'] = 'Manage rules';
Expand Down
Loading

0 comments on commit 9fc4f7d

Please sign in to comment.