mirrored from git://git.moodle.org/moodle.git
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MDL-68652 core_grades: Add a webservice to retrive only gradable users.
- Loading branch information
1 parent
76ff760
commit 7b91915
Showing
3 changed files
with
365 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
<?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_grades\external; | ||
|
||
defined('MOODLE_INTERNAL') || die; | ||
|
||
require_once($CFG->dirroot . '/grade/lib.php'); | ||
require_once($CFG->dirroot . '/user/externallib.php'); | ||
|
||
use coding_exception; | ||
use external_api; | ||
use core_user; | ||
use external_description; | ||
use external_function_parameters; | ||
use external_multiple_structure; | ||
use external_single_structure; | ||
use external_value; | ||
use external_warnings; | ||
use invalid_parameter_exception; | ||
use moodle_exception; | ||
use restricted_context_exception; | ||
use user_picture; | ||
|
||
/** | ||
* Get the gradable users in a course. | ||
* | ||
* @package core_grades | ||
* @copyright 2023 Ilya Tregubov <ilya.a.tregubov@gmail.com> | ||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | ||
* @since Moodle 4.1 | ||
*/ | ||
class get_gradable_users extends external_api { | ||
|
||
/** | ||
* Returns description of method parameters. | ||
* | ||
* @return external_function_parameters | ||
*/ | ||
public static function execute_parameters(): external_function_parameters { | ||
return new external_function_parameters ( | ||
[ | ||
'courseid' => new external_value(PARAM_INT, 'Course Id', VALUE_REQUIRED), | ||
'groupid' => new external_value(PARAM_INT, 'Group Id', VALUE_DEFAULT, 0), | ||
'onlyactive' => new external_value(PARAM_BOOL, 'Only active enrolment', VALUE_DEFAULT, false), | ||
] | ||
); | ||
} | ||
|
||
/** | ||
* Given a course ID find the gradable users within a group. | ||
* | ||
* @param int $courseid | ||
* @param int|null $groupid | ||
* @param bool $onlyactive | ||
* @return array Users and warnings. | ||
* @throws coding_exception | ||
* @throws invalid_parameter_exception | ||
* @throws moodle_exception | ||
* @throws restricted_context_exception | ||
*/ | ||
public static function execute(int $courseid, ?int $groupid = 0, bool $onlyactive = false): array { | ||
global $DB, $PAGE; | ||
|
||
$params = self::validate_parameters( | ||
self::execute_parameters(), | ||
[ | ||
'courseid' => $courseid, | ||
'groupid' => $groupid, | ||
'onlyactive' => $onlyactive, | ||
] | ||
); | ||
|
||
$warnings = []; | ||
$coursecontext = \context_course::instance($params['courseid']); | ||
parent::validate_context($coursecontext); | ||
|
||
require_capability('moodle/course:viewparticipants', $coursecontext); | ||
|
||
$course = $DB->get_record('course', ['id' => $params['courseid']]); | ||
// Create a graded_users_iterator because it will properly check the groups etc. | ||
$onlyactive = $onlyactive || !has_capability('moodle/course:viewsuspendedusers', $coursecontext); | ||
|
||
$gui = new \graded_users_iterator($course, null, $params['groupid']); | ||
$gui->require_active_enrolment($onlyactive); | ||
$gui->init(); | ||
|
||
// Flatten the users. | ||
$users = []; | ||
while ($user = $gui->next_user()) { | ||
$users[$user->user->id] = $user->user; | ||
} | ||
$gui->close(); | ||
|
||
$users = array_map(function ($user) use ($PAGE) { | ||
$user->fullname = fullname($user); | ||
$userpicture = new user_picture($user); | ||
$userpicture->size = 1; | ||
$user->profileimage = $userpicture->get_url($PAGE)->out(false); | ||
return $user; | ||
}, $users); | ||
sort($users); | ||
|
||
return [ | ||
'users' => $users, | ||
'warnings' => $warnings, | ||
]; | ||
} | ||
|
||
/** | ||
* Returns description of method result value. | ||
* | ||
* @return external_single_structure | ||
*/ | ||
public static function execute_returns(): external_single_structure { | ||
return new external_single_structure([ | ||
'users' => new external_multiple_structure(self::user_description()), | ||
'warnings' => new external_warnings(), | ||
]); | ||
} | ||
|
||
/** | ||
* Create user return value description. | ||
* | ||
* @return external_description | ||
*/ | ||
public static function user_description(): external_description { | ||
$userfields = [ | ||
'id' => new external_value(core_user::get_property_type('id'), 'ID of the user'), | ||
'profileimage' => new external_value( | ||
PARAM_URL, | ||
'The location of the users larger image', | ||
VALUE_OPTIONAL | ||
), | ||
'fullname' => new external_value(PARAM_TEXT, 'The full name of the user', VALUE_OPTIONAL), | ||
'firstname' => new external_value( | ||
core_user::get_property_type('firstname'), | ||
'The first name(s) of the user', | ||
VALUE_OPTIONAL), | ||
'lastname' => new external_value( | ||
core_user::get_property_type('lastname'), | ||
'The family name of the user', | ||
VALUE_OPTIONAL), | ||
]; | ||
return new external_single_structure($userfields); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
<?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_grades\external; | ||
|
||
use external_api; | ||
|
||
defined('MOODLE_INTERNAL') || die; | ||
|
||
global $CFG; | ||
|
||
require_once($CFG->dirroot . '/webservice/tests/helpers.php'); | ||
|
||
/** | ||
* Unit tests for the core_grades\external\get_gradable_users. | ||
* | ||
* @package core_grades | ||
* @category external | ||
* @copyright 2023 Ilya Tregubov <ilya.a.tregubov@gmail.com> | ||
* @covers \core_grades\external\get_gradable_users | ||
*/ | ||
class get_gradable_users_test extends \externallib_advanced_testcase { | ||
|
||
/** | ||
* Test the behaviour of get_gradable_users. | ||
* | ||
* @dataProvider execute_data | ||
* @param bool $onlyactiveenrol if we should only return active enrolments | ||
* @param bool $grouprestricted if we should only return users within a group | ||
* @param array $expected expected users | ||
*/ | ||
public function test_execute(bool $onlyactiveenrol, bool $grouprestricted, array $expected): void { | ||
global $DB; | ||
|
||
$this->resetAfterTest(); | ||
$this->setAdminUser(); | ||
$generator = $this->getDataGenerator(); | ||
$course = $generator->create_course(); | ||
|
||
// Create and enrol test users. | ||
$student1 = $generator->create_user(['username' => 'student1', 'firstname' => 'Apple', 'lastname' => 'Apricot']); | ||
$student2 = $generator->create_user(['username' => 'student2', 'firstname' => 'Banana', 'lastname' => 'Blueberry']); | ||
$student3 = $generator->create_user(['username' => 'student3', 'firstname' => 'Cherry', 'lastname' => 'Cranberry']); | ||
$student4 = $generator->create_user(['username' => 'student4', 'firstname' => 'Durian', 'lastname' => 'Dracontomelon']); | ||
$student5 = $generator->create_user(['username' => 'student5', 'firstname' => 'Eggplant', 'lastname' => 'Ensete']); | ||
|
||
$role = $DB->get_record('role', ['shortname' => 'student'], '*', MUST_EXIST); | ||
$generator->enrol_user($student1->id, $course->id, $role->id); | ||
$generator->enrol_user($student2->id, $course->id, $role->id); | ||
$generator->enrol_user($student3->id, $course->id, $role->id); | ||
$generator->enrol_user($student4->id, $course->id, $role->id); | ||
$generator->enrol_user($student5->id, $course->id, $role->id, 'manual', 0, 0, ENROL_USER_SUSPENDED); | ||
|
||
$group1 = $generator->create_group(['courseid' => $course->id]); | ||
$group2 = $generator->create_group(['courseid' => $course->id]); | ||
|
||
$generator->create_group_member(['userid' => $student1->id, 'groupid' => $group1->id]); | ||
$generator->create_group_member(['userid' => $student1->id, 'groupid' => $group2->id]); | ||
$generator->create_group_member(['userid' => $student2->id, 'groupid' => $group2->id]); | ||
$generator->create_group_member(['userid' => $student3->id, 'groupid' => $group2->id]); | ||
|
||
$DB->set_field('course', 'groupmode', SEPARATEGROUPS, ['id' => $course->id]); | ||
|
||
$teacher = $generator->create_user(['username' => 'teacher1']); | ||
$role = $DB->get_record('role', ['shortname' => 'editingteacher'], '*', MUST_EXIST); | ||
$generator->enrol_user($teacher->id, $course->id, $role->id); | ||
|
||
$generator->create_module('assign', ['course' => $course->id]); | ||
|
||
$groupid = $grouprestricted ? $group2->id : 0; | ||
$result = get_gradable_users::execute($course->id, $groupid, $onlyactiveenrol); | ||
$result = external_api::clean_returnvalue(get_gradable_users::execute_returns(), $result); | ||
|
||
$mapped = array_map(function($user) { | ||
return [ | ||
'fullname' => $user['fullname'], | ||
'firstname' => $user['firstname'], | ||
'lastname' => $user['lastname'], | ||
'profileimage' => $user['profileimage'], | ||
]; | ||
}, array_values($result['users'])); | ||
$this->assertEquals($expected, $mapped); | ||
} | ||
|
||
/** | ||
* Data provider for test_execute. | ||
* | ||
* @return array | ||
*/ | ||
public function execute_data(): array { | ||
return [ | ||
'All users' => [ | ||
false, | ||
false, | ||
[ | ||
[ | ||
'profileimage' => 'https://www.example.com/moodle/theme/image.php/_s/boost/core/1/u/f1', | ||
'firstname' => 'Apple', | ||
'lastname' => 'Apricot', | ||
'fullname' => 'Apple Apricot', | ||
], | ||
[ | ||
'profileimage' => 'https://www.example.com/moodle/theme/image.php/_s/boost/core/1/u/f1', | ||
'firstname' => 'Banana', | ||
'lastname' => 'Blueberry', | ||
'fullname' => 'Banana Blueberry', | ||
], | ||
[ | ||
'profileimage' => 'https://www.example.com/moodle/theme/image.php/_s/boost/core/1/u/f1', | ||
'firstname' => 'Cherry', | ||
'lastname' => 'Cranberry', | ||
'fullname' => 'Cherry Cranberry', | ||
], | ||
[ | ||
'profileimage' => 'https://www.example.com/moodle/theme/image.php/_s/boost/core/1/u/f1', | ||
'firstname' => 'Durian', | ||
'lastname' => 'Dracontomelon', | ||
'fullname' => 'Durian Dracontomelon', | ||
], | ||
[ | ||
'profileimage' => 'https://www.example.com/moodle/theme/image.php/_s/boost/core/1/u/f1', | ||
'firstname' => 'Eggplant', | ||
'lastname' => 'Ensete', | ||
'fullname' => 'Eggplant Ensete', | ||
], | ||
], | ||
], | ||
'Only active enrolment' => [ | ||
true, | ||
false, | ||
[ | ||
[ | ||
'profileimage' => 'https://www.example.com/moodle/theme/image.php/_s/boost/core/1/u/f1', | ||
'firstname' => 'Apple', | ||
'lastname' => 'Apricot', | ||
'fullname' => 'Apple Apricot', | ||
], | ||
[ | ||
'profileimage' => 'https://www.example.com/moodle/theme/image.php/_s/boost/core/1/u/f1', | ||
'firstname' => 'Banana', | ||
'lastname' => 'Blueberry', | ||
'fullname' => 'Banana Blueberry', | ||
], | ||
[ | ||
'profileimage' => 'https://www.example.com/moodle/theme/image.php/_s/boost/core/1/u/f1', | ||
'firstname' => 'Cherry', | ||
'lastname' => 'Cranberry', | ||
'fullname' => 'Cherry Cranberry', | ||
], | ||
[ | ||
'profileimage' => 'https://www.example.com/moodle/theme/image.php/_s/boost/core/1/u/f1', | ||
'firstname' => 'Durian', | ||
'lastname' => 'Dracontomelon', | ||
'fullname' => 'Durian Dracontomelon', | ||
], | ||
], | ||
], | ||
'Group restricted' => [ | ||
false, | ||
true, | ||
[ | ||
[ | ||
'profileimage' => 'https://www.example.com/moodle/theme/image.php/_s/boost/core/1/u/f1', | ||
'firstname' => 'Apple', | ||
'lastname' => 'Apricot', | ||
'fullname' => 'Apple Apricot', | ||
], | ||
[ | ||
'profileimage' => 'https://www.example.com/moodle/theme/image.php/_s/boost/core/1/u/f1', | ||
'firstname' => 'Banana', | ||
'lastname' => 'Blueberry', | ||
'fullname' => 'Banana Blueberry', | ||
], | ||
[ | ||
'profileimage' => 'https://www.example.com/moodle/theme/image.php/_s/boost/core/1/u/f1', | ||
'firstname' => 'Cherry', | ||
'lastname' => 'Cranberry', | ||
'fullname' => 'Cherry Cranberry', | ||
], | ||
], | ||
], | ||
]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters