Merge branch 'MDL-78530-master' of https://github.com/aanabit/moodle
This commit is contained in:
@@ -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'),
|
||||
|
||||
@@ -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'),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -103,7 +103,7 @@ 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.
|
||||
*/
|
||||
protected function add_completion_elements(
|
||||
@@ -111,9 +111,9 @@ trait form_trait {
|
||||
bool $supportviews = false,
|
||||
bool $supportgrades = false,
|
||||
bool $rating = false,
|
||||
bool $defaultcompletion = true
|
||||
?int $courseid = null
|
||||
): void {
|
||||
global $CFG;
|
||||
global $SITE;
|
||||
|
||||
$mform = $this->get_form();
|
||||
if ($modname === null) {
|
||||
@@ -123,7 +123,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.');
|
||||
}
|
||||
@@ -137,15 +136,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();
|
||||
@@ -204,12 +194,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 +349,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 +370,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?
|
||||
|
||||
@@ -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);
|
||||
@@ -550,9 +565,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']);
|
||||
@@ -569,13 +593,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.
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
@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.
|
||||
|
||||
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"
|
||||
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"
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Completion test generator for Behat
|
||||
*
|
||||
* @package core_completion
|
||||
* @copyright 2023 Amaia Anabitarte <[email protected]>
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Completion test generator
|
||||
*
|
||||
* @package core_completion
|
||||
* @copyright 2023 Amaia Anabitarte <[email protected]>
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_completion;
|
||||
|
||||
/**
|
||||
* PHPUnit data generator testcase
|
||||
*
|
||||
* @package core_completion
|
||||
* @category test
|
||||
* @copyright 2023 Amaia Anabitarte <[email protected]>
|
||||
* @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,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 <b>{$a}</b>';
|
||||
$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.';
|
||||
|
||||
@@ -93,3 +93,5 @@ devicedetectregexvalue,core_admin
|
||||
modshowcmtitle,core
|
||||
makeavailablecmtitle,core
|
||||
dateintervaldayshoursmins,core_langconfig
|
||||
completiondefault,core_completion
|
||||
configcompletiondefault,core_completion
|
||||
|
||||
@@ -3547,5 +3547,12 @@ privatefiles,moodle|/user/files.php';
|
||||
upgrade_main_savepoint(true, 2023082600.03);
|
||||
}
|
||||
|
||||
if ($oldversion < 2023082600.05) {
|
||||
unset_config('completiondefault');
|
||||
|
||||
// Main savepoint reached.
|
||||
upgrade_main_savepoint(true, 2023082600.05);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$version = 2023082600.04; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
$version = 2023082600.05; // 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
|
||||
|
||||
Reference in New Issue
Block a user