MDL-57503 enrol: allow course ids for enrol_get_my_courses
[moodle.git] / calendar / classes / local / event / data_access / event_vault.php
CommitLineData
84d865d6
RW
1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * Event vault class
19 *
20 * @package core_calendar
21 * @copyright 2017 Ryan Wyllie <ryan@moodle.com>
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25namespace core_calendar\local\event\data_access;
26
27use core_calendar\local\event\exceptions\limit_invalid_parameter_exception;
28use core_calendar\local\event\exceptions\timesort_invalid_parameter_exception;
29use core_calendar\local\interfaces\action_event_interface;
30use core_calendar\local\interfaces\event_interface;
31use core_calendar\local\interfaces\event_factory_interface;
32use core_calendar\local\interfaces\event_vault_interface;
33
34/**
35 * This class will handle interacting with the database layer to retrieve
36 * the records. This is required to house the complex logic required for
37 * pagination because it's not a one-to-one mapping between database records
38 * and users.
39 *
40 * This is a repository. It's called a vault to reduce confusion because
41 * Moodle has already taken the name repository. Vault is cooler anyway.
42 *
43 * @copyright 2017 Ryan Wyllie <ryan@moodle.com>
44 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
45 */
46class event_vault implements event_vault_interface {
47
48 private $factory;
49
50 /**
51 * Create an event vault.
52 *
53 * @param event_factory_interface $factory An event factory
54 */
55 public function __construct(event_factory_interface $factory) {
56 $this->factory = $factory;
57 }
58
59 /**
60 * Retrieve an event for the given id.
61 *
5e6e3bab 62 * @param int $id The event id
84d865d6
RW
63 * @return event_interface
64 */
5e6e3bab 65 public function get_event_by_id($id) {
84d865d6
RW
66 global $DB;
67
68 if ($record = $DB->get_record('event', ['id' => $id])) {
69 return $this->transform_from_database_record($record);
70 } else {
71 return false;
72 }
73 }
74
75 /**
76 * Retrieve an array of events for the given user and time constraints.
77 *
78 * @param \stdClass $user The user for whom the events belong
79 * @param int|null $timesortfrom Events with timesort from this value (inclusive)
80 * @param int|null $timesortto Events with timesort until this value (inclusive)
81 * @param event_interface|null $afterevent Only return events after this one
82 * @param int $limitnum Return at most this number of events
5e6e3bab
MN
83 * @throws timesort_invalid_parameter_exception
84 * @throws limit_invalid_parameter_exception
84d865d6
RW
85 * @return action_event_interface
86 */
87 public function get_action_events_by_timesort(
88 \stdClass $user,
5e6e3bab
MN
89 $timesortfrom = null,
90 $timesortto = null,
84d865d6 91 event_interface $afterevent = null,
5e6e3bab 92 $limitnum = 20
84d865d6
RW
93 ) {
94 global $DB;
95
96 if (is_null($timesortfrom) && is_null($timesortto)) {
97 throw new timesort_invalid_parameter_exception("Must provide a timesort to and/or from value");
98 }
99
100 if ($limitnum < 1 || $limitnum > 50) {
101 throw new limit_invalid_parameter_exception("Limit must be between 1 and 50 (inclusive)");
102 }
103
104 $params = ['type' => CALENDAR_EVENT_TYPE_ACTION];
105 $where = ['type = :type'];
106
107 if ($timesortfrom) {
108 $where[] = 'timesort >= :timesortfrom';
109 $params['timesortfrom'] = $timesortfrom;
110 }
111
112 if ($timesortto) {
113 $where[] = 'timesort <= :timesortto';
114 $params['timesortto'] = $timesortto;
115 }
116
117 if (!is_null($afterevent)) {
118 $where[] = 'id > :id';
119 $params['id'] = $afterevent->get_id();
120 }
121
122 $sql = sprintf("SELECT * FROM {event} WHERE %s ORDER BY timesort ASC, id ASC",
123 implode(' AND ', $where));
124
125 $offset = 0;
126 $events = [];
127 // We need to continue to pull records from the database until we reach
128 // the requested amount of events because not all records in the database
129 // will be visible for the current user.
130 while ($records = array_values($DB->get_records_sql($sql, $params, $offset, $limitnum))) {
131 foreach ($records as $record) {
132 if ($event = $this->transform_from_database_record($record)) {
133 if ($event instanceof action_event_interface) {
134 $events[] = $event;
135 }
136
137 if (count($events) == $limitnum) {
138 // We've got all of the events so break both loops.
139 break 2;
140 }
141 }
142 }
143
144 $offset += $limitnum;
145 }
146
147 return $events;
148 }
149
150 /**
151 * Create an event from a database record.
152 *
153 * @param \stdClass $record The database record
154 * @return event_interface|false
155 */
156 private function transform_from_database_record(\stdClass $record) {
157 return $this->factory->create_instance($record);
158 }
84d865d6 159}