mirror of
https://github.com/moodle/moodle.git
synced 2025-04-20 07:56:06 +02:00
Merge branch 'MDL-60826-master' of git://github.com/lameze/moodle
This commit is contained in:
commit
834054ee06
2
calendar/amd/build/event_form.min.js
vendored
2
calendar/amd/build/event_form.min.js
vendored
@ -1 +1 @@
|
||||
define(["jquery"],function(a){var b={EVENT_GROUP_COURSE_ID:'[name="groupcourseid"]',EVENT_GROUP_ID:'[name="groupid"]',SELECT_OPTION:"option"},c=function(c){c.find(b.EVENT_GROUP_ID).find(b.SELECT_OPTION).each(function(b,c){c=a(c);var d=c.attr("value"),e=d.split("-"),f=e[0];c.attr("data-course-id",f)})},d=function(c){var d=c.find(b.EVENT_GROUP_COURSE_ID),e=c.find(b.EVENT_GROUP_ID),f=e.find(b.SELECT_OPTION),g=function(){var b=d.val(),c=null,g=!1;f.each(function(d,e){e=a(e),e.attr("data-course-id")==b?(e.removeClass("hidden"),e.prop("disabled",!1),g=!0,(null===c||e.attr("selected"))&&(c=d)):(e.addClass("hidden"),e.prop("disabled",!0))}),g?e.prop("disabled",!1):e.prop("disabled",!0),e.prop("selectedIndex",c)};d.on("change",g),g()},e=function(b){var e=a("#"+b);c(e),d(e)};return{init:e}});
|
||||
define(["jquery","core_calendar/repository"],function(a,b){var c={EVENT_GROUP_COURSE_ID:'[name="groupcourseid"]',EVENT_GROUP_ID:'[name="groupid"]',SELECT_OPTION:"option"},d=function(d){var e=d.find(c.EVENT_GROUP_COURSE_ID),f=function(b){var e=d.find(c.EVENT_GROUP_ID),f=e.find(c.SELECT_OPTION),g=a(b);f.remove(),e.prop("disabled",!1),g.each(function(b,c){a(e).append(a("<option></option>").attr("value",c.id).text(c.name))})};e.on("change",function(){var a=d.find(c.EVENT_GROUP_COURSE_ID).val();b.getCourseGroupsData(a).then(function(a){return f(a)})["catch"](Notification.exception)})},e=function(b){var c=a("#"+b);d(c)};return{init:e}});
|
2
calendar/amd/build/repository.min.js
vendored
2
calendar/amd/build/repository.min.js
vendored
@ -1 +1 @@
|
||||
define(["jquery","core/ajax"],function(a,b){var c=function(a,c){"undefined"==typeof c&&(c=!1);var d={methodname:"core_calendar_delete_calendar_events",args:{events:[{eventid:a,repeat:c}]}};return b.call([d])[0]},d=function(a){var c={methodname:"core_calendar_get_calendar_event_by_id",args:{eventid:a}};return b.call([c])[0]},e=function(a){var c={methodname:"core_calendar_submit_create_update_form",args:{formdata:a}};return b.call([c])[0]},f=function(a,c,d,e,f,g){var h={methodname:"core_calendar_get_calendar_monthly_view",args:{year:a,month:c,courseid:d,categoryid:e,includenavigation:f,mini:g}};return b.call([h])[0]},g=function(a,c,d,e,f){var g={methodname:"core_calendar_get_calendar_day_view",args:{year:a,month:c,day:d,courseid:e,categoryid:f}};return b.call([g])[0]},h=function(a,c){var d={methodname:"core_calendar_update_event_start_day",args:{eventid:a,daytimestamp:c}};return b.call([d])[0]},i=function(a,c){var d={methodname:"core_calendar_get_calendar_upcoming_view",args:{courseid:a,categoryid:c}};return b.call([d])[0]};return{getEventById:d,deleteEvent:c,updateEventStartDay:h,submitCreateUpdateForm:e,getCalendarMonthData:f,getCalendarDayData:g,getCalendarUpcomingData:i}});
|
||||
define(["jquery","core/ajax"],function(a,b){var c=function(a,c){"undefined"==typeof c&&(c=!1);var d={methodname:"core_calendar_delete_calendar_events",args:{events:[{eventid:a,repeat:c}]}};return b.call([d])[0]},d=function(a){var c={methodname:"core_calendar_get_calendar_event_by_id",args:{eventid:a}};return b.call([c])[0]},e=function(a){var c={methodname:"core_calendar_submit_create_update_form",args:{formdata:a}};return b.call([c])[0]},f=function(a,c,d,e,f,g){var h={methodname:"core_calendar_get_calendar_monthly_view",args:{year:a,month:c,courseid:d,categoryid:e,includenavigation:f,mini:g}};return b.call([h])[0]},g=function(a,c,d,e,f){var g={methodname:"core_calendar_get_calendar_day_view",args:{year:a,month:c,day:d,courseid:e,categoryid:f}};return b.call([g])[0]},h=function(a,c){var d={methodname:"core_calendar_update_event_start_day",args:{eventid:a,daytimestamp:c}};return b.call([d])[0]},i=function(a,c){var d={methodname:"core_calendar_get_calendar_upcoming_view",args:{courseid:a,categoryid:c}};return b.call([d])[0]},j=function(a){var c={methodname:"core_group_get_course_groups",args:{courseid:a}};return b.call([c])[0]};return{getEventById:d,deleteEvent:c,updateEventStartDay:h,submitCreateUpdateForm:e,getCalendarMonthData:f,getCalendarDayData:g,getCalendarUpcomingData:i,getCourseGroupsData:j}});
|
@ -21,42 +21,12 @@
|
||||
* @copyright 2017 Ryan Wyllie <ryan@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery'], function($) {
|
||||
define(['jquery', 'core_calendar/repository'], function($, CalendarRepository) {
|
||||
|
||||
var SELECTORS = {
|
||||
EVENT_GROUP_COURSE_ID: '[name="groupcourseid"]',
|
||||
EVENT_GROUP_ID: '[name="groupid"]',
|
||||
SELECT_OPTION: 'option',
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse the group id select element in the event form and pull out
|
||||
* the course id from the value to allow us to toggle other select
|
||||
* elements based on the course id for the group a user selects.
|
||||
*
|
||||
* This is a little hacky but I couldn't find a better way to pass
|
||||
* the course id for each group id with the limitations of mforms.
|
||||
*
|
||||
* The group id options are rendered with a value like:
|
||||
* "<courseid>-<groupid>"
|
||||
* E.g.
|
||||
* For a group with id 10 in a course with id 3 the value of the
|
||||
* option will be 3-10.
|
||||
*
|
||||
* @method parseGroupSelect
|
||||
* @param {object} formElement The root form element
|
||||
*/
|
||||
var parseGroupSelect = function(formElement) {
|
||||
formElement.find(SELECTORS.EVENT_GROUP_ID)
|
||||
.find(SELECTORS.SELECT_OPTION)
|
||||
.each(function(index, element) {
|
||||
element = $(element);
|
||||
var value = element.attr('value');
|
||||
var splits = value.split('-');
|
||||
var courseId = splits[0];
|
||||
|
||||
element.attr('data-course-id', courseId);
|
||||
});
|
||||
SELECT_OPTION: 'option'
|
||||
};
|
||||
|
||||
/**
|
||||
@ -69,39 +39,29 @@ define(['jquery'], function($) {
|
||||
*/
|
||||
var addCourseGroupSelectListeners = function(formElement) {
|
||||
var courseGroupSelect = formElement.find(SELECTORS.EVENT_GROUP_COURSE_ID);
|
||||
var groupSelect = formElement.find(SELECTORS.EVENT_GROUP_ID);
|
||||
var groupSelectOptions = groupSelect.find(SELECTORS.SELECT_OPTION);
|
||||
var filterGroupSelectOptions = function() {
|
||||
var selectedCourseId = courseGroupSelect.val();
|
||||
var selectedIndex = null;
|
||||
var hasGroups = false;
|
||||
groupSelectOptions.each(function(index, element) {
|
||||
element = $(element);
|
||||
|
||||
if (element.attr('data-course-id') == selectedCourseId) {
|
||||
element.removeClass('hidden');
|
||||
element.prop('disabled', false);
|
||||
hasGroups = true;
|
||||
if (selectedIndex === null || element.attr('selected')) {
|
||||
selectedIndex = index;
|
||||
}
|
||||
} else {
|
||||
element.addClass('hidden');
|
||||
element.prop('disabled', true);
|
||||
}
|
||||
var loadGroupSelectOptions = function(groups) {
|
||||
var groupSelect = formElement.find(SELECTORS.EVENT_GROUP_ID),
|
||||
groupSelectOptions = groupSelect.find(SELECTORS.SELECT_OPTION),
|
||||
courseGroups = $(groups);
|
||||
|
||||
// Let's clear all options first.
|
||||
groupSelectOptions.remove();
|
||||
groupSelect.prop("disabled", false);
|
||||
courseGroups.each(function(id, group) {
|
||||
$(groupSelect).append($("<option></option>").attr("value", group.id).text(group.name));
|
||||
});
|
||||
|
||||
if (hasGroups) {
|
||||
groupSelect.prop('disabled', false);
|
||||
} else {
|
||||
groupSelect.prop('disabled', true);
|
||||
}
|
||||
|
||||
groupSelect.prop('selectedIndex', selectedIndex);
|
||||
};
|
||||
|
||||
courseGroupSelect.on('change', filterGroupSelectOptions);
|
||||
filterGroupSelectOptions();
|
||||
// If the user choose a course in the selector do a WS request to get groups.
|
||||
courseGroupSelect.on('change', function() {
|
||||
var courseId = formElement.find(SELECTORS.EVENT_GROUP_COURSE_ID).val();
|
||||
CalendarRepository.getCourseGroupsData(courseId)
|
||||
.then(function(groups) {
|
||||
return loadGroupSelectOptions(groups);
|
||||
})
|
||||
.catch(Notification.exception);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@ -112,8 +72,6 @@ define(['jquery'], function($) {
|
||||
*/
|
||||
var init = function(formId) {
|
||||
var formElement = $('#' + formId);
|
||||
|
||||
parseGroupSelect(formElement);
|
||||
addCourseGroupSelectListeners(formElement);
|
||||
};
|
||||
|
||||
|
@ -181,6 +181,23 @@ define(['jquery', 'core/ajax'], function($, Ajax) {
|
||||
return Ajax.call([request])[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the groups by course id.
|
||||
*
|
||||
* @param {Number} courseid The course id to fetch the groups from.
|
||||
* @return {promise} Resolved with the course groups.
|
||||
*/
|
||||
var getCourseGroupsData = function(courseid) {
|
||||
var request = {
|
||||
methodname: 'core_group_get_course_groups',
|
||||
args: {
|
||||
courseid: courseid
|
||||
}
|
||||
};
|
||||
|
||||
return Ajax.call([request])[0];
|
||||
};
|
||||
|
||||
return {
|
||||
getEventById: getEventById,
|
||||
deleteEvent: deleteEvent,
|
||||
@ -188,6 +205,7 @@ define(['jquery', 'core/ajax'], function($, Ajax) {
|
||||
submitCreateUpdateForm: submitCreateUpdateForm,
|
||||
getCalendarMonthData: getCalendarMonthData,
|
||||
getCalendarDayData: getCalendarDayData,
|
||||
getCalendarUpcomingData: getCalendarUpcomingData
|
||||
getCalendarUpcomingData: getCalendarUpcomingData,
|
||||
getCourseGroupsData: getCourseGroupsData
|
||||
};
|
||||
});
|
||||
|
@ -66,9 +66,11 @@ class create extends \moodleform {
|
||||
$mform = $this->_form;
|
||||
$starttime = isset($this->_customdata['starttime']) ? $this->_customdata['starttime'] : 0;
|
||||
$editoroptions = !(empty($this->_customdata['editoroptions'])) ? $this->_customdata['editoroptions'] : null;
|
||||
$eventtypes = calendar_get_all_allowed_types();
|
||||
$courseid = !(empty($this->_customdata['courseid'])) ? $this->_customdata['courseid'] : null;
|
||||
|
||||
if (empty($eventtypes)) {
|
||||
$eventtypes = calendar_get_allowed_event_types($courseid);
|
||||
|
||||
if (in_array(true, $eventtypes, true) === false) {
|
||||
print_error('nopermissiontoupdatecalendar');
|
||||
}
|
||||
|
||||
@ -120,18 +122,20 @@ class create extends \moodleform {
|
||||
* @return array
|
||||
*/
|
||||
public function validation($data, $files) {
|
||||
global $DB, $CFG;
|
||||
global $DB;
|
||||
|
||||
$errors = parent::validation($data, $files);
|
||||
$eventtypes = calendar_get_all_allowed_types();
|
||||
$eventtype = isset($data['eventtype']) ? $data['eventtype'] : null;
|
||||
$coursekey = ($eventtype == 'group') ? 'groupcourseid' : 'courseid';
|
||||
if (empty($eventtype) || !isset($eventtypes[$eventtype])) {
|
||||
$courseid = (!empty($data[$coursekey])) ? $data[$coursekey] : null;
|
||||
$eventtypes = calendar_get_allowed_event_types($courseid);
|
||||
|
||||
if (empty($eventtype) || !isset($eventtypes[$eventtype]) || $eventtypes[$eventtype] == false) {
|
||||
$errors['eventtype'] = get_string('invalideventtype', 'calendar');
|
||||
}
|
||||
|
||||
if (isset($data[$coursekey]) && $data[$coursekey] > 0) {
|
||||
if ($course = $DB->get_record('course', ['id' => $data[$coursekey]])) {
|
||||
if ($courseid && $courseid > 0) {
|
||||
if ($course = $DB->get_record('course', ['id' => $courseid])) {
|
||||
if ($data['timestart'] < $course->startdate) {
|
||||
$errors['timestart'] = get_string('errorbeforecoursestart', 'calendar');
|
||||
}
|
||||
@ -140,11 +144,15 @@ class create extends \moodleform {
|
||||
}
|
||||
}
|
||||
|
||||
if ($eventtype == 'course' && empty($data['courseid'])) {
|
||||
if ($eventtype == 'course' && empty($courseid)) {
|
||||
$errors['courseid'] = get_string('selectacourse');
|
||||
}
|
||||
|
||||
if ($eventtype == 'group' && empty($data['groupcourseid'])) {
|
||||
if ($eventtype == 'group' && (!empty($courseid) && empty($data['groupid']))) {
|
||||
$errors['groupcourseid'] = get_string('nogroups', 'core_group');
|
||||
}
|
||||
|
||||
if ($eventtype == 'group' && empty($courseid)) {
|
||||
$errors['groupcourseid'] = get_string('selectacourse');
|
||||
}
|
||||
|
||||
|
@ -53,28 +53,29 @@ trait eventtype {
|
||||
* @param array $eventtypes The available event types for the user
|
||||
*/
|
||||
protected function add_event_type_elements($mform, $eventtypes) {
|
||||
global $CFG, $DB;
|
||||
$options = [];
|
||||
|
||||
if (isset($eventtypes['user'])) {
|
||||
if (!empty($eventtypes['user'])) {
|
||||
$options['user'] = get_string('user');
|
||||
}
|
||||
if (isset($eventtypes['group'])) {
|
||||
if (!empty($eventtypes['group'])) {
|
||||
$options['group'] = get_string('group');
|
||||
}
|
||||
if (isset($eventtypes['course'])) {
|
||||
if (!empty($eventtypes['course'])) {
|
||||
$options['course'] = get_string('course');
|
||||
}
|
||||
if (isset($eventtypes['category'])) {
|
||||
if (!empty($eventtypes['category'])) {
|
||||
$options['category'] = get_string('category');
|
||||
}
|
||||
if (isset($eventtypes['site'])) {
|
||||
if (!empty($eventtypes['site'])) {
|
||||
$options['site'] = get_string('site');
|
||||
}
|
||||
|
||||
// If we only have one event type and it's 'user' event then don't bother
|
||||
// rendering the select boxes because there is no choice for the user to
|
||||
// make.
|
||||
if (count(array_keys($eventtypes)) == 1 && isset($eventtypes['user'])) {
|
||||
if (!empty($eventtypes['user']) && count($options) == 1) {
|
||||
$mform->addElement('hidden', 'eventtype');
|
||||
$mform->setType('eventtype', PARAM_TEXT);
|
||||
$mform->setDefault('eventtype', 'user');
|
||||
@ -87,9 +88,9 @@ trait eventtype {
|
||||
$mform->addElement('select', 'eventtype', get_string('eventkind', 'calendar'), $options);
|
||||
}
|
||||
|
||||
if (isset($eventtypes['category'])) {
|
||||
if (!empty($eventtypes['category'])) {
|
||||
$categoryoptions = [];
|
||||
foreach ($eventtypes['category'] as $id => $category) {
|
||||
foreach (\coursecat::make_categories_list('moodle/category:manage') as $id => $category) {
|
||||
$categoryoptions[$id] = $category;
|
||||
}
|
||||
|
||||
@ -97,33 +98,26 @@ trait eventtype {
|
||||
$mform->hideIf('categoryid', 'eventtype', 'noteq', 'category');
|
||||
}
|
||||
|
||||
if (isset($eventtypes['course'])) {
|
||||
$limit = !has_capability('moodle/calendar:manageentries', \context_system::instance());
|
||||
$mform->addElement('course', 'courseid', get_string('course'), ['limittoenrolled' => $limit]);
|
||||
$showall = $CFG->calendar_adminseesall && !has_capability('moodle/calendar:manageentries', \context_system::instance());
|
||||
if (!empty($eventtypes['course'])) {
|
||||
$mform->addElement('course', 'courseid', get_string('course'), ['limittoenrolled' => !$showall]);
|
||||
$mform->hideIf('courseid', 'eventtype', 'noteq', 'course');
|
||||
}
|
||||
|
||||
if (isset($eventtypes['group'])) {
|
||||
$options = ['limittoenrolled' => true];
|
||||
// Exclude courses without group.
|
||||
if (isset($eventtypes['course']) && isset($eventtypes['groupcourses'])) {
|
||||
$options['exclude'] = array_diff(array_keys($eventtypes['course']),
|
||||
array_keys($eventtypes['groupcourses']));
|
||||
}
|
||||
|
||||
$mform->addElement('course', 'groupcourseid', get_string('course'), $options);
|
||||
if (!empty($eventtypes['group'])) {
|
||||
$groups = !(empty($this->_customdata['groups'])) ? $this->_customdata['groups'] : null;
|
||||
// Get the list of courses without groups to filter on the course selector.
|
||||
$sql = "SELECT c.id
|
||||
FROM {course} c
|
||||
WHERE c.id NOT IN (
|
||||
SELECT DISTINCT courseid FROM {groups}
|
||||
)";
|
||||
$coursesnogroup = $DB->get_records_sql($sql);
|
||||
$mform->addElement('course', 'groupcourseid', get_string('course'), ['limittoenrolled' => !$showall,
|
||||
'exclude' => array_keys($coursesnogroup)]);
|
||||
$mform->hideIf('groupcourseid', 'eventtype', 'noteq', 'group');
|
||||
|
||||
$groupoptions = [];
|
||||
foreach ($eventtypes['group'] as $group) {
|
||||
// We are formatting it this way in order to provide the javascript both
|
||||
// the course and group ids so that it can enhance the form for the user.
|
||||
$index = "{$group->courseid}-{$group->id}";
|
||||
$groupoptions[$index] = format_string($group->name, true,
|
||||
['context' => \context_course::instance($group->courseid)]);
|
||||
}
|
||||
|
||||
$mform->addElement('select', 'groupid', get_string('group'), $groupoptions);
|
||||
$mform->addElement('select', 'groupid', get_string('group'), $groups);
|
||||
$mform->hideIf('groupid', 'eventtype', 'noteq', 'group');
|
||||
// We handle the group select hide/show actions on the event_form module.
|
||||
}
|
||||
|
@ -41,8 +41,8 @@ class managesubscriptions extends \moodleform {
|
||||
*/
|
||||
public function definition() {
|
||||
$mform = $this->_form;
|
||||
$eventtypes = calendar_get_all_allowed_types();
|
||||
if (empty($eventtypes)) {
|
||||
$eventtypes = calendar_get_allowed_event_types();
|
||||
if (in_array(true, $eventtypes, true) === false) {
|
||||
print_error('nopermissiontoupdatecalendar');
|
||||
}
|
||||
|
||||
@ -100,9 +100,10 @@ class managesubscriptions extends \moodleform {
|
||||
|
||||
$errors = parent::validation($data, $files);
|
||||
|
||||
$coursekey = isset($data['groupcourseid']) ? 'groupcourseid' : 'courseid';
|
||||
$eventtypes = calendar_get_all_allowed_types();
|
||||
$eventtype = isset($data['eventtype']) ? $data['eventtype'] : null;
|
||||
$coursekey = ($eventtype == 'group') ? 'groupcourseid' : 'courseid';
|
||||
$courseid = (!empty($data[$coursekey])) ? $data[$coursekey] : null;
|
||||
$eventtypes = calendar_get_allowed_event_types($courseid);
|
||||
|
||||
if (empty($eventtype) || !isset($eventtypes[$eventtype])) {
|
||||
$errors['eventtype'] = get_string('invalideventtype', 'calendar');
|
||||
|
@ -58,7 +58,7 @@ class create_update_form_mapper implements create_update_form_mapper_interface {
|
||||
|
||||
if ($legacyevent->eventtype == 'group') {
|
||||
// Set up the correct value for the to display on the form.
|
||||
$data->groupid = "{$legacyevent->courseid}-{$legacyevent->groupid}";
|
||||
$data->groupid = $legacyevent->groupid;
|
||||
$data->groupcourseid = $legacyevent->courseid;
|
||||
}
|
||||
if ($legacyevent->eventtype == 'course') {
|
||||
@ -93,12 +93,8 @@ class create_update_form_mapper implements create_update_form_mapper_interface {
|
||||
$properties->courseid = $data->groupcourseid;
|
||||
unset($properties->groupcourseid);
|
||||
}
|
||||
|
||||
// Pull the group id back out of the value. The form saves the value
|
||||
// as "<courseid>-<groupid>" to allow the javascript to work correctly.
|
||||
if (isset($data->groupid)) {
|
||||
list($courseid, $groupid) = explode('-', $data->groupid);
|
||||
$properties->groupid = $groupid;
|
||||
$properties->groupid = $data->groupid;
|
||||
}
|
||||
} else {
|
||||
// Default course id if none is set.
|
||||
|
@ -170,7 +170,7 @@ class raw_event_retrieval_strategy implements raw_event_retrieval_strategy_inter
|
||||
$subqueryconditions = [];
|
||||
|
||||
// Get the user's courses. Otherwise, get the default courses being shown by the calendar.
|
||||
$usercourses = calendar_get_default_courses();
|
||||
$usercourses = calendar_get_default_courses(null, 'id, category, groupmode, groupmodeforce');
|
||||
|
||||
// Set calendar filters.
|
||||
list($usercourses, $usergroups, $user) = calendar_set_filters($usercourses, true);
|
||||
|
@ -865,15 +865,31 @@ class core_calendar_external extends external_api {
|
||||
self::validate_context($context);
|
||||
parse_str($params['formdata'], $data);
|
||||
|
||||
$eventtype = isset($data['eventtype']) ? $data['eventtype'] : null;
|
||||
$coursekey = ($eventtype == 'group') ? 'groupcourseid' : 'courseid';
|
||||
$courseid = (!empty($data[$coursekey])) ? $data[$coursekey] : null;
|
||||
$editoroptions = \core_calendar\local\event\forms\create::build_editor_options($context);
|
||||
$formoptions = ['editoroptions' => $editoroptions, 'courseid' => $courseid];
|
||||
if ($courseid) {
|
||||
require_once($CFG->libdir . '/grouplib.php');
|
||||
$groupcoursedata = groups_get_course_data($courseid);
|
||||
if (!empty($groupcoursedata->groups)) {
|
||||
$formoptions['groups'] = [];
|
||||
foreach ($groupcoursedata->groups as $groupid => $groupdata) {
|
||||
$formoptions['groups'][$groupid] = $groupdata->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($data['id'])) {
|
||||
$eventid = clean_param($data['id'], PARAM_INT);
|
||||
$legacyevent = calendar_event::load($eventid);
|
||||
$legacyevent->count_repeats();
|
||||
$formoptions = ['event' => $legacyevent];
|
||||
$formoptions['event'] = $legacyevent;
|
||||
$mform = new update_event_form(null, $formoptions, 'post', '', null, true, $data);
|
||||
} else {
|
||||
$legacyevent = null;
|
||||
$mform = new create_event_form(null, null, 'post', '', null, true, $data);
|
||||
$mform = new create_event_form(null, $formoptions, 'post', '', null, true, $data);
|
||||
}
|
||||
|
||||
if ($validateddata = $mform->get_data()) {
|
||||
|
265
calendar/lib.php
265
calendar/lib.php
@ -1070,7 +1070,7 @@ class calendar_information {
|
||||
$category = (\coursecat::get($course->category, MUST_EXIST, true))->get_db_record();
|
||||
} else if (!empty($categoryid)) {
|
||||
$course = get_site();
|
||||
$courses = calendar_get_default_courses();
|
||||
$courses = calendar_get_default_courses(null, 'id, category, groupmode, groupmodeforce');
|
||||
|
||||
// Filter available courses to those within this category or it's children.
|
||||
$ids = [$categoryid];
|
||||
@ -1084,7 +1084,7 @@ class calendar_information {
|
||||
$calendar->context = context_coursecat::instance($categoryid);
|
||||
} else {
|
||||
$course = get_site();
|
||||
$courses = calendar_get_default_courses();
|
||||
$courses = calendar_get_default_courses(null, 'id, category, groupmode, groupmodeforce');
|
||||
$category = null;
|
||||
|
||||
$calendar->context = context_system::instance();
|
||||
@ -2570,76 +2570,6 @@ function calendar_get_allowed_types(&$allowed, $course = null, $groups = null, $
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the allowed types for all of the courses and groups
|
||||
* the logged in user belongs to.
|
||||
*
|
||||
* The returned array will optionally have 5 keys:
|
||||
* 'user' : true if the logged in user can create user events
|
||||
* 'site' : true if the logged in user can create site events
|
||||
* 'category' : array of course categories that the user can create events for
|
||||
* 'course' : array of courses that the user can create events for
|
||||
* 'group': array of groups that the user can create events for
|
||||
* 'groupcourses' : array of courses that the groups belong to (can
|
||||
* be different from the list in 'course'.
|
||||
*
|
||||
* @return array The array of allowed types.
|
||||
*/
|
||||
function calendar_get_all_allowed_types() {
|
||||
global $CFG, $USER, $DB;
|
||||
|
||||
require_once($CFG->libdir . '/enrollib.php');
|
||||
|
||||
$types = [];
|
||||
|
||||
$allowed = new stdClass();
|
||||
|
||||
calendar_get_allowed_types($allowed);
|
||||
|
||||
if ($allowed->user) {
|
||||
$types['user'] = true;
|
||||
}
|
||||
|
||||
if ($allowed->site) {
|
||||
$types['site'] = true;
|
||||
}
|
||||
|
||||
if (coursecat::has_manage_capability_on_any()) {
|
||||
$types['category'] = coursecat::make_categories_list('moodle/category:manage');
|
||||
}
|
||||
|
||||
// This function warms the context cache for the course so the calls
|
||||
// to load the course context in calendar_get_allowed_types don't result
|
||||
// in additional DB queries.
|
||||
$courses = calendar_get_default_courses(null, 'id, groupmode, groupmodeforce', true);
|
||||
|
||||
// We want to pre-fetch all of the groups for each course in a single
|
||||
// query to avoid calendar_get_allowed_types from hitting the DB for
|
||||
// each separate course.
|
||||
$groups = groups_get_all_groups_for_courses($courses);
|
||||
|
||||
foreach ($courses as $course) {
|
||||
$coursegroups = isset($groups[$course->id]) ? $groups[$course->id] : null;
|
||||
calendar_get_allowed_types($allowed, $course, $coursegroups);
|
||||
|
||||
if (!empty($allowed->courses)) {
|
||||
$types['course'][$course->id] = $course;
|
||||
}
|
||||
|
||||
if (!empty($allowed->groups)) {
|
||||
$types['groupcourses'][$course->id] = $course;
|
||||
|
||||
if (!isset($types['group'])) {
|
||||
$types['group'] = array_values($allowed->groups);
|
||||
} else {
|
||||
$types['group'] = array_merge($types['group'], array_values($allowed->groups));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $types;
|
||||
}
|
||||
|
||||
/**
|
||||
* See if user can add calendar entries at all used to print the "New Event" button.
|
||||
*
|
||||
@ -3508,18 +3438,18 @@ function calendar_get_view(\calendar_information $calendar, $view, $includenavig
|
||||
*/
|
||||
function calendar_output_fragment_event_form($args) {
|
||||
global $CFG, $OUTPUT, $USER;
|
||||
|
||||
require_once($CFG->libdir . '/grouplib.php');
|
||||
$html = '';
|
||||
$data = [];
|
||||
$eventid = isset($args['eventid']) ? clean_param($args['eventid'], PARAM_INT) : null;
|
||||
$starttime = isset($args['starttime']) ? clean_param($args['starttime'], PARAM_INT) : null;
|
||||
$courseid = isset($args['courseid']) ? clean_param($args['courseid'], PARAM_INT) : null;
|
||||
$courseid = (isset($args['courseid']) && $args['courseid'] != SITEID) ? clean_param($args['courseid'], PARAM_INT) : null;
|
||||
$categoryid = isset($args['categoryid']) ? clean_param($args['categoryid'], PARAM_INT) : null;
|
||||
$event = null;
|
||||
$hasformdata = isset($args['formdata']) && !empty($args['formdata']);
|
||||
$context = \context_user::instance($USER->id);
|
||||
$editoroptions = \core_calendar\local\event\forms\create::build_editor_options($context);
|
||||
$formoptions = ['editoroptions' => $editoroptions];
|
||||
$formoptions = ['editoroptions' => $editoroptions, 'courseid' => $courseid];
|
||||
$draftitemid = 0;
|
||||
|
||||
if ($hasformdata) {
|
||||
@ -3534,6 +3464,13 @@ function calendar_output_fragment_event_form($args) {
|
||||
}
|
||||
|
||||
if (is_null($eventid)) {
|
||||
if (!empty($courseid)) {
|
||||
$groupcoursedata = groups_get_course_data($courseid);
|
||||
$formoptions['groups'] = [];
|
||||
foreach ($groupcoursedata->groups as $groupid => $groupdata) {
|
||||
$formoptions['groups'][$groupid] = $groupdata->name;
|
||||
}
|
||||
}
|
||||
$mform = new \core_calendar\local\event\forms\create(
|
||||
null,
|
||||
$formoptions,
|
||||
@ -3545,16 +3482,19 @@ function calendar_output_fragment_event_form($args) {
|
||||
);
|
||||
|
||||
// Let's check first which event types user can add.
|
||||
calendar_get_allowed_types($allowed, $courseid);
|
||||
$eventtypes = calendar_get_allowed_event_types($courseid);
|
||||
|
||||
// If the user is on course context and is allowed to add course events set the event type default to course.
|
||||
if ($courseid != SITEID && !empty($allowed->courses)) {
|
||||
if ($courseid != SITEID && !empty($eventtypes['course'])) {
|
||||
$data['eventtype'] = 'course';
|
||||
$data['courseid'] = $courseid;
|
||||
$data['groupcourseid'] = $courseid;
|
||||
} else if (!empty($categoryid) && !empty($allowed->category)) {
|
||||
} else if (!empty($categoryid) && !empty($eventtypes['category'])) {
|
||||
$data['eventtype'] = 'category';
|
||||
$data['categoryid'] = $categoryid;
|
||||
} else if (!empty($groupcoursedata) && !empty($eventtypes['group'])) {
|
||||
$data['groupcourseid'] = $courseid;
|
||||
$data['groups'] = $groupcoursedata->groups;
|
||||
}
|
||||
$mform->set_data($data);
|
||||
} else {
|
||||
@ -3564,6 +3504,15 @@ function calendar_output_fragment_event_form($args) {
|
||||
$data = array_merge((array) $eventdata, $data);
|
||||
$event->count_repeats();
|
||||
$formoptions['event'] = $event;
|
||||
|
||||
if (!empty($event->courseid)) {
|
||||
$groupcoursedata = groups_get_course_data($event->courseid);
|
||||
$formoptions['groups'] = [];
|
||||
foreach ($groupcoursedata->groups as $groupid => $groupdata) {
|
||||
$formoptions['groups'][$groupid] = $groupdata->name;
|
||||
}
|
||||
}
|
||||
|
||||
$data['description']['text'] = file_prepare_draft_area(
|
||||
$draftitemid,
|
||||
$event->context->id,
|
||||
@ -3692,3 +3641,163 @@ function calendar_is_valid_eventtype($type) {
|
||||
];
|
||||
return in_array($type, $validtypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get event types the user can create event based on categories, courses and groups
|
||||
* the logged in user belongs to.
|
||||
*
|
||||
* @param int|null $courseid The course id.
|
||||
* @return array The array of allowed types.
|
||||
*/
|
||||
function calendar_get_allowed_event_types(int $courseid = null) {
|
||||
global $DB, $CFG, $USER;
|
||||
|
||||
$types = [
|
||||
'user' => false,
|
||||
'site' => false,
|
||||
'course' => false,
|
||||
'group' => false,
|
||||
'category' => false
|
||||
];
|
||||
|
||||
if (!empty($courseid) && $courseid != SITEID) {
|
||||
$context = \context_course::instance($courseid);
|
||||
$groups = groups_get_all_groups($courseid);
|
||||
|
||||
$types['user'] = has_capability('moodle/calendar:manageownentries', $context);
|
||||
|
||||
if (has_capability('moodle/calendar:manageentries', $context) || !empty($CFG->calendar_adminseesall)) {
|
||||
$types['course'] = true;
|
||||
|
||||
$types['group'] = (!empty($groups) && has_capability('moodle/site:accessallgroups', $context))
|
||||
|| array_filter($groups, function($group) use ($USER) {
|
||||
return groups_is_member($group->id);
|
||||
});
|
||||
} else if (has_capability('moodle/calendar:managegroupentries', $context)) {
|
||||
$types['group'] = (!empty($groups) && has_capability('moodle/site:accessallgroups', $context))
|
||||
|| array_filter($groups, function($group) use ($USER) {
|
||||
return groups_is_member($group->id);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (has_capability('moodle/calendar:manageentries', \context_course::instance(SITEID))) {
|
||||
$types['site'] = true;
|
||||
}
|
||||
|
||||
if (has_capability('moodle/calendar:manageownentries', \context_system::instance())) {
|
||||
$types['user'] = true;
|
||||
}
|
||||
if (coursecat::has_manage_capability_on_any()) {
|
||||
$types['category'] = true;
|
||||
}
|
||||
|
||||
// We still don't know if the user can create group and course events, so iterate over the courses to find out
|
||||
// if the user has capabilities in one of the courses.
|
||||
if ($types['course'] == false || $types['group'] == false) {
|
||||
if ($CFG->calendar_adminseesall && has_capability('moodle/calendar:manageentries', context_system::instance())) {
|
||||
$sql = "SELECT c.id, " . context_helper::get_preload_record_columns_sql('ctx') . "
|
||||
FROM {course} c
|
||||
JOIN {context} ctx ON ctx.contextlevel = ? AND ctx.instanceid = c.id
|
||||
WHERE c.id IN (
|
||||
SELECT DISTINCT courseid FROM {groups}
|
||||
)";
|
||||
$courseswithgroups = $DB->get_recordset_sql($sql, [CONTEXT_COURSE]);
|
||||
foreach ($courseswithgroups as $course) {
|
||||
context_helper::preload_from_record($course);
|
||||
$context = context_course::instance($course->id);
|
||||
|
||||
if (has_capability('moodle/calendar:manageentries', $context)) {
|
||||
if (has_any_capability(['moodle/site:accessallgroups', 'moodle/calendar:managegroupentries'], $context)) {
|
||||
// The user can manage group entries or access any group.
|
||||
$types['group'] = true;
|
||||
$types['course'] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$courseswithgroups->close();
|
||||
|
||||
if (false === $types['course']) {
|
||||
// Course is still not confirmed. There may have been no courses with a group in them.
|
||||
$ctxfields = context_helper::get_preload_record_columns_sql('ctx');
|
||||
$sql = "SELECT
|
||||
c.id, c.visible, {$ctxfields}
|
||||
FROM {course}
|
||||
JOIN {context} ctx ON (ctx.instanceid = c.id AND ctx.contextlevel = :contextlevel)";
|
||||
$params = [
|
||||
'contextlevel' => CONTEXT_COURSE,
|
||||
];
|
||||
$courses = $DB->get_recordset_sql($sql, $params);
|
||||
foreach ($courses as $course) {
|
||||
context_helper::preload_from_record($course);
|
||||
$context = context_course::instance($course->id);
|
||||
if (has_capability('moodle/calendar:manageentries', $context)) {
|
||||
$types['course'] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$courses->close();
|
||||
}
|
||||
|
||||
} else {
|
||||
$courses = calendar_get_default_courses(null, 'id');
|
||||
if (empty($courses)) {
|
||||
return $types;
|
||||
}
|
||||
|
||||
$courseids = array_map(function($c) {
|
||||
return $c->id;
|
||||
}, $courses);
|
||||
|
||||
list($insql, $params) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED);
|
||||
$sql = "SELECT c.id, " . context_helper::get_preload_record_columns_sql('ctx') . "
|
||||
FROM {course} c
|
||||
JOIN {context} ctx ON ctx.contextlevel = :contextlevel AND ctx.instanceid = c.id
|
||||
WHERE c.id $insql
|
||||
AND c.id IN (SELECT DISTINCT courseid FROM {groups})";
|
||||
$params['contextlevel'] = CONTEXT_COURSE;
|
||||
$courseswithgroups = $DB->get_recordset_sql($sql, $params);
|
||||
foreach ($courseswithgroups as $coursewithgroup) {
|
||||
context_helper::preload_from_record($coursewithgroup);
|
||||
$context = context_course::instance($coursewithgroup->id);
|
||||
|
||||
if (has_capability('moodle/calendar:manageentries', $context)) {
|
||||
$types['course'] = true;
|
||||
$types['group'] = (!empty(groups_get_all_groups($coursewithgroup->id, $USER->id))
|
||||
&& has_capability('moodle/calendar:managegroupentries', $context));
|
||||
}
|
||||
|
||||
// Okay, course and group event types are allowed, no need to keep the loop iteration.
|
||||
if ($types['course'] == true && $types['group'] == true) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
$courseswithgroups->close();
|
||||
|
||||
if (false === $types['course']) {
|
||||
list($insql, $params) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED);
|
||||
$contextsql = "SELECT c.id, " . context_helper::get_preload_record_columns_sql('ctx') . "
|
||||
FROM {course} c
|
||||
JOIN {context} ctx ON ctx.contextlevel = :contextlevel AND ctx.instanceid = c.id
|
||||
WHERE c.id $insql
|
||||
GROUP BY c.id, ctx.id";
|
||||
$params['contextlevel'] = CONTEXT_COURSE;
|
||||
$contextrecords = $DB->get_recordset_sql($contextsql, $params);
|
||||
foreach ($contextrecords as $course) {
|
||||
context_helper::preload_from_record($course);
|
||||
$coursecontext = context_course::instance($course->id);
|
||||
if (has_capability('moodle/calendar:manageentries', $coursecontext)
|
||||
&& ($courseid == $course->id || empty($courseid))) {
|
||||
$types['course'] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$contextrecords->close();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return $types;
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ if (!calendar_user_can_add_event($course)) {
|
||||
print_error('errorcannotimport', 'calendar');
|
||||
}
|
||||
|
||||
$form = new \core_calendar\local\event\forms\managesubscriptions();
|
||||
$form = new \core_calendar\local\event\forms\managesubscriptions(null, ['courseid' => $course->id]);
|
||||
$form->set_data(array(
|
||||
'course' => $course->id
|
||||
));
|
||||
@ -105,26 +105,26 @@ if (!empty($formdata)) {
|
||||
}
|
||||
}
|
||||
|
||||
$types = calendar_get_all_allowed_types();
|
||||
$types = calendar_get_allowed_event_types($courseid);
|
||||
|
||||
$searches = [];
|
||||
$params = [];
|
||||
|
||||
$usedefaultfilters = true;
|
||||
if (!empty($courseid) && $courseid == SITEID && isset($types['site'])) {
|
||||
if (!empty($courseid) && $courseid == SITEID && !empty($types['site'])) {
|
||||
$searches[] = "(eventtype = 'site')";
|
||||
$searches[] = "(eventtype = 'user' AND userid = :userid)";
|
||||
$params['userid'] = $USER->id;
|
||||
$usedefaultfilters = false;
|
||||
}
|
||||
|
||||
if (!empty($courseid) && isset($types['course']) && array_key_exists($courseid, $types['course'])) {
|
||||
if (!empty($courseid) && !empty($types['course'])) {
|
||||
$searches[] = "((eventtype = 'course' OR eventtype = 'group') AND courseid = :courseid)";
|
||||
$params += ['courseid' => $courseid];
|
||||
$usedefaultfilters = false;
|
||||
}
|
||||
|
||||
if (!empty($categoryid) && isset($types['category']) && array_key_exists($categoryid, $types['category'])) {
|
||||
if (!empty($categoryid) && !empty($types['category'])) {
|
||||
$searches[] = "(eventtype = 'category' AND categoryid = :categoryid)";
|
||||
$params += ['categoryid' => $categoryid];
|
||||
$usedefaultfilters = false;
|
||||
@ -134,19 +134,27 @@ if ($usedefaultfilters) {
|
||||
$searches[] = "(eventtype = 'user' AND userid = :userid)";
|
||||
$params['userid'] = $USER->id;
|
||||
|
||||
if (isset($types['site'])) {
|
||||
if (!empty($types['site'])) {
|
||||
$searches[] = "(eventtype = 'site' AND courseid = :siteid)";
|
||||
$params += ['siteid' => SITEID];
|
||||
}
|
||||
|
||||
if (isset($types['course'])) {
|
||||
list($courseinsql, $courseparams) = $DB->get_in_or_equal(array_keys($types['course']), SQL_PARAMS_NAMED, 'course');
|
||||
$searches[] = "((eventtype = 'course' OR eventtype = 'group') AND courseid {$courseinsql})";
|
||||
$params += $courseparams;
|
||||
if (!empty($types['course'])) {
|
||||
$courses = calendar_get_default_courses(null, 'id', true);
|
||||
if (!empty($courses)) {
|
||||
$courseids = array_map(function ($c) {
|
||||
return $c->id;
|
||||
}, $courses);
|
||||
|
||||
list($courseinsql, $courseparams) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED, 'course');
|
||||
$searches[] = "((eventtype = 'course' OR eventtype = 'group') AND courseid {$courseinsql})";
|
||||
$params += $courseparams;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($types['category'])) {
|
||||
list($categoryinsql, $categoryparams) = $DB->get_in_or_equal(array_keys($types['category']), SQL_PARAMS_NAMED, 'category');
|
||||
if (!empty($types['category'])) {
|
||||
list($categoryinsql, $categoryparams) = $DB->get_in_or_equal(
|
||||
array_keys(\coursecat::make_categories_list('moodle/category:manage')), SQL_PARAMS_NAMED, 'category');
|
||||
$searches[] = "(eventtype = 'category' AND categoryid {$categoryinsql})";
|
||||
$params += $categoryparams;
|
||||
}
|
||||
|
@ -1989,12 +1989,12 @@ class core_calendar_externallib_testcase extends externallib_advanced_testcase {
|
||||
$this->resetAfterTest(true);
|
||||
$this->setUser($user);
|
||||
|
||||
$this->expectException('moodle_exception');
|
||||
|
||||
external_api::clean_returnvalue(
|
||||
$result = external_api::clean_returnvalue(
|
||||
core_calendar_external::submit_create_update_form_returns(),
|
||||
core_calendar_external::submit_create_update_form($querystring)
|
||||
);
|
||||
|
||||
$this->assertTrue($result['validationerror']);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2027,7 +2027,7 @@ class core_calendar_externallib_testcase extends externallib_advanced_testcase {
|
||||
'minute' => 0,
|
||||
],
|
||||
'eventtype' => 'group',
|
||||
'groupid' => "{$course->id}-{$group->id}", // The form format.
|
||||
'groupid' => $group->id,
|
||||
'groupcourseid' => $course->id,
|
||||
'description' => [
|
||||
'text' => '',
|
||||
@ -2100,7 +2100,7 @@ class core_calendar_externallib_testcase extends externallib_advanced_testcase {
|
||||
'minute' => 0,
|
||||
],
|
||||
'eventtype' => 'group',
|
||||
'groupid' => "{$course->id}-{$group->id}", // The form format.
|
||||
'groupid' => $group->id,
|
||||
'groupcourseid' => $course->id,
|
||||
'description' => [
|
||||
'text' => '',
|
||||
@ -2174,7 +2174,7 @@ class core_calendar_externallib_testcase extends externallib_advanced_testcase {
|
||||
'minute' => 0,
|
||||
],
|
||||
'eventtype' => 'group',
|
||||
'groupid' => "{$course->id}-{$group->id}", // The form format.
|
||||
'groupid' => $group->id,
|
||||
'groupcourseid' => $course->id,
|
||||
'description' => [
|
||||
'text' => '',
|
||||
@ -2248,7 +2248,7 @@ class core_calendar_externallib_testcase extends externallib_advanced_testcase {
|
||||
'minute' => 0,
|
||||
],
|
||||
'eventtype' => 'group',
|
||||
'groupid' => "{$course->id}-{$group->id}", // The form format.
|
||||
'groupid' => $group->id,
|
||||
'groupcourseid' => $course->id,
|
||||
'description' => [
|
||||
'text' => '',
|
||||
|
@ -418,269 +418,6 @@ class core_calendar_lib_testcase extends advanced_testcase {
|
||||
$this->assertCount(3, $events);
|
||||
}
|
||||
|
||||
public function test_calendar_get_all_allowed_types_no_types() {
|
||||
$generator = $this->getDataGenerator();
|
||||
$user = $generator->create_user();
|
||||
$systemcontext = context_system::instance();
|
||||
$sitecontext = context_course::instance(SITEID);
|
||||
$roleid = $generator->create_role();
|
||||
|
||||
$generator->role_assign($roleid, $user->id, $systemcontext->id);
|
||||
$generator->role_assign($roleid, $user->id, $sitecontext->id);
|
||||
$this->setUser($user);
|
||||
|
||||
assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $sitecontext, true);
|
||||
assign_capability('moodle/calendar:manageownentries', CAP_PROHIBIT, $roleid, $systemcontext, true);
|
||||
|
||||
$types = calendar_get_all_allowed_types();
|
||||
$this->assertEmpty($types);
|
||||
}
|
||||
|
||||
public function test_calendar_get_all_allowed_types_user() {
|
||||
$generator = $this->getDataGenerator();
|
||||
$user = $generator->create_user();
|
||||
$context = context_system::instance();
|
||||
$roleid = $generator->create_role();
|
||||
|
||||
$generator->role_assign($roleid, $user->id, $context->id);
|
||||
$this->setUser($user);
|
||||
|
||||
assign_capability('moodle/calendar:manageownentries', CAP_ALLOW, $roleid, $context, true);
|
||||
|
||||
$types = calendar_get_all_allowed_types();
|
||||
$this->assertTrue($types['user']);
|
||||
|
||||
assign_capability('moodle/calendar:manageownentries', CAP_PROHIBIT, $roleid, $context, true);
|
||||
|
||||
$types = calendar_get_all_allowed_types();
|
||||
$this->assertArrayNotHasKey('user', $types);
|
||||
}
|
||||
|
||||
public function test_calendar_get_all_allowed_types_site() {
|
||||
$generator = $this->getDataGenerator();
|
||||
$user = $generator->create_user();
|
||||
$context = context_course::instance(SITEID);
|
||||
$roleid = $generator->create_role();
|
||||
|
||||
$generator->role_assign($roleid, $user->id, $context->id);
|
||||
$this->setUser($user);
|
||||
|
||||
assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
|
||||
|
||||
$types = calendar_get_all_allowed_types();
|
||||
$this->assertTrue($types['site']);
|
||||
|
||||
assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context, true);
|
||||
|
||||
$types = calendar_get_all_allowed_types();
|
||||
$this->assertArrayNotHasKey('site', $types);
|
||||
}
|
||||
|
||||
public function test_calendar_get_all_allowed_types_course() {
|
||||
$generator = $this->getDataGenerator();
|
||||
$user = $generator->create_user();
|
||||
$course1 = $generator->create_course(); // Has capability.
|
||||
$course2 = $generator->create_course(); // Doesn't have capability.
|
||||
$course3 = $generator->create_course(); // Not enrolled.
|
||||
$context1 = context_course::instance($course1->id);
|
||||
$context2 = context_course::instance($course2->id);
|
||||
$context3 = context_course::instance($course3->id);
|
||||
$roleid = $generator->create_role();
|
||||
$contexts = [$context1, $context2, $context3];
|
||||
$enrolledcourses = [$course1, $course2];
|
||||
|
||||
foreach ($enrolledcourses as $course) {
|
||||
$generator->enrol_user($user->id, $course->id, 'student');
|
||||
}
|
||||
|
||||
foreach ($contexts as $context) {
|
||||
$generator->role_assign($roleid, $user->id, $context->id);
|
||||
}
|
||||
|
||||
$this->setUser($user);
|
||||
|
||||
assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context1, true);
|
||||
assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context2, true);
|
||||
|
||||
// The user only has the correct capability in course 1 so that is the only
|
||||
// one that should be in the results.
|
||||
$types = calendar_get_all_allowed_types();
|
||||
$typecourses = $types['course'];
|
||||
$this->assertCount(1, $typecourses);
|
||||
$this->assertEquals($course1->id, $typecourses[$course1->id]->id);
|
||||
|
||||
assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context2, true);
|
||||
|
||||
// The user only now has the correct capability in both course 1 and 2 so we
|
||||
// expect both to be in the results.
|
||||
$types = calendar_get_all_allowed_types();
|
||||
$typecourses = $types['course'];
|
||||
// Sort the results by id ascending to ensure the test is consistent
|
||||
// and repeatable.
|
||||
usort($typecourses, function($a, $b) {
|
||||
$aid = $a->id;
|
||||
$bid = $b->id;
|
||||
|
||||
if ($aid == $bid) {
|
||||
return 0;
|
||||
}
|
||||
return ($aid < $bid) ? -1 : 1;
|
||||
});
|
||||
|
||||
$this->assertCount(2, $typecourses);
|
||||
$this->assertEquals($course1->id, $typecourses[0]->id);
|
||||
$this->assertEquals($course2->id, $typecourses[1]->id);
|
||||
}
|
||||
|
||||
public function test_calendar_get_all_allowed_types_group_no_groups() {
|
||||
$generator = $this->getDataGenerator();
|
||||
$user = $generator->create_user();
|
||||
$course = $generator->create_course();
|
||||
$context = context_course::instance($course->id);
|
||||
$roleid = $generator->create_role();
|
||||
|
||||
$generator->enrol_user($user->id, $course->id, 'student');
|
||||
$generator->role_assign($roleid, $user->id, $context->id);
|
||||
|
||||
$this->setUser($user);
|
||||
|
||||
assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
|
||||
|
||||
// The user has the correct capability in the course but there are
|
||||
// no groups so we shouldn't see a group type.
|
||||
$types = calendar_get_all_allowed_types();
|
||||
$typecourses = $types['course'];
|
||||
$this->assertCount(1, $typecourses);
|
||||
$this->assertEquals($course->id, $typecourses[$course->id]->id);
|
||||
$this->assertArrayNotHasKey('group', $types);
|
||||
$this->assertArrayNotHasKey('groupcourses', $types);
|
||||
}
|
||||
|
||||
public function test_calendar_get_all_allowed_types_group_no_acces_to_diff_groups() {
|
||||
$generator = $this->getDataGenerator();
|
||||
$user = $generator->create_user();
|
||||
$course = $generator->create_course();
|
||||
$context = context_course::instance($course->id);
|
||||
$group1 = $generator->create_group(array('courseid' => $course->id));
|
||||
$group2 = $generator->create_group(array('courseid' => $course->id));
|
||||
$roleid = $generator->create_role();
|
||||
|
||||
$generator->enrol_user($user->id, $course->id, 'student');
|
||||
$generator->role_assign($roleid, $user->id, $context->id);
|
||||
|
||||
$this->setUser($user);
|
||||
|
||||
assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
|
||||
assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT, $roleid, $context, true);
|
||||
|
||||
// The user has the correct capability in the course but they aren't a member
|
||||
// of any of the groups and don't have the accessallgroups capability.
|
||||
$types = calendar_get_all_allowed_types();
|
||||
$typecourses = $types['course'];
|
||||
$this->assertCount(1, $typecourses);
|
||||
$this->assertEquals($course->id, $typecourses[$course->id]->id);
|
||||
$this->assertArrayNotHasKey('group', $types);
|
||||
$this->assertArrayNotHasKey('groupcourses', $types);
|
||||
}
|
||||
|
||||
public function test_calendar_get_all_allowed_types_group_access_all_groups() {
|
||||
$generator = $this->getDataGenerator();
|
||||
$user = $generator->create_user();
|
||||
$course1 = $generator->create_course();
|
||||
$course2 = $generator->create_course();
|
||||
$context1 = context_course::instance($course1->id);
|
||||
$context2 = context_course::instance($course2->id);
|
||||
$group1 = $generator->create_group(array('courseid' => $course1->id));
|
||||
$group2 = $generator->create_group(array('courseid' => $course1->id));
|
||||
$roleid = $generator->create_role();
|
||||
|
||||
$generator->enrol_user($user->id, $course1->id, 'student');
|
||||
$generator->enrol_user($user->id, $course2->id, 'student');
|
||||
$generator->role_assign($roleid, $user->id, $context1->id);
|
||||
$generator->role_assign($roleid, $user->id, $context2->id);
|
||||
|
||||
$this->setUser($user);
|
||||
|
||||
assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context1, true);
|
||||
assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context2, true);
|
||||
assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $roleid, $context1, true);
|
||||
assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $roleid, $context2, true);
|
||||
|
||||
// The user has the correct capability in the course and has
|
||||
// the accessallgroups capability.
|
||||
$types = calendar_get_all_allowed_types();
|
||||
$typecourses = $types['course'];
|
||||
$typegroups = $types['group'];
|
||||
$typegroupcourses = $types['groupcourses'];
|
||||
$idascfunc = function($a, $b) {
|
||||
$aid = $a->id;
|
||||
$bid = $b->id;
|
||||
|
||||
if ($aid == $bid) {
|
||||
return 0;
|
||||
}
|
||||
return ($aid < $bid) ? -1 : 1;
|
||||
};
|
||||
// Sort the results by id ascending to ensure the test is consistent
|
||||
// and repeatable.
|
||||
usort($typecourses, $idascfunc);
|
||||
usort($typegroups, $idascfunc);
|
||||
|
||||
$this->assertCount(2, $typecourses);
|
||||
$this->assertEquals($course1->id, $typecourses[0]->id);
|
||||
$this->assertEquals($course2->id, $typecourses[1]->id);
|
||||
$this->assertCount(1, $typegroupcourses);
|
||||
$this->assertEquals($course1->id, $typegroupcourses[$course1->id]->id);
|
||||
$this->assertCount(2, $typegroups);
|
||||
$this->assertEquals($group1->id, $typegroups[0]->id);
|
||||
$this->assertEquals($group2->id, $typegroups[1]->id);
|
||||
}
|
||||
|
||||
public function test_calendar_get_all_allowed_types_group_no_access_all_groups() {
|
||||
$generator = $this->getDataGenerator();
|
||||
$user = $generator->create_user();
|
||||
$course = $generator->create_course();
|
||||
$context = context_course::instance($course->id);
|
||||
$group1 = $generator->create_group(array('courseid' => $course->id));
|
||||
$group2 = $generator->create_group(array('courseid' => $course->id));
|
||||
$group3 = $generator->create_group(array('courseid' => $course->id));
|
||||
$roleid = $generator->create_role();
|
||||
|
||||
$generator->enrol_user($user->id, $course->id, 'student');
|
||||
$generator->role_assign($roleid, $user->id, $context->id);
|
||||
$generator->create_group_member(array('groupid' => $group1->id, 'userid' => $user->id));
|
||||
$generator->create_group_member(array('groupid' => $group2->id, 'userid' => $user->id));
|
||||
|
||||
$this->setUser($user);
|
||||
|
||||
assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
|
||||
assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT, $roleid, $context, true);
|
||||
|
||||
// The user has the correct capability in the course but can't access
|
||||
// groups that they are not a member of.
|
||||
$types = calendar_get_all_allowed_types();
|
||||
$typegroups = $types['group'];
|
||||
$typegroupcourses = $types['groupcourses'];
|
||||
$idascfunc = function($a, $b) {
|
||||
$aid = $a->id;
|
||||
$bid = $b->id;
|
||||
|
||||
if ($aid == $bid) {
|
||||
return 0;
|
||||
}
|
||||
return ($aid < $bid) ? -1 : 1;
|
||||
};
|
||||
// Sort the results by id ascending to ensure the test is consistent
|
||||
// and repeatable.
|
||||
usort($typegroups, $idascfunc);
|
||||
|
||||
$this->assertCount(1, $typegroupcourses);
|
||||
$this->assertEquals($course->id, $typegroupcourses[$course->id]->id);
|
||||
$this->assertCount(2, $typegroups);
|
||||
$this->assertEquals($group1->id, $typegroups[0]->id);
|
||||
$this->assertEquals($group2->id, $typegroups[1]->id);
|
||||
}
|
||||
|
||||
public function test_calendar_get_default_courses() {
|
||||
global $USER, $CFG;
|
||||
|
||||
@ -765,4 +502,129 @@ class core_calendar_lib_testcase extends advanced_testcase {
|
||||
|
||||
$this->assertEquals($event->id, $data->events[0]->id);
|
||||
}
|
||||
|
||||
public function test_calendar_get_allowed_event_types_course() {
|
||||
$generator = $this->getDataGenerator();
|
||||
$user = $generator->create_user();
|
||||
$course1 = $generator->create_course(); // Has capability.
|
||||
$course2 = $generator->create_course(); // Doesn't have capability.
|
||||
$course3 = $generator->create_course(); // Not enrolled.
|
||||
$context1 = context_course::instance($course1->id);
|
||||
$context2 = context_course::instance($course2->id);
|
||||
$context3 = context_course::instance($course3->id);
|
||||
$roleid = $generator->create_role();
|
||||
$contexts = [$context1, $context2, $context3];
|
||||
$enrolledcourses = [$course1, $course2];
|
||||
|
||||
foreach ($enrolledcourses as $course) {
|
||||
$generator->enrol_user($user->id, $course->id, 'student');
|
||||
}
|
||||
|
||||
foreach ($contexts as $context) {
|
||||
$generator->role_assign($roleid, $user->id, $context->id);
|
||||
}
|
||||
|
||||
$this->setUser($user);
|
||||
|
||||
assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context1, true);
|
||||
assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context2, true);
|
||||
|
||||
// The user only has the correct capability in course 1 so that is the only
|
||||
// one that should be in the results.
|
||||
$types = calendar_get_allowed_event_types($course1->id);
|
||||
$this->assertTrue($types['course']);
|
||||
|
||||
assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context1, true);
|
||||
|
||||
// The user only now has the correct capability in both course 1 and 2 so we
|
||||
// expect both to be in the results.
|
||||
$types = calendar_get_allowed_event_types($course3->id);
|
||||
$this->assertFalse($types['course']);
|
||||
}
|
||||
|
||||
public function test_calendar_get_allowed_event_types_group_no_acces_to_diff_groups() {
|
||||
$generator = $this->getDataGenerator();
|
||||
$user = $generator->create_user();
|
||||
$course = $generator->create_course();
|
||||
$context = context_course::instance($course->id);
|
||||
$roleid = $generator->create_role();
|
||||
|
||||
$generator->enrol_user($user->id, $course->id, 'student');
|
||||
$generator->role_assign($roleid, $user->id, $context->id);
|
||||
|
||||
$this->setUser($user);
|
||||
|
||||
assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
|
||||
assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT, $roleid, $context, true);
|
||||
|
||||
// The user has the correct capability in the course but they aren't a member
|
||||
// of any of the groups and don't have the accessallgroups capability.
|
||||
$types = calendar_get_allowed_event_types($course->id);
|
||||
$this->assertTrue($types['course']);
|
||||
$this->assertFalse($types['group']);
|
||||
}
|
||||
|
||||
public function test_calendar_get_allowed_event_types_group_no_groups() {
|
||||
$generator = $this->getDataGenerator();
|
||||
$user = $generator->create_user();
|
||||
$course = $generator->create_course();
|
||||
$context = context_course::instance($course->id);
|
||||
$roleid = $generator->create_role();
|
||||
$generator->enrol_user($user->id, $course->id, 'student');
|
||||
$generator->role_assign($roleid, $user->id, $context->id);
|
||||
$this->setUser($user);
|
||||
assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
|
||||
// The user has the correct capability in the course but there are
|
||||
// no groups so we shouldn't see a group type.
|
||||
$types = calendar_get_allowed_event_types($course->id);
|
||||
$this->assertTrue($types['course']);
|
||||
}
|
||||
|
||||
public function test_calendar_get_allowed_event_types_group_access_all_groups() {
|
||||
$generator = $this->getDataGenerator();
|
||||
$user = $generator->create_user();
|
||||
$course1 = $generator->create_course();
|
||||
$course2 = $generator->create_course();
|
||||
$generator->create_group(array('courseid' => $course1->id));
|
||||
$generator->create_group(array('courseid' => $course2->id));
|
||||
$context1 = context_course::instance($course1->id);
|
||||
$context2 = context_course::instance($course2->id);
|
||||
$roleid = $generator->create_role();
|
||||
$generator->enrol_user($user->id, $course1->id, 'student');
|
||||
$generator->enrol_user($user->id, $course2->id, 'student');
|
||||
$generator->role_assign($roleid, $user->id, $context1->id);
|
||||
$generator->role_assign($roleid, $user->id, $context2->id);
|
||||
$this->setUser($user);
|
||||
assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context1, true);
|
||||
assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context2, true);
|
||||
assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $roleid, $context1, true);
|
||||
assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $roleid, $context2, true);
|
||||
// The user has the correct capability in the course and has
|
||||
// the accessallgroups capability.
|
||||
$types = calendar_get_allowed_event_types($course1->id);
|
||||
$this->assertTrue($types['group']);
|
||||
}
|
||||
public function test_calendar_get_allowed_event_types_group_no_access_all_groups() {
|
||||
$generator = $this->getDataGenerator();
|
||||
$user = $generator->create_user();
|
||||
$course = $generator->create_course();
|
||||
$context = context_course::instance($course->id);
|
||||
$group1 = $generator->create_group(array('courseid' => $course->id));
|
||||
$group2 = $generator->create_group(array('courseid' => $course->id));
|
||||
$roleid = $generator->create_role();
|
||||
$generator->enrol_user($user->id, $course->id, 'student');
|
||||
$generator->role_assign($roleid, $user->id, $context->id);
|
||||
$generator->create_group_member(array('groupid' => $group1->id, 'userid' => $user->id));
|
||||
$generator->create_group_member(array('groupid' => $group2->id, 'userid' => $user->id));
|
||||
$this->setUser($user);
|
||||
assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT, $roleid, $context, true);
|
||||
// The user has the correct capability in the course but can't access
|
||||
// groups that they are not a member of.
|
||||
$types = calendar_get_allowed_event_types($course->id);
|
||||
$this->assertFalse($types['group']);
|
||||
assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
|
||||
assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $roleid, $context, true);
|
||||
$types = calendar_get_allowed_event_types($course->id);
|
||||
$this->assertTrue($types['group']);
|
||||
}
|
||||
}
|
||||
|
@ -764,6 +764,7 @@ $functions = array(
|
||||
'classpath' => 'group/externallib.php',
|
||||
'description' => 'Returns all groups in specified course.',
|
||||
'type' => 'read',
|
||||
'ajax' => true,
|
||||
'capabilities' => 'moodle/course:managegroups'
|
||||
),
|
||||
'core_group_get_course_user_groups' => array(
|
||||
|
@ -6394,3 +6394,222 @@ function message_delete_message($message, $userid) {
|
||||
|
||||
return \core_message\api::delete_message($userid, $message->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the allowed types for all of the courses and groups
|
||||
* the logged in user belongs to.
|
||||
*
|
||||
* The returned array will optionally have 5 keys:
|
||||
* 'user' : true if the logged in user can create user events
|
||||
* 'site' : true if the logged in user can create site events
|
||||
* 'category' : array of course categories that the user can create events for
|
||||
* 'course' : array of courses that the user can create events for
|
||||
* 'group': array of groups that the user can create events for
|
||||
* 'groupcourses' : array of courses that the groups belong to (can
|
||||
* be different from the list in 'course'.
|
||||
* @deprecated since 3.6
|
||||
* @return array The array of allowed types.
|
||||
*/
|
||||
function calendar_get_all_allowed_types() {
|
||||
debugging('calendar_get_all_allowed_types() is deprecated. Please use calendar_get_allowed_types() instead.',
|
||||
DEBUG_DEVELOPER);
|
||||
|
||||
global $CFG, $USER, $DB;
|
||||
|
||||
require_once($CFG->libdir . '/enrollib.php');
|
||||
|
||||
$types = [];
|
||||
|
||||
$allowed = new stdClass();
|
||||
|
||||
calendar_get_allowed_types($allowed);
|
||||
|
||||
if ($allowed->user) {
|
||||
$types['user'] = true;
|
||||
}
|
||||
|
||||
if ($allowed->site) {
|
||||
$types['site'] = true;
|
||||
}
|
||||
|
||||
if (coursecat::has_manage_capability_on_any()) {
|
||||
$types['category'] = coursecat::make_categories_list('moodle/category:manage');
|
||||
}
|
||||
|
||||
// This function warms the context cache for the course so the calls
|
||||
// to load the course context in calendar_get_allowed_types don't result
|
||||
// in additional DB queries.
|
||||
$courses = calendar_get_default_courses(null, 'id, groupmode, groupmodeforce', true);
|
||||
|
||||
// We want to pre-fetch all of the groups for each course in a single
|
||||
// query to avoid calendar_get_allowed_types from hitting the DB for
|
||||
// each separate course.
|
||||
$groups = groups_get_all_groups_for_courses($courses);
|
||||
|
||||
foreach ($courses as $course) {
|
||||
$coursegroups = isset($groups[$course->id]) ? $groups[$course->id] : null;
|
||||
calendar_get_allowed_types($allowed, $course, $coursegroups);
|
||||
|
||||
if (!empty($allowed->courses)) {
|
||||
$types['course'][$course->id] = $course;
|
||||
}
|
||||
|
||||
if (!empty($allowed->groups)) {
|
||||
$types['groupcourses'][$course->id] = $course;
|
||||
|
||||
if (!isset($types['group'])) {
|
||||
$types['group'] = array_values($allowed->groups);
|
||||
} else {
|
||||
$types['group'] = array_merge($types['group'], array_values($allowed->groups));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets array of all groups in a set of course.
|
||||
*
|
||||
* @category group
|
||||
* @param array $courses Array of course objects or course ids.
|
||||
* @return array Array of groups indexed by course id.
|
||||
*/
|
||||
function groups_get_all_groups_for_courses($courses) {
|
||||
global $DB;
|
||||
|
||||
if (empty($courses)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$groups = [];
|
||||
$courseids = [];
|
||||
|
||||
foreach ($courses as $course) {
|
||||
$courseid = is_object($course) ? $course->id : $course;
|
||||
$groups[$courseid] = [];
|
||||
$courseids[] = $courseid;
|
||||
}
|
||||
|
||||
$groupfields = [
|
||||
'g.id as gid',
|
||||
'g.courseid',
|
||||
'g.idnumber',
|
||||
'g.name',
|
||||
'g.description',
|
||||
'g.descriptionformat',
|
||||
'g.enrolmentkey',
|
||||
'g.picture',
|
||||
'g.hidepicture',
|
||||
'g.timecreated',
|
||||
'g.timemodified'
|
||||
];
|
||||
|
||||
$groupsmembersfields = [
|
||||
'gm.id as gmid',
|
||||
'gm.groupid',
|
||||
'gm.userid',
|
||||
'gm.timeadded',
|
||||
'gm.component',
|
||||
'gm.itemid'
|
||||
];
|
||||
|
||||
$concatidsql = $DB->sql_concat_join("'-'", ['g.id', 'COALESCE(gm.id, 0)']) . ' AS uniqid';
|
||||
list($courseidsql, $params) = $DB->get_in_or_equal($courseids);
|
||||
$groupfieldssql = implode(',', $groupfields);
|
||||
$groupmembersfieldssql = implode(',', $groupsmembersfields);
|
||||
$sql = "SELECT {$concatidsql}, {$groupfieldssql}, {$groupmembersfieldssql}
|
||||
FROM {groups} g
|
||||
LEFT JOIN {groups_members} gm
|
||||
ON gm.groupid = g.id
|
||||
WHERE g.courseid {$courseidsql}";
|
||||
|
||||
$results = $DB->get_records_sql($sql, $params);
|
||||
|
||||
// The results will come back as a flat dataset thanks to the left
|
||||
// join so we will need to do some post processing to blow it out
|
||||
// into a more usable data structure.
|
||||
//
|
||||
// This loop will extract the distinct groups from the result set
|
||||
// and add it's list of members to the object as a property called
|
||||
// 'members'. Then each group will be added to the result set indexed
|
||||
// by it's course id.
|
||||
//
|
||||
// The resulting data structure for $groups should be:
|
||||
// $groups = [
|
||||
// '1' = [
|
||||
// '1' => (object) [
|
||||
// 'id' => 1,
|
||||
// <rest of group properties>
|
||||
// 'members' => [
|
||||
// '1' => (object) [
|
||||
// <group member properties>
|
||||
// ],
|
||||
// '2' => (object) [
|
||||
// <group member properties>
|
||||
// ]
|
||||
// ]
|
||||
// ],
|
||||
// '2' => (object) [
|
||||
// 'id' => 2,
|
||||
// <rest of group properties>
|
||||
// 'members' => [
|
||||
// '1' => (object) [
|
||||
// <group member properties>
|
||||
// ],
|
||||
// '3' => (object) [
|
||||
// <group member properties>
|
||||
// ]
|
||||
// ]
|
||||
// ]
|
||||
// ]
|
||||
// ]
|
||||
//
|
||||
foreach ($results as $key => $result) {
|
||||
$groupid = $result->gid;
|
||||
$courseid = $result->courseid;
|
||||
$coursegroups = $groups[$courseid];
|
||||
$groupsmembersid = $result->gmid;
|
||||
$reducefunc = function($carry, $field) use ($result) {
|
||||
// Iterate over the groups properties and pull
|
||||
// them out into a separate object.
|
||||
list($prefix, $field) = explode('.', $field);
|
||||
|
||||
if (property_exists($result, $field)) {
|
||||
$carry[$field] = $result->{$field};
|
||||
}
|
||||
|
||||
return $carry;
|
||||
};
|
||||
|
||||
if (isset($coursegroups[$groupid])) {
|
||||
$group = $coursegroups[$groupid];
|
||||
} else {
|
||||
$initial = [
|
||||
'id' => $groupid,
|
||||
'members' => []
|
||||
];
|
||||
$group = (object) array_reduce(
|
||||
$groupfields,
|
||||
$reducefunc,
|
||||
$initial
|
||||
);
|
||||
}
|
||||
|
||||
if (!empty($groupsmembersid)) {
|
||||
$initial = ['id' => $groupsmembersid];
|
||||
$groupsmembers = (object) array_reduce(
|
||||
$groupsmembersfields,
|
||||
$reducefunc,
|
||||
$initial
|
||||
);
|
||||
|
||||
$group->members[$groupsmembers->userid] = $groupsmembers;
|
||||
}
|
||||
|
||||
$coursegroups[$groupid] = $group;
|
||||
$groups[$courseid] = $coursegroups;
|
||||
}
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
146
lib/grouplib.php
146
lib/grouplib.php
@ -295,152 +295,6 @@ function groups_get_all_groups($courseid, $userid=0, $groupingid=0, $fields='g.*
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets array of all groups in a set of course.
|
||||
*
|
||||
* @category group
|
||||
* @param array $courses Array of course objects or course ids.
|
||||
* @return array Array of groups indexed by course id.
|
||||
*/
|
||||
function groups_get_all_groups_for_courses($courses) {
|
||||
global $DB;
|
||||
|
||||
if (empty($courses)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$groups = [];
|
||||
$courseids = [];
|
||||
|
||||
foreach ($courses as $course) {
|
||||
$courseid = is_object($course) ? $course->id : $course;
|
||||
$groups[$courseid] = [];
|
||||
$courseids[] = $courseid;
|
||||
}
|
||||
|
||||
$groupfields = [
|
||||
'g.id as gid',
|
||||
'g.courseid',
|
||||
'g.idnumber',
|
||||
'g.name',
|
||||
'g.description',
|
||||
'g.descriptionformat',
|
||||
'g.enrolmentkey',
|
||||
'g.picture',
|
||||
'g.hidepicture',
|
||||
'g.timecreated',
|
||||
'g.timemodified'
|
||||
];
|
||||
|
||||
$groupsmembersfields = [
|
||||
'gm.id as gmid',
|
||||
'gm.groupid',
|
||||
'gm.userid',
|
||||
'gm.timeadded',
|
||||
'gm.component',
|
||||
'gm.itemid'
|
||||
];
|
||||
|
||||
$concatidsql = $DB->sql_concat_join("'-'", ['g.id', 'COALESCE(gm.id, 0)']) . ' AS uniqid';
|
||||
list($courseidsql, $params) = $DB->get_in_or_equal($courseids);
|
||||
$groupfieldssql = implode(',', $groupfields);
|
||||
$groupmembersfieldssql = implode(',', $groupsmembersfields);
|
||||
$sql = "SELECT {$concatidsql}, {$groupfieldssql}, {$groupmembersfieldssql}
|
||||
FROM {groups} g
|
||||
LEFT JOIN {groups_members} gm
|
||||
ON gm.groupid = g.id
|
||||
WHERE g.courseid {$courseidsql}";
|
||||
|
||||
$results = $DB->get_records_sql($sql, $params);
|
||||
|
||||
// The results will come back as a flat dataset thanks to the left
|
||||
// join so we will need to do some post processing to blow it out
|
||||
// into a more usable data structure.
|
||||
//
|
||||
// This loop will extract the distinct groups from the result set
|
||||
// and add it's list of members to the object as a property called
|
||||
// 'members'. Then each group will be added to the result set indexed
|
||||
// by it's course id.
|
||||
//
|
||||
// The resulting data structure for $groups should be:
|
||||
// $groups = [
|
||||
// '1' = [
|
||||
// '1' => (object) [
|
||||
// 'id' => 1,
|
||||
// <rest of group properties>
|
||||
// 'members' => [
|
||||
// '1' => (object) [
|
||||
// <group member properties>
|
||||
// ],
|
||||
// '2' => (object) [
|
||||
// <group member properties>
|
||||
// ]
|
||||
// ]
|
||||
// ],
|
||||
// '2' => (object) [
|
||||
// 'id' => 2,
|
||||
// <rest of group properties>
|
||||
// 'members' => [
|
||||
// '1' => (object) [
|
||||
// <group member properties>
|
||||
// ],
|
||||
// '3' => (object) [
|
||||
// <group member properties>
|
||||
// ]
|
||||
// ]
|
||||
// ]
|
||||
// ]
|
||||
// ]
|
||||
//
|
||||
foreach ($results as $key => $result) {
|
||||
$groupid = $result->gid;
|
||||
$courseid = $result->courseid;
|
||||
$coursegroups = $groups[$courseid];
|
||||
$groupsmembersid = $result->gmid;
|
||||
$reducefunc = function($carry, $field) use ($result) {
|
||||
// Iterate over the groups properties and pull
|
||||
// them out into a separate object.
|
||||
list($prefix, $field) = explode('.', $field);
|
||||
|
||||
if (property_exists($result, $field)) {
|
||||
$carry[$field] = $result->{$field};
|
||||
}
|
||||
|
||||
return $carry;
|
||||
};
|
||||
|
||||
if (isset($coursegroups[$groupid])) {
|
||||
$group = $coursegroups[$groupid];
|
||||
} else {
|
||||
$initial = [
|
||||
'id' => $groupid,
|
||||
'members' => []
|
||||
];
|
||||
$group = (object) array_reduce(
|
||||
$groupfields,
|
||||
$reducefunc,
|
||||
$initial
|
||||
);
|
||||
}
|
||||
|
||||
if (!empty($groupsmembersid)) {
|
||||
$initial = ['id' => $groupsmembersid];
|
||||
$groupsmembers = (object) array_reduce(
|
||||
$groupsmembersfields,
|
||||
$reducefunc,
|
||||
$initial
|
||||
);
|
||||
|
||||
$group->members[$groupsmembers->userid] = $groupsmembers;
|
||||
}
|
||||
|
||||
$coursegroups[$groupid] = $group;
|
||||
$groups[$courseid] = $coursegroups;
|
||||
}
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets array of all groups in current user.
|
||||
*
|
||||
|
@ -1547,168 +1547,4 @@ class core_grouplib_testcase extends advanced_testcase {
|
||||
$this->assertCount(2, $members); // Now I see members of group 3.
|
||||
$this->assertEquals([$user1->id, $user3->id], array_keys($members), '', 0.0, 10, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test groups_get_all_groups_for_courses() method.
|
||||
*/
|
||||
public function test_groups_get_all_groups_for_courses_no_courses() {
|
||||
$this->resetAfterTest(true);
|
||||
$generator = $this->getDataGenerator();
|
||||
|
||||
$this->assertEquals([], groups_get_all_groups_for_courses([]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test groups_get_all_groups_for_courses() method.
|
||||
*/
|
||||
public function test_groups_get_all_groups_for_courses_with_courses() {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest(true);
|
||||
$generator = $this->getDataGenerator();
|
||||
|
||||
// Create courses.
|
||||
$course1 = $generator->create_course(); // no groups.
|
||||
$course2 = $generator->create_course(); // one group, no members.
|
||||
$course3 = $generator->create_course(); // one group, one member.
|
||||
$course4 = $generator->create_course(); // one group, multiple members.
|
||||
$course5 = $generator->create_course(); // two groups, no members.
|
||||
$course6 = $generator->create_course(); // two groups, one member.
|
||||
$course7 = $generator->create_course(); // two groups, multiple members.
|
||||
|
||||
$courses = [$course1, $course2, $course3, $course4, $course5, $course6, $course7];
|
||||
// Create users.
|
||||
$user1 = $generator->create_user();
|
||||
$user2 = $generator->create_user();
|
||||
$user3 = $generator->create_user();
|
||||
$user4 = $generator->create_user();
|
||||
|
||||
// Enrol users.
|
||||
foreach ($courses as $course) {
|
||||
$generator->enrol_user($user1->id, $course->id);
|
||||
$generator->enrol_user($user2->id, $course->id);
|
||||
$generator->enrol_user($user3->id, $course->id);
|
||||
$generator->enrol_user($user4->id, $course->id);
|
||||
}
|
||||
|
||||
// Create groups.
|
||||
$group1 = $generator->create_group(array('courseid' => $course2->id)); // no members.
|
||||
$group2 = $generator->create_group(array('courseid' => $course3->id)); // one member.
|
||||
$group3 = $generator->create_group(array('courseid' => $course4->id)); // multiple members.
|
||||
$group4 = $generator->create_group(array('courseid' => $course5->id)); // no members.
|
||||
$group5 = $generator->create_group(array('courseid' => $course5->id)); // no members.
|
||||
$group6 = $generator->create_group(array('courseid' => $course6->id)); // one member.
|
||||
$group7 = $generator->create_group(array('courseid' => $course6->id)); // one member.
|
||||
$group8 = $generator->create_group(array('courseid' => $course7->id)); // multiple members.
|
||||
$group9 = $generator->create_group(array('courseid' => $course7->id)); // multiple members.
|
||||
|
||||
// Assign users to groups.
|
||||
$generator->create_group_member(array('groupid' => $group2->id, 'userid' => $user1->id));
|
||||
$generator->create_group_member(array('groupid' => $group3->id, 'userid' => $user1->id));
|
||||
$generator->create_group_member(array('groupid' => $group3->id, 'userid' => $user2->id));
|
||||
$generator->create_group_member(array('groupid' => $group6->id, 'userid' => $user1->id));
|
||||
$generator->create_group_member(array('groupid' => $group7->id, 'userid' => $user1->id));
|
||||
$generator->create_group_member(array('groupid' => $group8->id, 'userid' => $user1->id));
|
||||
$generator->create_group_member(array('groupid' => $group8->id, 'userid' => $user2->id));
|
||||
$generator->create_group_member(array('groupid' => $group9->id, 'userid' => $user1->id));
|
||||
$generator->create_group_member(array('groupid' => $group9->id, 'userid' => $user2->id));
|
||||
|
||||
// The process of modifying group members changes the timemodified of the group.
|
||||
// Refresh the group records.
|
||||
$group1 = $DB->get_record('groups', ['id' => $group1->id]);
|
||||
$group2 = $DB->get_record('groups', ['id' => $group2->id]);
|
||||
$group3 = $DB->get_record('groups', ['id' => $group3->id]);
|
||||
$group4 = $DB->get_record('groups', ['id' => $group4->id]);
|
||||
$group5 = $DB->get_record('groups', ['id' => $group5->id]);
|
||||
$group6 = $DB->get_record('groups', ['id' => $group6->id]);
|
||||
$group7 = $DB->get_record('groups', ['id' => $group7->id]);
|
||||
$group8 = $DB->get_record('groups', ['id' => $group8->id]);
|
||||
$group9 = $DB->get_record('groups', ['id' => $group9->id]);
|
||||
|
||||
$result = groups_get_all_groups_for_courses($courses);
|
||||
$assertpropertiesmatch = function($expected, $actual) {
|
||||
$props = get_object_vars($expected);
|
||||
|
||||
foreach ($props as $name => $val) {
|
||||
$got = $actual->{$name};
|
||||
$this->assertEquals(
|
||||
$val,
|
||||
$actual->{$name},
|
||||
"Failed asserting that {$got} equals {$val} for property {$name}"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Course 1 has no groups.
|
||||
$this->assertEquals([], $result[$course1->id]);
|
||||
|
||||
// Course 2 has one group with no members.
|
||||
$coursegroups = $result[$course2->id];
|
||||
$coursegroup = $coursegroups[$group1->id];
|
||||
$this->assertCount(1, $coursegroups);
|
||||
$this->assertEquals([], $coursegroup->members);
|
||||
$assertpropertiesmatch($group1, $coursegroup);
|
||||
|
||||
// Course 3 has one group with one member.
|
||||
$coursegroups = $result[$course3->id];
|
||||
$coursegroup = $coursegroups[$group2->id];
|
||||
$groupmember1 = $coursegroup->members[$user1->id];
|
||||
$this->assertCount(1, $coursegroups);
|
||||
$this->assertCount(1, $coursegroup->members);
|
||||
$assertpropertiesmatch($group2, $coursegroup);
|
||||
$this->assertEquals($user1->id, $groupmember1->userid);
|
||||
|
||||
// Course 4 has one group with multiple members.
|
||||
$coursegroups = $result[$course4->id];
|
||||
$coursegroup = $coursegroups[$group3->id];
|
||||
$groupmember1 = $coursegroup->members[$user1->id];
|
||||
$groupmember2 = $coursegroup->members[$user2->id];
|
||||
$this->assertCount(1, $coursegroups);
|
||||
$this->assertCount(2, $coursegroup->members);
|
||||
$assertpropertiesmatch($group3, $coursegroup);
|
||||
$this->assertEquals($user1->id, $groupmember1->userid);
|
||||
$this->assertEquals($user2->id, $groupmember2->userid);
|
||||
|
||||
// Course 5 has multiple groups with no members.
|
||||
$coursegroups = $result[$course5->id];
|
||||
$coursegroup1 = $coursegroups[$group4->id];
|
||||
$coursegroup2 = $coursegroups[$group5->id];
|
||||
$this->assertCount(2, $coursegroups);
|
||||
$this->assertEquals([], $coursegroup1->members);
|
||||
$this->assertEquals([], $coursegroup2->members);
|
||||
$assertpropertiesmatch($group4, $coursegroup1);
|
||||
$assertpropertiesmatch($group5, $coursegroup2);
|
||||
|
||||
// Course 6 has multiple groups with one member.
|
||||
$coursegroups = $result[$course6->id];
|
||||
$coursegroup1 = $coursegroups[$group6->id];
|
||||
$coursegroup2 = $coursegroups[$group7->id];
|
||||
$group1member1 = $coursegroup1->members[$user1->id];
|
||||
$group2member1 = $coursegroup2->members[$user1->id];
|
||||
$this->assertCount(2, $coursegroups);
|
||||
$this->assertCount(1, $coursegroup1->members);
|
||||
$this->assertCount(1, $coursegroup2->members);
|
||||
$assertpropertiesmatch($group6, $coursegroup1);
|
||||
$assertpropertiesmatch($group7, $coursegroup2);
|
||||
$this->assertEquals($user1->id, $group1member1->userid);
|
||||
$this->assertEquals($user1->id, $group2member1->userid);
|
||||
|
||||
// Course 7 has multiple groups with multiple members.
|
||||
$coursegroups = $result[$course7->id];
|
||||
$coursegroup1 = $coursegroups[$group8->id];
|
||||
$coursegroup2 = $coursegroups[$group9->id];
|
||||
$group1member1 = $coursegroup1->members[$user1->id];
|
||||
$group1member2 = $coursegroup1->members[$user2->id];
|
||||
$group2member1 = $coursegroup2->members[$user1->id];
|
||||
$group2member2 = $coursegroup2->members[$user2->id];
|
||||
$this->assertCount(2, $coursegroups);
|
||||
$this->assertCount(2, $coursegroup1->members);
|
||||
$this->assertCount(2, $coursegroup2->members);
|
||||
$assertpropertiesmatch($group8, $coursegroup1);
|
||||
$assertpropertiesmatch($group9, $coursegroup2);
|
||||
$this->assertEquals($user1->id, $group1member1->userid);
|
||||
$this->assertEquals($user2->id, $group1member2->userid);
|
||||
$this->assertEquals($user1->id, $group2member1->userid);
|
||||
$this->assertEquals($user2->id, $group2member2->userid);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user