diff --git a/completion/classes/manager.php b/completion/classes/manager.php index 29f0d77f7f7..48ae29d0f0b 100644 --- a/completion/classes/manager.php +++ b/completion/classes/manager.php @@ -262,10 +262,14 @@ class manager { /** * Gets the available completion tabs for the current course and user. * + * @deprecated since Moodle 4.0 * @param stdClass|int $courseorid the course object or id. * @return tabobject[] */ public static function get_available_completion_tabs($courseorid) { + debugging('get_available_completion_tabs() has been deprecated. Please use ' . + 'core_completion\manager::get_available_completion_options() instead.', DEBUG_DEVELOPER); + $tabs = []; $courseid = is_object($courseorid) ? $courseorid->id : $courseorid; @@ -298,6 +302,34 @@ class manager { return $tabs; } + /** + * Returns an array with the available completion options (url => name) for the current course and user. + * + * @param int $courseid The course id. + * @return array + */ + public static function get_available_completion_options(int $courseid): array { + $coursecontext = context_course::instance($courseid); + $options = []; + + if (has_capability('moodle/course:update', $coursecontext)) { + $completionlink = new moodle_url('/course/completion.php', ['id' => $courseid]); + $options[$completionlink->out(false)] = get_string('coursecompletion', 'completion'); + } + + if (has_capability('moodle/course:manageactivities', $coursecontext)) { + $defaultcompletionlink = new moodle_url('/course/defaultcompletion.php', ['id' => $courseid]); + $options[$defaultcompletionlink->out(false)] = get_string('defaultcompletion', 'completion'); + } + + if (self::can_edit_bulk_completion($courseid)) { + $bulkcompletionlink = new moodle_url('/course/bulkcompletion.php', ['id' => $courseid]); + $options[$bulkcompletionlink->out(false)] = get_string('bulkactivitycompletion', 'completion'); + } + + return $options; + } + /** * Applies completion from the bulk edit form to all selected modules * diff --git a/completion/tests/behat/bulk_edit_activity_completion.feature b/completion/tests/behat/bulk_edit_activity_completion.feature index 316ca4654cd..acf560ef82c 100644 --- a/completion/tests/behat/bulk_edit_activity_completion.feature +++ b/completion/tests/behat/bulk_edit_activity_completion.feature @@ -37,7 +37,7 @@ Feature: Allow teachers to bulk edit activity completion rules in a course. Given I log in as "teacher1" And I am on "Course 1" course homepage with editing mode on When I navigate to "Course completion" in current page administration - And I follow "Bulk edit activity completion" + And I select "Bulk edit activity completion" from the "Course completion tertiary navigation" singleselect And I click on "Test assignment one" "checkbox" And I click on "Test assignment two" "checkbox" And I click on "Edit" "button" @@ -68,7 +68,7 @@ Feature: Allow teachers to bulk edit activity completion rules in a course. Given I log in as "teacher1" And I am on "Course 1" course homepage with editing mode on When I navigate to "Course completion" in current page administration - And I follow "Bulk edit activity completion" + And I select "Bulk edit activity completion" from the "Course completion tertiary navigation" singleselect And I click on "Test assignment one" "checkbox" And I click on "Test assignment two" "checkbox" And I click on "Edit" "button" diff --git a/completion/tests/behat/default_activity_completion.feature b/completion/tests/behat/default_activity_completion.feature index 26fa3b08dba..95fecc79a55 100644 --- a/completion/tests/behat/default_activity_completion.feature +++ b/completion/tests/behat/default_activity_completion.feature @@ -30,7 +30,7 @@ Feature: Allow teachers to edit the default activity completion rules in a cours | Enable completion tracking | Yes | And I press "Save and display" When I navigate to "Course completion" in current page administration - And I follow "Default activity completion" + And I select "Default activity completion" from the "Course completion tertiary navigation" singleselect And I click on "Assignments" "checkbox" And I click on "Edit" "button" And I should see "Completion tracking" diff --git a/completion/upgrade.txt b/completion/upgrade.txt index e4e576c162c..52a90662f6d 100644 --- a/completion/upgrade.txt +++ b/completion/upgrade.txt @@ -8,6 +8,11 @@ information provided here is intended especially for developers. tested. Currently contains - viewed, usegrade, passgrade. Any plugin that are dependent on these criteria can now check this array instead of retesting it. * The method \completion_criteria_completion::mark_complete() now has the optional $timecompleted parameter to specify when the criteria was completed. +* New method get_available_completion_options() has been added in the core_completion\manager class. This method can be used + to obtain an array with the available completion options ([url => name]) for the current course and user. +* The method get_available_completion_tabs() in the core_completion\manager class has been deprecated because the tabs navigation + structure is no longer used in the completion pages. Please use core_completion\manager::get_available_completion_options() + instead. === 3.11 === * New Behat steps for activity completion in the behat_completion class: diff --git a/course/bulkcompletion.php b/course/bulkcompletion.php index 0f012b1cedc..2f1534d1995 100644 --- a/course/bulkcompletion.php +++ b/course/bulkcompletion.php @@ -69,9 +69,11 @@ $renderer = $PAGE->get_renderer('core_course', 'bulk_activity_completion'); // Print the form. echo $OUTPUT->header(); -echo $OUTPUT->heading(get_string('bulkactivitycompletion', 'completion')); -echo $renderer->navigation($course, 'bulkcompletion'); +$actionbar = new \core_course\output\completion_action_bar($course->id, $PAGE->url); +echo $renderer->render_course_completion_action_bar($actionbar); + +echo $OUTPUT->heading(get_string('bulkactivitycompletion', 'completion')); $PAGE->requires->js_call_amd('core_form/changechecker', 'watchFormById', ['theform']); diff --git a/course/classes/output/bulk_activity_completion_renderer.php b/course/classes/output/bulk_activity_completion_renderer.php index 9d4b7525992..d560d0b352c 100644 --- a/course/classes/output/bulk_activity_completion_renderer.php +++ b/course/classes/output/bulk_activity_completion_renderer.php @@ -38,11 +38,16 @@ class core_course_bulk_activity_completion_renderer extends plugin_renderer_base /** * Render the navigation tabs for the completion page. * + * @deprecated since Moodle 4.0 * @param int|stdClass $courseorid the course object or id. * @param String $page the tab to focus. * @return string html */ public function navigation($courseorid, $page) { + debugging('navigation() has been deprecated as the tabs navigation structure in the completion page ' . + 'has been replaced with tertiary navigation. Please use render_course_completion_action_bar() instead.', + DEBUG_DEVELOPER); + $tabs = core_completion\manager::get_available_completion_tabs($courseorid); if (count($tabs) > 1) { return $this->tabtree($tabs, $page); @@ -112,4 +117,15 @@ class core_course_bulk_activity_completion_renderer extends plugin_renderer_base ]; return parent::render_from_template('core_course/editdefaultcompletion', $data); } + + /** + * Renders the course completion action bar. + * + * @param \core_course\output\completion_action_bar $actionbar + * @return string The HTML output + */ + public function render_course_completion_action_bar(\core_course\output\completion_action_bar $actionbar): string { + $data = $actionbar->export_for_template($this->output); + return $this->output->render_from_template('core_course/completion_action_bar', $data); + } } diff --git a/course/classes/output/completion_action_bar.php b/course/classes/output/completion_action_bar.php new file mode 100644 index 00000000000..54f0b8f9daf --- /dev/null +++ b/course/classes/output/completion_action_bar.php @@ -0,0 +1,68 @@ +. + +namespace core_course\output; + +use core_completion\manager; +use moodle_url; +use renderable; +use renderer_base; +use templatable; +use url_select; + +/** + * Renderable class for the action bar elements in the course completion pages. + * + * @package core_course + * @copyright 2022 Mihail Geshoski + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class completion_action_bar implements templatable, renderable { + + /** @var int $courseid The course id. */ + private $courseid; + + /** @var moodle_url $currenturl The URL of the current page. */ + private $currenturl; + + /** + * The class constructor. + * + * @param int $courseid The course id. + * @param moodle_url $pageurl The URL of the current page. + */ + public function __construct(int $courseid, moodle_url $pageurl) { + $this->courseid = $courseid; + $this->currenturl = $pageurl; + } + + /** + * Export the data for the mustache template. + * + * @param renderer_base $output renderer to be used to render the action bar elements. + * @return array The array which contains the data required to output the tertiary navigation selector for the course + * completion pages. + */ + public function export_for_template(renderer_base $output): array { + $urlselect = new url_select(manager::get_available_completion_options($this->courseid), + $this->currenturl->out(false), null, 'coursecompletionactionselect'); + $urlselect->set_label(get_string('coursecompletionnavigation', 'completion'), ['class' => 'sr-only']); + + return [ + 'urlselect' => $urlselect->export_for_template($output), + ]; + } +} diff --git a/course/completion.php b/course/completion.php index 26f03cfeb70..a5e7be30235 100644 --- a/course/completion.php +++ b/course/completion.php @@ -57,8 +57,9 @@ if ($id) { if (!has_capability('moodle/course:update', $context)) { // User is not allowed to modify course completion. // Check if they can see default completion or edit bulk completion and redirect there. - if ($tabs = core_completion\manager::get_available_completion_tabs($course)) { - redirect($tabs[0]->link); + if ($options = core_completion\manager::get_available_completion_options($course->id)) { + // Redirect to the first available completion page. + redirect(array_key_first($options)); } else { require_capability('moodle/course:update', $context); } @@ -161,9 +162,11 @@ $renderer = $PAGE->get_renderer('core_course', 'bulk_activity_completion'); // Print the form. echo $OUTPUT->header(); -echo $OUTPUT->heading(get_string('editcoursecompletionsettings', 'core_completion')); -echo $renderer->navigation($course, 'completion'); +$actionbar = new \core_course\output\completion_action_bar($course->id, $PAGE->url); +echo $renderer->render_course_completion_action_bar($actionbar); + +echo $OUTPUT->heading(get_string('editcoursecompletionsettings', 'core_completion')); $form->display(); diff --git a/course/defaultcompletion.php b/course/defaultcompletion.php index 3d209a86e2e..e9b03cca5b1 100644 --- a/course/defaultcompletion.php +++ b/course/defaultcompletion.php @@ -51,7 +51,7 @@ if ($id) { // Set up the page. navigation_node::override_active_url(new moodle_url('/course/completion.php', array('id' => $course->id))); $PAGE->set_course($course); -$PAGE->set_url('/course/bulkcompletion.php', array('id' => $course->id)); +$PAGE->set_url('/course/defaultcompletion.php', array('id' => $course->id)); $PAGE->set_title($course->shortname); $PAGE->set_heading($course->fullname); $PAGE->set_pagelayout('admin'); @@ -64,9 +64,11 @@ $renderer = $PAGE->get_renderer('core_course', 'bulk_activity_completion'); // Print the form. echo $OUTPUT->header(); -echo $OUTPUT->heading(get_string('defaultcompletion', 'completion')); -echo $renderer->navigation($course, 'defaultcompletion'); +$actionbar = new \core_course\output\completion_action_bar($course->id, $PAGE->url); +echo $renderer->render_course_completion_action_bar($actionbar); + +echo $OUTPUT->heading(get_string('defaultcompletion', 'completion')); $PAGE->requires->js_call_amd('core_form/changechecker', 'watchFormById', ['theform']); diff --git a/course/editbulkcompletion.php b/course/editbulkcompletion.php index 65d60ac899a..f930d953a60 100644 --- a/course/editbulkcompletion.php +++ b/course/editbulkcompletion.php @@ -67,9 +67,8 @@ if ($form->is_cancelled()) { $renderer = $PAGE->get_renderer('core_course', 'bulk_activity_completion'); echo $OUTPUT->header(); -echo $OUTPUT->heading(get_string('bulkactivitycompletion', 'completion')); -echo $renderer->navigation($course, 'bulkcompletion'); +echo $OUTPUT->heading(get_string('bulkactivitycompletion', 'completion')); echo $renderer->edit_bulk_completion($form, $manager->get_activities(array_keys($cms))); diff --git a/course/editdefaultcompletion.php b/course/editdefaultcompletion.php index 5ae3c27924e..9a73f39ad83 100644 --- a/course/editdefaultcompletion.php +++ b/course/editdefaultcompletion.php @@ -65,9 +65,8 @@ if ($form->is_cancelled()) { $renderer = $PAGE->get_renderer('core_course', 'bulk_activity_completion'); echo $OUTPUT->header(); -echo $OUTPUT->heading(get_string('defaultcompletion', 'completion')); -echo $renderer->navigation($course, 'defaultcompletion'); +echo $OUTPUT->heading(get_string('defaultcompletion', 'completion')); echo $renderer->edit_default_completion($form, $modules); diff --git a/course/lib.php b/course/lib.php index 59b6c1daf9f..badbaf67fe9 100644 --- a/course/lib.php +++ b/course/lib.php @@ -4125,12 +4125,11 @@ function course_get_user_administration_options($course, $context) { global $CFG; $isfrontpage = $course->id == SITEID; $completionenabled = $CFG->enablecompletion && $course->enablecompletion; - $hascompletiontabs = count(core_completion\manager::get_available_completion_tabs($course, $context)) > 0; + $hascompletionoptions = count(core_completion\manager::get_available_completion_options($course->id)) > 0; $options = new stdClass; $options->update = has_capability('moodle/course:update', $context); - $options->editcompletion = $CFG->enablecompletion && - $course->enablecompletion && - ($options->update || $hascompletiontabs); + $options->editcompletion = $CFG->enablecompletion && $course->enablecompletion && + ($options->update || $hascompletionoptions); $options->filters = has_capability('moodle/filter:manage', $context) && count(filter_get_available_in_context($context)) > 0; $options->reports = has_capability('moodle/site:viewreports', $context); diff --git a/course/templates/completion_action_bar.mustache b/course/templates/completion_action_bar.mustache new file mode 100644 index 00000000000..0ad8699f913 --- /dev/null +++ b/course/templates/completion_action_bar.mustache @@ -0,0 +1,53 @@ +{{! + This file is part of Moodle - http://moodle.org/ + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template core_course/completion_action_bar + + Actions bar in the course completion pages. + + Context variables required for this template: + * urlselect - The data object containing the required properties to render core/url_select. + + Example context (json): + { + "urlselect": { + "id": "url_select_test", + "action": "https://example.com/post", + "formid": "url_select_form", + "sesskey": "sesskey", + "classes": "urlselect", + "label": "", + "helpicon": false, + "showbutton": null, + "options": [ + { + "name": "Some name", + "value": "/mod/data/someurl.php", + "selected": false + } + ], + "disabled": false, + "title": null + } + } +}} +
+
+ {{#urlselect}} + + {{/urlselect}} +
+
diff --git a/course/upgrade.txt b/course/upgrade.txt index cdf444d1cc3..d7b19cb0929 100644 --- a/course/upgrade.txt +++ b/course/upgrade.txt @@ -89,6 +89,9 @@ course formats don't have their own renderer. category pages. * New core_course_category::get_nearest_editable_subcategory(): - Return the core_course_category object for the first subcategory that the current user has the permission on it. +* The method navigation() in the core_course_bulk_activity_completion_renderer class has been deprecated as the tabs navigation + structure in the course competency pages has been replaced with tertiary navigation. To render the navigation, please + render_course_completion_action_bar() instead. === 3.11 === * A new callback xxx_coursemodule_definition_after_data that allows plugins to extend activity forms after the data is set. @@ -102,6 +105,7 @@ course formats don't have their own renderer. - activity_dates_information_in_activity_should_not_exist() - Given the activity date information in "" should not exist * A user preference usemodchooser has been removed and the activities/resources (non-ajax) activity chooser has been deprecated and will be removed in the future. + === 3.10 === * The function make_categories_options() has now been deprecated. Please use \core_course_category::make_categories_list() instead. diff --git a/lang/en/completion.php b/lang/en/completion.php index bb85efba1cd..61449661c4e 100644 --- a/lang/en/completion.php +++ b/lang/en/completion.php @@ -129,6 +129,7 @@ $string['coursecompleted'] = 'Course completed'; $string['coursecompletedmessage'] = '

Congratulations!

You have completed the course {$a->coursename}.

'; $string['coursecompletion'] = 'Course completion'; $string['coursecompletioncondition'] = 'Condition: {$a}'; +$string['coursecompletionnavigation'] = 'Course completion tertiary navigation'; $string['coursegrade'] = 'Course grade'; $string['coursesavailable'] = 'Courses available'; $string['coursesavailableexplaination'] = 'Note: Course completion conditions must be set for a course to appear in the above list.';