<?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 tool_lp;
use core_competency\api;
< use core_competency\invalid_persistent_exception;
< use core_competency\plan;
< use core_competency\related_competency;
< use core_competency\user_competency;
< use core_competency\user_competency_plan;
< use core_competency\plan_competency;
< use core_competency\template;
< use core_competency\template_competency;
< use core_competency\course_competency_settings;
> use core_external\external_api;
use externallib_advanced_testcase;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
/**
* External learning plans webservice API tests.
*
* @package tool_lp
* @copyright 2015 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class externallib_test extends externallib_advanced_testcase {
/** @var \stdClass $creator User with enough permissions to create insystem context. */
protected $creator = null;
/** @var \stdClass $catcreator User with enough permissions to create incategory context. */
protected $catcreator = null;
/** @var \stdClass $category Category */
protected $category = null;
/** @var \stdClass $category Category */
protected $othercategory = null;
/** @var \stdClass $user User with enough permissions to view insystem context */
protected $user = null;
/** @var \stdClass $catuser User with enough permissions to view incategory context */
protected $catuser = null;
/** @var int Creator role id */
protected $creatorrole = null;
/** @var int User role id */
protected $userrole = null;
/**
* Setup function- we will create a course and add an assign instance to it.
*/
protected function setUp(): void {
global $DB, $CFG;
$this->resetAfterTest(true);
// Create some users.
$creator = $this->getDataGenerator()->create_user();
$user = $this->getDataGenerator()->create_user();
$catuser = $this->getDataGenerator()->create_user();
$catcreator = $this->getDataGenerator()->create_user();
$category = $this->getDataGenerator()->create_category();
$othercategory = $this->getDataGenerator()->create_category();
$syscontext = \context_system::instance();
$catcontext = \context_coursecat::instance($category->id);
// Fetching default authenticated user role.
$authrole = $DB->get_record('role', array('id' => $CFG->defaultuserroleid));
// Reset all default authenticated users permissions.
unassign_capability('moodle/competency:competencygrade', $authrole->id);
unassign_capability('moodle/competency:competencymanage', $authrole->id);
unassign_capability('moodle/competency:competencyview', $authrole->id);
unassign_capability('moodle/competency:planmanage', $authrole->id);
unassign_capability('moodle/competency:planmanagedraft', $authrole->id);
unassign_capability('moodle/competency:planmanageown', $authrole->id);
unassign_capability('moodle/competency:planview', $authrole->id);
unassign_capability('moodle/competency:planviewdraft', $authrole->id);
unassign_capability('moodle/competency:planviewown', $authrole->id);
unassign_capability('moodle/competency:planviewowndraft', $authrole->id);
unassign_capability('moodle/competency:templatemanage', $authrole->id);
unassign_capability('moodle/competency:templateview', $authrole->id);
unassign_capability('moodle/cohort:manage', $authrole->id);
unassign_capability('moodle/competency:coursecompetencyconfigure', $authrole->id);
// Creating specific roles.
$this->creatorrole = create_role('Creator role', 'lpcreatorrole', 'learning plan creator role description');
$this->userrole = create_role('User role', 'lpuserrole', 'learning plan user role description');
assign_capability('moodle/competency:competencymanage', CAP_ALLOW, $this->creatorrole, $syscontext->id);
assign_capability('moodle/competency:coursecompetencyconfigure', CAP_ALLOW, $this->creatorrole, $syscontext->id);
assign_capability('moodle/competency:planmanage', CAP_ALLOW, $this->creatorrole, $syscontext->id);
assign_capability('moodle/competency:planmanagedraft', CAP_ALLOW, $this->creatorrole, $syscontext->id);
assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $this->creatorrole, $syscontext->id);
assign_capability('moodle/competency:planview', CAP_ALLOW, $this->creatorrole, $syscontext->id);
assign_capability('moodle/competency:planviewdraft', CAP_ALLOW, $this->creatorrole, $syscontext->id);
assign_capability('moodle/competency:templatemanage', CAP_ALLOW, $this->creatorrole, $syscontext->id);
assign_capability('moodle/competency:competencygrade', CAP_ALLOW, $this->creatorrole, $syscontext->id);
assign_capability('moodle/cohort:manage', CAP_ALLOW, $this->creatorrole, $syscontext->id);
assign_capability('moodle/competency:competencyview', CAP_ALLOW, $this->userrole, $syscontext->id);
assign_capability('moodle/competency:templateview', CAP_ALLOW, $this->userrole, $syscontext->id);
assign_capability('moodle/competency:planviewown', CAP_ALLOW, $this->userrole, $syscontext->id);
assign_capability('moodle/competency:planviewowndraft', CAP_ALLOW, $this->userrole, $syscontext->id);
role_assign($this->creatorrole, $creator->id, $syscontext->id);
role_assign($this->creatorrole, $catcreator->id, $catcontext->id);
role_assign($this->userrole, $user->id, $syscontext->id);
role_assign($this->userrole, $catuser->id, $catcontext->id);
$this->creator = $creator;
$this->catcreator = $catcreator;
$this->user = $user;
$this->catuser = $catuser;
$this->category = $category;
$this->othercategory = $othercategory;
accesslib_clear_all_caches_for_unit_testing();
}
public function test_search_users_by_capability() {
global $CFG;
$this->resetAfterTest(true);
$dg = $this->getDataGenerator();
$ux = $dg->create_user();
$u1 = $dg->create_user(array('idnumber' => 'Cats', 'firstname' => 'Bob', 'lastname' => 'Dyyylan',
'email' => 'bobbyyy@dyyylan.com', 'phone1' => '123456', 'phone2' => '78910', 'department' => 'Marketing',
'institution' => 'HQ'));
// First we search with no capability assigned.
$this->setUser($ux);
$result = external::search_users('yyylan', 'moodle/competency:planmanage');
< $result = \external_api::clean_returnvalue(external::search_users_returns(), $result);
> $result = external_api::clean_returnvalue(external::search_users_returns(), $result);
$this->assertCount(0, $result['users']);
$this->assertEquals(0, $result['count']);
// Now we assign a different capability.
$usercontext = \context_user::instance($u1->id);
$systemcontext = \context_system::instance();
$customrole = $this->assignUserCapability('moodle/competency:planview', $usercontext->id);
$result = external::search_users('yyylan', 'moodle/competency:planmanage');
< $result = \external_api::clean_returnvalue(external::search_users_returns(), $result);
> $result = external_api::clean_returnvalue(external::search_users_returns(), $result);
$this->assertCount(0, $result['users']);
$this->assertEquals(0, $result['count']);
// Now we assign a matching capability in the same role.
$usercontext = \context_user::instance($u1->id);
$this->assignUserCapability('moodle/competency:planmanage', $usercontext->id, $customrole);
$result = external::search_users('yyylan', 'moodle/competency:planmanage');
< $result = \external_api::clean_returnvalue(external::search_users_returns(), $result);
> $result = external_api::clean_returnvalue(external::search_users_returns(), $result);
$this->assertCount(1, $result['users']);
$this->assertEquals(1, $result['count']);
// Now assign another role with the same capability (test duplicates).
role_assign($this->creatorrole, $ux->id, $usercontext->id);
$result = external::search_users('yyylan', 'moodle/competency:planmanage');
< $result = \external_api::clean_returnvalue(external::search_users_returns(), $result);
> $result = external_api::clean_returnvalue(external::search_users_returns(), $result);
$this->assertCount(1, $result['users']);
$this->assertEquals(1, $result['count']);
// Now lets try a different user with only the role at system level.
$ux2 = $dg->create_user();
role_assign($this->creatorrole, $ux2->id, $systemcontext->id);
$this->setUser($ux2);
$result = external::search_users('yyylan', 'moodle/competency:planmanage');
< $result = \external_api::clean_returnvalue(external::search_users_returns(), $result);
> $result = external_api::clean_returnvalue(external::search_users_returns(), $result);
$this->assertCount(1, $result['users']);
$this->assertEquals(1, $result['count']);
// Now lets try a different user with only the role at user level.
$ux3 = $dg->create_user();
role_assign($this->creatorrole, $ux3->id, $usercontext->id);
$this->setUser($ux3);
$result = external::search_users('yyylan', 'moodle/competency:planmanage');
< $result = \external_api::clean_returnvalue(external::search_users_returns(), $result);
> $result = external_api::clean_returnvalue(external::search_users_returns(), $result);
$this->assertCount(1, $result['users']);
$this->assertEquals(1, $result['count']);
// Switch back.
$this->setUser($ux);
// Now add a prevent override (will change nothing because we still have an ALLOW).
assign_capability('moodle/competency:planmanage', CAP_PREVENT, $customrole, $usercontext->id);
$result = external::search_users('yyylan', 'moodle/competency:planmanage');
< $result = \external_api::clean_returnvalue(external::search_users_returns(), $result);
> $result = external_api::clean_returnvalue(external::search_users_returns(), $result);
$this->assertCount(1, $result['users']);
$this->assertEquals(1, $result['count']);
// Now change to a prohibit override (should prevent access).
assign_capability('moodle/competency:planmanage', CAP_PROHIBIT, $customrole, $usercontext->id);
$result = external::search_users('yyylan', 'moodle/competency:planmanage');
< $result = \external_api::clean_returnvalue(external::search_users_returns(), $result);
> $result = external_api::clean_returnvalue(external::search_users_returns(), $result);
$this->assertCount(1, $result['users']);
$this->assertEquals(1, $result['count']);
}
/**
* Ensures that overrides, as well as system permissions, are respected.
*/
public function test_search_users_by_capability_the_comeback() {
$this->resetAfterTest();
$dg = $this->getDataGenerator();
$master = $dg->create_user();
$manager = $dg->create_user();
$slave1 = $dg->create_user(array('lastname' => 'MOODLER'));
$slave2 = $dg->create_user(array('lastname' => 'MOODLER'));
$slave3 = $dg->create_user(array('lastname' => 'MOODLER'));
$syscontext = \context_system::instance();
$slave1context = \context_user::instance($slave1->id);
$slave2context = \context_user::instance($slave2->id);
$slave3context = \context_user::instance($slave3->id);
// Creating a role giving the site config.
$roleid = $dg->create_role();
assign_capability('moodle/site:config', CAP_ALLOW, $roleid, $syscontext->id, true);
// Create a role override for slave 2.
assign_capability('moodle/site:config', CAP_PROHIBIT, $roleid, $slave2context->id, true);
// Assigning the role.
// Master -> System context.
// Manager -> User context.
role_assign($roleid, $master->id, $syscontext);
role_assign($roleid, $manager->id, $slave1context);
// Flush accesslib.
accesslib_clear_all_caches_for_unit_testing();
// Confirm.
// Master has system permissions.
$this->setUser($master);
$this->assertTrue(has_capability('moodle/site:config', $syscontext));
$this->assertTrue(has_capability('moodle/site:config', $slave1context));
$this->assertFalse(has_capability('moodle/site:config', $slave2context));
$this->assertTrue(has_capability('moodle/site:config', $slave3context));
// Manager only has permissions in slave 1.
$this->setUser($manager);
$this->assertFalse(has_capability('moodle/site:config', $syscontext));
$this->assertTrue(has_capability('moodle/site:config', $slave1context));
$this->assertFalse(has_capability('moodle/site:config', $slave2context));
$this->assertFalse(has_capability('moodle/site:config', $slave3context));
// Now do the test.
$this->setUser($master);
$result = external::search_users('MOODLER', 'moodle/site:config');
$this->assertCount(2, $result['users']);
$this->assertEquals(2, $result['count']);
$this->assertArrayHasKey($slave1->id, $result['users']);
$this->assertArrayHasKey($slave3->id, $result['users']);
$this->setUser($manager);
$result = external::search_users('MOODLER', 'moodle/site:config');
$this->assertCount(1, $result['users']);
$this->assertEquals(1, $result['count']);
$this->assertArrayHasKey($slave1->id, $result['users']);
}
public function test_search_users() {
global $CFG;
$this->resetAfterTest(true);
$dg = $this->getDataGenerator();
$ux = $dg->create_user();
$u1 = $dg->create_user(array('idnumber' => 'Cats', 'firstname' => 'Bob', 'lastname' => 'Dyyylan',
'email' => 'bobbyyy@dyyylan.com', 'phone1' => '123456', 'phone2' => '78910', 'department' => 'Marketing',
'institution' => 'HQ'));
$u2 = $dg->create_user(array('idnumber' => 'Dogs', 'firstname' => 'Alice', 'lastname' => 'Dyyylan',
'email' => 'alyyyson@dyyylan.com', 'phone1' => '33333', 'phone2' => '77777', 'department' => 'Development',
'institution' => 'O2'));
$u3 = $dg->create_user(array('idnumber' => 'Fish', 'firstname' => 'Thomas', 'lastname' => 'Xow',
'email' => 'fishyyy@moodle.com', 'phone1' => '77777', 'phone2' => '33333', 'department' => 'Research',
'institution' => 'Bob'));
// We need to give the user the capability we are searching for on each of the test users.
$this->setAdminUser();
$usercontext = \context_user::instance($u1->id);
$dummyrole = $this->assignUserCapability('moodle/competency:planmanage', $usercontext->id);
$usercontext = \context_user::instance($u2->id);
$this->assignUserCapability('moodle/competency:planmanage', $usercontext->id, $dummyrole);
$usercontext = \context_user::instance($u3->id);
$this->assignUserCapability('moodle/competency:planmanage', $usercontext->id, $dummyrole);
$this->setUser($ux);
$usercontext = \context_user::instance($u1->id);
$this->assignUserCapability('moodle/competency:planmanage', $usercontext->id, $dummyrole);
$usercontext = \context_user::instance($u2->id);
$this->assignUserCapability('moodle/competency:planmanage', $usercontext->id, $dummyrole);
$usercontext = \context_user::instance($u3->id);
$this->assignUserCapability('moodle/competency:planmanage', $usercontext->id, $dummyrole);
$this->setAdminUser();
// No identity fields.
$CFG->showuseridentity = '';
$result = external::search_users('cats', 'moodle/competency:planmanage');
< $result = \external_api::clean_returnvalue(external::search_users_returns(), $result);
> $result = external_api::clean_returnvalue(external::search_users_returns(), $result);
$this->assertCount(0, $result['users']);
$this->assertEquals(0, $result['count']);
// Filter by name.
$CFG->showuseridentity = '';
$result = external::search_users('dyyylan', 'moodle/competency:planmanage');
< $result = \external_api::clean_returnvalue(external::search_users_returns(), $result);
> $result = external_api::clean_returnvalue(external::search_users_returns(), $result);
$this->assertCount(2, $result['users']);
$this->assertEquals(2, $result['count']);
$this->assertEquals($u2->id, $result['users'][0]['id']);
$this->assertEquals($u1->id, $result['users'][1]['id']);
// Filter by institution and name.
$CFG->showuseridentity = 'institution';
$result = external::search_users('bob', 'moodle/competency:planmanage');
< $result = \external_api::clean_returnvalue(external::search_users_returns(), $result);
> $result = external_api::clean_returnvalue(external::search_users_returns(), $result);
$this->assertCount(2, $result['users']);
$this->assertEquals(2, $result['count']);
$this->assertEquals($u1->id, $result['users'][0]['id']);
$this->assertEquals($u3->id, $result['users'][1]['id']);
// Filter by id number.
$CFG->showuseridentity = 'idnumber';
$result = external::search_users('cats', 'moodle/competency:planmanage');
< $result = \external_api::clean_returnvalue(external::search_users_returns(), $result);
> $result = external_api::clean_returnvalue(external::search_users_returns(), $result);
$this->assertCount(1, $result['users']);
$this->assertEquals(1, $result['count']);
$this->assertEquals($u1->id, $result['users'][0]['id']);
$this->assertEquals($u1->idnumber, $result['users'][0]['idnumber']);
$this->assertEmpty($result['users'][0]['email']);
$this->assertEmpty($result['users'][0]['phone1']);
$this->assertEmpty($result['users'][0]['phone2']);
$this->assertEmpty($result['users'][0]['department']);
$this->assertEmpty($result['users'][0]['institution']);
// Filter by email.
$CFG->showuseridentity = 'email';
$result = external::search_users('yyy', 'moodle/competency:planmanage');
< $result = \external_api::clean_returnvalue(external::search_users_returns(), $result);
> $result = external_api::clean_returnvalue(external::search_users_returns(), $result);
$this->assertCount(3, $result['users']);
$this->assertEquals(3, $result['count']);
$this->assertEquals($u2->id, $result['users'][0]['id']);
$this->assertEquals($u2->email, $result['users'][0]['email']);
$this->assertEquals($u1->id, $result['users'][1]['id']);
$this->assertEquals($u1->email, $result['users'][1]['email']);
$this->assertEquals($u3->id, $result['users'][2]['id']);
$this->assertEquals($u3->email, $result['users'][2]['email']);
// Filter by any.
$CFG->showuseridentity = 'idnumber,email,phone1,phone2,department,institution';
$result = external::search_users('yyy', 'moodle/competency:planmanage');
< $result = \external_api::clean_returnvalue(external::search_users_returns(), $result);
> $result = external_api::clean_returnvalue(external::search_users_returns(), $result);
$this->assertCount(3, $result['users']);
$this->assertEquals(3, $result['count']);
$this->assertArrayHasKey('idnumber', $result['users'][0]);
$this->assertArrayHasKey('email', $result['users'][0]);
$this->assertArrayHasKey('phone1', $result['users'][0]);
$this->assertArrayHasKey('phone2', $result['users'][0]);
$this->assertArrayHasKey('department', $result['users'][0]);
$this->assertArrayHasKey('institution', $result['users'][0]);
// Switch to a user that cannot view identity fields.
$this->setUser($ux);
$CFG->showuseridentity = 'idnumber,email,phone1,phone2,department,institution';
// Only names are included.
$result = external::search_users('fish');
< $result = \external_api::clean_returnvalue(external::search_users_returns(), $result);
> $result = external_api::clean_returnvalue(external::search_users_returns(), $result);
$this->assertCount(0, $result['users']);
$this->assertEquals(0, $result['count']);
$result = external::search_users('bob', 'moodle/competency:planmanage');
< $result = \external_api::clean_returnvalue(external::search_users_returns(), $result);
> $result = external_api::clean_returnvalue(external::search_users_returns(), $result);
$this->assertCount(1, $result['users']);
$this->assertEquals(1, $result['count']);
$this->assertEquals($u1->id, $result['users'][0]['id']);
$this->assertEmpty($result['users'][0]['idnumber']);
$this->assertEmpty($result['users'][0]['email']);
$this->assertEmpty($result['users'][0]['phone1']);
$this->assertEmpty($result['users'][0]['phone2']);
$this->assertEmpty($result['users'][0]['department']);
$this->assertEmpty($result['users'][0]['institution']);
}
public function test_data_for_user_competency_summary_in_plan() {
global $CFG;
$this->setUser($this->creator);
$dg = $this->getDataGenerator();
$lpg = $dg->get_plugin_generator('core_competency');
$f1 = $lpg->create_framework();
$c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
$tpl = $lpg->create_template();
$lpg->create_template_competency(array('templateid' => $tpl->get('id'), 'competencyid' => $c1->get('id')));
$plan = $lpg->create_plan(array('userid' => $this->user->id, 'templateid' => $tpl->get('id'), 'name' => 'Evil'));
$uc = $lpg->create_user_competency(array('userid' => $this->user->id, 'competencyid' => $c1->get('id')));
$evidence = \core_competency\external::grade_competency_in_plan($plan->get('id'), $c1->get('id'), 1, true);
$evidence = \core_competency\external::grade_competency_in_plan($plan->get('id'), $c1->get('id'), 2, true);
$summary = external::data_for_user_competency_summary_in_plan($c1->get('id'), $plan->get('id'));
$this->assertTrue($summary->usercompetencysummary->cangrade);
$this->assertEquals('Evil', $summary->plan->name);
$this->assertEquals('B', $summary->usercompetencysummary->usercompetency->gradename);
$this->assertEquals('B', $summary->usercompetencysummary->evidence[0]->gradename);
$this->assertEquals('A', $summary->usercompetencysummary->evidence[1]->gradename);
}
public function test_data_for_user_competency_summary() {
$this->setUser($this->creator);
$dg = $this->getDataGenerator();
$lpg = $dg->get_plugin_generator('core_competency');
$f1 = $lpg->create_framework();
$c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
$evidence = \core_competency\external::grade_competency($this->user->id, $c1->get('id'), 1, true);
$evidence = \core_competency\external::grade_competency($this->user->id, $c1->get('id'), 2, true);
$summary = external::data_for_user_competency_summary($this->user->id, $c1->get('id'));
$this->assertTrue($summary->cangrade);
$this->assertEquals('B', $summary->usercompetency->gradename);
$this->assertEquals('B', $summary->evidence[0]->gradename);
$this->assertEquals('A', $summary->evidence[1]->gradename);
}
public function test_data_for_course_competency_page() {
$this->setAdminUser();
$dg = $this->getDataGenerator();
$lpg = $dg->get_plugin_generator('core_competency');
$f1 = $lpg->create_framework();
$c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
$course1 = $dg->create_course(array('category' => $this->category->id));
$cc = api::add_competency_to_course($course1->id, $c1->get('id'));
$evidence = \core_competency\external::grade_competency($this->user->id, $c1->get('id'), 1, true);
$evidence = \core_competency\external::grade_competency($this->user->id, $c1->get('id'), 2, true);
$pagegenerator = $this->getDataGenerator()->get_plugin_generator('mod_page');
$page = $pagegenerator->create_instance(array('course' => $course1->id));
$page2 = $pagegenerator->create_instance(array('course' => $course1->id));
$cm = get_coursemodule_from_instance('page', $page->id);
$cm2 = get_coursemodule_from_instance('page', $page2->id);
// Add the competency to the course module.
$ccm = api::add_competency_to_course_module($cm, $c1->get('id'));
$summary = external::data_for_course_competencies_page($course1->id, 0);
$summary2 = external::data_for_course_competencies_page($course1->id, $cm->id);
$summary3 = external::data_for_course_competencies_page($course1->id, $cm2->id);
$this->assertEquals(count($summary->competencies), 1);
$this->assertEquals(count($summary->competencies), count($summary2->competencies));
$this->assertEquals(count($summary3->competencies), 0);
}
}