Commit a60e8ba5 authored by Damyon Wiese's avatar Damyon Wiese Committed by Dan Poltawski
Browse files

MDL-59365 enrol_manual: Rewrite the yui enrolment popup in amd

The add/roles thing was only converted to bootstrap 2/4 markup and the yui left in place.

The modal for adding users to a course was unsavable so I rewrote it with an mform in a popup, still calling
the same (barely) modified ajax script.

The webservice for searching cohorts was taken from admin/tool/lp and moved into /cohort. I added a generic "cohort"
mform element at the same time.

The webservice for searching for users was taken from the original ajax script.
parent bdf31b09
......@@ -920,119 +920,6 @@ class external extends external_api {
));
}
/**
* Returns the description of external function parameters.
*
* @return external_function_parameters
*/
public static function search_cohorts_parameters() {
$query = new external_value(
PARAM_RAW,
'Query string'
);
$includes = new external_value(
PARAM_ALPHA,
'What other contexts to fetch the frameworks from. (all, parents, self)',
VALUE_DEFAULT,
'parents'
);
$limitfrom = new external_value(
PARAM_INT,
'limitfrom we are fetching the records from',
VALUE_DEFAULT,
0
);
$limitnum = new external_value(
PARAM_INT,
'Number of records to fetch',
VALUE_DEFAULT,
25
);
return new external_function_parameters(array(
'query' => $query,
'context' => self::get_context_parameters(),
'includes' => $includes,
'limitfrom' => $limitfrom,
'limitnum' => $limitnum
));
}
/**
* Search cohorts.
* TODO: MDL-52243 Move this function to cohorts/externallib.php
*
* @param string $query
* @param array $context
* @param string $includes
* @param int $limitfrom
* @param int $limitnum
* @return array
*/
public static function search_cohorts($query, $context, $includes = 'parents', $limitfrom = 0, $limitnum = 25) {
global $DB, $CFG, $PAGE;
require_once($CFG->dirroot . '/cohort/lib.php');
$params = self::validate_parameters(self::search_cohorts_parameters(), array(
'query' => $query,
'context' => $context,
'includes' => $includes,
'limitfrom' => $limitfrom,
'limitnum' => $limitnum,
));
$query = $params['query'];
$includes = $params['includes'];
$context = self::get_context_from_params($params['context']);
$limitfrom = $params['limitfrom'];
$limitnum = $params['limitnum'];
self::validate_context($context);
$output = $PAGE->get_renderer('tool_lp');
$manager = has_capability('moodle/cohort:manage', $context);
if (!$manager) {
require_capability('moodle/cohort:view', $context);
}
// TODO Make this more efficient.
if ($includes == 'self') {
$results = cohort_get_cohorts($context->id, $limitfrom, $limitnum, $query);
$results = $results['cohorts'];
} else if ($includes == 'parents') {
$results = cohort_get_cohorts($context->id, $limitfrom, $limitnum, $query);
$results = $results['cohorts'];
if (!$context instanceof context_system) {
$results = array_merge($results, cohort_get_available_cohorts($context, COHORT_ALL, $limitfrom, $limitnum, $query));
}
} else if ($includes == 'all') {
$results = cohort_get_all_cohorts($limitfrom, $limitnum, $query);
$results = $results['cohorts'];
} else {
throw new coding_exception('Invalid parameter value for \'includes\'.');
}
$cohorts = array();
foreach ($results as $key => $cohort) {
$cohortcontext = context::instance_by_id($cohort->contextid);
$exporter = new cohort_summary_exporter($cohort, array('context' => $cohortcontext));
$newcohort = $exporter->export($output);
$cohorts[$key] = $newcohort;
}
return array('cohorts' => $cohorts);
}
/**
* Returns description of external function result value.
*
* @return external_description
*/
public static function search_cohorts_returns() {
return new external_single_structure(array(
'cohorts' => new external_multiple_structure(cohort_summary_exporter::get_read_structure())
));
}
/**
* Returns description of external function.
*
......
......@@ -131,10 +131,11 @@ $functions = array(
'capabilities' => '',
'ajax' => true,
),
// This function was originally in this plugin but has been moved to core.
'tool_lp_search_cohorts' => array(
'classname' => 'tool_lp\external',
'classname' => 'core_cohort_external',
'methodname' => 'search_cohorts',
'classpath' => '',
'classpath' => 'cohort/externallib.php',
'description' => 'Search for cohorts.',
'type' => 'read',
'capabilities' => 'moodle/cohort:view',
......
......@@ -461,76 +461,4 @@ class tool_lp_external_testcase extends externallib_advanced_testcase {
$this->assertEquals('A', $summary->evidence[1]->gradename);
}
/**
* Search cohorts.
*/
public function test_search_cohorts() {
$this->resetAfterTest(true);
$syscontext = array('contextid' => context_system::instance()->id);
$catcontext = array('contextid' => context_coursecat::instance($this->category->id)->id);
$othercatcontext = array('contextid' => context_coursecat::instance($this->othercategory->id)->id);
$cohort1 = $this->getDataGenerator()->create_cohort(array_merge($syscontext, array('name' => 'Cohortsearch 1')));
$cohort2 = $this->getDataGenerator()->create_cohort(array_merge($catcontext, array('name' => 'Cohortsearch 2')));
$cohort3 = $this->getDataGenerator()->create_cohort(array_merge($othercatcontext, array('name' => 'Cohortsearch 3')));
// Check for parameter $includes = 'parents'.
// A user without permission in the system.
$this->setUser($this->user);
try {
$result = external::search_cohorts("Cohortsearch", $syscontext, 'parents');
$this->fail('Invalid permissions in system');
} catch (required_capability_exception $e) {
// All good.
}
// A user without permission in a category.
$this->setUser($this->catuser);
try {
$result = external::search_cohorts("Cohortsearch", $catcontext, 'parents');
$this->fail('Invalid permissions in category');
} catch (required_capability_exception $e) {
// All good.
}
// A user with permissions in the system.
$this->setUser($this->creator);
$result = external::search_cohorts("Cohortsearch", $syscontext, 'parents');
$this->assertEquals(1, count($result['cohorts']));
$this->assertEquals('Cohortsearch 1', $result['cohorts'][$cohort1->id]->name);
// A user with permissions in the category.
$this->setUser($this->catcreator);
$result = external::search_cohorts("Cohortsearch", $catcontext, 'parents');
$this->assertEquals(2, count($result['cohorts']));
$cohorts = array();
foreach ($result['cohorts'] as $cohort) {
$cohorts[] = $cohort->name;
}
$this->assertTrue(in_array('Cohortsearch 1', $cohorts));
$this->assertTrue(in_array('Cohortsearch 2', $cohorts));
// Check for parameter $includes = 'self'.
$this->setUser($this->creator);
$result = external::search_cohorts("Cohortsearch", $othercatcontext, 'self');
$this->assertEquals(1, count($result['cohorts']));
$this->assertEquals('Cohortsearch 3', $result['cohorts'][$cohort3->id]->name);
// Check for parameter $includes = 'all'.
$this->setUser($this->creator);
$result = external::search_cohorts("Cohortsearch", $syscontext, 'all');
$this->assertEquals(3, count($result['cohorts']));
// Detect invalid parameter $includes.
$this->setUser($this->creator);
try {
$result = external::search_cohorts("Cohortsearch", $syscontext, 'invalid');
$this->fail('Invalid parameter includes');
} catch (coding_exception $e) {
// All good.
}
}
}
......@@ -25,6 +25,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
$plugin->version = 2017062700; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2017050500; // Requires this Moodle version.
$plugin->component = 'tool_lp'; // Full name of the plugin (used for diagnostics).
......@@ -274,6 +274,137 @@ class core_cohort_external extends external_api {
);
}
/**
* Returns the description of external function parameters.
*
* @return external_function_parameters
*/
public static function search_cohorts_parameters() {
$query = new external_value(
PARAM_RAW,
'Query string'
);
$includes = new external_value(
PARAM_ALPHA,
'What other contexts to fetch the frameworks from. (all, parents, self)',
VALUE_DEFAULT,
'parents'
);
$limitfrom = new external_value(
PARAM_INT,
'limitfrom we are fetching the records from',
VALUE_DEFAULT,
0
);
$limitnum = new external_value(
PARAM_INT,
'Number of records to fetch',
VALUE_DEFAULT,
25
);
return new external_function_parameters(array(
'query' => $query,
'context' => self::get_context_parameters(),
'includes' => $includes,
'limitfrom' => $limitfrom,
'limitnum' => $limitnum
));
}
/**
* Search cohorts.
*
* @param string $query
* @param array $context
* @param string $includes
* @param int $limitfrom
* @param int $limitnum
* @return array
*/
public static function search_cohorts($query, $context, $includes = 'parents', $limitfrom = 0, $limitnum = 25) {
global $DB, $CFG, $PAGE;
require_once($CFG->dirroot . '/cohort/lib.php');
$params = self::validate_parameters(self::search_cohorts_parameters(), array(
'query' => $query,
'context' => $context,
'includes' => $includes,
'limitfrom' => $limitfrom,
'limitnum' => $limitnum,
));
$query = $params['query'];
$includes = $params['includes'];
$context = self::get_context_from_params($params['context']);
$limitfrom = $params['limitfrom'];
$limitnum = $params['limitnum'];
self::validate_context($context);
$output = $PAGE->get_renderer('tool_lp');
$manager = has_capability('moodle/cohort:manage', $context);
if (!$manager) {
require_capability('moodle/cohort:view', $context);
}
// TODO Make this more efficient.
if ($includes == 'self') {
$results = cohort_get_cohorts($context->id, $limitfrom, $limitnum, $query);
$results = $results['cohorts'];
} else if ($includes == 'parents') {
$results = cohort_get_cohorts($context->id, $limitfrom, $limitnum, $query);
$results = $results['cohorts'];
if (!$context instanceof context_system) {
$results = array_merge($results, cohort_get_available_cohorts($context, COHORT_ALL, $limitfrom, $limitnum, $query));
}
} else if ($includes == 'all') {
$results = cohort_get_all_cohorts($limitfrom, $limitnum, $query);
$results = $results['cohorts'];
} else {
throw new coding_exception('Invalid parameter value for \'includes\'.');
}
$cohorts = array();
foreach ($results as $key => $cohort) {
$cohortcontext = context::instance_by_id($cohort->contextid);
if (!isset($cohort->description)) {
$cohort->description = '';
}
if (!isset($cohort->descriptionformat)) {
$cohort->descriptionformat = FORMAT_PLAIN;
}
list($cohort->description, $cohort->descriptionformat) =
external_format_text($cohort->description, $cohort->descriptionformat,
$cohortcontext->id, 'cohort', 'description', $cohort->id);
$cohorts[$key] = $cohort;
}
return array('cohorts' => $cohorts);
}
/**
* Returns description of external function result value.
*
* @return external_description
*/
public static function search_cohorts_returns() {
return new external_single_structure(array(
'cohorts' => new external_multiple_structure(
new external_single_structure(array(
'id' => new external_value(PARAM_INT, 'ID of the cohort'),
'name' => new external_value(PARAM_RAW, 'cohort name'),
'idnumber' => new external_value(PARAM_RAW, 'cohort idnumber'),
'description' => new external_value(PARAM_RAW, 'cohort description'),
'descriptionformat' => new external_format_value('description'),
'visible' => new external_value(PARAM_BOOL, 'cohort visible'),
))
)
));
}
/**
* Returns description of method parameters
*
......
......@@ -330,6 +330,33 @@ function cohort_can_view_cohort($cohortorid, $currentcontext) {
return false;
}
/**
* Get a cohort by id. Also does a visibility check and returns false if the user cannot see this cohort.
*
* @param stdClass|int $cohortorid cohort object or id
* @param context $currentcontext current context (course) where visibility is checked
* @return stdClass|boolean
*/
function cohort_get_cohort($cohortorid, $currentcontext) {
global $DB;
if (is_numeric($cohortorid)) {
$cohort = $DB->get_record('cohort', array('id' => $cohortorid), 'id, contextid, visible');
} else {
$cohort = $cohortorid;
}
if ($cohort && in_array($cohort->contextid, $currentcontext->get_parent_context_ids())) {
if ($cohort->visible) {
return $cohort;
}
$cohortcontext = context::instance_by_id($cohort->contextid);
if (has_capability('moodle/cohort:view', $cohortcontext)) {
return $cohort;
}
}
return false;
}
/**
* Produces a part of SQL query to filter cohorts by the search string
*
......
......@@ -454,4 +454,102 @@ class core_cohort_externallib_testcase extends externallib_advanced_testcase {
$this->unassignUserCapability('moodle/cohort:assign', $context->id, $roleid);
core_cohort_external::delete_cohort_members(array($cohortdel1, $cohortdel2));
}
/**
* Search cohorts.
*/
public function test_search_cohorts() {
$this->resetAfterTest(true);
$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.
$userroles = get_archetype_roles('user');
$this->assertCount(1, $userroles);
$authrole = array_pop($userroles);
// Reset all default authenticated users permissions.
unassign_capability('moodle/cohort:manage', $authrole->id);
// Creating specific roles.
$creatorrole = create_role('Creator role', 'creatorrole', 'creator role description');
$userrole = create_role('User role', 'userrole', 'user role description');
assign_capability('moodle/cohort:manage', CAP_ALLOW, $creatorrole, $syscontext->id);
// Check for parameter $includes = 'parents'.
role_assign($creatorrole, $creator->id, $syscontext->id);
role_assign($creatorrole, $catcreator->id, $catcontext->id);
role_assign($userrole, $user->id, $syscontext->id);
role_assign($userrole, $catuser->id, $catcontext->id);
$syscontext = array('contextid' => context_system::instance()->id);
$catcontext = array('contextid' => context_coursecat::instance($category->id)->id);
$othercatcontext = array('contextid' => context_coursecat::instance($othercategory->id)->id);
$cohort1 = $this->getDataGenerator()->create_cohort(array_merge($syscontext, array('name' => 'Cohortsearch 1')));
$cohort2 = $this->getDataGenerator()->create_cohort(array_merge($catcontext, array('name' => 'Cohortsearch 2')));
$cohort3 = $this->getDataGenerator()->create_cohort(array_merge($othercatcontext, array('name' => 'Cohortsearch 3')));
// A user without permission in the system.
$this->setUser($user);
try {
$result = core_cohort_external::search_cohorts("Cohortsearch", $syscontext, 'parents');
$this->fail('Invalid permissions in system');
} catch (required_capability_exception $e) {
// All good.
}
// A user without permission in a category.
$this->setUser($catuser);
try {
$result = core_cohort_external::search_cohorts("Cohortsearch", $catcontext, 'parents');
$this->fail('Invalid permissions in category');
} catch (required_capability_exception $e) {
// All good.
}
// A user with permissions in the system.
$this->setUser($creator);
$result = core_cohort_external::search_cohorts("Cohortsearch", $syscontext, 'parents');
$this->assertEquals(1, count($result['cohorts']));
$this->assertEquals('Cohortsearch 1', $result['cohorts'][$cohort1->id]->name);
// A user with permissions in the category.
$this->setUser($catcreator);
$result = core_cohort_external::search_cohorts("Cohortsearch", $catcontext, 'parents');
$this->assertEquals(2, count($result['cohorts']));
$cohorts = array();
foreach ($result['cohorts'] as $cohort) {
$cohorts[] = $cohort->name;
}
$this->assertTrue(in_array('Cohortsearch 1', $cohorts));
// Check for parameter $includes = 'self'.
$this->setUser($creator);
$result = core_cohort_external::search_cohorts("Cohortsearch", $othercatcontext, 'self');
$this->assertEquals(1, count($result['cohorts']));
$this->assertEquals('Cohortsearch 3', $result['cohorts'][$cohort3->id]->name);
// Check for parameter $includes = 'all'.
$this->setUser($creator);
$result = core_cohort_external::search_cohorts("Cohortsearch", $syscontext, 'all');
$this->assertEquals(3, count($result['cohorts']));
// Detect invalid parameter $includes.
$this->setUser($creator);
try {
$result = core_cohort_external::search_cohorts("Cohortsearch", $syscontext, 'invalid');
$this->fail('Invalid parameter includes');
} catch (coding_exception $e) {
// All good.
}
}
}
......@@ -385,6 +385,81 @@ class core_enrol_external extends external_api {
);
}
/**
* Returns description of method parameters value
*
* @return external_description
*/
public static function get_potential_users_parameters() {
return new external_function_parameters(
array(
'courseid' => new external_value(PARAM_INT, 'course id'),
'enrolid' => new external_value(PARAM_INT, 'enrolment id'),
'search' => new external_value(PARAM_RAW, 'query'),
'searchanywhere' => new external_value(PARAM_BOOL, 'find a match anywhere, or only at the beginning'),
'page' => new external_value(PARAM_INT, 'Page number'),
'perpage' => new external_value(PARAM_INT, 'Number per page'),
)
);
}
/**
* Get potential users.
*
* @param int $courseid Course id
* @param int $enrolid Enrolment id
* @param string $search The query
* @param boolean $searchanywhere Match anywhere in the string
* @param int $page Page number
* @param int $perpage Max per page
* @return array An array of users
*/
public static function get_potential_users($courseid, $enrolid, $search, $searchanywhere, $page, $perpage) {
global $PAGE;
$params = self::validate_parameters(
self::get_potential_users_parameters(),
array(
'courseid' => $courseid,
'enrolid' => $enrolid,
'search' => $search,
'searchanywhere' => $searchanywhere,
'page' => $page,
'perpage' => $perpage
)
);
$context = context_course::instance($params['courseid']);
require_capability('moodle/course:enrolreview', $context);
$course = $DB->get_record('course', array('id' => $params['courseid']));
$manager = new course_enrolment_manager($PAGE, $course);
$users = $manager->get_potential_users($params['enrolid'],
$params['search'],
$params['searchanywhere'],
$params['page'],
$params['perpage']);
$results = array();
foreach ($users as $id => $user) {
if ($userdetails = user_get_user_details($user)) {
$results[] = $userdetails;
}
}
return $results;
}
/**
* Returns description of method result value
*
* @return external_description
*/
public static function get_potential_users_returns() {
global $CFG;
require_once($CFG->dirroot . '/user/externallib.php');
return new external_multiple_structure(core_user_external::user_description());
}
/**
* Returns description of method parameters
*
......
......@@ -61,62 +61,32 @@ $outcome->error = '';
$searchanywhere = get_user_preferences('userselector_searchanywhere', false);
switch ($action) {
case 'getassignable':
$otheruserroles = optional_param('otherusers', false, PARAM_BOOL);
$outcome->response = array_reverse($manager->get_assignable_roles($otheruserroles), true);
break;
case 'searchusers':
case 'enrol':
$enrolid = required_param('enrolid', PARAM_INT);
$search = optional_param('search', '', PARAM_RAW);
$page = optional_param('page', 0, PARAM_INT);
$addedenrollment = optional_param('enrolcount', 0, PARAM_INT);
$perpage = optional_param('perpage', 25, PARAM_INT); // This value is hard-coded to 25 in quickenrolment.js
$outcome->response = $manager->get_potential_users($enrolid, $search, $searchanywhere, $page, $perpage, $addedenrollment);
$extrafields = get_extra_user_fields($context);
$useroptions = array();
// User is not enrolled yet, either link to site profile or do not link at all.
if (has_capability('moodle/user:viewdetails', context_system::instance())) {