Skip to content

Commit

Permalink
issue #94: add support for autocomplete user profile field
Browse files Browse the repository at this point in the history
  • Loading branch information
dmitriim committed Jun 22, 2024
1 parent 89bc942 commit df3068d
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 2 deletions.
5 changes: 5 additions & 0 deletions classes/condition_base.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ abstract class condition_base {
*/
public const FIELD_DATA_TYPE_DATETIME = 'datetime';

/**
* Value for autocomplete field types.
*/
public const FIELD_DATA_TYPE_AUTOCOMPLETE = 'autocomplete';

/**
* Value for operator text contains.
*/
Expand Down
69 changes: 69 additions & 0 deletions classes/local/tool_dynamic_cohorts/condition/fields_trait.php
Original file line number Diff line number Diff line change
Expand Up @@ -411,4 +411,73 @@ protected function get_date_sql(string $tablealias, string $fieldname): conditio

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

/**
* Get SQL data for multi select type fields.
*
* @param string $tablealias Alias for a table.
* @param string $fieldname Field name.
* @param bool $addspace Does a field type add space?
* @return condition_sql
*/
protected function get_multiselect_sql(string $tablealias, string $fieldname, bool $addspace = true): condition_sql {
global $DB;

$fieldvalue = $this->get_field_value();
$operatorvalue = $this->get_operator_value();

if ($this->is_broken()) {
return new condition_sql('', '', []);
}
// For some reason user profile field autocomplete adds space when saving field values
// like implode(', ', $data). However multiselect custom field doesn't do it, instead it does
// like implode(',', $data). To make it flexible we add space when we consider (or not) an extra
// space when we build following SQL.
$space = $addspace ? ' ' : '';

// User data for multiselect fields is stored like Option 1, Option 2, Option 3.
// So to be accurate in our SQL we have to cover three scenarios:
// 1. Value is in the beginning of the string.
// 2. Value is somewhere in the middle.
// 3. Value is at the end of the string.
// So our SQL should like:
// WHERE data like 'value%' OR data like '% value, %' OR data like '%, value'
// This is a bit hacky, but should give us accurate results.
$startparam = condition_sql::generate_param_alias();
$middleparam = condition_sql::generate_param_alias();
$endparam = condition_sql::generate_param_alias();

switch ($operatorvalue) {
case self::TEXT_IS_EQUAL_TO:
$value = $DB->sql_like_escape($fieldvalue);

$where = $DB->sql_like("$tablealias.$fieldname", ":$startparam", false, false);
$params[$startparam] = "$value%";

$where .= ' OR ' . $DB->sql_like("$tablealias.$fieldname", ":$middleparam", false, false);
$params[$middleparam] = "%,$space$value,$space%";

$where .= ' OR ' . $DB->sql_like("$tablealias.$fieldname", ":$endparam", false, false);
$params[$endparam] = "%,$space$value";

break;
case self::TEXT_IS_NOT_EQUAL_TO:
$value = $DB->sql_like_escape($fieldvalue);

$where = $DB->sql_like("$tablealias.$fieldname", ":$startparam", false, false, true);
$params[$startparam] = "$value%";

$where .= ' AND ' . $DB->sql_like("$tablealias.$fieldname", ":$middleparam", false, false, true);
$params[$middleparam] = "%,$space$value,$space%";

$where .= ' AND ' . $DB->sql_like("$tablealias.$fieldname", ":$endparam", false, false, true);
$params[$endparam] = "%,$space$value";

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,8 +53,13 @@ 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, self::FIELD_DATA_TYPE_DATETIME];
return [
self::FIELD_DATA_TYPE_TEXT,
self::FIELD_DATA_TYPE_MENU,
self::FIELD_DATA_TYPE_CHECKBOX,
self::FIELD_DATA_TYPE_DATETIME,
self::FIELD_DATA_TYPE_AUTOCOMPLETE,
];
}

/**
Expand All @@ -79,6 +84,7 @@ protected function get_fields_info(): array {

switch ($field->datatype) {
case self::FIELD_DATA_TYPE_MENU:
case self::FIELD_DATA_TYPE_AUTOCOMPLETE:
$options = explode("\n", $field->param1);
$field->param1 = array_combine($options, $options);
break;
Expand Down Expand Up @@ -124,6 +130,7 @@ public function config_form_add(\MoodleQuickForm $mform): void {
$this->add_text_field($mform, $group, $field, $shortname);
break;
case self::FIELD_DATA_TYPE_MENU:
case self::FIELD_DATA_TYPE_AUTOCOMPLETE:
$this->add_menu_field($mform, $group, $field, $shortname);
break;
case self::FIELD_DATA_TYPE_CHECKBOX:
Expand Down Expand Up @@ -192,6 +199,9 @@ public function get_sql(): condition_sql {
case self::FIELD_DATA_TYPE_DATETIME:
$result = $this->get_date_sql($ud, 'data');
break;
case self::FIELD_DATA_TYPE_AUTOCOMPLETE:
$result = $this->get_multiselect_sql($ud, 'data');
break;
}

if (!empty($result->get_params())) {
Expand Down

0 comments on commit df3068d

Please sign in to comment.