diff --git a/calendar/classes/local/event/core_container.php b/calendar/classes/local/event/core_container.php index 4811ea60ed2..9776d5c68ce 100644 --- a/calendar/classes/local/event/core_container.php +++ b/calendar/classes/local/event/core_container.php @@ -33,6 +33,7 @@ defined('MOODLE_INTERNAL') || die(); use core_calendar\action_factory; use core_calendar\local\event\factories\action_event_factory; use core_calendar\local\event\factories\event_factory; +use core_calendar\local\event\factories\event_vault_factory; use core_calendar\local\event\mappers\event_mapper; use core_calendar\local\interfaces\event_interface; @@ -63,6 +64,11 @@ class core_container { */ protected static $actionfactory; + /** + * @var event_vault $eventvault Event vault. + */ + private static $eventvault; + /** * Initialises the dependency graph if it hasn't yet been. */ @@ -93,6 +99,11 @@ class core_container { } ); } + + if (empty(self::$eventvault)) { + $vaultfactory = new event_vault_factory(); + self::$eventvault = $vaultfactory->create_instance(self::$eventfactory); + } } /** @@ -114,4 +125,14 @@ class core_container { self::init(); return self::$eventmapper; } + + /** + * Return an event vault. + * + * @return event_vault + */ + public static function get_event_vault() { + self::init(); + return self::$eventvault; + } } diff --git a/calendar/classes/local/event/data_access/event_vault.php b/calendar/classes/local/event/data_access/event_vault.php new file mode 100644 index 00000000000..019d491a8c0 --- /dev/null +++ b/calendar/classes/local/event/data_access/event_vault.php @@ -0,0 +1,174 @@ +. + +/** + * Event vault class + * + * @package core_calendar + * @copyright 2017 Ryan Wyllie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_calendar\local\event\data_access; + +use core_calendar\local\event\exceptions\limit_invalid_parameter_exception; +use core_calendar\local\event\exceptions\timesort_invalid_parameter_exception; +use core_calendar\local\interfaces\action_event_interface; +use core_calendar\local\interfaces\event_interface; +use core_calendar\local\interfaces\event_factory_interface; +use core_calendar\local\interfaces\event_vault_interface; + +/** + * This class will handle interacting with the database layer to retrieve + * the records. This is required to house the complex logic required for + * pagination because it's not a one-to-one mapping between database records + * and users. + * + * This is a repository. It's called a vault to reduce confusion because + * Moodle has already taken the name repository. Vault is cooler anyway. + * + * @copyright 2017 Ryan Wyllie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class event_vault implements event_vault_interface { + + private $factory; + + /** + * Create an event vault. + * + * @param event_factory_interface $factory An event factory + */ + public function __construct(event_factory_interface $factory) { + $this->factory = $factory; + } + + /** + * Retrieve an event for the given id. + * + * @param in $id The event id + * @return event_interface + */ + public function get_event_by_id(int $id) { + global $DB; + + if ($record = $DB->get_record('event', ['id' => $id])) { + return $this->transform_from_database_record($record); + } else { + return false; + } + } + + /** + * Retrieve an array of events for the given user and time constraints. + * + * @param \stdClass $user The user for whom the events belong + * @param int|null $timesortfrom Events with timesort from this value (inclusive) + * @param int|null $timesortto Events with timesort until this value (inclusive) + * @param event_interface|null $afterevent Only return events after this one + * @param int $limitnum Return at most this number of events + * @return action_event_interface + */ + public function get_action_events_by_timesort( + \stdClass $user, + int $timesortfrom = null, + int $timesortto = null, + event_interface $afterevent = null, + int $limitnum = 20 + ) { + global $DB; + + if (is_null($timesortfrom) && is_null($timesortto)) { + throw new timesort_invalid_parameter_exception("Must provide a timesort to and/or from value"); + } + + if ($limitnum < 1 || $limitnum > 50) { + throw new limit_invalid_parameter_exception("Limit must be between 1 and 50 (inclusive)"); + } + + $params = ['type' => CALENDAR_EVENT_TYPE_ACTION]; + $where = ['type = :type']; + + if ($timesortfrom) { + $where[] = 'timesort >= :timesortfrom'; + $params['timesortfrom'] = $timesortfrom; + } + + if ($timesortto) { + $where[] = 'timesort <= :timesortto'; + $params['timesortto'] = $timesortto; + } + + if (!is_null($afterevent)) { + $where[] = 'id > :id'; + $params['id'] = $afterevent->get_id(); + } + + $sql = sprintf("SELECT * FROM {event} WHERE %s ORDER BY timesort ASC, id ASC", + implode(' AND ', $where)); + + $offset = 0; + $events = []; + // We need to continue to pull records from the database until we reach + // the requested amount of events because not all records in the database + // will be visible for the current user. + while ($records = array_values($DB->get_records_sql($sql, $params, $offset, $limitnum))) { + foreach ($records as $record) { + if ($event = $this->transform_from_database_record($record)) { + if ($event instanceof action_event_interface) { + $events[] = $event; + } + + if (count($events) == $limitnum) { + // We've got all of the events so break both loops. + break 2; + } + } + } + + $offset += $limitnum; + } + + return $events; + } + + /** + * Create an event from a database record. + * + * @param \stdClass $record The database record + * @return event_interface|false + */ + private function transform_from_database_record(\stdClass $record) { + return $this->factory->create_instance($record); + } + + /** + * Create an array of events from an array of database records. + * + * @param array $records The database records + * @return array + */ + private function transform_from_database_records(array $records) { + $events = []; + foreach ($records as $record) { + if ($event = $this->transform_from_database_record($record)) { + $events[] = $event; + } + } + + return $events; + } +} diff --git a/calendar/classes/local/event/exceptions/invalid_parameter_exception.php b/calendar/classes/local/event/exceptions/invalid_parameter_exception.php new file mode 100644 index 00000000000..93b831f357f --- /dev/null +++ b/calendar/classes/local/event/exceptions/invalid_parameter_exception.php @@ -0,0 +1,36 @@ +. + +/** + * General invalid parameter exception. + * + * @package core_calendar + * @copyright 2017 Ryan Wyllie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_calendar\local\event\exceptions; + +defined('MOODLE_INTERNAL') || die(); + +/** + * General invalid parameter exception. + * + * @copyright 2017 Ryan Wyllie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class invalid_parameter_exception extends \moodle_exception { +} diff --git a/calendar/classes/local/event/exceptions/limit_invalid_parameter_exception.php b/calendar/classes/local/event/exceptions/limit_invalid_parameter_exception.php new file mode 100644 index 00000000000..9f2b92c7e58 --- /dev/null +++ b/calendar/classes/local/event/exceptions/limit_invalid_parameter_exception.php @@ -0,0 +1,36 @@ +. + +/** + * Invalid limit parameter exception. + * + * @package core_calendar + * @copyright 2017 Ryan Wyllie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_calendar\local\event\exceptions; + +defined('MOODLE_INTERNAL') || die(); + +/** + * Invalid limit parameter exception. + * + * @copyright 2017 Ryan Wyllie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class limit_invalid_parameter_exception extends invalid_parameter_exception { +} diff --git a/calendar/classes/local/event/exceptions/timesort_invalid_parameter_exception.php b/calendar/classes/local/event/exceptions/timesort_invalid_parameter_exception.php new file mode 100644 index 00000000000..ee034bbb86b --- /dev/null +++ b/calendar/classes/local/event/exceptions/timesort_invalid_parameter_exception.php @@ -0,0 +1,36 @@ +. + +/** + * Invalid timesort parameter exception. + * + * @package core_calendar + * @copyright 2017 Ryan Wyllie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_calendar\local\event\exceptions; + +defined('MOODLE_INTERNAL') || die(); + +/** + * Invalid timesort parameter exception. + * + * @copyright 2017 Ryan Wyllie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class timesort_invalid_parameter_exception extends invalid_parameter_exception { +} diff --git a/calendar/classes/local/event/factories/event_vault_factory.php b/calendar/classes/local/event/factories/event_vault_factory.php new file mode 100644 index 00000000000..130d2b4ad86 --- /dev/null +++ b/calendar/classes/local/event/factories/event_vault_factory.php @@ -0,0 +1,47 @@ +. + +/** + * Event vault factory class + * + * @package core_calendar + * @copyright 2017 Ryan Wyllie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_calendar\local\event\factories; + +use core_calendar\local\event\data_access\event_vault; +use core_calendar\local\interfaces\event_factory_interface; +use core_calendar\local\interfaces\event_vault_factory_interface; + +/** + * Event vault factory class + * + * @copyright 2017 Ryan Wyllie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class event_vault_factory implements event_vault_factory_interface { + /** + * Creates an instance of an event vault + * + * @param event_factory_interface $eventfactory The event factory + * @return event_vault_interface + */ + public function create_instance(event_factory_interface $eventfactory) { + return new event_vault($eventfactory); + } +} diff --git a/calendar/classes/local/interfaces/event_vault_factory_interface.php b/calendar/classes/local/interfaces/event_vault_factory_interface.php new file mode 100644 index 00000000000..0cdc89c7d90 --- /dev/null +++ b/calendar/classes/local/interfaces/event_vault_factory_interface.php @@ -0,0 +1,41 @@ +. + +/** + * Event vault factory interface + * + * @package core_calendar + * @copyright 2017 Ryan Wyllie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_calendar\local\interfaces; + +/** + * Interface for an event vault factory class + * + * @copyright 2017 Ryan Wyllie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +interface event_vault_factory_interface { + /** + * Creates an instance of an event vault + * + * @param event_factory_interface $eventfactory The event factory + * @return event_vault_interface + */ + public function create_instance(event_factory_interface $eventfactory); +} diff --git a/calendar/classes/local/interfaces/event_vault_interface.php b/calendar/classes/local/interfaces/event_vault_interface.php new file mode 100644 index 00000000000..0f2c107f16a --- /dev/null +++ b/calendar/classes/local/interfaces/event_vault_interface.php @@ -0,0 +1,59 @@ +. + +/** + * Event vault interface + * + * @package core_calendar + * @copyright 2017 Ryan Wyllie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_calendar\local\interfaces; + +/** + * Interface for an event vault class + * + * @copyright 2017 Ryan Wyllie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +interface event_vault_interface { + /** + * Retrieve an event for the given id. + * + * @param in $id The event id + * @return event_interface|false + */ + public function get_event_by_id(int $id); + + /** + * Retrieve an array of events for the given user and time constraints. + * + * @param \stdClass $user The user for whom the events belong + * @param int $timesortfrom Events with timesort from this value (inclusive) + * @param int $timesortto Events with timesort until this value (inclusive) + * @param event_interface $afterevent Only return events after this one + * @param int $limitnum Return at most this number of events + * @return event_interface + */ + public function get_action_events_by_timesort( + \stdClass $user, + int $timesortfrom, + int $timesortto, + event_interface $afterevent, + int $limitnum + ); +}