From 086f6ba6db73eb707c29b0deee6c60ba77ec2b65 Mon Sep 17 00:00:00 2001 From: Mark Johnson Date: Wed, 11 Dec 2024 15:09:00 +0000 Subject: [PATCH] MDL-83881 qbank_viewcreator: Creator and modifier name filters Add additional question filters for the "Created by" name and "Modified by" name. These filters will operate on all name fields that are selected for these columns, as the exact text displayed is determined by the fullname() function and not he query. --- .../classes/createdby_condition.php | 45 ++++++++++ .../classes/modifiedby_condition.php | 42 +++++++++ .../viewcreator/classes/plugin_feature.php | 2 + .../viewcreator/classes/user_condition.php | 65 ++++++++++++++ .../viewcreator/lang/en/qbank_viewcreator.php | 1 - .../filter_condition_creator_name.feature | 83 +++++++++++++++++ .../filter_condition_modifier_name.feature | 88 +++++++++++++++++++ 7 files changed, 325 insertions(+), 1 deletion(-) create mode 100644 question/bank/viewcreator/classes/createdby_condition.php create mode 100644 question/bank/viewcreator/classes/modifiedby_condition.php create mode 100644 question/bank/viewcreator/classes/user_condition.php create mode 100644 question/bank/viewcreator/tests/behat/filter_condition_creator_name.feature create mode 100644 question/bank/viewcreator/tests/behat/filter_condition_modifier_name.feature diff --git a/question/bank/viewcreator/classes/createdby_condition.php b/question/bank/viewcreator/classes/createdby_condition.php new file mode 100644 index 00000000000..e6c3342a4fd --- /dev/null +++ b/question/bank/viewcreator/classes/createdby_condition.php @@ -0,0 +1,45 @@ +. + +namespace qbank_viewcreator; + +use core\output\datafilter; +use core_question\local\bank\condition; + +/** + * Filter condition for filtering on creator name + * + * @package qbank_viewcreator + * @copyright 2025 onwards Catalyst IT EU {@link https://catalyst-eu.net} + * @author Mark Johnson + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class createdby_condition extends user_condition { + #[\Override] + public function get_title() { + return get_string('createdby', 'question'); + } + + #[\Override] + public static function get_condition_key() { + return 'createdby'; + } + + #[\Override] + protected static function get_table_alias(): string { + return 'uc'; + } +} diff --git a/question/bank/viewcreator/classes/modifiedby_condition.php b/question/bank/viewcreator/classes/modifiedby_condition.php new file mode 100644 index 00000000000..ed16ed9b5b8 --- /dev/null +++ b/question/bank/viewcreator/classes/modifiedby_condition.php @@ -0,0 +1,42 @@ +. + +namespace qbank_viewcreator; + +/** + * Filter condition for filtering on modifier name + * + * @package qbank_viewcreator + * @copyright 2025 onwards Catalyst IT EU {@link https://catalyst-eu.net} + * @author Mark Johnson + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class modifiedby_condition extends user_condition { + #[\Override] + public function get_title() { + return get_string('modifiedby', 'qbank_viewcreator'); + } + + #[\Override] + public static function get_condition_key() { + return 'modifiername'; + } + + #[\Override] + protected static function get_table_alias(): string { + return 'um'; + } +} diff --git a/question/bank/viewcreator/classes/plugin_feature.php b/question/bank/viewcreator/classes/plugin_feature.php index 703d9188432..8fb98d50a0e 100644 --- a/question/bank/viewcreator/classes/plugin_feature.php +++ b/question/bank/viewcreator/classes/plugin_feature.php @@ -40,6 +40,8 @@ class plugin_feature extends plugin_features_base { public function get_question_filters(?view $qbank = null): array { return [ new timemodified_condition($qbank), + new createdby_condition($qbank), + new modifiedby_condition($qbank), ]; } } diff --git a/question/bank/viewcreator/classes/user_condition.php b/question/bank/viewcreator/classes/user_condition.php new file mode 100644 index 00000000000..58207cdcd9c --- /dev/null +++ b/question/bank/viewcreator/classes/user_condition.php @@ -0,0 +1,65 @@ +. + +namespace qbank_viewcreator; + +use core\output\datafilter; +use core_question\local\bank\condition; + +/** + * Abstract class for conditions filtering by user. + * + * @package qbank_viewcreator + * @copyright 2025 onwards Catalyst IT EU {@link https://catalyst-eu.net} + * @author Mark Johnson + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +abstract class user_condition extends condition { + + /** + * Return the alias for the instance of the user table to filter on. + * + * @return string + */ + abstract protected static function get_table_alias(): string; + + #[\Override] + public function get_filter_class() { + return 'core/datafilter/filtertypes/keyword'; + } + + #[\Override] + public static function build_query_from_filter(array $filter): array { + global $DB; + + $conditions = []; + $params = []; + $notlike = $filter['jointype'] === datafilter::JOINTYPE_NONE; + $tablealias = static::get_table_alias(); + $allnames = array_map(fn($field) => "{$tablealias}.{$field}", \core_user\fields::get_name_fields()); + $allnames = $DB->sql_concat(...$allnames); + $conditionkey = static::get_condition_key(); + foreach ($filter['values'] as $key => $value) { + $params["{$conditionkey}{$key}"] = "%$value%"; + $conditions[] = $DB->sql_like($allnames, ":{$conditionkey}{$key}", casesensitive: false, notlike: $notlike); + } + $delimiter = $filter['jointype'] === datafilter::JOINTYPE_ANY ? ' OR ' : ' AND '; + return [ + implode($delimiter, $conditions), + $params, + ]; + } +} diff --git a/question/bank/viewcreator/lang/en/qbank_viewcreator.php b/question/bank/viewcreator/lang/en/qbank_viewcreator.php index acb17bee976..2a5976846c9 100644 --- a/question/bank/viewcreator/lang/en/qbank_viewcreator.php +++ b/question/bank/viewcreator/lang/en/qbank_viewcreator.php @@ -22,7 +22,6 @@ * @author Ghaly Marc-Alexandre * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - $string['history'] = 'History'; $string['modifiedby'] = 'Modified by'; $string['timemodified'] = 'Time modified'; diff --git a/question/bank/viewcreator/tests/behat/filter_condition_creator_name.feature b/question/bank/viewcreator/tests/behat/filter_condition_creator_name.feature new file mode 100644 index 00000000000..830195c3b48 --- /dev/null +++ b/question/bank/viewcreator/tests/behat/filter_condition_creator_name.feature @@ -0,0 +1,83 @@ +@qbank @qbank_viewcreator @javascript +Feature: Filter questions by creator name + As a teacher + In order to organise my questions + I want to filter the list of questions by creator name + + Background: + Given the following "courses" exist: + | fullname | shortname | category | + | Course 1 | C1 | 0 | + And the following "users" exist: + | username | firstname | lastname | firstnamephonetic | lastnamephonetic | middlename | alternatename | + | aa | Aaron | Aaronson | Aron | Aronsun | Andrew | Andy | + | bb | Bob | Bobson | | | | | + | cc | Clare | Clareson | | | | | + And the following "activities" exist: + | activity | name | intro | course | idnumber | + | qbank | Qbank 1 | Question bank 1 | C1 | qbank1 | + And the following "question categories" exist: + | contextlevel | reference | name | + | Activity module | qbank1 | Test questions | + And the following "course enrolments" exist: + | course | user | role | + | C1 | aa | editingteacher | + | C1 | bb | editingteacher | + | C1 | cc | editingteacher | + And the following "questions" exist: + | qtype | questioncategory | name | user | + | truefalse | Test questions | First question | aa | + | truefalse | Test questions | Second question | bb | + | truefalse | Test questions | Third question | cc | + And I am on the "Qbank 1" "core_question > question bank" page logged in as "admin" + And I should see "First question" + And I should see "Second question" + And I should see "Third question" + + Scenario: Filter by a single word + When I apply question bank filter "Created by" with value "Aaron" + Then I should see "First question" + And I should not see "Second question" + And I should not see "Third question" + + Scenario: Filter by any word + When I apply question bank filter "Created by" with value "Aaron, Clare" + Then I should see "First question" + And I should not see "Second question" + And I should see "Third question" + + Scenario: Filter by all words + When I add question bank filter "Created by" + And I set the field "Created by" to "son, Aar" + And I set the field "Match" in the "Filter 3" "fieldset" to "All" + And I press "Apply filters" + Then I should see "First question" + And I should not see "Second question" + And I should not see "Third question" + + Scenario: Filter by additional name fields + When I apply question bank filter "Created by" with value "Aron" + Then I should see "First question" + And I should not see "Second question" + And I should not see "Third question" + When I apply question bank filter "Created by" with value "sun" + Then I should see "First question" + And I should not see "Second question" + And I should not see "Third question" + When I apply question bank filter "Created by" with value "drew" + Then I should see "First question" + And I should not see "Second question" + And I should not see "Third question" + When I apply question bank filter "Created by" with value "Andy" + Then I should see "First question" + And I should not see "Second question" + And I should not see "Third question" + + Scenario: Exclude names by filter + When I add question bank filter "Created by" + And I set the field "Created by" to "Aron, Clare" + And I set the field "Match" in the "Filter 3" "fieldset" to "None" + And I press "Apply filters" + Then I should not see "First question" + And I should see "Second question" + And I should not see "Third question" diff --git a/question/bank/viewcreator/tests/behat/filter_condition_modifier_name.feature b/question/bank/viewcreator/tests/behat/filter_condition_modifier_name.feature new file mode 100644 index 00000000000..08b0d471a07 --- /dev/null +++ b/question/bank/viewcreator/tests/behat/filter_condition_modifier_name.feature @@ -0,0 +1,88 @@ +@qbank @qbank_viewcreator @javascript +Feature: Filter questions by modifier name + As a teacher + In order to organise my questions + I want to filter the list of questions by modifier name + + Background: + Given the following "courses" exist: + | fullname | shortname | category | + | Course 1 | C1 | 0 | + And the following "users" exist: + | username | firstname | lastname | firstnamephonetic | lastnamephonetic | middlename | alternatename | + | aa | Aaron | Aaronson | Aron | Aronsun | Andrew | Andy | + | bb | Bob | Bobson | | | | | + | cc | Clare | Clareson | | | | | + And the following "activities" exist: + | activity | name | intro | course | idnumber | + | qbank | Qbank 1 | Question bank 1 | C1 | qbank1 | + And the following "question categories" exist: + | contextlevel | reference | name | + | Activity module | qbank1 | Test questions | + And the following "course enrolments" exist: + | course | user | role | + | C1 | aa | editingteacher | + | C1 | bb | editingteacher | + | C1 | cc | editingteacher | + And the following "questions" exist: + | qtype | questioncategory | name | + | truefalse | Test questions | First question | + | truefalse | Test questions | Second question | + | truefalse | Test questions | Third question | + And the following "core_question > updated questions" exist: + | questioncategory | question | name | modifiedbyuser | + | Test questions | First question | First question | aa | + | Test questions | Second question | Second question | bb | + | Test questions | Third question | Third question | cc | + And I am on the "Qbank 1" "core_question > question bank" page logged in as "admin" + And I should see "First question" + And I should see "Second question" + And I should see "Third question" + + Scenario: Filter by a single word + When I apply question bank filter "Modified by" with value "Aaron" + Then I should see "First question" + And I should not see "Second question" + And I should not see "Third question" + + Scenario: Filter by any word + When I apply question bank filter "Modified by" with value "Aaron, Clare" + Then I should see "First question" + And I should not see "Second question" + And I should see "Third question" + + Scenario: Filter by all words + When I add question bank filter "Modified by" + And I set the field "Modified by" to "son, Aar" + And I set the field "Match" in the "Filter 3" "fieldset" to "All" + And I press "Apply filters" + Then I should see "First question" + And I should not see "Second question" + And I should not see "Third question" + + Scenario: Filter by additional name fields + When I apply question bank filter "Modified by" with value "Aron" + Then I should see "First question" + And I should not see "Second question" + And I should not see "Third question" + When I apply question bank filter "Modified by" with value "sun" + Then I should see "First question" + And I should not see "Second question" + And I should not see "Third question" + When I apply question bank filter "Modified by" with value "drew" + Then I should see "First question" + And I should not see "Second question" + And I should not see "Third question" + When I apply question bank filter "Modified by" with value "Andy" + Then I should see "First question" + And I should not see "Second question" + And I should not see "Third question" + + Scenario: Exclude names by filter + When I add question bank filter "Modified by" + And I set the field "Modified by" to "Aron, Clare" + And I set the field "Match" in the "Filter 3" "fieldset" to "None" + And I press "Apply filters" + Then I should not see "First question" + And I should see "Second question" + And I should not see "Third question"