first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
+36
View File
@@ -0,0 +1,36 @@
@core_enrol @core_group
Feature: Users can be added to multiple groups at once
In order to manage group membership effectively
As a user
I need to add another user to multiple groups
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
And the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | topics |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C1 | G1 |
| Group 2 | C1 | G2 |
| Group 3 | C1 | G3 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | editingteacher |
@javascript @skip_chrome_zerosize
Scenario: Adding a user to multiple groups
Given I log in as "teacher1"
And I am on "Course 1" course homepage
And I follow "Participants"
And I click on "Edit groups for \"Student 1\"" "link" in the "student1" "table_row"
And I open the autocomplete suggestions list in the "student1" "table_row"
And I click on "Group 1" item in the autocomplete list
And I click on "Group 2" item in the autocomplete list
And I press the escape key
And I click on "Save changes" "link" in the "student1" "table_row"
Then I should see "Group 1, Group 2"
+113
View File
@@ -0,0 +1,113 @@
<?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/>.
/**
* Enrolment steps definitions.
*
* @package core_enrol
* @category test
* @copyright 2013 David Monllaó
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
require_once(__DIR__ . '/../../../lib/behat/behat_base.php');
use Behat\Gherkin\Node\TableNode as TableNode;
/**
* Steps definitions for general enrolment actions.
*
* @package core_enrol
* @category test
* @copyright 2013 David Monllaó
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_enrol extends behat_base {
/**
* Add the specified enrolment method to the specified course filling the form with the provided data.
*
* @Given /^I add "(?P<enrolment_method_name_string>(?:[^"]|\\")*)" enrolment method in "(?P<course_identifier_string>(?:[^"]|\\")*)" with:$/
* @param string $enrolmethod The enrolment method being used
* @param string $courseidentifier The courseidentifier such as short name
* @param TableNode $table Enrolment details
*/
public function i_add_enrolment_method_for_with(string $enrolmethod, string $courseidentifier, TableNode $table): void {
$this->execute("behat_navigation::i_am_on_page_instance", [$courseidentifier, 'enrolment methods']);
// Select enrolment method.
$this->execute('behat_forms::i_select_from_the_singleselect',
array($this->escape($enrolmethod), get_string('addinstance', 'enrol'))
);
// Wait again, for page to reloaded.
$this->execute('behat_general::i_wait_to_be_redirected');
// Set form fields.
$this->execute("behat_forms::i_set_the_following_fields_to_these_values", $table);
// Ensure we get button in focus, before pressing button.
if ($this->running_javascript()) {
$this->execute('behat_general::i_press_named_key', ['', 'tab']);
}
// Save changes.
$this->execute("behat_forms::press_button", get_string('addinstance', 'enrol'));
}
/**
* Enrols the specified user in the current course without options.
*
* This is a simple step, to set enrolment options would be better to
* create a separate step as a TableNode will be required.
*
* @Given /^I enrol "(?P<user_fullname_string>(?:[^"]|\\")*)" user as "(?P<rolename_string>(?:[^"]|\\")*)"$/
* @param string $userfullname
* @param string $rolename
*/
public function i_enrol_user_as($userfullname, $rolename) {
// Navigate to enrolment page.
try {
$parentnodes = get_string('users', 'admin');
$this->execute("behat_navigation::i_navigate_to_in_current_page_administration",
array($parentnodes . ' > '. get_string('enrolledusers', 'enrol'))
);
} catch (Exception $e) {
$this->execute("behat_general::i_click_on", [get_string('participants'), 'link']);
}
$this->execute("behat_forms::press_button", get_string('enrolusers', 'enrol'));
if ($this->running_javascript()) {
$this->execute('behat_forms::i_set_the_field_to', array(get_string('assignrole', 'enrol_manual'), $rolename));
// We have a div here, not a tr.
$this->execute('behat_forms::i_set_the_field_to', array(get_string('selectusers', 'enrol_manual'), $userfullname));
$enrolusers = get_string('enrolusers', 'enrol_manual');
$this->execute('behat_general::i_click_on_in_the', [$enrolusers, 'button', $enrolusers, 'dialogue']);
} else {
$this->execute('behat_forms::i_set_the_field_to', array(get_string('assignrole', 'role'), $rolename));
$this->execute('behat_forms::i_set_the_field_to', array("addselect", $userfullname));
$this->execute("behat_forms::press_button", "add");
}
}
}
+26
View File
@@ -0,0 +1,26 @@
@enrol
Feature: User can be enrolled into a course
In order to let them participate in course activities
As an admin
I must be able to enrol users
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| student1 | Studie | One | student1@example.com |
And the following "courses" exist:
| fullname | shortname |
| Course 001 | C001 |
And I log in as "admin"
And I am on "Course 001" course homepage
Scenario: User can be enrolled without javascript
When I enrol "Studie One" user as "Student"
And I am on the "Course 001" "Enrolled users" page
Then I should see "Studie One"
@javascript
Scenario: User can be enrolled with javascript enrol element
When I enrol "Studie One" user as "Student"
And I am on the "Course 001" "Enrolled users" page
Then I should see "Studie One"
+36
View File
@@ -0,0 +1,36 @@
@core @core_enrol
Feature: Test role visibility for the participants page
In order to control access
As an admin
I need to control which roles can see each other
Background: Add a bunch of users
Given the following "courses" exist:
| fullname | shortname |
| Course 1 | C1 |
And the following "users" exist:
| username | firstname | lastname | email |
| learner1 | Learner | 1 | learner1@example.com |
| teacher1 | Teacher | 1 | teacher1@example.com |
| manager1 | Manager | 1 | manager1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| learner1 | C1 | student |
| teacher1 | C1 | editingteacher |
| manager1 | C1 | manager |
Scenario: Check the default roles are visible
Given I log in as "manager1"
And I am on the "Course 1" "enrolled users" page
Then "Learner 1" row "Roles" column of "participants" table should contain "Student"
And "Teacher 1" row "Roles" column of "participants" table should contain "Teacher"
And "Manager 1" row "Roles" column of "participants" table should contain "Manager"
And I should not see "No Roles" in the "table#participants" "css_element"
Scenario: Do not allow managers to view any roles but manager and check they are hidden
Given I log in as "teacher1"
And I am on the "Course 1" "enrolled users" page
Then "Learner 1" row "Roles" column of "participants" table should contain "Student"
And "Teacher 1" row "Roles" column of "participants" table should contain "Teacher"
And "Manager 1" row "Roles" column of "participants" table should not contain "Manager"
And "Manager 1" row "Roles" column of "participants" table should contain "No roles"
@@ -0,0 +1,647 @@
<?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_enrol;
use context_course;
use course_enrolment_manager;
use stdClass;
/**
* Test course_enrolment_manager parts.
*
* @package core_enrol
* @category test
* @copyright 2016 Ruslan Kabalin, Lancaster University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \course_enrolment_manager
*/
class course_enrolment_manager_test extends \advanced_testcase {
/**
* The course used in tests.
* @var \stdClass
*/
private $course = null;
/**
* List of users used in tests.
* @var array
*/
private $users = array();
/**
* List of groups used in tests.
* @var array
*/
private $groups = array();
/**
* Tests set up
*/
protected function setUp(): void {
global $CFG;
require_once($CFG->dirroot . '/enrol/locallib.php');
$this->setAdminUser();
$users = array();
$groups = array();
// Create the course and the users.
$course = $this->getDataGenerator()->create_course();
$users['user0'] = $this->getDataGenerator()->create_user(
array('username' => 'user0', 'firstname' => 'user0')); // A user without group.
$users['user1'] = $this->getDataGenerator()->create_user(
array('username' => 'user1', 'firstname' => 'user1')); // User for group 1.
$users['user21'] = $this->getDataGenerator()->create_user(
array('username' => 'user21', 'firstname' => 'user21')); // Two users for group 2.
$users['user22'] = $this->getDataGenerator()->create_user(
array('username' => 'user22', 'firstname' => 'user22'));
$users['userall'] = $this->getDataGenerator()->create_user(
array('username' => 'userall', 'firstname' => 'userall')); // A user in all groups.
$users['usertch'] = $this->getDataGenerator()->create_user(
array('username' => 'usertch', 'firstname' => 'usertch')); // A user with teacher role.
// Enrol the users in the course.
$this->getDataGenerator()->enrol_user($users['user0']->id, $course->id, 'student'); // Student.
$this->getDataGenerator()->enrol_user($users['user1']->id, $course->id, 'student'); // Student.
$this->getDataGenerator()->enrol_user($users['user21']->id, $course->id, 'student'); // Student.
$this->getDataGenerator()->enrol_user($users['user22']->id, $course->id, 'student', 'manual', 0, 0, ENROL_USER_SUSPENDED); // Suspended student.
$this->getDataGenerator()->enrol_user($users['userall']->id, $course->id, 'student'); // Student.
$this->getDataGenerator()->enrol_user($users['usertch']->id, $course->id, 'editingteacher'); // Teacher.
// Create 2 groups.
$groups['group1'] = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
$groups['group2'] = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
// Add the users to the groups.
$this->getDataGenerator()->create_group_member(
array('groupid' => $groups['group1']->id, 'userid' => $users['user1']->id));
$this->getDataGenerator()->create_group_member(
array('groupid' => $groups['group2']->id, 'userid' => $users['user21']->id));
$this->getDataGenerator()->create_group_member(
array('groupid' => $groups['group2']->id, 'userid' => $users['user22']->id));
$this->getDataGenerator()->create_group_member(
array('groupid' => $groups['group1']->id, 'userid' => $users['userall']->id));
$this->getDataGenerator()->create_group_member(
array('groupid' => $groups['group2']->id, 'userid' => $users['userall']->id));
// Make setup data accessible from test methods.
$this->course = $course;
$this->users = $users;
$this->groups = $groups;
// Make sample users and not enroll to any course.
$this->getDataGenerator()->create_user([
'username' => 'testapiuser1',
'firstname' => 'testapiuser 1'
]);
$this->getDataGenerator()->create_user([
'username' => 'testapiuser2',
'firstname' => 'testapiuser 2'
]);
$this->getDataGenerator()->create_user([
'username' => 'testapiuser3',
'firstname' => 'testapiuser 3'
]);
}
/**
* Verify get_total_users() returned number of users expected in every situation.
*/
public function test_get_total_users(): void {
global $PAGE;
$this->resetAfterTest();
// All users filtering.
$manager = new course_enrolment_manager($PAGE, $this->course);
$totalusers = $manager->get_total_users();
$this->assertEquals(6, $totalusers, 'All users must be returned when no filtering is applied.');
// Student role filtering.
$manager = new course_enrolment_manager($PAGE, $this->course, null, 5);
$totalusers = $manager->get_total_users();
$this->assertEquals(5, $totalusers, 'Only students must be returned when student role filtering is applied.');
// Teacher role filtering.
$manager = new course_enrolment_manager($PAGE, $this->course, null, 3);
$totalusers = $manager->get_total_users();
$this->assertEquals(1, $totalusers, 'Only teacher must be returned when teacher role filtering is applied.');
// Search user filtering.
$manager = new course_enrolment_manager($PAGE, $this->course, null, 0, 'userall');
$totalusers = $manager->get_total_users();
$this->assertEquals(1, $totalusers, 'Only searchable user must be returned when search filtering is applied.');
// Group 1 filtering.
$manager = new course_enrolment_manager($PAGE, $this->course, null, 0, '', $this->groups['group1']->id);
$totalusers = $manager->get_total_users();
$this->assertEquals(2, $totalusers, 'Only group members must be returned when group filtering is applied.');
// Group 2 filtering.
$manager = new course_enrolment_manager($PAGE, $this->course, null, 0, '', $this->groups['group2']->id);
$totalusers = $manager->get_total_users();
$this->assertEquals(3, $totalusers, 'Only group members must be returned when group filtering is applied.');
// 'No groups' filtering.
$manager = new course_enrolment_manager($PAGE, $this->course, null, 0, '', -1);
$totalusers = $manager->get_total_users();
$this->assertEquals(2, $totalusers, 'Only non-group members must be returned when \'no groups\' filtering is applied.');
// Active users filtering.
$manager = new course_enrolment_manager($PAGE, $this->course, null, 0, '', 0, ENROL_USER_ACTIVE);
$totalusers = $manager->get_total_users();
$this->assertEquals(5, $totalusers, 'Only active users must be returned when active users filtering is applied.');
// Suspended users filtering.
$manager = new course_enrolment_manager($PAGE, $this->course, null, 0, '', 0, ENROL_USER_SUSPENDED);
$totalusers = $manager->get_total_users();
$this->assertEquals(1, $totalusers, 'Only suspended users must be returned when suspended users filtering is applied.');
}
/**
* Verify get_users() returned number of users expected in every situation.
*/
public function test_get_users(): void {
global $PAGE;
$this->resetAfterTest();
// All users filtering.
$manager = new course_enrolment_manager($PAGE, $this->course);
$users = $manager->get_users('id');
$this->assertCount(6, $users, 'All users must be returned when no filtering is applied.');
$this->assertArrayHasKey($this->users['user0']->id, $users);
$this->assertArrayHasKey($this->users['user1']->id, $users);
$this->assertArrayHasKey($this->users['user21']->id, $users);
$this->assertArrayHasKey($this->users['user22']->id, $users);
$this->assertArrayHasKey($this->users['userall']->id, $users);
$this->assertArrayHasKey($this->users['usertch']->id, $users);
// Student role filtering.
$manager = new course_enrolment_manager($PAGE, $this->course, null, 5);
$users = $manager->get_users('id');
$this->assertCount(5, $users, 'Only students must be returned when student role filtering is applied.');
$this->assertArrayHasKey($this->users['user0']->id, $users);
$this->assertArrayHasKey($this->users['user1']->id, $users);
$this->assertArrayHasKey($this->users['user21']->id, $users);
$this->assertArrayHasKey($this->users['user22']->id, $users);
$this->assertArrayHasKey($this->users['userall']->id, $users);
// Teacher role filtering.
$manager = new course_enrolment_manager($PAGE, $this->course, null, 3);
$users = $manager->get_users('id');
$this->assertCount(1, $users, 'Only teacher must be returned when teacher role filtering is applied.');
$this->assertArrayHasKey($this->users['usertch']->id, $users);
// Search user filtering.
$manager = new course_enrolment_manager($PAGE, $this->course, null, 0, 'userall');
$users = $manager->get_users('id');
$this->assertCount(1, $users, 'Only searchable user must be returned when search filtering is applied.');
$this->assertArrayHasKey($this->users['userall']->id, $users);
// Group 1 filtering.
$manager = new course_enrolment_manager($PAGE, $this->course, null, 0, '', $this->groups['group1']->id);
$users = $manager->get_users('id');
$this->assertCount(2, $users, 'Only group members must be returned when group filtering is applied.');
$this->assertArrayHasKey($this->users['user1']->id, $users);
$this->assertArrayHasKey($this->users['userall']->id, $users);
// Group 2 filtering.
$manager = new course_enrolment_manager($PAGE, $this->course, null, 0, '', $this->groups['group2']->id);
$users = $manager->get_users('id');
$this->assertCount(3, $users, 'Only group members must be returned when group filtering is applied.');
$this->assertArrayHasKey($this->users['user21']->id, $users);
$this->assertArrayHasKey($this->users['user22']->id, $users);
$this->assertArrayHasKey($this->users['userall']->id, $users);
// 'No groups' filtering.
$manager = new course_enrolment_manager($PAGE, $this->course, null, 0, '', -1);
$users = $manager->get_users('id');
$this->assertCount(2, $users, 'Only non-group members must be returned when \'no groups\' filtering is applied.');
$this->assertArrayHasKey($this->users['user0']->id, $users);
$this->assertArrayHasKey($this->users['usertch']->id, $users);
// Active users filtering.
$manager = new course_enrolment_manager($PAGE, $this->course, null, 0, '', 0, ENROL_USER_ACTIVE);
$users = $manager->get_users('id');
$this->assertCount(5, $users, 'Only active users must be returned when active users filtering is applied.');
$this->assertArrayHasKey($this->users['user0']->id, $users);
$this->assertArrayHasKey($this->users['user1']->id, $users);
$this->assertArrayHasKey($this->users['user21']->id, $users);
$this->assertArrayHasKey($this->users['userall']->id, $users);
$this->assertArrayHasKey($this->users['usertch']->id, $users);
// Suspended users filtering.
$manager = new course_enrolment_manager($PAGE, $this->course, null, 0, '', 0, ENROL_USER_SUSPENDED);
$users = $manager->get_users('id');
$this->assertCount(1, $users, 'Only suspended users must be returned when suspended users filtering is applied.');
$this->assertArrayHasKey($this->users['user22']->id, $users);
}
/**
* Sets up a custom profile field and the showuseridentity option, and creates a test user
* with suitable values set.
*
* @return \stdClass Test user
*/
protected function setup_for_user_identity_tests(): \stdClass {
// Configure extra fields to include one normal user field and one profile field, and
// set the values for a new test user.
$generator = $this->getDataGenerator();
$generator->create_custom_profile_field(['datatype' => 'text',
'shortname' => 'researchtopic', 'name' => 'Research topic']);
set_config('showuseridentity', 'email,department,profile_field_researchtopic');
return $generator->create_user(
['username' => 'newuser', 'department' => 'Amphibian studies', 'email' => 'x@x.org',
'profile_field_researchtopic' => 'Frogs', 'imagealt' => 'Smart suit']);
}
/**
* Checks that the get_users function returns the correct user fields.
*/
public function test_get_users_fields(): void {
global $PAGE;
$this->resetAfterTest();
$newuser = $this->setup_for_user_identity_tests();
// Enrol the user in test course.
$this->getDataGenerator()->enrol_user($newuser->id, $this->course->id, 'student');
// Get all users and fish out the one we're interested in.
$manager = new course_enrolment_manager($PAGE, $this->course);
$users = $manager->get_users('id');
$user = $users[$newuser->id];
// Should include core required fields...
$this->assertEquals($newuser->id, $user->id);
// ...And the ones specified in showuseridentity (one of which is also needed for user pics).
$this->assertEquals('Amphibian studies', $user->department);
$this->assertEquals('Frogs', $user->profile_field_researchtopic);
$this->assertEquals('x@x.org', $user->email);
// And the ones necessary for user pics.
$this->assertEquals('Smart suit', $user->imagealt);
// But not some random other field like city.
$this->assertObjectNotHasProperty('city', $user);
}
/**
* Checks that the get_other_users function returns the correct user fields.
*/
public function test_get_other_users_fields(): void {
global $PAGE, $DB;
$this->resetAfterTest();
// Configure extra fields to include one normal user field and one profile field, and
// set the values for a new test user.
$newuser = $this->setup_for_user_identity_tests();
$context = \context_course::instance($this->course->id);
role_assign($DB->get_field('role', 'id', ['shortname' => 'manager']), $newuser->id, $context->id);
// Get the 'other' (role but not enrolled) users and fish out the one we're interested in.
$manager = new course_enrolment_manager($PAGE, $this->course);
$users = array_values($manager->get_other_users('id'));
$user = $users[0];
// Should include core required fields...
$this->assertEquals($newuser->id, $user->id);
// ...And the ones specified in showuseridentity (one of which is also needed for user pics).
$this->assertEquals('Amphibian studies', $user->department);
$this->assertEquals('Frogs', $user->profile_field_researchtopic);
$this->assertEquals('x@x.org', $user->email);
// And the ones necessary for user pics.
$this->assertEquals('Smart suit', $user->imagealt);
// But not some random other field like city.
$this->assertObjectNotHasProperty('city', $user);
}
/**
* Checks that the get_potential_users function returns the correct user fields.
*/
public function test_get_potential_users_fields(): void {
global $PAGE;
$this->resetAfterTest();
// Configure extra fields to include one normal user field and one profile field, and
// set the values for a new test user.
$newuser = $this->setup_for_user_identity_tests();
// Get the 'potential' (not enrolled) users and fish out the one we're interested in.
$manager = new course_enrolment_manager($PAGE, $this->course);
foreach (enrol_get_instances($this->course->id, true) as $enrolinstance) {
if ($enrolinstance->enrol === 'manual') {
$enrolid = $enrolinstance->id;
}
}
$users = array_values($manager->get_potential_users($enrolid));
$user = $users[0][$newuser->id];
// Should include core required fields...
$this->assertEquals($newuser->id, $user->id);
// ...And the ones specified in showuseridentity (one of which is also needed for user pics).
$this->assertEquals('Amphibian studies', $user->department);
$this->assertEquals('Frogs', $user->profile_field_researchtopic);
$this->assertEquals('x@x.org', $user->email);
// And the ones necessary for user pics.
$this->assertEquals('Smart suit', $user->imagealt);
// But not some random other field like city.
$this->assertObjectNotHasProperty('city', $user);
}
/**
* Test get_potential_users without returnexactcount param.
*
* @dataProvider search_users_provider
*
* @param int $perpage Number of users per page.
* @param bool $returnexactcount Return the exact count or not.
* @param int $expectedusers Expected number of users return.
* @param int $expectedtotalusers Expected total of users in database.
* @param bool $expectedmoreusers Expected for more users return or not.
*/
public function test_get_potential_users($perpage, $returnexactcount, $expectedusers, $expectedtotalusers, $expectedmoreusers): void {
global $DB, $PAGE;
$this->resetAfterTest();
$this->setAdminUser();
$enrol = $DB->get_record('enrol', array('courseid' => $this->course->id, 'enrol' => 'manual'));
$manager = new course_enrolment_manager($PAGE, $this->course);
$users = $manager->get_potential_users($enrol->id,
'testapiuser',
true,
0,
$perpage,
0,
$returnexactcount);
$this->assertCount($expectedusers, $users['users']);
$this->assertEquals($expectedmoreusers, $users['moreusers']);
if ($returnexactcount) {
$this->assertArrayHasKey('totalusers', $users);
$this->assertEquals($expectedtotalusers, $users['totalusers']);
} else {
$this->assertArrayNotHasKey('totalusers', $users);
}
}
/**
* Tests get_potential_users when the search term includes a custom field.
*/
public function test_get_potential_users_search_fields(): void {
global $PAGE;
$this->resetAfterTest();
// Configure extra fields to include one normal user field and one profile field, and
// set the values for a new test user.
$newuser = $this->setup_for_user_identity_tests();
// Set up the enrolment manager.
$manager = new course_enrolment_manager($PAGE, $this->course);
foreach (enrol_get_instances($this->course->id, true) as $enrolinstance) {
if ($enrolinstance->enrol === 'manual') {
$enrolid = $enrolinstance->id;
}
}
// Search for text included in a 'standard' (user table) identity field.
$users = array_values($manager->get_potential_users($enrolid, 'Amphibian studies'));
$this->assertEquals([$newuser->id], array_keys($users[0]));
// And for text included in a custom field.
$users = array_values($manager->get_potential_users($enrolid, 'Frogs'));
$this->assertEquals([$newuser->id], array_keys($users[0]));
// With partial matches.
$users = array_values($manager->get_potential_users($enrolid, 'Amphibian'));
$this->assertEquals([$newuser->id], array_keys($users[0]));
$users = array_values($manager->get_potential_users($enrolid, 'Fro'));
$this->assertEquals([$newuser->id], array_keys($users[0]));
// With partial in-the-middle matches.
$users = array_values($manager->get_potential_users($enrolid, 'phibian'));
$this->assertEquals([], array_keys($users[0]));
$users = array_values($manager->get_potential_users($enrolid, 'rog'));
$this->assertEquals([], array_keys($users[0]));
$users = array_values($manager->get_potential_users($enrolid, 'phibian', true));
$this->assertEquals([$newuser->id], array_keys($users[0]));
$users = array_values($manager->get_potential_users($enrolid, 'rog', true));
$this->assertEquals([$newuser->id], array_keys($users[0]));
// If the current user doesn't have access to identity fields then these searches won't work.
$this->setUser($this->getDataGenerator()->create_user());
$users = array_values($manager->get_potential_users($enrolid, 'Amphibian studies'));
$this->assertEquals([], array_keys($users[0]));
$users = array_values($manager->get_potential_users($enrolid, 'Frogs'));
$this->assertEquals([], array_keys($users[0]));
// Search for username field (there is special handling for this one field).
set_config('showuseridentity', 'username');
$this->setAdminUser();
$users = array_values($manager->get_potential_users($enrolid, 'newuse'));
$this->assertEquals([$newuser->id], array_keys($users[0]));
}
/**
* Test search_other_users with returnexactcount param.
*
* @dataProvider search_users_provider
*
* @param int $perpage Number of users per page.
* @param bool $returnexactcount Return the exact count or not.
* @param int $expectedusers Expected number of users return.
* @param int $expectedtotalusers Expected total of users in database.
* @param bool $expectedmoreusers Expected for more users return or not.
*/
public function test_search_other_users($perpage, $returnexactcount, $expectedusers, $expectedtotalusers, $expectedmoreusers): void {
global $PAGE;
$this->resetAfterTest();
$this->setAdminUser();
$manager = new course_enrolment_manager($PAGE, $this->course);
$users = $manager->search_other_users(
'testapiuser',
true,
0,
$perpage,
$returnexactcount);
$this->assertCount($expectedusers, $users['users']);
$this->assertEquals($expectedmoreusers, $users['moreusers']);
if ($returnexactcount) {
$this->assertArrayHasKey('totalusers', $users);
$this->assertEquals($expectedtotalusers, $users['totalusers']);
} else {
$this->assertArrayNotHasKey('totalusers', $users);
}
}
/**
* Test case for test_get_potential_users, test_search_other_users and test_search_users tests.
*
* @return array Dataset
*/
public function search_users_provider() {
return [
[2, false, 2, 3, true],
[5, false, 3, 3, false],
[2, true, 2, 3, true],
[5, true, 3, 3, false]
];
}
/**
* Test search_users function.
*
* @dataProvider search_users_provider
*
* @param int $perpage Number of users per page.
* @param bool $returnexactcount Return the exact count or not.
* @param int $expectedusers Expected number of users return.
* @param int $expectedtotalusers Expected total of users in database.
* @param bool $expectedmoreusers Expected for more users return or not.
*/
public function test_search_users($perpage, $returnexactcount, $expectedusers, $expectedtotalusers, $expectedmoreusers): void {
global $PAGE;
$this->resetAfterTest();
$this->getDataGenerator()->create_and_enrol($this->course, 'student', ['firstname' => 'sutest 1']);
$this->getDataGenerator()->create_and_enrol($this->course, 'student', ['firstname' => 'sutest 2']);
$this->getDataGenerator()->create_and_enrol($this->course, 'student', ['firstname' => 'sutest 3']);
$manager = new course_enrolment_manager($PAGE, $this->course);
$users = $manager->search_users(
'sutest',
true,
0,
$perpage,
$returnexactcount
);
$this->assertCount($expectedusers, $users['users']);
$this->assertEquals($expectedmoreusers, $users['moreusers']);
if ($returnexactcount) {
$this->assertArrayHasKey('totalusers', $users);
$this->assertEquals($expectedtotalusers, $users['totalusers']);
} else {
$this->assertArrayNotHasKey('totalusers', $users);
}
}
/**
* Test that search_users observes course group mode restrictions correctly
*/
public function test_search_users_course_groupmode(): void {
global $DB, $PAGE;
$this->resetAfterTest();
// Create the forum.
$record = new stdClass();
$record->introformat = FORMAT_HTML;
$record->course = $this->course->id;
$forum = self::getDataGenerator()->create_module('forum', $record, ['groupmode' => SEPARATEGROUPS]);
$contextid = $DB->get_field('context', 'id', ['instanceid' => $forum->cmid, 'contextlevel' => CONTEXT_MODULE]);
$teacher = $this->getDataGenerator()->create_and_enrol($this->course, 'teacher');
$this->getDataGenerator()->create_group_member(['groupid' => $this->groups['group1']->id, 'userid' => $teacher->id]);
$this->setUser($teacher);
$courseusers = (new course_enrolment_manager($PAGE, $this->course))->search_users('', false, 0, 25, true);
$this->assertEqualsCanonicalizing([
$teacher->username,
$this->users['user0']->username,
$this->users['user1']->username,
$this->users['user21']->username,
$this->users['user22']->username,
$this->users['userall']->username,
$this->users['usertch']->username,
], array_column($courseusers['users'], 'username'));
$this->assertEquals(7, $courseusers['totalusers']);
$forumusers = (new course_enrolment_manager($PAGE, $this->course))->search_users('', false, 0, 25, true, $contextid);
$this->assertEqualsCanonicalizing([
$teacher->username,
$this->users['user1']->username,
$this->users['userall']->username,
], array_column($forumusers['users'], 'username'));
$this->assertEquals(3, $forumusers['totalusers']);
// Switch course to separate groups and forum to no group.
$this->course->groupmode = SEPARATEGROUPS;
update_course($this->course);
set_coursemodule_groupmode($forum->cmid, NOGROUPS);
$courseusers = (new course_enrolment_manager($PAGE, $this->course))->search_users('', false, 0, 25, true);
$this->assertEqualsCanonicalizing([
$teacher->username,
$this->users['user1']->username,
$this->users['userall']->username,
], array_column($courseusers['users'], 'username'));
$this->assertEquals(3, $courseusers['totalusers']);
$forumusers = (new course_enrolment_manager($PAGE, $this->course))->search_users('', false, 0, 25, true, $contextid);
$this->assertEqualsCanonicalizing([
$teacher->username,
$this->users['user0']->username,
$this->users['user1']->username,
$this->users['user21']->username,
$this->users['user22']->username,
$this->users['userall']->username,
$this->users['usertch']->username,
], array_column($forumusers['users'], 'username'));
$this->assertEquals(7, $forumusers['totalusers']);
set_coursemodule_groupmode($forum->cmid, SEPARATEGROUPS);
// Allow teacher to access all groups.
$roleid = $DB->get_field('role', 'id', ['shortname' => 'teacher']);
assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $roleid, context_course::instance($this->course->id)->id);
$courseusers = (new course_enrolment_manager($PAGE, $this->course))->search_users('', false, 0, 25, true);
$this->assertEqualsCanonicalizing([
$teacher->username,
$this->users['user0']->username,
$this->users['user1']->username,
$this->users['user21']->username,
$this->users['user22']->username,
$this->users['userall']->username,
$this->users['usertch']->username,
], array_column($courseusers['users'], 'username'));
$this->assertEquals(7, $courseusers['totalusers']);
$forumusers = (new course_enrolment_manager($PAGE, $this->course))->search_users('', false, 0, 25, true, $contextid);
$this->assertEqualsCanonicalizing([
$teacher->username,
$this->users['user0']->username,
$this->users['user1']->username,
$this->users['user21']->username,
$this->users['user22']->username,
$this->users['userall']->username,
$this->users['usertch']->username,
], array_column($forumusers['users'], 'username'));
$this->assertEquals(7, $forumusers['totalusers']);
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+272
View File
@@ -0,0 +1,272 @@
<?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/>.
/**
* Privacy test for the core_enrol implementation of the privacy API.
*
* @package core_enrol
* @category test
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_enrol\privacy;
defined('MOODLE_INTERNAL') || die();
use core_enrol\privacy\provider;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\writer;
use core_privacy\tests\provider_testcase;
use core_privacy\local\request\transform;
use core_privacy\local\request\approved_userlist;
/**
* Privacy test for the core_enrol.
*
* @package core_enrol
* @category test
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider_test extends provider_testcase {
/**
* Check that a course context is returned if there is any user data for this user.
*/
public function test_get_contexts_for_userid(): void {
$this->resetAfterTest();
$user1 = $this->getDataGenerator()->create_user();
$course1 = $this->getDataGenerator()->create_course();
$this->assertEmpty(provider::get_contexts_for_userid($user1->id));
// Enrol user into courses and check contextlist.
$this->getDataGenerator()->enrol_user($user1->id, $course1->id, null, 'manual');
$contextlist = provider::get_contexts_for_userid($user1->id);
// Check that we only get back two context.
$this->assertCount(1, $contextlist);
// Check that the context is returned is the expected.
$coursecontext1 = \context_course::instance($course1->id);
$this->assertEquals($coursecontext1->id, $contextlist->get_contextids()[0]);
}
/**
* Test that user data is exported correctly.
*/
public function test_export_user_data(): void {
global $DB;
$this->resetAfterTest();
$user1 = $this->getDataGenerator()->create_user();
$course1 = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$this->getDataGenerator()->enrol_user($user1->id, $course1->id, null, 'manual');
$this->getDataGenerator()->enrol_user($user1->id, $course1->id, null, 'self');
$this->getDataGenerator()->enrol_user($user1->id, $course2->id, null, 'manual');
$subcontexts = [
get_string('privacy:metadata:user_enrolments', 'core_enrol')
];
$coursecontext1 = \context_course::instance($course1->id);
$coursecontext2 = \context_course::instance($course2->id);
$this->setUser($user1);
$writer = writer::with_context($coursecontext1);
$this->assertFalse($writer->has_any_data());
$this->export_context_data_for_user($user1->id, $coursecontext1, 'core_enrol');
$data = $writer->get_related_data($subcontexts);
$this->assertCount(2, (array)$data);
$sql = "SELECT ue.id,
ue.status,
ue.timestart,
ue.timeend,
ue.timecreated,
ue.timemodified
FROM {user_enrolments} ue
JOIN {enrol} e
ON e.id = ue.enrolid
AND e.courseid = :courseid
WHERE ue.userid = :userid";
$enrolmentcouse2 = $DB->get_record_sql($sql, array('userid' => $user1->id, 'courseid' => $course2->id));
writer::reset();
$writer = writer::with_context($coursecontext2);
$this->export_context_data_for_user($user1->id, $coursecontext2, 'core_enrol');
$data = (array)$writer->get_related_data($subcontexts, 'manual');
$this->assertEquals($enrolmentcouse2->status, reset($data)->status);
$this->assertEquals(transform::datetime($enrolmentcouse2->timestart), reset($data)->timestart);
$this->assertEquals(transform::datetime($enrolmentcouse2->timeend), reset($data)->timeend);
$this->assertEquals(transform::datetime($enrolmentcouse2->timecreated), reset($data)->timecreated);
$this->assertEquals(transform::datetime($enrolmentcouse2->timemodified), reset($data)->timemodified);
}
/**
* Test deleting all user data for a specific context.
*/
public function test_delete_data_for_all_users_in_context(): void {
global $DB;
$this->resetAfterTest();
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$user3 = $this->getDataGenerator()->create_user();
$course1 = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$this->getDataGenerator()->enrol_user($user1->id, $course1->id, null, 'manual');
$this->getDataGenerator()->enrol_user($user2->id, $course1->id, null, 'manual');
$this->getDataGenerator()->enrol_user($user3->id, $course1->id, null, 'manual');
$this->getDataGenerator()->enrol_user($user1->id, $course2->id, null, 'manual');
$this->getDataGenerator()->enrol_user($user2->id, $course2->id, null, 'manual');
// Get all user enrolments.
$userenrolments = $DB->get_records('user_enrolments', array());
$this->assertCount(5, $userenrolments);
// Get all user enrolments match with course1.
$sql = "SELECT ue.id
FROM {user_enrolments} ue
JOIN {enrol} e
ON e.id = ue.enrolid
AND e.courseid = :courseid";
$userenrolments = $DB->get_records_sql($sql, array('courseid' => $course1->id));
$this->assertCount(3, $userenrolments);
// Delete everything for the first course context.
$coursecontext1 = \context_course::instance($course1->id);
provider::delete_data_for_all_users_in_context($coursecontext1);
// Get all user enrolments match with this course contest.
$userenrolments = $DB->get_records_sql($sql, array('courseid' => $course1->id));
$this->assertCount(0, $userenrolments);
// Get all user enrolments.
$userenrolments = $DB->get_records('user_enrolments', array());
$this->assertCount(2, $userenrolments);
}
/**
* This should work identical to the above test.
*/
public function test_delete_data_for_user(): void {
global $DB;
$this->resetAfterTest();
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$user3 = $this->getDataGenerator()->create_user();
$course1 = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$this->getDataGenerator()->enrol_user($user1->id, $course1->id, null, 'manual');
$this->getDataGenerator()->enrol_user($user2->id, $course1->id, null, 'manual');
$this->getDataGenerator()->enrol_user($user3->id, $course1->id, null, 'manual');
$this->getDataGenerator()->enrol_user($user1->id, $course2->id, null, 'manual');
// Get all user enrolments.
$userenrolments = $DB->get_records('user_enrolments', array());
$this->assertCount(4, $userenrolments);
// Get all user enrolments match with user1.
$userenrolments = $DB->get_records('user_enrolments', array('userid' => $user1->id));
$this->assertCount(2, $userenrolments);
// Delete everything for the user1 in the context course 1.
$coursecontext1 = \context_course::instance($course1->id);
$approvedlist = new approved_contextlist($user1, 'core_enrol', [$coursecontext1->id]);
provider::delete_data_for_user($approvedlist);
// Get all user enrolments match with user.
$userenrolments = $DB->get_records('user_enrolments', ['userid' => $user1->id]);
$this->assertCount(1, $userenrolments);
// Get all user enrolments accounts.
$userenrolments = $DB->get_records('user_enrolments', array());
$this->assertCount(3, $userenrolments);
}
/**
* Test that only users within a course context are fetched.
*/
public function test_get_users_in_context(): void {
$this->resetAfterTest();
$component = 'core_enrol';
$user = $this->getDataGenerator()->create_user();
$usercontext = \context_user::instance($user->id);
$course = $this->getDataGenerator()->create_course();
$coursecontext = \context_course::instance($course->id);
$userlist1 = new \core_privacy\local\request\userlist($coursecontext, $component);
provider::get_users_in_context($userlist1);
$this->assertCount(0, $userlist1);
// Enrol user into course.
$this->getDataGenerator()->enrol_user($user->id, $course->id, null, 'manual');
// The list of users within the course context should contain user.
provider::get_users_in_context($userlist1);
$this->assertCount(1, $userlist1);
$expected = [$user->id];
$actual = $userlist1->get_userids();
$this->assertEquals($expected, $actual);
// The list of users within the user context should be empty.
$userlist2 = new \core_privacy\local\request\userlist($usercontext, $component);
provider::get_users_in_context($userlist2);
$this->assertCount(0, $userlist2);
}
/**
* Test that data for users in approved userlist is deleted.
*/
public function test_delete_data_for_users(): void {
$this->resetAfterTest();
$component = 'core_enrol';
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$user3 = $this->getDataGenerator()->create_user();
$course1 = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$coursecontext1 = \context_course::instance($course1->id);
$coursecontext2 = \context_course::instance($course2->id);
$systemcontext = \context_system::instance();
// Enrol user1 into course1.
$this->getDataGenerator()->enrol_user($user1->id, $course1->id, null, 'manual');
// Enrol user2 into course1.
$this->getDataGenerator()->enrol_user($user2->id, $course1->id, null, 'manual');
// Enrol user3 into course2.
$this->getDataGenerator()->enrol_user($user3->id, $course2->id, null, 'manual');
$userlist1 = new \core_privacy\local\request\userlist($coursecontext1, $component);
provider::get_users_in_context($userlist1);
$this->assertCount(2, $userlist1);
$userlist2 = new \core_privacy\local\request\userlist($coursecontext2, $component);
provider::get_users_in_context($userlist2);
$this->assertCount(1, $userlist2);
// Convert $userlist1 into an approved_contextlist.
$approvedlist1 = new approved_userlist($coursecontext1, $component, $userlist1->get_userids());
// Delete using delete_data_for_user.
provider::delete_data_for_users($approvedlist1);
// Re-fetch users in coursecontext1.
$userlist1 = new \core_privacy\local\request\userlist($coursecontext1, $component);
provider::get_users_in_context($userlist1);
// The user data in coursecontext1 should be deleted.
$this->assertCount(0, $userlist1);
// Re-fetch users in coursecontext2.
$userlist2 = new \core_privacy\local\request\userlist($coursecontext2, $component);
provider::get_users_in_context($userlist2);
// The user data in coursecontext2 should be still present.
$this->assertCount(1, $userlist2);
// Convert $userlist2 into an approved_contextlist in the system context.
$approvedlist2 = new approved_userlist($systemcontext, $component, $userlist2->get_userids());
// Delete using delete_data_for_user.
provider::delete_data_for_users($approvedlist2);
// Re-fetch users in coursecontext1.
$userlist2 = new \core_privacy\local\request\userlist($coursecontext2, $component);
provider::get_users_in_context($userlist2);
// The user data in systemcontext should not be deleted.
$this->assertCount(1, $userlist2);
}
}
+147
View File
@@ -0,0 +1,147 @@
<?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_enrol;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
require_once($CFG->dirroot . '/enrol/externallib.php');
/**
* Role external PHPunit tests
*
* @package core_enrol
* @category test
* @copyright 2012 Jerome Mouneyrac
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 2.4
*/
class role_external_test extends \externallib_advanced_testcase {
/**
* Tests set up
*/
protected function setUp(): void {
global $CFG;
require_once($CFG->dirroot . '/enrol/externallib.php');
}
/**
* Test assign_roles
*/
public function test_assign_roles(): void {
global $USER;
$this->resetAfterTest(true);
$course = self::getDataGenerator()->create_course();
// Set the required capabilities by the external function.
$context = \context_course::instance($course->id);
$roleid = $this->assignUserCapability('moodle/role:assign', $context->id);
$this->assignUserCapability('moodle/course:view', $context->id, $roleid);
// Add manager role to $USER.
// So $USER is allowed to assign 'manager', 'editingteacher', 'teacher' and 'student'.
role_assign(1, $USER->id, \context_system::instance()->id);
// Check the teacher role has not been assigned to $USER.
$users = get_role_users(3, $context);
$this->assertEquals(count($users), 0);
// Call the external function. Assign teacher role to $USER with contextid.
\core_role_external::assign_roles(array(
array('roleid' => 3, 'userid' => $USER->id, 'contextid' => $context->id)));
// Check the role has been assigned.
$users = get_role_users(3, $context);
$this->assertEquals(count($users), 1);
// Unassign role.
role_unassign(3, $USER->id, $context->id);
$users = get_role_users(3, $context);
$this->assertEquals(count($users), 0);
// Call the external function. Assign teacher role to $USER.
\core_role_external::assign_roles(array(
array('roleid' => 3, 'userid' => $USER->id, 'contextlevel' => "course", 'instanceid' => $course->id)));
$users = get_role_users(3, $context);
$this->assertEquals(count($users), 1);
// Call without required capability.
$this->unassignUserCapability('moodle/role:assign', $context->id, $roleid);
$this->expectException('moodle_exception');
$categories = \core_role_external::assign_roles(
array('roleid' => 3, 'userid' => $USER->id, 'contextid' => $context->id));
}
/**
* Test unassign_roles
*/
public function test_unassign_roles(): void {
global $USER;
$this->resetAfterTest(true);
$course = self::getDataGenerator()->create_course();
// Set the required capabilities by the external function.
$context = \context_course::instance($course->id);
$roleid = $this->assignUserCapability('moodle/role:assign', $context->id);
$this->assignUserCapability('moodle/course:view', $context->id, $roleid);
// Add manager role to $USER.
// So $USER is allowed to assign 'manager', 'editingteacher', 'teacher' and 'student'.
role_assign(1, $USER->id, \context_system::instance()->id);
// Add teacher role to $USER on course context.
role_assign(3, $USER->id, $context->id);
// Check the teacher role has been assigned to $USER on course context.
$users = get_role_users(3, $context);
$this->assertEquals(count($users), 1);
// Call the external function. Unassign teacher role using contextid.
\core_role_external::unassign_roles(array(
array('roleid' => 3, 'userid' => $USER->id, 'contextid' => $context->id)));
// Check the role has been unassigned on course context.
$users = get_role_users(3, $context);
$this->assertEquals(count($users), 0);
// Add teacher role to $USER on course context.
role_assign(3, $USER->id, $context->id);
$users = get_role_users(3, $context);
$this->assertEquals(count($users), 1);
// Call the external function. Unassign teacher role using context level and instanceid.
\core_role_external::unassign_roles(array(
array('roleid' => 3, 'userid' => $USER->id, 'contextlevel' => "course", 'instanceid' => $course->id)));
// Check the role has been unassigned on course context.
$users = get_role_users(3, $context);
$this->assertEquals(count($users), 0);
// Call without required capability.
$this->unassignUserCapability('moodle/role:assign', $context->id, $roleid);
$this->expectException('moodle_exception');
$categories = \core_role_external::unassign_roles(
array('roleid' => 3, 'userid' => $USER->id, 'contextid' => $context->id));
}
}