Skip to content

Commit

Permalink
MDL-58736 core_calendar: Revert calendar_get_events to 3.2 implementa…
Browse files Browse the repository at this point in the history
…tion

We modified calendar_get_events in a non backwards compatible way
so instead of fixing that, an easier approch is to simply revert
it to the 3.2 implementation. This should be fine since the way
to get events is going to change in an upcomming release, and we
had to swap all occurences of calendar_get_events in core with
calendar_get_legacy_events to make sure the calendar and overview match.
  • Loading branch information
cameorn1730 committed May 4, 2017
1 parent 932bc91 commit eeb27f0
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 303 deletions.
179 changes: 42 additions & 137 deletions calendar/lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -1076,186 +1076,91 @@ public function add_sidecalendar_blocks(core_calendar_renderer $renderer, $showf
* @return array $events of selected events or an empty array if there aren't any (or there was an error)
*/
function calendar_get_events($tstart, $tend, $users, $groups, $courses, $withduration=true, $ignorehidden=true) {
// We have a new implementation of this function in the calendar API class, which has slightly different behaviour
// so the old implementation must remain here.
global $DB;
$params = array();

$whereclause = '';
$params = array();
// Quick test.
if (empty($users) && empty($groups) && empty($courses)) {
return array();
}

// Array of filter conditions. To be concatenated by the OR operator.
$filters = [];

// User filter.
if ((is_array($users) && !empty($users)) or is_numeric($users)) {
// Events from a number of users.
// Events from a number of users
if(!empty($whereclause)) $whereclause .= ' OR';
list($insqlusers, $inparamsusers) = $DB->get_in_or_equal($users, SQL_PARAMS_NAMED);
$filters[] = "(e.userid $insqlusers AND e.courseid = 0 AND e.groupid = 0)";
$whereclause .= " (e.userid $insqlusers AND e.courseid = 0 AND e.groupid = 0)";
$params = array_merge($params, $inparamsusers);
} else if ($users === true) {
// Events from ALL users.
$filters[] = "(e.userid != 0 AND e.courseid = 0 AND e.groupid = 0)";
} else if($users === true) {
// Events from ALL users
if(!empty($whereclause)) $whereclause .= ' OR';
$whereclause .= ' (e.userid != 0 AND e.courseid = 0 AND e.groupid = 0)';
} else if($users === false) {
// No user at all, do nothing
}

// Boolean false (no users at all): We don't need to do anything.
// Group filter.
if ((is_array($groups) && !empty($groups)) or is_numeric($groups)) {
// Events from a number of groups.
// Events from a number of groups
if(!empty($whereclause)) $whereclause .= ' OR';
list($insqlgroups, $inparamsgroups) = $DB->get_in_or_equal($groups, SQL_PARAMS_NAMED);
$filters[] = "e.groupid $insqlgroups";
$whereclause .= " e.groupid $insqlgroups ";
$params = array_merge($params, $inparamsgroups);
} else if ($groups === true) {
// Events from ALL groups.
$filters[] = "e.groupid != 0";
} else if($groups === true) {
// Events from ALL groups
if(!empty($whereclause)) $whereclause .= ' OR ';
$whereclause .= ' e.groupid != 0';
}
// boolean false (no groups at all): we don't need to do anything

// Boolean false (no groups at all): We don't need to do anything.
// Course filter.
if ((is_array($courses) && !empty($courses)) or is_numeric($courses)) {
if(!empty($whereclause)) $whereclause .= ' OR';
list($insqlcourses, $inparamscourses) = $DB->get_in_or_equal($courses, SQL_PARAMS_NAMED);
$filters[] = "(e.groupid = 0 AND e.courseid $insqlcourses)";
$whereclause .= " (e.groupid = 0 AND e.courseid $insqlcourses)";
$params = array_merge($params, $inparamscourses);
} else if ($courses === true) {
// Events from ALL courses.
$filters[] = "(e.groupid = 0 AND e.courseid != 0)";
// Events from ALL courses
if(!empty($whereclause)) $whereclause .= ' OR';
$whereclause .= ' (e.groupid = 0 AND e.courseid != 0)';
}

// Security check: if, by now, we have NOTHING in $whereclause, then it means
// that NO event-selecting clauses were defined. Thus, we won't be returning ANY
// events no matter what. Allowing the code to proceed might return a completely
// valid query with only time constraints, thus selecting ALL events in that time frame!
if (empty($filters)) {
if(empty($whereclause)) {
return array();
}

// Build our clause for the filters.
$filterclause = implode(' OR ', $filters);

// Array of where conditions for our query. To be concatenated by the AND operator.
$whereconditions = ["($filterclause)"];

// Time clause.
if ($withduration) {
$timeclause = "((e.timestart >= :tstart1 OR e.timestart + e.timeduration > :tstart2) AND e.timestart <= :tend)";
$params['tstart1'] = $tstart;
$params['tstart2'] = $tstart;
$params['tend'] = $tend;
} else {
$timeclause = "(e.timestart >= :tstart AND e.timestart <= :tend)";
$params['tstart'] = $tstart;
$params['tend'] = $tend;
}
$whereconditions[] = $timeclause;

// Show visible only.
if ($ignorehidden) {
$whereconditions[] = "(e.visible = 1)";
}

// Build the main query's WHERE clause.
$whereclause = implode(' AND ', $whereconditions);

// Build SQL subquery and conditions for filtered events based on priorities.
$subquerywhere = '';
$subqueryconditions = [];

// Get the user's courses. Otherwise, get the default courses being shown by the calendar.
$usercourses = calendar_get_default_courses();

// Set calendar filters.
list($usercourses, $usergroups, $user) = calendar_set_filters($usercourses, true);
$subqueryparams = [];

// Flag to indicate whether the query needs to exclude group overrides.
$viewgroupsonly = false;
if ($user) {
// Set filter condition for the user's events.
$subqueryconditions[] = "(ev.userid = :user AND ev.courseid = 0 AND ev.groupid = 0)";
$subqueryparams['user'] = $user;
foreach ($usercourses as $courseid) {
if (has_capability('moodle/site:accessallgroups', context_course::instance($courseid))) {
$usergroupmembership = groups_get_all_groups($courseid, $user, 0, 'g.id');
if (count($usergroupmembership) == 0) {
$viewgroupsonly = true;
break;
}
}
}
}

// Set filter condition for the user's group events.
if ($usergroups === true || $viewgroupsonly) {
// Fetch group events, but not group overrides.
$subqueryconditions[] = "(ev.groupid != 0 AND ev.eventtype = 'group')";
} else if (!empty($usergroups)) {
// Fetch group events and group overrides.
list($inusergroups, $inusergroupparams) = $DB->get_in_or_equal($usergroups, SQL_PARAMS_NAMED);
$subqueryconditions[] = "(ev.groupid $inusergroups)";
$subqueryparams = array_merge($subqueryparams, $inusergroupparams);
if($withduration) {
$timeclause = '(e.timestart >= '.$tstart.' OR e.timestart + e.timeduration > '.$tstart.') AND e.timestart <= '.$tend;
}

// Get courses to be used for the subquery.
$subquerycourses = [];
if (is_array($courses)) {
$subquerycourses = $courses;
} else if (is_numeric($courses)) {
$subquerycourses[] = $courses;
else {
$timeclause = 'e.timestart >= '.$tstart.' AND e.timestart <= '.$tend;
}

// Merge with user courses, if necessary.
if (!empty($usercourses)) {
$subquerycourses = array_merge($subquerycourses, $usercourses);
// Make sure we remove duplicate values.
$subquerycourses = array_unique($subquerycourses);
if(!empty($whereclause)) {
// We have additional constraints
$whereclause = $timeclause.' AND ('.$whereclause.')';
}

// Set subquery filter condition for the courses.
if (!empty($subquerycourses)) {
list($incourses, $incoursesparams) = $DB->get_in_or_equal($subquerycourses, SQL_PARAMS_NAMED);
$subqueryconditions[] = "(ev.groupid = 0 AND ev.courseid $incourses)";
$subqueryparams = array_merge($subqueryparams, $incoursesparams);
else {
// Just basic time filtering
$whereclause = $timeclause;
}

// Build the WHERE condition for the sub-query.
if (!empty($subqueryconditions)) {
$subquerywhere = 'WHERE ' . implode(" OR ", $subqueryconditions);
}

// Merge subquery parameters to the parameters of the main query.
if (!empty($subqueryparams)) {
$params = array_merge($params, $subqueryparams);
if ($ignorehidden) {
$whereclause .= ' AND e.visible = 1';
}

// Sub-query that fetches the list of unique events that were filtered based on priority.
$subquery = "SELECT ev.modulename,
ev.instance,
ev.eventtype,
MIN(ev.priority) as priority
FROM {event} ev
$subquerywhere
GROUP BY ev.modulename, ev.instance, ev.eventtype";

// Build the main query.
$sql = "SELECT e.*
FROM {event} e
INNER JOIN ($subquery) fe
ON e.modulename = fe.modulename
AND e.instance = fe.instance
AND e.eventtype = fe.eventtype
AND (e.priority = fe.priority OR (e.priority IS NULL AND fe.priority IS NULL))
LEFT JOIN {modules} m
ON e.modulename = m.name
WHERE (m.visible = 1 OR m.visible IS NULL) AND $whereclause
ORDER BY e.timestart";
FROM {event} e
LEFT JOIN {modules} m ON e.modulename = m.name
-- Non visible modules will have a value of 0.
WHERE (m.visible = 1 OR m.visible IS NULL) AND $whereclause
ORDER BY e.timestart";
$events = $DB->get_records_sql($sql, $params);

if ($events === false) {
$events = array();
}

return $events;
}

Expand Down
Loading

0 comments on commit eeb27f0

Please sign in to comment.