From e37e0c39e877876f809d0eefa914d0289191ae9c Mon Sep 17 00:00:00 2001 From: Amaia Anabitarte Date: Fri, 21 Jul 2023 12:27:26 +0200 Subject: [PATCH 1/4] MDL-78530 core_completion: New site default activity completion page --- admin/settings/courses.php | 8 +++ completion/classes/defaultedit_form.php | 3 +- completion/classes/edit_base_form.php | 4 +- completion/classes/form/form_trait.php | 32 +++++++----- completion/classes/manager.php | 21 ++++++-- .../site_default_activity_completion.feature | 14 ++++++ course/defaultcompletion.php | 49 +++++++++++-------- course/moodleform_mod.php | 2 +- 8 files changed, 95 insertions(+), 38 deletions(-) create mode 100644 completion/tests/behat/site_default_activity_completion.feature diff --git a/admin/settings/courses.php b/admin/settings/courses.php index 00ac40918ac..210ca35091e 100644 --- a/admin/settings/courses.php +++ b/admin/settings/courses.php @@ -264,6 +264,14 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) { $defaulprovider, $communicationproviders)); $ADMIN->add('coursedefaultsettings', $temp); + if (!empty($CFG->enablecompletion)) { + $ADMIN->add('coursedefaultsettings', new admin_externalpage( + 'sitedefaultcompletion', + new lang_string('defaultcompletion', 'completion'), + new moodle_url('/course/defaultcompletion.php', ['id' => $SITE->id]), + ['moodle/course:manageactivities']) + ); + } $ADMIN->add('coursedefaultsettings', new admin_externalpage( 'course_customfield', new lang_string('course_customfield', 'admin'), diff --git a/completion/classes/defaultedit_form.php b/completion/classes/defaultedit_form.php index 2d0431160c6..b92e2044eaa 100644 --- a/completion/classes/defaultedit_form.php +++ b/completion/classes/defaultedit_form.php @@ -104,7 +104,8 @@ class core_completion_defaultedit_form extends core_completion_edit_base_form { * Form definition, */ public function definition() { - $this->course = $this->_customdata['course']; + $course = $this->_customdata['course']; + $this->course = is_numeric($course) ? get_course($course) : $course; $this->modules = $this->_customdata['modules']; $mform = $this->_form; diff --git a/completion/classes/edit_base_form.php b/completion/classes/edit_base_form.php index 52de135b51b..e0b9c948501 100644 --- a/completion/classes/edit_base_form.php +++ b/completion/classes/edit_base_form.php @@ -204,7 +204,9 @@ abstract class core_completion_edit_base_form extends moodleform { $this->add_completion_elements( $this->get_module_name(), $this->support_views(), - $this->support_grades() + $this->support_grades(), + false, + $this->course->id ); if ($conflicts = $this->get_modules_with_hidden_rules()) { diff --git a/completion/classes/form/form_trait.php b/completion/classes/form/form_trait.php index e539767d74c..90e5eabf6e3 100644 --- a/completion/classes/form/form_trait.php +++ b/completion/classes/form/form_trait.php @@ -104,6 +104,7 @@ trait form_trait { * @param bool $supportgrades True if the module supports grades and false otherwise. * @param bool $rating True if the rating feature is enabled and false otherwise. * @param bool $defaultcompletion True if the default completion is enabled and false otherwise. To review in MDL-78531. + * @param int|null $courseid Course where to add completion elements. * @throws \coding_exception If the form is not moodleform_mod and $modname is null. */ protected function add_completion_elements( @@ -111,9 +112,10 @@ trait form_trait { bool $supportviews = false, bool $supportgrades = false, bool $rating = false, - bool $defaultcompletion = true + bool $defaultcompletion = true, + ?int $courseid = null ): void { - global $CFG; + global $CFG, $SITE; $mform = $this->get_form(); if ($modname === null) { @@ -204,12 +206,15 @@ trait form_trait { } // Completion expected at particular date? (For progress tracking). - $completionexpectedel = 'completionexpected' . $suffix; - $mform->addElement('date_time_selector', $completionexpectedel, get_string('completionexpected', 'completion'), + // We don't show completion expected at site level default completion. + if ($courseid != $SITE->id) { + $completionexpectedel = 'completionexpected' . $suffix; + $mform->addElement('date_time_selector', $completionexpectedel, get_string('completionexpected', 'completion'), ['optional' => true]); - $a = get_string('pluginname', $modname); - $mform->addHelpButton($completionexpectedel, 'completionexpected', 'completion', '', false, $a); - $mform->hideIf($completionexpectedel, 'completion', 'eq', COMPLETION_TRACKING_NONE); + $a = get_string('pluginname', $modname); + $mform->addHelpButton($completionexpectedel, 'completionexpected', 'completion', '', false, $a); + $mform->hideIf($completionexpectedel, 'completion', 'eq', COMPLETION_TRACKING_NONE); + } } /** @@ -356,16 +361,19 @@ trait form_trait { * It should be called from the definition_after_data() to setup the completion settings in the form. */ protected function definition_after_data_completion(): void { - global $COURSE; + global $COURSE, $SITE; $mform = $this->get_form(); $completion = new \completion_info($COURSE); - if ($completion->is_enabled()) { + // We use $SITE course for site default activity completion, + // so users could set default values regardless of whether completion is enabled or not.". + if ($completion->is_enabled() || $COURSE->id == $SITE->id) { $suffix = $this->get_suffix(); // If anybody has completed the activity, these options will be 'locked'. $cm = $this->get_cm(); - $completedcount = empty($cm) ? 0 : $completion->count_user_data($cm); + // We use $SITE course for site default activity completion, so we don't need any unlock button. + $completedcount = (empty($cm) || $COURSE->id == $SITE->id) ? 0 : $completion->count_user_data($cm); $freeze = false; if (!$completedcount) { // The unlock buttons don't need suffix because they are only displayed in the module settings page. @@ -374,7 +382,9 @@ trait form_trait { } // Automatically set to unlocked. Note: this is necessary in order to make it recalculate completion once // the option is changed, maybe someone has completed it now. - $mform->getElement('completionunlocked')->setValue(1); + if ($mform->elementExists('completionunlocked')) { + $mform->getElement('completionunlocked')->setValue(1); + } } else { // Has the element been unlocked, either by the button being pressed in this request, or the field already // being set from a previous one? diff --git a/completion/classes/manager.php b/completion/classes/manager.php index 3e3cc7964b9..64e5bb710cc 100644 --- a/completion/classes/manager.php +++ b/completion/classes/manager.php @@ -25,6 +25,7 @@ namespace core_completion; +use core\context; use stdClass; use context_course; use cm_info; @@ -56,6 +57,20 @@ class manager { $this->courseid = $courseid; } + /** + * Returns current course context or system level for $SITE courseid. + * + * @return context The course based on current courseid or system context. + */ + protected function get_context(): context { + global $SITE; + + if ($this->courseid && $this->courseid != $SITE->id) { + return context_course::instance($this->courseid); + } + return \context_system::instance(); + } + /** * Gets the data (context) to be used with the bulkactivitycompletion template. * @@ -220,13 +235,13 @@ class manager { $data->helpicon = $OUTPUT->help_icon('bulkcompletiontracking', 'core_completion'); // Add icon information. $data->modules = array_values($modules); - $coursecontext = context_course::instance($this->courseid); - $canmanage = has_capability('moodle/course:manageactivities', $coursecontext); + $context = $this->get_context(); + $canmanage = has_capability('moodle/course:manageactivities', $context); $course = get_course($this->courseid); foreach ($data->modules as $module) { $module->icon = $OUTPUT->image_url('monologo', $module->name)->out(); $module->formattedname = format_string(get_string('modulename', 'mod_' . $module->name), - true, ['context' => $coursecontext]); + true, ['context' => $context]); $module->canmanage = $canmanage && course_allowed_module($course, $module->name); if ($includedefaults) { $defaults = self::get_default_completion($course, $module, false); diff --git a/completion/tests/behat/site_default_activity_completion.feature b/completion/tests/behat/site_default_activity_completion.feature new file mode 100644 index 00000000000..21b6d9d231a --- /dev/null +++ b/completion/tests/behat/site_default_activity_completion.feature @@ -0,0 +1,14 @@ +@core @core_completion +Feature: Allow admins to edit the default activity completion rules at site level. + In order to set the activity completion defaults for new activities + As an admin + I need to be able to edit the completion rules for a group of activities at site level. + + Scenario: Navigate to site default activity completion + Given I navigate to "Courses > Default settings > Default activity completion" in site administration + When I should see "Default activity completion" + Then I should see "These are the default completion conditions for activities in all courses." + And the following config values are set as admin: + | enablecompletion | 0 | + And I navigate to "Courses > Default settings" in site administration + And I should not see "Default activity completion" diff --git a/course/defaultcompletion.php b/course/defaultcompletion.php index cc443214a40..bf04e77b62f 100644 --- a/course/defaultcompletion.php +++ b/course/defaultcompletion.php @@ -30,32 +30,35 @@ require_once($CFG->libdir.'/completionlib.php'); $id = required_param('id', PARAM_INT); // Course id. $modids = optional_param_array('modids', [], PARAM_INT); -// Perform some basic access control checks. if ($id) { - - if ($id == SITEID) { - // Don't allow editing of 'site course' using this form. - throw new \moodle_exception('cannoteditsiteform'); - } - if (!$course = $DB->get_record('course', array('id' => $id))) { throw new \moodle_exception('invalidcourseid'); } - require_login($course); - require_capability('moodle/course:manageactivities', context_course::instance($course->id)); - -} else { - require_login(); - throw new \moodle_exception('needcourseid'); } +if ($id == SITEID) { + $context = context_system::instance(); + $title = get_string('defaultcompletion', 'completion'); + $heading = format_string($SITE->fullname, true, ['context' => $context]); +} else { + $context = context_course::instance($id); + $title = $course->shortname; + $heading = $course->fullname; +} +require_login($course); +require_capability('moodle/course:manageactivities', $context); + // 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/defaultcompletion.php', array('id' => $course->id)); -$PAGE->set_title($course->shortname); -$PAGE->set_heading($course->fullname); +if ($id != SITEID) { + navigation_node::override_active_url(new moodle_url('/course/completion.php', array('id' => $course->id))); + $PAGE->set_course($course); +} +$PAGE->set_url('/course/defaultcompletion.php', ['id' => $id]); +$PAGE->set_context($context); $PAGE->set_pagelayout('admin'); +$PAGE->set_title($title); +$PAGE->set_heading($heading); + // Get list of modules that have been sent in the form. $manager = new \core_completion\manager($course->id); @@ -79,10 +82,14 @@ if (!empty($modules)) { $renderer = $PAGE->get_renderer('core_course', 'bulk_activity_completion'); // Print the form. -echo $OUTPUT->header(); +echo $renderer->header(); -$actionbar = new \core_course\output\completion_action_bar($course->id, $PAGE->url); -echo $renderer->render_course_completion_action_bar($actionbar); +if ($id == SITEID) { + echo $renderer->heading($title); +} else { + $actionbar = new \core_course\output\completion_action_bar($course->id, $PAGE->url); + echo $renderer->render_course_completion_action_bar($actionbar); +} echo $renderer->defaultcompletion($allmodules, $modules, $form); diff --git a/course/moodleform_mod.php b/course/moodleform_mod.php index 56b8c87249e..bb1aaee3583 100644 --- a/course/moodleform_mod.php +++ b/course/moodleform_mod.php @@ -642,7 +642,7 @@ abstract class moodleform_mod extends moodleform { // Add the completion tracking elements to the form. if ($completion->is_enabled()) { $mform->addElement('header', 'activitycompletionheader', get_string('activitycompletion', 'completion')); - $this->add_completion_elements(); + $this->add_completion_elements(null, false, false, false, $this->_course->id); } // Populate module tags. From ded74e1e65c3ec0b2a073178498b6d3ca4a203d7 Mon Sep 17 00:00:00 2001 From: Amaia Anabitarte Date: Wed, 2 Aug 2023 20:38:48 +0200 Subject: [PATCH 2/4] MDL-78530 core_completion: New default completion behat generator --- .../behat_core_completion_generator.php | 59 ++++++++ completion/tests/generator/lib.php | 63 ++++++++ completion/tests/generator_test.php | 138 ++++++++++++++++++ lib/testing/tests/testing_generator_test.php | 4 +- 4 files changed, 262 insertions(+), 2 deletions(-) create mode 100644 completion/tests/generator/behat_core_completion_generator.php create mode 100644 completion/tests/generator/lib.php create mode 100644 completion/tests/generator_test.php diff --git a/completion/tests/generator/behat_core_completion_generator.php b/completion/tests/generator/behat_core_completion_generator.php new file mode 100644 index 00000000000..903817bafa6 --- /dev/null +++ b/completion/tests/generator/behat_core_completion_generator.php @@ -0,0 +1,59 @@ +. + +/** + * Completion test generator for Behat + * + * @package core_completion + * @copyright 2023 Amaia Anabitarte + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class behat_core_completion_generator extends behat_generator_base { + + /** + * Get a list of the entities that can be created for completion + * + * @return array[] + */ + protected function get_creatable_entities(): array { + return [ + 'Course defaults' => [ + 'singular' => 'Course default', + 'datagenerator' => 'default_completion', + 'required' => [ + 'course', + 'module', + ], + 'switchids' => [ + 'course' => 'course', + 'module' => 'module', + ], + ], + ]; + } + + /** + * Look up module ID from given name + * + * @param string $name + * @return int + */ + protected function get_module_id(string $name): int { + global $DB; + + return (int) $DB->get_field('modules', 'id', ['name' => $name], MUST_EXIST); + } +} diff --git a/completion/tests/generator/lib.php b/completion/tests/generator/lib.php new file mode 100644 index 00000000000..2b661704403 --- /dev/null +++ b/completion/tests/generator/lib.php @@ -0,0 +1,63 @@ +. + +/** + * Completion test generator + * + * @package core_completion + * @copyright 2023 Amaia Anabitarte + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class core_completion_generator extends component_generator_base { + + /** + * Create default completion + * + * @param array|stdClass $record + * @return stdClass + */ + public function create_default_completion($record): stdClass { + global $DB; + + $record = (array) $record; + + if (!array_key_exists('course', $record) || !is_numeric($record['course'])) { + throw new moodle_exception('courserequired'); + } + if (!$DB->get_record('course', ['id' => $record['course']])) { + throw new moodle_exception('invalidcourseid'); + } + + if (!array_key_exists('module', $record) || !is_numeric($record['module'])) { + throw new moodle_exception('modulerequired'); + } + if (!$DB->get_record('modules', ['id' => $record['module']])) { + throw new moodle_exception('invalidmoduleid'); + } + + $record = (object) array_merge([ + 'completion' => 0, + 'completionview' => 0, + 'completionusegrade' => 0, + 'completionpassgrade' => 0, + 'completionexpected' => 0, + 'customrules' => '', + ], $record); + $record->id = $DB->insert_record('course_completion_defaults', $record); + + return $record; + } +} diff --git a/completion/tests/generator_test.php b/completion/tests/generator_test.php new file mode 100644 index 00000000000..7c5f6826bcc --- /dev/null +++ b/completion/tests/generator_test.php @@ -0,0 +1,138 @@ +. + +namespace core_completion; + +/** + * PHPUnit data generator testcase + * + * @package core_completion + * @category test + * @copyright 2023 Amaia Anabitarte + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @coversDefaultClass \core_completion_generator + */ +class generator_test extends \advanced_testcase { + + /** + * Test create_default_completion. + * + * @dataProvider create_default_completion_provider + * + * @param int|null|string $course The course to add the default activities conditions to. + * @param int|null|string $module The module to add the default activities conditions to. + * @param bool $exception Whether an exception is expected or not. + * @param int $count The number of default activity completions to be created. + * @param int $completion The value for completion setting. + * + * @covers ::create_default_completion + */ + public function test_create_default_completion($course, $module, bool $exception, int $count, int $completion = 0) { + global $DB; + + $this->resetAfterTest(true); + $generator = $this->getDataGenerator()->get_plugin_generator('core_completion'); + + $record = [ + 'course' => $course, + 'module' => $module, + 'completion' => $completion, + ]; + $result = (object) array_merge([ + 'completion' => 0, + 'completionview' => 0, + 'completionusegrade' => 0, + 'completionpassgrade' => 0, + 'completionexpected' => 0, + 'customrules' => '', + ], $record); + + if ($exception) { + $this->expectException('moodle_exception'); + } + $defaultcompletion = $generator->create_default_completion($record); + + if (!$exception) { + foreach ($result as $key => $value) { + $this->assertEquals($defaultcompletion->{$key}, $value); + } + } + $this->assertEquals( + $count, + $DB->count_records('course_completion_defaults', ['course' => $course, 'module' => $module]) + ); + } + + /** + * Data provider for test_create_default_completion(). + * @return array[] + */ + public function create_default_completion_provider(): array { + global $SITE; + + return [ + 'Null course' => [ + 'course' => null, + 'module' => null, + 'exception' => true, + 'count' => 0, + ], + 'Empty course' => [ + 'course' => '', + 'module' => null, + 'exception' => true, + 'count' => 0, + ], + 'Invalid course' => [ + 'course' => 0, + 'module' => null, + 'exception' => true, + 'count' => 0, + ], + 'Null module' => [ + 'course' => $SITE->id, + 'module' => null, + 'exception' => true, + 'count' => 0, + ], + 'Empty module' => [ + 'course' => $SITE->id, + 'module' => null, + 'exception' => true, + 'count' => 0, + ], + 'Invalid module' => [ + 'course' => $SITE->id, + 'module' => 0, + 'exception' => true, + 'count' => 0, + ], + 'Default activity completion: NONE' => [ + 'course' => $SITE->id, + 'module' => 1, + 'exception' => false, + 'count' => 1, + ], + 'Default activity completion: AUTOMATIC' => [ + 'course' => $SITE->id, + 'module' => 1, + 'exception' => false, + 'count' => 1, + 'completion' => 2, + ], + ]; + } +} diff --git a/lib/testing/tests/testing_generator_test.php b/lib/testing/tests/testing_generator_test.php index 0291121d49b..46ae0f9e926 100644 --- a/lib/testing/tests/testing_generator_test.php +++ b/lib/testing/tests/testing_generator_test.php @@ -47,8 +47,8 @@ class testing_generator_test extends \advanced_testcase { */ public function test_get_plugin_generator_no_component_dir() { $this->expectException(\coding_exception::class); - $this->expectExceptionMessage('Component core_completion does not support generators yet. Missing tests/generator/lib.php.'); - $generator = $this->getDataGenerator()->get_plugin_generator('core_completion'); + $this->expectExceptionMessage('Component core_cohort does not support generators yet. Missing tests/generator/lib.php.'); + $generator = $this->getDataGenerator()->get_plugin_generator('core_cohort'); } public function test_create_user() { From 1f68fe635ff85f2d2d759abe67b8161070946252 Mon Sep 17 00:00:00 2001 From: Amaia Anabitarte Date: Wed, 26 Jul 2023 17:59:02 +0200 Subject: [PATCH 3/4] MDL-78530 core_completion: Use site default completion or none When creating a new activity we should use course level default completion and site level completion if there is no course level default completion. For non defined default completion values use COMPLETION_TRACKING_NONE instead of COMPLETION_TRACKING_MANUAL. --- completion/classes/form/form_trait.php | 12 +--- completion/classes/manager.php | 22 +++--- .../site_default_activity_completion.feature | 71 +++++++++++++++++++ 3 files changed, 84 insertions(+), 21 deletions(-) diff --git a/completion/classes/form/form_trait.php b/completion/classes/form/form_trait.php index 90e5eabf6e3..3986d68d3d6 100644 --- a/completion/classes/form/form_trait.php +++ b/completion/classes/form/form_trait.php @@ -115,7 +115,7 @@ trait form_trait { bool $defaultcompletion = true, ?int $courseid = null ): void { - global $CFG, $SITE; + global $SITE; $mform = $this->get_form(); if ($modname === null) { @@ -125,7 +125,6 @@ trait form_trait { $supportviews = plugin_supports('mod', $modname, FEATURE_COMPLETION_TRACKS_VIEWS, false); $supportgrades = plugin_supports('mod', $modname, FEATURE_GRADE_HAS_GRADE, false); $rating = $this->_features->rating; - $defaultcompletion = $CFG->completiondefault && $this->_features->defaultcompletion; } else { throw new \coding_exception('You must specify the modname parameter if you are not using a moodleform_mod.'); } @@ -139,15 +138,6 @@ trait form_trait { $mform->setType('completionunlocked', PARAM_INT); $trackingdefault = COMPLETION_TRACKING_NONE; - // If system and activity default completion is on, set it. - if ($defaultcompletion) { - $hasrules = plugin_supports('mod', $modname, FEATURE_COMPLETION_HAS_RULES, true); - if ($hasrules || $supportviews) { - $trackingdefault = COMPLETION_TRACKING_AUTOMATIC; - } else { - $trackingdefault = COMPLETION_TRACKING_MANUAL; - } - } // Get the sufix to add to the completion elements name. $suffix = $this->get_suffix(); diff --git a/completion/classes/manager.php b/completion/classes/manager.php index 64e5bb710cc..896fb4acf8a 100644 --- a/completion/classes/manager.php +++ b/completion/classes/manager.php @@ -559,9 +559,18 @@ class manager { * @return stdClass */ public static function get_default_completion($course, $module, $flatten = true, string $suffix = '') { - global $DB, $CFG; - if ($data = $DB->get_record('course_completion_defaults', ['course' => $course->id, 'module' => $module->id], - 'completion, completionview, completionexpected, completionusegrade, completionpassgrade, customrules')) { + global $DB, $CFG, $SITE; + + $fields = 'completion, completionview, completionexpected, completionusegrade, completionpassgrade, customrules'; + // Check course default completion values. + $params = ['course' => $course->id, 'module' => $module->id]; + $data = $DB->get_record('course_completion_defaults', $params, $fields); + if (!$data && $course->id != $SITE->id) { + // If there is no course default completion, check site level default completion values ($SITE->id). + $params['course'] = $SITE->id; + $data = $DB->get_record('course_completion_defaults', $params, $fields); + } + if ($data) { if ($data->customrules && ($customrules = @json_decode($data->customrules, true))) { // MDL-72375 This will override activity id for new mods. Skip this field, it is already exposed as courseid. unset($customrules['id']); @@ -578,13 +587,6 @@ class manager { } else { $data = new stdClass(); $data->completion = COMPLETION_TRACKING_NONE; - if ($CFG->completiondefault) { - $completion = new \completion_info(get_fast_modinfo($course->id)->get_course()); - if ($completion->is_enabled() && plugin_supports('mod', $module->name, FEATURE_MODEDIT_DEFAULT_COMPLETION, true)) { - $data->completion = COMPLETION_TRACKING_MANUAL; - $data->completionview = 1; - } - } } // If the suffix is not empty, the completion rules need to be renamed to avoid conflicts. diff --git a/completion/tests/behat/site_default_activity_completion.feature b/completion/tests/behat/site_default_activity_completion.feature index 21b6d9d231a..e78c56b70e9 100644 --- a/completion/tests/behat/site_default_activity_completion.feature +++ b/completion/tests/behat/site_default_activity_completion.feature @@ -4,6 +4,77 @@ Feature: Allow admins to edit the default activity completion rules at site leve As an admin I need to be able to edit the completion rules for a group of activities at site level. + Background: + Given the following "courses" exist: + | fullname | shortname | category | enablecompletion | + | Course 1 | C1 | 0 | 1 | + And I log in as "admin" + + @javascript + Scenario: Default activity completion rules with no site or course default completion + Given the following "activity" exists: + | activity | assign | + | course | C1 | + | name | Test assignment one | + | completion | 1 | + And I am on "Course 1" course homepage with editing mode on + When I add a "Assignment" to section "0" + And I expand all fieldsets + # Completion tracking 0 = Do not indicate activity completion. + Then the field "Completion tracking" matches value "0" + # Default values don't affect existing activities. + But I am on the "Test assignment one" "assign activity editing" page + And I navigate to "Settings" in current page administration + And I expand all fieldsets + And the field "Completion tracking" matches value "1" + + @javascript + Scenario: Default activity completion rules with site default completion but with no course default completion + Given the following "activity" exists: + | activity | assign | + | course | C1 | + | name | Test assignment one | + | completion | 0 | + And the following "core_completion > Course default" exist: + | course | module | completion | completionview | completionusegrade | completionsubmit | + | Acceptance test site | assign | 2 | 0 | 1 | 1 | + And I am on "Course 1" course homepage with editing mode on + When I add a "Assignment" to section "0" + And I expand all fieldsets + Then the field "Completion tracking" matches value "2" + And the field "completionview" matches value "0" + And the field "completionusegrade" matches value "1" + And the field "completionsubmit" matches value "1" + # Default values don't affect existing activities. + But I am on the "Test assignment one" "assign activity editing" page + And I navigate to "Settings" in current page administration + And I expand all fieldsets + And the field "Completion tracking" matches value "0" + + @javascript + Scenario: Default activity completion rules with site default completion and course default completion + Given the following "activity" exists: + | activity | assign | + | course | C1 | + | name | Test assignment one | + | completion | 0 | + And the following "core_completion > Course defaults" exist: + | course | module | completion | completionview | completionusegrade | completionsubmit | + | Acceptance test site | assign | 2 | 0 | 1 | 1 | + | C1 | assign | 2 | 1 | 0 | 1 | + And I am on "Course 1" course homepage with editing mode on + When I add a "Assignment" to section "0" + And I expand all fieldsets + Then the field "Completion tracking" matches value "2" + And the field "completionview" matches value "1" + And the field "completionusegrade" matches value "0" + And the field "completionsubmit" matches value "1" + # Default values don't affect existing activities. + But I am on the "Test assignment one" "assign activity editing" page + And I navigate to "Settings" in current page administration + And I expand all fieldsets + And the field "Completion tracking" matches value "0" + Scenario: Navigate to site default activity completion Given I navigate to "Courses > Default settings > Default activity completion" in site administration When I should see "Default activity completion" From 4c4e2224e116d887ebe7dc2398c85622b9e6750c Mon Sep 17 00:00:00 2001 From: Amaia Anabitarte Date: Wed, 26 Jul 2023 18:24:15 +0200 Subject: [PATCH 4/4] MDL-78530 core_completion: Remove $CFG->completiondefault setting --- admin/settings/subsystems.php | 2 -- completion/classes/form/form_trait.php | 2 -- completion/upgrade.txt | 1 + lang/en/completion.php | 6 ++++-- lang/en/deprecated.txt | 2 ++ lib/db/upgrade.php | 7 +++++++ version.php | 2 +- 7 files changed, 15 insertions(+), 7 deletions(-) diff --git a/admin/settings/subsystems.php b/admin/settings/subsystems.php index 8500721a478..409f902227a 100644 --- a/admin/settings/subsystems.php +++ b/admin/settings/subsystems.php @@ -31,8 +31,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page 1 => get_string('completionactivitydefault', 'completion'), 0 => get_string('completion_none', 'completion') ); - $optionalsubsystems->add(new admin_setting_configselect('completiondefault', new lang_string('completiondefault', 'completion'), - new lang_string('configcompletiondefault', 'completion'), 1, $options)); $optionalsubsystems->add($checkbox = new admin_setting_configcheckbox('enableavailability', new lang_string('enableavailability', 'availability'), diff --git a/completion/classes/form/form_trait.php b/completion/classes/form/form_trait.php index 3986d68d3d6..3c66ad4c51d 100644 --- a/completion/classes/form/form_trait.php +++ b/completion/classes/form/form_trait.php @@ -103,7 +103,6 @@ trait form_trait { * @param bool $supportviews True if the module supports views and false otherwise. * @param bool $supportgrades True if the module supports grades and false otherwise. * @param bool $rating True if the rating feature is enabled and false otherwise. - * @param bool $defaultcompletion True if the default completion is enabled and false otherwise. To review in MDL-78531. * @param int|null $courseid Course where to add completion elements. * @throws \coding_exception If the form is not moodleform_mod and $modname is null. */ @@ -112,7 +111,6 @@ trait form_trait { bool $supportviews = false, bool $supportgrades = false, bool $rating = false, - bool $defaultcompletion = true, ?int $courseid = null ): void { global $SITE; diff --git a/completion/upgrade.txt b/completion/upgrade.txt index c4ec027b023..b19fd6dac56 100644 --- a/completion/upgrade.txt +++ b/completion/upgrade.txt @@ -13,6 +13,7 @@ information provided here is intended especially for developers. through the form and the current form that has been sent. * Support for deprecated `[modname]_get_completion_state` callbacks has been removed, custom completion rules must be implemented by appropriate `mod_[modname]\completion\custom_completion` class instead +* $CFG->completiondefault setting has been removed. === 4.0 === * New method mark_course_completions_activity_criteria() has been added to mark course completions instantly. It is diff --git a/lang/en/completion.php b/lang/en/completion.php index 3e8d7bb3b74..886564e7754 100644 --- a/lang/en/completion.php +++ b/lang/en/completion.php @@ -88,7 +88,6 @@ $string['completion_link'] = 'activity/completion'; $string['completion_manual'] = 'Students can manually mark the activity as completed'; $string['completion_none'] = 'Do not indicate activity completion'; $string['completionactivitydefault'] = 'Use activity default'; -$string['completiondefault'] = 'Default completion tracking'; $string['completiondisabled'] = 'Disabled, not shown in activity settings'; $string['completionenabled'] = 'Enabled, control via completion and activity settings'; $string['completionexpected'] = 'Set reminder in Timeline'; @@ -118,7 +117,6 @@ $string['completionusegrade_help'] = 'If enabled, the activity is considered com $string['completionupdated'] = 'Updated completion for activity {$a}'; $string['completionview'] = 'Require view'; $string['completionview_desc'] = 'Student must view this activity to complete it'; -$string['configcompletiondefault'] = 'The default setting for completion tracking when creating new activities.'; $string['configenablecompletion'] = 'If enabled, course and activity completion conditions may be set. Setting activity completion conditions is recommended so that meaningful data is displayed for users in their course overview on the Dashboard.'; $string['confirmselfcompletion'] = 'Confirm self completion'; $string['courseaggregation'] = 'Condition requires'; @@ -260,4 +258,8 @@ $string['youmust'] = 'You must'; // Deprecated since Moodle 4.0. $string['yourprogress'] = 'Your progress'; + +// Deprecated since Moodle 4.3. $string['editcoursecompletionsettings'] = 'Edit course completion settings'; +$string['completiondefault'] = 'Default completion tracking'; +$string['configcompletiondefault'] = 'The default setting for completion tracking when creating new activities.'; diff --git a/lang/en/deprecated.txt b/lang/en/deprecated.txt index c27394bf2fb..ae5de49675a 100644 --- a/lang/en/deprecated.txt +++ b/lang/en/deprecated.txt @@ -92,3 +92,5 @@ devicedetectregexexpression,core_admin devicedetectregexvalue,core_admin modshowcmtitle,core makeavailablecmtitle,core +completiondefault,core_completion +configcompletiondefault,core_completion diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index 6dc52e62102..d9ecd277c40 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -3501,5 +3501,12 @@ privatefiles,moodle|/user/files.php'; upgrade_main_savepoint(true, 2023082200.04); } + if ($oldversion < 2023082600.01) { + unset_config('completiondefault'); + + // Main savepoint reached. + upgrade_main_savepoint(true, 2023082600.01); + } + return true; } diff --git a/version.php b/version.php index 23257d6c911..0ca461b88e7 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2023082600.00; // YYYYMMDD = weekly release date of this DEV branch. +$version = 2023082600.01; // YYYYMMDD = weekly release date of this DEV branch. // RR = release increments - 00 in DEV branches. // .XX = incremental changes. $release = '4.3dev+ (Build: 20230826)'; // Human-friendly version name