diff --git a/classes/local/table/interaction_remaining_table.php b/classes/local/table/interaction_remaining_table.php index 37453372..1d48795e 100644 --- a/classes/local/table/interaction_remaining_table.php +++ b/classes/local/table/interaction_remaining_table.php @@ -43,6 +43,10 @@ class interaction_remaining_table extends interaction_table { /** @var manual_trigger_tool[] $availabletools list of all available trigger tools. */ private $availabletools; + /** @var array[] $trigger2courses map from manual trigger id to courses that are selected by + * automatic trigger(s) which is (are) associated to manual trigger. + */ + private $trigger2courses = []; /** * Constructor for deactivated_workflows_table. @@ -51,9 +55,41 @@ class interaction_remaining_table extends interaction_table { */ public function __construct($uniqueid, $courseids) { parent::__construct($uniqueid); - global $PAGE, $CFG; + global $PAGE, $CFG, $DB; $this->availabletools = workflow_manager::get_manual_trigger_tools_for_active_workflows(); + foreach ($this->availabletools as $tool) { + // Check if there is an automatic trigger associated with the manual trigger. + $records = $DB->get_records_select('tool_lifecycle_trigger', "subpluginname != :plugin and workflowid in + (select workflowid from {tool_lifecycle_trigger} where id = :id)", + ['id' => $tool->triggerid, 'plugin' => 'manual']); + if ($records && count($records) > 0) { + $first = reset($records); + // There is at least one automatic trigger associated + // => check for AND condition. + $field = $DB->get_field('tool_lifecycle_workflow', 'andor', ['id' => $first->workflowid]); + if ($field) { + // No AND condition => OR condition is not supported. + echo 'OR condition is not supported.
'; + continue; + } + // Ok, we have an AND condition => + // Store courses selected by this (these) trigger(s). + $triggers = []; + foreach ($records as $record) { + $triggers[] = $record; + } + if (count($triggers) > 0) { + $processor = new \tool_lifecycle\processor(); + $recordset = $processor->get_course_recordset($triggers); + $courses = []; + foreach ($recordset as $element) { + $courses[] = $element->id; + } + $this->trigger2courses[$tool->triggerid] = $courses; + } + } + } // COALESCE returns l.time if l.time != null and 0 otherwise. // We need to do this, so that courses without any action have a smaller timestamp than courses with an recorded action. @@ -122,7 +158,7 @@ public function init() { * @throws \moodle_exception */ public function col_tools($row) { - global $PAGE, $OUTPUT; + global $PAGE, $OUTPUT, $DB; if ($row->processid !== null) { return '--'; @@ -132,6 +168,26 @@ public function col_tools($row) { } $actions = []; foreach ($this->availabletools as $tool) { + // Check if the manual trigger has at least one automatic trigger associated. + if (array_key_exists($tool->triggerid, $this->trigger2courses)) { + // There is at least one automatic trigger => + // Check if 'this' course is included in course set. + $found = false; + foreach ($this->trigger2courses[$tool->triggerid] as $element) { + if ($row->courseid === $element) { + // Course is included in course set of automatic trigger(s). + $found = true; + break; + } + } + if (!$found) { + // Course is not included in automatic trigger(s) set + // => do not display action in action menu. + continue; + } + } + + // Check capability. if (has_capability($tool->capability, \context_course::instance($row->courseid), null, false)) { $actions[$tool->triggerid] = new \action_menu_link_secondary( new \moodle_url($PAGE->url, ['triggerid' => $tool->triggerid, diff --git a/tests/behat/trigger_combination.feature b/tests/behat/trigger_combination.feature new file mode 100644 index 00000000..893e8131 --- /dev/null +++ b/tests/behat/trigger_combination.feature @@ -0,0 +1,155 @@ +@tool @tool_lifecycle @manual_trigger +Feature: Combine triggers with 'and' operation and test view and actions + + Background: + Given the following "users" exist: + | username | firstname | lastname | email | + | teacher1 | Teacher | 1 | teacher1@example.com | + | teacher2 | Teacher | 2 | teacher2@example.com | + And the following "categories" exist: + | name | category | idnumber | + | cata | 0 | cata | + | catba | cata | catba | + | catc | 0 | catc | + | archive | 0 | archive | + And the following "courses" exist: + | fullname | shortname | category | + | Course A | CA | cata | + | Course BA | CBA | catba | + | Course C | CC | catc | + | ArchCourse | CArch | archive | + And the following "course enrolments" exist: + | user | course | role | + | teacher1 | CA | editingteacher | + | teacher1 | CBA | editingteacher | + | teacher1 | CC | editingteacher | + | teacher1 | CArch | editingteacher | + | teacher2 | CA | editingteacher | + | teacher2 | CBA | student | + | teacher2 | CC | student | + | teacher2 | CArch | editingteacher | + + @javascript + Scenario: Combine manual trigger with automatic categories trigger (backup and course deletion) + # => category archive is excluded, so course ArchCourse shall not be deleted + Given I log in as "admin" + And I am on workflowdrafts page + And I click on "Create new workflow" "link" + And I set the following fields to these values: + | Title | My Workflow | + | Displayed workflow title | Teachers view on workflow | + And I press "Save changes" + And I select "Manual trigger" from the "tool_lifecycle-choose-trigger" singleselect + And I set the following fields to these values: + | Instance name | My Trigger | + | Icon | t/delete | + | Action name | Delete course | + | Capability | moodle/course:manageactivities | + And I press "Save changes" + + And I select "Categories trigger" from the "tool_lifecycle-choose-trigger" singleselect + And I set the following fields to these values: + | Instance name | Categories | + And I set the following fields to these values: + | Categories, for which the workflow should be triggered | cata, catc | + And I press "Save changes" + + And I select "Create backup step" from the "tool_lifecycle-choose-step" singleselect + And I set the field "Instance name" to "Create backup step" + And I press "Save changes" + And I select "Delete course step" from the "tool_lifecycle-choose-step" singleselect + And I set the field "Instance name" to "Delete Course 2" + And I press "Save changes" + + And I am on workflowdrafts page + And I press "Activate" + And I log out + And I log in as "teacher1" + + And I am on lifecycle view + Then I should see the tool "Delete course" in the "Course A" row of the "tool_lifecycle_remaining" table + And I should see the tool "Delete course" in the "Course BA" row of the "tool_lifecycle_remaining" table + And I should see the tool "Delete course" in the "Course C" row of the "tool_lifecycle_remaining" table + And I should not see "Action" in the "ArchCourse" "table_row" + + When I click on the tool "Delete course" in the "Course C" row of the "tool_lifecycle_remaining" table + And I should not see the tool "Delete course" in the "Course C" row of the "tool_lifecycle_remaining" table + And I should see the tool "Delete course" in the "Course BA" row of the "tool_lifecycle_remaining" table + And I should see the tool "Delete course" in the "Course A" row of the "tool_lifecycle_remaining" table + When I log out + And I log in as "admin" + And I run the scheduled task "tool_lifecycle\task\lifecycle_task" + And I wait "5" seconds + And I run the scheduled task "tool_lifecycle\task\lifecycle_task" + And I wait "5" seconds + And I run the scheduled task "tool_lifecycle\task\lifecycle_task" + And I wait "5" seconds + And I log out + And I log in as "teacher1" + And I am on lifecycle view + Then I should not see "Course C" + And I should see "Course BA" + And I should see "Course A" + And I should see "ArchCourse" + When I log out + And I log in as "admin" + And I am on coursebackups page + Then I should see "Course C" + And I should not see "Course BA" + And I should not see "Course A" + And I should not see "ArchCourse" + + @javascript + Scenario: Combine automatic triggers (backup and course deletion) + Given I log in as "admin" + And I am on workflowdrafts page + And I click on "Create new workflow" "link" + And I set the following fields to these values: + | Title | My Workflow | + | Displayed workflow title | Teachers view on workflow | + And I press "Save changes" + + And I select "Trigger courses by roles missing" from the "tool_lifecycle-choose-trigger" singleselect + And I set the following fields to these values: + | Instance name | Roles | + | Responsible Roles in courses | student | + And I press "Save changes" + + And I select "Categories trigger" from the "tool_lifecycle-choose-trigger" singleselect + And I set the following fields to these values: + | Instance name | Categories | + And I set the following fields to these values: + | Categories, for which the workflow should be triggered | cata, catc | + And I press "Save changes" + + And I select "Create backup step" from the "tool_lifecycle-choose-step" singleselect + And I set the field "Instance name" to "Create backup step" + And I press "Save changes" + And I select "Delete course step" from the "tool_lifecycle-choose-step" singleselect + And I set the field "Instance name" to "Delete Course 2" + And I press "Save changes" + + And I am on workflowdrafts page + And I press "Activate" + + And I run the scheduled task "tool_lifecycle\task\lifecycle_task" + And I wait "2" seconds + And I run the scheduled task "tool_lifecycle\task\lifecycle_task" + And I wait "2" seconds + And I run the scheduled task "tool_lifecycle\task\lifecycle_task" + And I wait "2" seconds + + And I log out + And I log in as "teacher1" + And I am on lifecycle view + Then I should not see "Course A" + And I should see "Course BA" + And I should see "Course C" + And I should see "ArchCourse" + When I log out + And I log in as "admin" + And I am on coursebackups page + Then I should see "Course A" + And I should not see "Course BA" + And I should not see "Course CS" + And I should not see "ArchCourse"