mirror of
https://github.com/moodle/moodle.git
synced 2025-08-04 16:36:37 +02:00
MDL-71189 core_completion: Implementing custom completion sort ordering
This adds the requirement for activities supporting custom completion to specify the order all completion conditions should be displayed for that activity. It also implements the sorting that takes place.
This commit is contained in:
parent
c997fc7784
commit
f105612d7f
4 changed files with 158 additions and 3 deletions
|
@ -184,4 +184,11 @@ abstract class activity_custom_completion {
|
|||
* @return 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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue