MDL-75449 reportbuilder: add no tags/exclude tags filter operators.

Allow user to filter for elements that either contain no tags, plus
those that don't contain selected tags.
This commit is contained in:
Paul Holden 2022-08-18 13:02:56 +01:00
parent 3bc792b9b8
commit fd01461b7a
3 changed files with 29 additions and 2 deletions

View File

@ -45,6 +45,12 @@ class tags extends base {
/** @var int Filter for selected tags */
public const EQUAL_TO = 2;
/** @var int Tags are not present */
public const EMPTY = 3;
/** @var int Filter for excluded tags */
public const NOT_EQUAL_TO = 4;
/**
* Returns an array of comparison operators
*
@ -54,7 +60,9 @@ class tags extends base {
$operators = [
self::ANY_VALUE => new lang_string('filterisanyvalue', 'core_reportbuilder'),
self::NOT_EMPTY => new lang_string('filterisnotempty', 'core_reportbuilder'),
self::EMPTY => new lang_string('filterisempty', 'core_reportbuilder'),
self::EQUAL_TO => new lang_string('filterisequalto', 'core_reportbuilder'),
self::NOT_EQUAL_TO => new lang_string('filterisnotequalto', 'core_reportbuilder'),
];
return $this->filter->restrict_limited_operators($operators);
@ -84,7 +92,7 @@ class tags extends base {
$valuelabel = get_string('filterfieldvalue', 'core_reportbuilder', $this->get_header());
$mform->addElement('autocomplete', "{$this->name}_value", $valuelabel, $tags, ['multiple' => true])
->setHiddenLabel(true);
$mform->hideIf("{$this->name}_value", "{$this->name}_operator", 'neq', self::EQUAL_TO);
$mform->hideIf("{$this->name}_value", "{$this->name}_operator", 'in', [self::ANY_VALUE, self::EMPTY, self::NOT_EMPTY]);
}
/**
@ -104,12 +112,21 @@ class tags extends base {
if ($operator === self::NOT_EMPTY) {
$select = "{$fieldsql} IS NOT NULL";
} else if ($operator === self::EMPTY) {
$select = "{$fieldsql} IS NULL";
} else if ($operator === self::EQUAL_TO && !empty($tags)) {
[$tagselect, $tagselectparams] = $DB->get_in_or_equal($tags, SQL_PARAMS_NAMED,
database::generate_param_name() . '_');
$select = "{$fieldsql} {$tagselect}";
$params = array_merge($params, $tagselectparams);
} else if ($operator === self::NOT_EQUAL_TO && !empty($tags)) {
[$tagselect, $tagselectparams] = $DB->get_in_or_equal($tags, SQL_PARAMS_NAMED,
database::generate_param_name() . '_', false);
// We should also return those elements that aren't tagged at all.
$select = "COALESCE({$fieldsql}, 0) {$tagselect}";
$params = array_merge($params, $tagselectparams);
} else {
// Invalid/inactive (any value) filter..
return ['', []];

View File

@ -42,8 +42,11 @@ class tags_test extends advanced_testcase {
return [
'Any value' => [tags::ANY_VALUE, null, ['course01', 'course01', 'course02', 'course03']],
'Not empty' => [tags::NOT_EMPTY, null, ['course01', 'course01', 'course02']],
'Empty' => [tags::EMPTY, null, ['course03']],
'Equal to unselected' => [tags::EQUAL_TO, null, ['course01', 'course01', 'course02', 'course03']],
'Equal to selected tag' => [tags::EQUAL_TO, 'cat', ['course01']],
'Not equal to unselected' => [tags::NOT_EQUAL_TO, null, ['course01', 'course01', 'course02', 'course03']],
'Not equal to selected tag' => [tags::NOT_EQUAL_TO, 'fish', ['course01', 'course01', 'course03']],
];
}

View File

@ -166,10 +166,17 @@ class tags_test extends core_reportbuilder_testcase {
], false],
// Tag.
'Filter tag name' => ['tag:name', [
'Filter tag name equal to' => ['tag:name', [
'tag:name_operator' => tags_filter::EQUAL_TO,
'tag:name_value' => [-1],
], false],
'Filter tag name not equal to' => ['tag:name', [
'tag:name_operator' => tags_filter::NOT_EQUAL_TO,
'tag:name_value' => [-1],
], true],
'Filter tag name empty' => ['tag:name', [
'tag:name_operator' => tags_filter::EMPTY,
], false],
'Filter tag name not empty' => ['tag:name', [
'tag:name_operator' => tags_filter::NOT_EMPTY,
], true],