Merge branch 'MDL-71189-master-3' of git://github.com/mickhawkins/moodle

This commit is contained in:
Víctor Déniz 2021-05-03 08:08:34 +01:00
commit 6d3107641d
17 changed files with 330 additions and 13 deletions

View File

@ -169,19 +169,26 @@ abstract class activity_custom_completion {
* @param string $rule The completion rule.
* @return int The completion state.
*/
public abstract function get_state(string $rule): int;
abstract public function get_state(string $rule): int;
/**
* Fetch the list of custom completion rules that this module defines.
*
* @return array
*/
public abstract static function get_defined_custom_rules(): array;
abstract public static function get_defined_custom_rules(): array;
/**
* Returns an associative array of the descriptions of custom completion rules.
*
* @return array
*/
public abstract function get_custom_rule_descriptions(): array;
abstract public function get_custom_rule_descriptions(): array;
/**
* Returns an array of all completion rules, in the order they should be displayed to users.
*
* @return array
*/
abstract public function get_sort_order(): array;
}

View File

@ -18,7 +18,7 @@
* Contains the class for building the user's activity completion details.
*
* @package core_completion
* @copyright Jun Pataleta <jun@moodle.com>
* @copyright 2021 Jun Pataleta <jun@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@ -33,7 +33,7 @@ use completion_info;
* Class for building the user's activity completion details.
*
* @package core_completion
* @copyright Jun Pataleta <jun@moodle.com>
* @copyright 2021 Jun Pataleta <jun@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cm_completion_details {
@ -79,6 +79,7 @@ class cm_completion_details {
* Fetches the completion details for a user.
*
* @return array An array of completion details for a user containing the completion requirement's description and status.
* @throws \coding_exception
*/
public function get_details(): array {
if (!$this->is_automatic()) {
@ -135,6 +136,8 @@ class cm_completion_details {
'description' => $this->cmcompletion->get_custom_rule_description($rule),
];
}
$details = $this->sort_completion_details($details);
}
} else {
if (function_exists($this->cminfo->modname . '_get_completion_state')) {
@ -149,10 +152,36 @@ class cm_completion_details {
}
}
return $details;
}
/**
* Sort completion details in the order specified by the activity's custom completion implementation.
*
* @param array $details The completion details to be sorted.
* @return array
* @throws \coding_exception
*/
protected function sort_completion_details(array $details): array {
$sortorder = $this->cmcompletion->get_sort_order();
$sorteddetails = [];
foreach ($sortorder as $sortedkey) {
if (isset($details[$sortedkey])) {
$sorteddetails[$sortedkey] = $details[$sortedkey];
}
}
// Make sure the sorted list includes all of the conditions that were set.
if (count($sorteddetails) < count($details)) {
$exceptiontext = get_class($this->cmcompletion) .'::get_sort_order() is missing one or more completion conditions.' .
' All custom and standard conditions that apply to this activity must be listed.';
throw new \coding_exception($exceptiontext);
}
return $sorteddetails;
}
/**
* Fetches the overall completion state of this course module.
*

View File

@ -18,7 +18,7 @@
* Contains unit tests for core_completion/cm_completion_details.
*
* @package core_completion
* @copyright Jun Pataleta <jun@moodle.com>
* @copyright 2021 Jun Pataleta <jun@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@ -39,7 +39,7 @@ require_once($CFG->libdir . '/completionlib.php');
* Class for unit testing core_completion/cm_completion_details.
*
* @package core_completion
* @copyright Jun Pataleta <jun@moodle.com>
* @copyright 2021 Jun Pataleta <jun@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cm_completion_details_test extends advanced_testcase {
@ -52,10 +52,12 @@ class cm_completion_details_test extends advanced_testcase {
*
* @param int|null $completion The completion tracking mode for the module.
* @param array $completionoptions Completion options (e.g. completionview, completionusegrade, etc.)
* @param object $mockcompletiondata Mock data to be returned by get_data.
* @param string $modname The modname to set in the cm if a specific one is required.
* @return cm_completion_details
*/
protected function setup_data(?int $completion, array $completionoptions = [],
object $mockcompletiondata = null): cm_completion_details {
object $mockcompletiondata = null, $modname = 'somenonexistentmod'): cm_completion_details {
if (is_null($completion)) {
$completion = COMPLETION_TRACKING_AUTOMATIC;
}
@ -88,7 +90,7 @@ class cm_completion_details_test extends advanced_testcase {
->will($this->returnValueMap([
['completion', $completion],
['instance', 1],
['modname', 'somenonexistentmod'],
['modname', $modname],
['completionview', $completionoptions['completionview'] ?? COMPLETION_VIEW_NOT_REQUIRED],
['completiongradeitemnumber', $completionoptions['completionusegrade'] ?? null],
]));
@ -280,4 +282,118 @@ class cm_completion_details_test extends advanced_testcase {
$cmcompletion = $this->setup_data($completion, $options, $getdatareturn);
$this->assertEquals($expecteddetails, $cmcompletion->get_details());
}
/**
* Data provider for test_get_details().
* @return array[]
*/
public function get_details_custom_order_provider() {
return [
'Custom and view/grade standard conditions, view first and grade last' => [
true,
true,
[
'completionsubmit' => true,
],
'assign',
['completionview', 'completionsubmit', 'completionusegrade'],
],
'Custom and view/grade standard conditions, grade not last' => [
true,
true,
[
'completionminattempts' => 2,
'completionusegrade' => 50,
'completionpassorattemptsexhausted' => 1,
],
'quiz',
['completionview', 'completionminattempts', 'completionusegrade', 'completionpassorattemptsexhausted'],
],
'Custom and grade standard conditions only, no view condition' => [
false,
true,
[
'completionsubmit' => true,
],
'assign',
['completionsubmit', 'completionusegrade'],
],
'Custom and view standard conditions only, no grade condition' => [
true,
false,
[
'completionsubmit' => true
],
'assign',
['completionview', 'completionsubmit'],
],
'View and grade conditions only, activity with no custom conditions' => [
true,
true,
[
'completionview' => true,
'completionusegrade' => true
],
'workshop',
['completionview', 'completionusegrade'],
],
'View condition only, activity with no custom conditions' => [
true,
false,
[
'completionview' => true,
],
'workshop',
['completionview'],
],
];
}
/**
* Test custom sort order is functioning in \core_completion\cm_completion_details::get_details().
*
* @dataProvider get_details_custom_order_provider
* @param bool $completionview Completion status of the "view" completion condition.
* @param bool $completiongrade Completion status of the "must receive grade" completion condition.
* @param array $customcompletionrules Custom completion requirements, along with their values.
* @param string $modname The name of the module having data fetched.
* @param array $expectedorder The expected order of completion conditions returned about the module.
*/
public function test_get_details_custom_order(bool $completionview, bool $completiongrade, array $customcompletionrules,
string $modname, array $expectedorder) {
$options['customcompletion'] = [];
$customcompletiondata = [];
if ($completionview) {
$options['completionview'] = true;
}
if ($completiongrade) {
$options['completionusegrade'] = true;
}
// Set up the completion rules for the completion info.
foreach ($customcompletionrules as $customtype => $isenabled) {
$customcompletiondata[$customtype] = COMPLETION_COMPLETE;
}
$getdatareturn = (object)[
'viewed' => $completionview ? COMPLETION_COMPLETE : COMPLETION_INCOMPLETE,
'completiongrade' => $completiongrade ? COMPLETION_COMPLETE : COMPLETION_INCOMPLETE,
'customcompletion' => $customcompletiondata,
];
$cmcompletion = $this->setup_data(COMPLETION_TRACKING_AUTOMATIC, $options, $getdatareturn, $modname);
$this->completioninfo->expects($this->any())
->method('get_data')
->willReturn($getdatareturn);
$fetcheddetails = $cmcompletion->get_details();
// Check the expected number of items are returned, and sorted in the correct order.
$this->assertCount(count($expectedorder), $fetcheddetails);
$this->assertTrue((array_keys($fetcheddetails) === $expectedorder));
}
}

View File

@ -109,6 +109,9 @@ information provided here is intended especially for developers.
- get_custom_rule_descriptions(): Returns an associative array with values containing the user-facing textual description
of the custom completion rules (which serve as the keys to these values).
e.g. ['completionsubmit' => 'Must submit']
- get_sort_order(): Returns an array listing the order the activity module's completion rules should be displayed to the user,
including both custom completion and relevant core completion rules
e.g. ['completionview', 'completionsubmit', 'completionusegrade']
* Admin setting admin_setting_configmulticheckbox now supports lazy-loading the options list by
supplying a callback function instead of an array of options.
* A new core API class \core_user\fields provides ways to get lists of user fields, and SQL related to

View File

@ -78,5 +78,17 @@ class custom_completion extends activity_custom_completion {
'completionsubmit' => get_string('completiondetail:submit', 'assign')
];
}
}
/**
* Returns an array of all completion rules, in the order they should be displayed to users.
*
* @return array
*/
public function get_sort_order(): array {
return [
'completionview',
'completionsubmit',
'completionusegrade',
];
}
}

View File

@ -69,4 +69,16 @@ class custom_completion extends activity_custom_completion {
'completionsubmit' => get_string('completiondetail:submit', 'choice')
];
}
/**
* Returns an array of all completion rules, in the order they should be displayed to users.
*
* @return array
*/
public function get_sort_order(): array {
return [
'completionview',
'completionsubmit',
];
}
}

View File

@ -69,4 +69,17 @@ class custom_completion extends activity_custom_completion {
'completionentries' => get_string('completiondetail:entries', 'data', $entries),
];
}
/**
* Returns an array of all completion rules, in the order they should be displayed to users.
*
* @return array
*/
public function get_sort_order(): array {
return [
'completionview',
'completionentries',
'completionusegrade',
];
}
}

View File

@ -67,4 +67,16 @@ class custom_completion extends activity_custom_completion {
'completionsubmit' => get_string('completiondetail:submit', 'feedback')
];
}
/**
* Returns an array of all completion rules, in the order they should be displayed to users.
*
* @return array
*/
public function get_sort_order(): array {
return [
'completionview',
'completionsubmit',
];
}
}

View File

@ -99,4 +99,19 @@ class custom_completion extends activity_custom_completion {
'completionposts' => get_string('completiondetail:posts', 'forum', $completionposts),
];
}
/**
* Returns an array of all completion rules, in the order they should be displayed to users.
*
* @return array
*/
public function get_sort_order(): array {
return [
'completionview',
'completiondiscussions',
'completionreplies',
'completionposts',
'completionusegrade',
];
}
}

View File

@ -73,4 +73,17 @@ class custom_completion extends activity_custom_completion {
'completionentries' => get_string('completiondetail:entries', 'glossary', $completionentries),
];
}
/**
* Returns an array of all completion rules, in the order they should be displayed to users.
*
* @return array
*/
public function get_sort_order(): array {
return [
'completionview',
'completionentries',
'completionusegrade',
];
}
}

View File

@ -70,4 +70,14 @@ class custom_completion extends activity_custom_completion {
public function manual_completion_always_shown(): bool {
return true;
}
/**
* Returns an array of all completion rules, in the order they should be displayed to users.
*
* @return array
*/
public function get_sort_order(): array {
// This module only supports manual completion.
return [];
}
}

View File

@ -91,4 +91,18 @@ class custom_completion extends activity_custom_completion {
'completionendreached' => get_string('completiondetail:reachend', 'lesson'),
];
}
/**
* Returns an array of all completion rules, in the order they should be displayed to users.
*
* @return array
*/
public function get_sort_order(): array {
return [
'completionview',
'completiontimespent',
'completionendreached',
'completionusegrade',
];
}
}

View File

@ -145,9 +145,9 @@ class custom_completion extends activity_custom_completion {
* @return array
*/
public function get_custom_rule_descriptions(): array {
$minattempts = $this->cm->customdata['customcompletionrules']['completionminattempts'];
$minattempts = $this->cm->customdata['customcompletionrules']['completionminattempts'] ?? 0;
$completionpassorattempts = $this->cm->customdata['customcompletionrules']['completionpassorattemptsexhausted'];
$completionpassorattempts = $this->cm->customdata['customcompletionrules']['completionpassorattemptsexhausted'] ?? [];
if (!empty($completionpassorattempts['completionattemptsexhausted'])) {
$passorallattemptslabel = get_string('completiondetail:passorexhaust', 'mod_quiz');
} else {
@ -159,4 +159,18 @@ class custom_completion extends activity_custom_completion {
'completionminattempts' => get_string('completiondetail:minattempts', 'mod_quiz', $minattempts),
];
}
/**
* Returns an array of all completion rules, in the order they should be displayed to users.
*
* @return array
*/
public function get_sort_order(): array {
return [
'completionview',
'completionminattempts',
'completionusegrade',
'completionpassorattemptsexhausted',
];
}
}

View File

@ -79,4 +79,14 @@ class custom_completion extends activity_custom_completion {
return in_array($display, $displaytypes);
}
/**
* Returns an array of all completion rules, in the order they should be displayed to users.
*
* @return array
*/
public function get_sort_order(): array {
// This module only supports manual completion.
return [];
}
}

View File

@ -202,4 +202,20 @@ class custom_completion extends activity_custom_completion {
'completionstatusallscos' => get_string('completiondetail:allscos', 'scorm'),
];
}
/**
* Returns an array of all completion rules, in the order they should be displayed to users.
*
* @return array
*/
public function get_sort_order(): array {
return [
'completionview',
'completionstatusallscos',
'completionstatusrequired',
'completionusegrade',
'completionscorerequired',
];
}
}

View File

@ -67,4 +67,16 @@ class custom_completion extends activity_custom_completion {
'completionsubmit' => get_string('completiondetail:submit', 'survey')
];
}
/**
* Returns an array of all completion rules, in the order they should be displayed to users.
*
* @return array
*/
public function get_sort_order(): array {
return [
'completionview',
'completionsubmit',
];
}
}

View File

@ -82,4 +82,13 @@ class custom_completion extends activity_custom_completion {
return in_array($display, $displaytypes);
}
/**
* Returns an array of all completion rules, in the order they should be displayed to users.
*
* @return array
*/
public function get_sort_order(): array {
// This module only supports manual completion.
return [];
}
}