diff --git a/calendar/classes/action_factory.php b/calendar/classes/action_factory.php new file mode 100644 index 00000000000..11cbb89b460 --- /dev/null +++ b/calendar/classes/action_factory.php @@ -0,0 +1,42 @@ +. + +/** + * Action factory. + * + * @package core_calendar + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_calendar; + +defined('MOODLE_INTERNAL') || die(); + +use core_calendar\local\interfaces\action_factory_interface; +use core_calendar\local\event\value_objects\action; + +/** + * Action factory class. + * + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class action_factory implements action_factory_interface { + public function create_instance($name, \moodle_url $url, $itemcount ) { + return new action ($name, $url, $itemcount); + } +} diff --git a/calendar/classes/local/event/core_container.php b/calendar/classes/local/event/core_container.php new file mode 100644 index 00000000000..4811ea60ed2 --- /dev/null +++ b/calendar/classes/local/event/core_container.php @@ -0,0 +1,117 @@ +. + +/** + * Core container for calendar events. + * + * The purpose of this class is simply to wire together the various + * implementations of calendar event components to produce a solution + * to the problems Moodle core wants to solve. + * + * @package core_calendar + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_calendar\local\event; + +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\mappers\event_mapper; +use core_calendar\local\interfaces\event_interface; + +/** + * Core container. + * + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class core_container { + /** + * @var event_factory $eventfactory Event factory. + */ + protected static $eventfactory; + + /** + * @var action_event_factory $actioneventfactory Action event factory. + */ + protected static $actioneventfactory; + + /** + * @var event_mapper_interface $eventmapper Event mapper. + */ + protected static $eventmapper; + + /** + * @var action_factory $actionfactory Action factory. + */ + protected static $actionfactory; + + /** + * Initialises the dependency graph if it hasn't yet been. + */ + private static function init() { + if (empty(self::$eventfactory)) { + self::$actionfactory = new action_factory(); + self::$actioneventfactory = new action_event_factory(); + self::$eventmapper = new event_mapper( + new event_factory( + function(event_interface $event) { + return $event; + } + ) + ); + self::$eventfactory = new event_factory( + function(event_interface $event) { + $mapper = self::$eventmapper; + $action = component_callback( + 'mod_' . $event->get_course_module()->get('modname'), + 'core_calendar_provide_event_action', + [ + $mapper->from_event_to_legacy_event($event), + self::$actionfactory + ] + ); + + return $action ? self::$actioneventfactory->create_instance($event, $action) : $event; + } + ); + } + } + + /** + * Gets the event factory. + * + * @return event_factory + */ + public static function get_event_factory() { + self::init(); + return self::$eventfactory; + } + + /** + * Gets the event mapper + * + * @return event_mapper_interface + */ + public static function get_event_mapper() { + self::init(); + return self::$eventmapper; + } +} diff --git a/calendar/classes/local/event/entities/action_event.php b/calendar/classes/local/event/entities/action_event.php index 372f9a1bb3f..99f082af194 100644 --- a/calendar/classes/local/event/entities/action_event.php +++ b/calendar/classes/local/event/entities/action_event.php @@ -53,7 +53,7 @@ class action_event implements action_event_interface { protected $action; /** - * Constructor + * Constructor. * * @param event_interface $event The event to delegate to. * @param action_interface $action The action associated with this event. @@ -103,8 +103,8 @@ class action_event implements action_event_interface { return $this->event->get_repeats(); } - public function get_subscription_id() { - return $this->event->get_subscription_id(); + public function get_subscription() { + return $this->event->get_subscription(); } public function is_visible() { diff --git a/calendar/classes/local/event/entities/event.php b/calendar/classes/local/event/entities/event.php index 40feabb94f0..e13772f53ba 100644 --- a/calendar/classes/local/event/entities/event.php +++ b/calendar/classes/local/event/entities/event.php @@ -95,9 +95,9 @@ class event implements event_interface { protected $visible; /** - * @var int $subscriptionid The event's subscription ID. + * @var proxy_interface $subscription Subscription for this event. */ - protected $subscriptionid; + protected $subscription; /** * Constructor. @@ -113,7 +113,7 @@ class event implements event_interface { * @param string $type The event's type. * @param times_interface $times The times associated with the event. * @param bool $visible The event's visibility. True for visible, false for invisible. - * @param int $subscriptionid The event's subscription ID. + * @param proxy_interface $subscription The event's subscription. */ public function __construct( $id, @@ -127,7 +127,7 @@ class event implements event_interface { $type, times_interface $times, $visible, - $subscriptionid + proxy_interface $subscription = null ) { $this->id = $id; $this->name = $name; @@ -140,7 +140,7 @@ class event implements event_interface { $this->type = $type; $this->times = $times; $this->visible = $visible; - $this->subscriptionid = $subscriptionid; + $this->subscription = $subscription; } public function get_id() { @@ -183,8 +183,8 @@ class event implements event_interface { return $this->repeats; } - public function get_subscription_id() { - return $this->subscriptionid; + public function get_subscription() { + return $this->subscription; } public function is_visible() { diff --git a/calendar/classes/local/event/entities/repeat_event_collection.php b/calendar/classes/local/event/entities/repeat_event_collection.php index 80216c4214f..1d4b693d065 100644 --- a/calendar/classes/local/event/entities/repeat_event_collection.php +++ b/calendar/classes/local/event/entities/repeat_event_collection.php @@ -97,25 +97,7 @@ class repeat_event_collection implements event_collection_interface { foreach ($this->load_event_records() as $eventrecords) { foreach ($eventrecords as $eventrecord) { // In the case of the repeat event having unset information, fallback on the parent. - yield $this->factory->create_instance( - $eventrecord->id, - !empty($eventrecord->name) ? $eventrecord->name : $parentrecord->name, - !empty($eventrecord->description) ? $eventrecord->description : $parentrecord->description, - !empty($eventrecord->format) ? $eventrecord->format : $parentrecord->format, - !empty($eventrecord->courseid) ? $eventrecord->courseid : $parentrecord->courseid, - !empty($eventrecord->groupid) ? $eventrecord->groupid : $parentrecord->groupid, - !empty($eventrecord->userid) ? $eventrecord->userid : $parentrecord->userid, - !empty($eventrecord->repeatid) ? $eventrecord->repeatid : $parentrecord->repeatid, - !empty($eventrecord->modulename) ? $eventrecord->modulename : $parentrecord->modulename, - !empty($eventrecord->instance) ? $eventrecord->instance : $parentrecord->instance, - !empty($eventrecord->eventtype) ? $eventrecord->eventtype : $parentrecord->eventtype, - !empty($eventrecord->timestart) ? $eventrecord->timestart : $parentrecord->timestart, - !empty($eventrecord->timeduration) ? $eventrecord->timeduration : $parentrecord->timeduration, - !empty($eventrecord->timemodified) ? $eventrecord->timemodified : $parentrecord->timemodified, - !empty($eventrecord->timesort) ? $eventrecord->timesort : $parentrecord->timesort, - !empty($eventrecord->visible) ? $eventrecord->visible : $parentrecord->visible, - !empty($eventrecord->subscriptionid) ? $eventrecord->subscriptionid : $parentrecord->subscriptionid - ); + yield $this->factory->create_instance((object)array_merge((array)$parentrecord, (array)$eventrecord)); } } } @@ -132,7 +114,7 @@ class repeat_event_collection implements event_collection_interface { return $this->parentrecord; } - return $DB->get_record('event', ['id' => $this->parentid]); + return $DB->get_record('event', ['id' => $this->parentid]); } /** diff --git a/calendar/classes/local/event/exceptions/invalid_callback_exception.php b/calendar/classes/local/event/exceptions/invalid_callback_exception.php new file mode 100644 index 00000000000..257a4c226a0 --- /dev/null +++ b/calendar/classes/local/event/exceptions/invalid_callback_exception.php @@ -0,0 +1,36 @@ +. + +/** + * Invalid callback exception. + * + * @package core_calendar + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_calendar\local\event\exceptions; + +defined('MOODLE_INTERNAL') || die(); + +/** + * Invalid callback exception. + * + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class invalid_callback_exception extends \moodle_exception { +} diff --git a/calendar/classes/local/event/factories/action_event_factory.php b/calendar/classes/local/event/factories/action_event_factory.php new file mode 100644 index 00000000000..415a52fe5af --- /dev/null +++ b/calendar/classes/local/event/factories/action_event_factory.php @@ -0,0 +1,47 @@ +. + +/** + * Action event factory. + * + * @package core_calendar + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_calendar\local\event\factories; + +defined('MOODLE_INTERNAL') || die(); + +use core_calendar\local\event\entities\action_event; +use core_calendar\local\interfaces\action_event_factory_interface; +use core_calendar\local\interfaces\action_interface; +use core_calendar\local\interfaces\event_interface; + +/** + * Action event factory class. + * + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class action_event_factory implements action_event_factory_interface { + public function create_instance( + event_interface $event, + action_interface $action + ) { + return new action_event($event, $action); + } +} diff --git a/calendar/classes/local/event/factories/event_abstract_factory.php b/calendar/classes/local/event/factories/event_abstract_factory.php new file mode 100644 index 00000000000..4fae8657d19 --- /dev/null +++ b/calendar/classes/local/event/factories/event_abstract_factory.php @@ -0,0 +1,133 @@ +. + +/** + * Abstract event factory. + * + * @package core_calendar + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_calendar\local\event\factories; + +defined('MOODLE_INTERNAL') || die(); + +use core_calendar\local\event\entities\event; +use core_calendar\local\event\entities\repeat_event_collection; +use core_calendar\local\event\proxies\std_proxy; +use core_calendar\local\event\value_objects\event_description; +use core_calendar\local\event\value_objects\event_times; +use core_calendar\local\interfaces\action_event_factory_interface; +use core_calendar\local\interfaces\event_factory_interface; +use core_calendar\local\interfaces\event_interface; + +/** + * Abstract factory for creating calendar events. + * + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +abstract class event_abstract_factory implements event_factory_interface { + /** + * @var callable $callbackapplier Function to apply component callbacks. + */ + protected $callbackapplier; + + /** + * Applies component actions to the event. + * + * @param event_interface $event The event to be updated. + * @return event_interface The potentially modified event. + */ + protected abstract function apply_component_action(event_interface $event); + + /** + * Constructor. + * + * @param callable $callbackapplier Function to apply component callbacks. + */ + public function __construct(callable $callbackapplier) { + $this->callbackapplier = $callbackapplier; + } + + public function create_instance(\stdClass $dbrow) { + $coursecache = []; + $course = null; + $group = null; + $user = null; + $module = null; + $subscription = null; + + if ($dbrow->courseid) { + $course = new std_proxy($dbrow->courseid, function($id) use ($coursecache) { + return \core_calendar\api::get_course_cached($coursecache, $id); + }); + } + + if ($dbrow->groupid) { + $group = new std_proxy($dbrow->groupid, function($id) { + return \core_calendar\api::get_group_cached($id); + }); + } + + if ($dbrow->userid) { + $user = new std_proxy($dbrow->userid, function($id) { + global $DB; + return $DB->get_record('user', ['id' => $id]); + }); + } + + if ($dbrow->instance && $dbrow->modulename) { + $modulename = $dbrow->modulename; + $module = new std_proxy($dbrow->instance, function($id) use ($modulename) { + return get_coursemodule_from_instance($modulename, $id); + }, + (object)[ + 'modname' => $modulename, + 'instance' => $dbrow->instance + ]); + } + + if ($dbrow->subscriptionid) { + $subscription = new std_proxy($dbrow->subscriptionid, function($id) { + return \core_calendar\api::get_subscription($id); + }); + } + + return $this->apply_component_action( + new event( + $dbrow->id, + $dbrow->name, + new event_description($dbrow->description, $dbrow->format), + $course, + $group, + $user, + new repeat_event_collection($dbrow->id, $this), + $module, + $dbrow->eventtype, + new event_times( + (new \DateTimeImmutable())->setTimestamp($dbrow->timestart), + (new \DateTimeImmutable())->setTimestamp($dbrow->timestart + $dbrow->timeduration), + (new \DateTimeImmutable())->setTimestamp($dbrow->timesort ? $dbrow->timesort : $dbrow->timestart), + (new \DateTimeImmutable())->setTimestamp($dbrow->timemodified) + ), + !empty($dbrow->visible), + $subscription + ) + ); + } +} diff --git a/calendar/classes/local/event/factories/event_factory.php b/calendar/classes/local/event/factories/event_factory.php new file mode 100644 index 00000000000..11dc0d1bea0 --- /dev/null +++ b/calendar/classes/local/event/factories/event_factory.php @@ -0,0 +1,54 @@ +. + +/** + * Event factory class. + * + * @package core_calendar + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_calendar\local\event\factories; + +defined('MOODLE_INTERNAL') || die(); + +use core_calendar\local\event\exceptions\invalid_callback_exception; +use core_calendar\local\event\factories\event_abstract_factory; +use core_calendar\local\interfaces\event_interface; + +/** + * Event factory class. + * + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class event_factory extends event_abstract_factory { + protected function apply_component_action(event_interface $event) { + if (!$event->get_course_module()) { + return $event; + } + + $callbackapplier = $this->callbackapplier; + $callbackresult = $callbackapplier($event); + + if (!$callbackresult instanceof event_interface) { + throw new invalid_callback_exception('Event factory callback applier must return an instance of action_interface'); + } + + return $callbackresult; + } +} diff --git a/calendar/classes/local/event/mappers/event_mapper.php b/calendar/classes/local/event/mappers/event_mapper.php new file mode 100644 index 00000000000..ab03791ffb4 --- /dev/null +++ b/calendar/classes/local/event/mappers/event_mapper.php @@ -0,0 +1,106 @@ +. + +/** + * Event mapper. + * + * @package core_calendar + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_calendar\local\event\mappers; + +defined('MOODLE_INTERNAL') || die(); + +use core_calendar\event; +use core_calendar\local\interfaces\event_factory_interface; +use core_calendar\local\interfaces\event_interface; +use core_calendar\local\interfaces\event_mapper_interface; + +/** + * Event mapper class. + * + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class event_mapper implements event_mapper_interface { + /** + * @var event_factory_interface $factory Event factory. + */ + protected $factory; + + /** + * Constructor. + * + * @param event_factory_interface $factory Event factory. + */ + public function __construct(event_factory_interface $factory) { + $this->factory = $factory; + } + + public function from_legacy_event_to_event(event $legacyevent) { + $coalesce = function($property) use ($legacyevent) { + return property_exists($legacyevent, $property) ? $legacyevent->{$property} : null; + }; + + return $this->factory->create_instance( + (object)[ + $coalesce('id'), + $coalesce('name'), + $coalesce('description'), + $coalesce('format'), + $coalesce('courseid'), + $coalesce('groupid'), + $coalesce('userid'), + $coalesce('repeatid'), + $coalesce('modulename'), + $coalesce('instance'), + $coalesce('type'), + $coalesce('timestart'), + $coalesce('timeduration'), + $coalesce('timemodified'), + $coalesce('timesort'), + $coalesce('visible'), + $coalesce('subscriptioni') + ] + ); + } + + public function from_event_to_legacy_event(event_interface $event) { + $timeduration = $event->get_times()->get_end_time()->getTimestamp() - $event->get_times()->get_start_time()->getTimestamp(); + + return new event((object) [ + 'id' => $event->get_id(), + 'name' => $event->get_name(), + 'description' => $event->get_description()->get_value(), + 'format' => $event->get_description()->get_format(), + 'courseid' => $event->get_course() ? $event->get_course()->get_id() : null, + 'groupid' => $event->get_group() ? $event->get_group()->get_id() : null, + 'userid' => $event->get_user() ? $event->get_user()->get_id() : null, + 'repeatid' => $event->get_repeats()->get_id(), + 'modulename' => $event->get_course_module()->get('modname'), + 'instance' => $event->get_course_module()->get('instance'), + 'eventtype' => $event->get_type(), + 'timestart' => $event->get_times()->get_start_time()->getTimestamp(), + 'timeduration' => $timeduration, + 'timesort' => $event->get_times()->get_sort_time()->getTimestamp(), + 'visible' => $event->is_visible() ? 1 : 0, + 'timemodified' => $event->get_times()->get_modified_time()->getTimestamp(), + 'subscriptionid' => $event->get_subscription() ? $event->get_subscription()->get_id() : null + ]); + } +} diff --git a/calendar/classes/local/event/value_objects/event_description.php b/calendar/classes/local/event/value_objects/event_description.php index 8f767fe1c49..c9aa8fe3c74 100644 --- a/calendar/classes/local/event/value_objects/event_description.php +++ b/calendar/classes/local/event/value_objects/event_description.php @@ -45,8 +45,8 @@ class event_description implements description_interface { */ protected $format; - /* - * Constructor + /** + * Constructor. * * @param stirng $value The description's value. * @param int $format The description's format. diff --git a/calendar/classes/local/interfaces/action_event_factory_interface.php b/calendar/classes/local/interfaces/action_event_factory_interface.php new file mode 100644 index 00000000000..bad320a3cb9 --- /dev/null +++ b/calendar/classes/local/interfaces/action_event_factory_interface.php @@ -0,0 +1,51 @@ +. + +/** + * Action event factory interface. + * + * @package core_calendar + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_calendar\local\interfaces; + +defined('MOODLE_INTERNAL') || die(); + +use core_calendar\local\interfaces\event_interface; +use core_calendar\local\interfaces\action_interface; + +/** + * Interface for an action event factory class. + * + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +interface action_event_factory_interface { + /** + * Create an instance of an action event. + * + * @param event_interface $event The event the action event will be attached to. + * @param action_interface $action The action tha the action event is attached to. + * + * @return event_interface + */ + public function create_instance( + event_interface $event, + action_interface $action + ); +} diff --git a/calendar/classes/local/interfaces/action_factory_interface.php b/calendar/classes/local/interfaces/action_factory_interface.php new file mode 100644 index 00000000000..a6bcf368bb5 --- /dev/null +++ b/calendar/classes/local/interfaces/action_factory_interface.php @@ -0,0 +1,39 @@ +. + +/** + * Action factory interface. + * + * @package core_calendar + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_calendar\local\interfaces; + +defined('MOODLE_INTERNAL') || die(); + +interface action_factory_interface { + /** + * Creates an instance of an action. + * + * @param string $name The action's name. + * @param \moodle_url $url The action's URL. + * @param int $itemcount The number of items needing action. + * @return \core_calendar\local\interfaces\action_interface The action. + */ + public function create_instance($name, \moodle_url $url, $itemcount); +} diff --git a/calendar/classes/local/interfaces/event_factory_interface.php b/calendar/classes/local/interfaces/event_factory_interface.php index e4ef3209a03..92ea0e0af9c 100644 --- a/calendar/classes/local/interfaces/event_factory_interface.php +++ b/calendar/classes/local/interfaces/event_factory_interface.php @@ -36,42 +36,8 @@ interface event_factory_interface { /** * Creates an instance of an event. * - * @param int $id The event's ID from the database. - * @param string $name The event's name. - * @param string $descriptionvalue The event's description value. - * @param string $descriptionformat The event's description format. - * @param int $courseid The course ID associated with the event. - * @param int $groupid The group ID associated with the event. - * @param int $userid The user ID associated with the event. - * @param int $repeatid ID of an event this event is a repeat of. - * @param string $modulename The name of the module that created this event. - * @param int $moduleinstance The instance ID of the module that created this event. - * @param string $type The type of the event. - * @param int $timestart Timestamp for when the event starts. - * @param int $timeduration The duration of the event in seconds. - * @param int $timemodified Timestamp of when the event was last modified. - * @param int $timesort Timestamp by which to sort events. - * @param bool $visible The event's visibility. True for visible, false for invisible. - * @param int $subscriptionid The subscription ID of the event. + * @param \stdClass $dbrow The event row from the database. * @return \core_calendar\local\interfaces\event_interface */ - public function create_instance( - $id, - $name, - $descriptionvalue, - $descriptionformat, - $courseid, - $groupid, - $userid, - $repeatid, - $modulename, - $moduleinstance, - $type, - $timestart, - $timeduration, - $timemodified, - $timesort, - $visible, - $subscriptionid - ); + public function create_instance(\stdClass $dbrow); } diff --git a/calendar/classes/local/interfaces/event_interface.php b/calendar/classes/local/interfaces/event_interface.php index 71604269337..21219482fb8 100644 --- a/calendar/classes/local/interfaces/event_interface.php +++ b/calendar/classes/local/interfaces/event_interface.php @@ -104,11 +104,11 @@ interface event_interface { public function get_repeats(); /** - * Get the event's subscritpion ID. + * Get the event's subscritpion. * - * @return int + * @return \core_calendar\local\event\proxies\proxy_interface */ - public function get_subscription_id(); + public function get_subscription(); /** * Get the event's visibility. diff --git a/calendar/classes/local/interfaces/event_mapper_interface.php b/calendar/classes/local/interfaces/event_mapper_interface.php new file mode 100644 index 00000000000..676da86fa6f --- /dev/null +++ b/calendar/classes/local/interfaces/event_mapper_interface.php @@ -0,0 +1,54 @@ +. + +/** + * Event mapper interface. + * + * @package core_calendar + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_calendar\local\interfaces; + +defined('MOODLE_INTERNAL') || die(); + +use core_calendar\event; +use core_calendar\local\interfaces\event_interface; + +/** + * Interface for an event mapper class + * + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +interface event_mapper_interface { + /** + * Map a legacy event to an event. + * + * @param event $event The legacy event. + * @return event_interface The mapped event. + */ + public function from_legacy_event_to_event(event $event); + + /** + * Map an event to a legacy event. + * + * @param event_interface $event The legacy event. + * @return event The mapped legacy event. + */ + public function from_event_to_legacy_event(event_interface $event); +} diff --git a/calendar/classes/local/interfaces/proxy_interface.php b/calendar/classes/local/interfaces/proxy_interface.php index d1cf6624dc9..b307336f95e 100644 --- a/calendar/classes/local/interfaces/proxy_interface.php +++ b/calendar/classes/local/interfaces/proxy_interface.php @@ -37,7 +37,8 @@ interface proxy_interface { * Retrieve a member of the proxied class. * * @param string $member The name of the member to retrieve - * @throws \core_calendar\local\event\exceptions\member_does_not_exist_exception If the proxied class does not have the requested member. + * @throws \core_calendar\local\event\exceptions\member_does_not_exist_exception If the proxied class does not have the + * requested member. * @return mixed The member. */ public function get($member); @@ -53,7 +54,8 @@ interface proxy_interface { * * @param string $member The name of the member to set * @param mixed $value The value to set the member to - * @throws \core_calendar\local\event\exceptions\member_does_not_exist_exception If the proxied class does not have the requested member. + * @throws \core_calendar\local\event\exceptions\member_does_not_exist_exception If the proxied class does not have the + * requested member. * @return void */ public function set($member, $value); diff --git a/calendar/lib.php b/calendar/lib.php index 103740a94d0..9a4b8961a6d 100644 --- a/calendar/lib.php +++ b/calendar/lib.php @@ -125,6 +125,16 @@ define('CALENDAR_SUBSCRIPTION_REMOVE', 2); */ define('CALENDAR_EVENT_USER_OVERRIDE_PRIORITY', 9999999); +/** + * CALENDAR_EVENT_TYPE_STANDARD - Standard events. + */ +define('CALENDAR_EVENT_TYPE_STANDARD', 0); + +/** + * CALENDAR_EVENT_TYPE_ACTION - Action events. + */ +define('CALENDAR_EVENT_TYPE_ACTION', 1); + /** * Calendar information class * diff --git a/calendar/tests/action_event_factory_test.php b/calendar/tests/action_event_factory_test.php new file mode 100644 index 00000000000..bd3fe974362 --- /dev/null +++ b/calendar/tests/action_event_factory_test.php @@ -0,0 +1,116 @@ +. + +/** + * Action event factory tests. + * + * @package core_calendar + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +use core_calendar\local\event\factories\action_event_factory; +use core_calendar\local\interfaces\action_event_interface; +use core_calendar\local\interfaces\event_interface; +use core_calendar\local\event\value_objects\action; + +/** + * Action testcase. + * + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class core_calendar_action_event_factory_testcase extends advanced_testcase { + /** + * Test create instance. + */ + public function test_create_instance() { + $factory = new action_event_factory(); + $instance = $factory->create_instance( + new action_event_factory_test_event(), + new action( + 'Test', + new \moodle_url('http://example.com'), + 1729 + ) + ); + + $this->assertInstanceOf(action_event_interface::class, $instance); + } +} + +/** + * A test event factory. + * + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class action_event_factory_test_event implements event_interface { + public function get_id() { + return 1729; + } + + public function get_name() { + return 'Jeff'; + } + + public function get_description() { + return new event_description('asdf', 1); + } + + public function get_course() { + return new \stdClass(); + } + + public function get_course_module() { + return new \stdClass(); + } + + public function get_group() { + return new \stdClass(); + } + + public function get_user() { + return new \stdClass(); + } + + public function get_type() { + return 'asdf'; + } + + public function get_times() { + return new event_times( + (new \DateTimeImmutable())->setTimestamp('-2461276800'), + (new \DateTimeImmutable())->setTimestamp('115776000'), + (new \DateTimeImmutable())->setTimestamp('115776000'), + (new \DateTimeImmutable())->setTimestamp(time()) + ); + } + + public function get_repeats() { + return new test_event_collection(); + } + + public function get_subscription() { + return new \stdClass(); + } + + public function is_visible() { + return true; + } +} diff --git a/calendar/tests/action_event_test.php b/calendar/tests/action_event_test.php index be949a5e2a8..b8d63ebd470 100644 --- a/calendar/tests/action_event_test.php +++ b/calendar/tests/action_event_test.php @@ -138,8 +138,8 @@ class core_calendar_action_event_test_event implements event_interface { return new core_calendar_action_event_test_event_collection(); } - public function get_subscription_id() { - return 1729; + public function get_subscription() { + return new \stdClass(); } public function is_visible() { diff --git a/calendar/tests/action_factory_test.php b/calendar/tests/action_factory_test.php new file mode 100644 index 00000000000..5bd64482a77 --- /dev/null +++ b/calendar/tests/action_factory_test.php @@ -0,0 +1,50 @@ +. + +/** + * Action factory test. + * + * @package core_calendar + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +use core_calendar\action_factory; +use core_calendar\local\interfaces\action_interface; + +/** + * Action factory testcase. + * + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class core_calendar_action_factory_test extends advanced_testcase { + /** + * Test action factory. + */ + public function test_action_factory() { + $factory = new action_factory(); + $instance = $factory->create_instance( + 'test', + new \moodle_url('http://example.com'), + 1729 + ); + + $this->assertInstanceOf(action_interface::class, $instance); + } +} diff --git a/calendar/tests/core_container_test.php b/calendar/tests/core_container_test.php new file mode 100644 index 00000000000..3f073d6aa59 --- /dev/null +++ b/calendar/tests/core_container_test.php @@ -0,0 +1,186 @@ +. + +/** + * Event container tests. + * + * @package core_calendar + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +use core_calendar\local\event\entities\action_event; +use core_calendar\local\event\entities\event; +use core_calendar\local\event\factories\event_factory; +use core_calendar\local\event\mappers\event_mapper; +use core_calendar\local\interfaces\event_factory_interface; +use core_calendar\local\interfaces\event_interface; +use core_calendar\local\interfaces\event_mapper_interface; + +/** + * Core container testcase. + * + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class core_calendar_container_testcase extends advanced_testcase { + /** + * Test getting the event factory. + * + * @dataProvider get_event_factory_testcases() + * @param \stdClass $dbrow Row from the "database". + */ + public function test_get_event_factory($dbrow) { + $this->resetAfterTest(true); + $this->setAdminUser(); + + $legacyevent = $this->create_event($dbrow); + $factory = \core_calendar\local\event\core_container::get_event_factory(); + + $this->assertInstanceOf(event_factory_interface::class, $factory); + $this->assertInstanceOf(event_factory::class, $factory); + + $factory2 = \core_calendar\local\event\core_container::get_event_factory(); + + $this->assertTrue($factory === $factory2); + + $dbrow->id = $legacyevent->id; + $event = $factory->create_instance($dbrow); + + $this->assertInstanceOf(event_interface::class, $event); + $this->assertTrue($event instanceof event || $event instanceof action_event); + + $this->assertEquals($legacyevent->id, $event->get_id()); + $this->assertEquals($dbrow->description, $event->get_description()->get_value()); + $this->assertEquals($dbrow->format, $event->get_description()->get_format()); + $this->assertEquals($dbrow->courseid, $event->get_course()->get_id()); + + if ($dbrow->groupid == 0) { + $this->assertNull($event->get_group()); + } else { + $this->assertEquals($dbrow->groupid, $event->get_group()->get_id()); + } + + $this->assertEquals($dbrow->userid, $event->get_user()->get_id()); + $this->assertEquals($legacyevent->id, $event->get_repeats()->get_id()); + $this->assertEquals($dbrow->modulename, $event->get_course_module()->get('modname')); + $this->assertEquals($dbrow->instance, $event->get_course_module()->get('instance')); + $this->assertEquals($dbrow->timestart, $event->get_times()->get_start_time()->getTimestamp()); + $this->assertEquals($dbrow->timemodified, $event->get_times()->get_modified_time()->getTimestamp()); + $this->assertEquals($dbrow->timesort, $event->get_times()->get_sort_time()->getTimestamp()); + + if ($dbrow->visible == 1) { + $this->assertTrue($event->is_visible()); + } else { + $this->assertFalse($event->is_visible()); + } + + if (!$dbrow->subscriptionid) { + $this->assertNull($event->get_subscription()); + } else { + $this->assertEquals($event->get_subscription()->get_id()); + } + } + + /** + * Test getting the event mapper. + */ + public function test_get_event_mapper() { + $mapper = \core_calendar\local\event\core_container::get_event_mapper(); + + $this->assertInstanceOf(event_mapper_interface::class, $mapper); + $this->assertInstanceOf(event_mapper::class, $mapper); + + $mapper2 = \core_calendar\local\event\core_container::get_event_mapper(); + + $this->assertTrue($mapper === $mapper2); + } + + /** + * Test cases for the get event factory test. + */ + public function get_event_factory_testcases() { + return [ + 'Data set 1' => [ + 'dbrow' => (object)[ + 'name' => 'Test event', + 'description' => 'Hello', + 'format' => 1, + 'courseid' => 1, + 'groupid' => 0, + 'userid' => 1, + 'repeatid' => 0, + 'modulename' => 'assign', + 'instance' => 2, + 'eventtype' => 'due', + 'timestart' => 1486396800, + 'timeduration' => 0, + 'timesort' => 1486396800, + 'visible' => 1, + 'timemodified' => 1485793098, + 'subscriptionid' => null + ] + ], + + 'Data set 2' => [ + 'dbrow' => (object)[ + 'name' => 'Test event', + 'description' => 'Hello', + 'format' => 1, + 'courseid' => 1, + 'groupid' => 1, + 'userid' => 1, + 'repeatid' => 1, + 'modulename' => 'assign', + 'instance' => 2, + 'eventtype' => 'due', + 'timestart' => 1486396800, + 'timeduration' => 0, + 'timesort' => 1486396800, + 'visible' => 1, + 'timemodified' => 1485793098, + 'subscriptionid' => null + ] + ] + ]; + } + + /** + * Helper function to create calendar events using the old code. + * + * @param array $properties A list of calendar event properties to set + * @return event + */ + protected function create_event($properties = []) { + $record = new \stdClass(); + $record->name = 'event name'; + $record->eventtype = 'global'; + $record->timestart = time(); + $record->timeduration = 0; + $record->timesort = 0; + $record->type = 1; + $record->courseid = 0; + + foreach ($properties as $name => $value) { + $record->$name = $value; + } + + $event = new \core_calendar\event($record); + return $event->create($record, false); + } +} diff --git a/calendar/tests/event_factory_test.php b/calendar/tests/event_factory_test.php new file mode 100644 index 00000000000..fce22191bc0 --- /dev/null +++ b/calendar/tests/event_factory_test.php @@ -0,0 +1,148 @@ +. + +/** + * Event factory test. + * + * @package core_calendar + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +use core_calendar\local\event\factories\event_factory; +use core_calendar\local\interfaces\event_interface; + +/** + * Event factory testcase. + * + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class core_calendar_event_factory_testcase extends advanced_testcase { + /** + * Test event class getters. + * + * @dataProvider create_instance_testcases() + * @param array $instanceparams Associative array of instance parameters. + */ + public function test_create_instance( + $dbrow, + callable $callbackapplier, + $expectedattributevalue + ) { + $this->resetAfterTest(true); + $this->setAdminUser(); + $event = $this->create_event(); + + $factory = new event_factory($callbackapplier); + $dbrow->id = $event->id; + $instance = $factory->create_instance($dbrow); + + $this->assertEquals($instance->testattribute, $expectedattributevalue); + } + + /** + * Test invalid callback exception. + * + * @expectedException \core_calendar\local\event\exceptions\invalid_callback_exception + */ + public function test_invalid_callback() { + $this->resetAfterTest(true); + $this->setAdminUser(); + $event = $this->create_event(); + $factory = new event_factory(function () { + return 'hello'; + }); + + $factory->create_instance( + (object)[ + 'id' => $event->id, + 'name' => 'test', + 'description' => 'Test description', + 'format' => 2, + 'courseid' => 1, + 'groupid' => 1, + 'userid' => 1, + 'repeatid' => 1, + 'modulename' => 'assign', + 'instance' => 1, + 'eventtype' => 'due', + 'timestart' => 123456789, + 'timeduration' => 12, + 'timemodified' => 123456789, + 'timesort' => 123456789, + 'visible' => 1, + 'subscriptionid' => 1 + ] + ); + } + + public function create_instance_testcases() { + return [ + 'Sample event record' => [ + 'dbrow' => (object)[ + 'name' => 'Test event', + 'description' => 'Hello', + 'format' => 1, + 'courseid' => 1, + 'groupid' => 1, + 'userid' => 1, + 'repeatid' => null, + 'modulename' => 'Test module', + 'instance' => 1, + 'eventtype' => 'Due', + 'timestart' => 123456789, + 'timeduration' => 123456789, + 'timemodified' => 123456789, + 'timesort' => 123456789, + 'visible' => true, + 'subscriptionid' => 1 + ], + 'callbackapplier' => function(event_interface $event) { + $event->testattribute = 'Hello'; + return $event; + }, + 'Hello' + ] + ]; + } + + /** + * Helper function to create calendar events using the old code. + * + * @param array $properties A list of calendar event properties to set + * @return event + */ + protected function create_event($properties = []) { + $record = new \stdClass(); + $record->name = 'event name'; + $record->eventtype = 'global'; + $record->timestart = time(); + $record->timeduration = 0; + $record->timesort = 0; + $record->type = 1; + $record->courseid = 0; + + foreach ($properties as $name => $value) { + $record->$name = $value; + } + + $event = new \core_calendar\event($record); + return $event->create($record, false); + } +} diff --git a/calendar/tests/event_mapper_test.php b/calendar/tests/event_mapper_test.php new file mode 100644 index 00000000000..17429c7a580 --- /dev/null +++ b/calendar/tests/event_mapper_test.php @@ -0,0 +1,293 @@ +. + +/** + * Event mapper test. + * + * @package core_calendar + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +use core_calendar\event; +use core_calendar\local\event\mappers\event_mapper; +use core_calendar\local\event\value_objects\event_description; +use core_calendar\local\event\value_objects\event_times; +use core_calendar\local\interfaces\event_collection_interface; +use core_calendar\local\interfaces\event_factory_interface; +use core_calendar\local\interfaces\event_interface; +use core_calendar\local\interfaces\proxy_interface; + +/** + * Event mapper testcase. + * + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class core_calendar_event_mapper_testcase extends advanced_testcase { + /** + * Test legacy event -> event. + */ + public function test_from_legacy_event_to_event() { + $this->resetAfterTest(true); + $this->setAdminUser(); + $legacyevent = $this->create_event(); + $mapper = new event_mapper( + new event_mapper_test_event_factory() + ); + $event = $mapper->from_legacy_event_to_event($legacyevent); + $this->assertInstanceOf(event_interface::class, $event); + } + + /** + * Test event -> legacy event + */ + public function test_from_event_to_legacy_event() { + $this->resetAfterTest(true); + $this->setAdminUser(); + $legacyevent = $this->create_event(['modname' => 'assign', 'instance' => 1]); + $event = new event_mapper_test_event($legacyevent); + $mapper = new event_mapper( + new event_mapper_test_event_factory() + ); + $legacyevent = $mapper->from_event_to_legacy_event($event); + $this->assertInstanceOf(event::class, $legacyevent); + } + + /** + * Helper function to create calendar events using the old code. + * + * @param array $properties A list of calendar event properties to set + * @return event + */ + protected function create_event($properties = []) { + $record = new \stdClass(); + $record->name = 'event name'; + $record->eventtype = 'global'; + $record->timestart = time(); + $record->timeduration = 0; + $record->timesort = 0; + $record->type = 1; + $record->courseid = 0; + + foreach ($properties as $name => $value) { + $record->$name = $value; + } + + $event = new \core_calendar\event($record); + return $event->create($record, false); + } +} + +/** + * A test event factory. + * + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class event_mapper_test_event_factory implements event_factory_interface { + public function create_instance(\stdClass $dbrow) { + return new event_mapper_test_event(); + } +} + +/** + * A test event. + * + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class event_mapper_test_event implements event_interface { + /** + * @var proxy_interface $courseproxy Course proxy. + */ + protected $courseproxy; + + /** + * @var proxy_interface $cmproxy Course module proxy. + */ + protected $cmproxy; + + /** + * @var proxy_interface $groupproxy Group proxy. + */ + protected $groupproxy; + + /** + * @var proxy_interface $userproxy User proxy. + */ + protected $userproxy; + + /** + * @var proxy_interface $subscriptionproxy Subscription proxy. + */ + protected $subscriptionproxy; + + /** + * Constructor. + * + * @param \core_calendar\event $legacyevent Legacy event to exctract IDs etc from. + */ + public function __construct($legacyevent = null) { + if ($legacyevent) { + $this->courseproxy = new event_mapper_test_proxy($legacyevent->courseid); + $this->cmproxy = new event_mapper_test_proxy(1729, + [ + 'modname' => $legacyevent->modname, + 'instance' => $legacyevent->instance + ] + ); + $this->groupproxy = new event_mapper_test_proxy(0); + $this->userproxy = new event_mapper_test_proxy($legacyevent->userid); + $this->subscriptionproxy = new event_mapper_test_proxy(null); + } + } + + public function get_id() { + return 1729; + } + + public function get_name() { + return 'Jeff'; + } + + public function get_description() { + return new event_description('asdf', 1); + } + + public function get_course() { + return $this->courseproxy; + } + + public function get_course_module() { + return $this->cmproxy; + } + + public function get_group() { + return $this->groupproxy; + } + + public function get_user() { + return $this->userproxy; + } + + public function get_type() { + return 'asdf'; + } + + public function get_times() { + return new event_times( + (new \DateTimeImmutable())->setTimestamp('-2461276800'), + (new \DateTimeImmutable())->setTimestamp('115776000'), + (new \DateTimeImmutable())->setTimestamp('115776000'), + (new \DateTimeImmutable())->setTimestamp(time()) + ); + } + + public function get_repeats() { + return new core_calendar_event_mapper_test_event_collection(); + } + + public function get_subscription() { + return $this->subscriptionproxy; + } + + public function is_visible() { + return true; + } +} + +/** + * A test proxy. + * + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class event_mapper_test_proxy implements proxy_interface { + + /** + * @var int $id Proxied ID. + */ + protected $id; + + /** + * @var array $params Params to proxy. + */ + protected $params; + + /** + * Constructor. + * + * @param int $id Proxied ID. + * @param array $params Params to proxy. + */ + public function __construct($id, $params = []) { + $this->params = $params; + } + + public function get($member) { + return isset($params[$member]) ? $params[$member] : null; + } + + public function get_id() { + return $this->id; + } + + public function set($member, $value) { + } + + public function get_proxied_instance() { + } +} + +/** + * A test event. + * + * @copyright 2017 Cameron Ball + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class core_calendar_event_mapper_test_event_collection implements event_collection_interface { + /** + * @var array $events Array of events. + */ + protected $events; + + /** + * Constructor. + */ + public function __construct() { + $this->events = [ + 'not really an event hahaha', + 'also not really. gottem.' + ]; + } + + public function get_id() { + return 1729; + } + + public function get_num() { + return 2; + } + + public function getIterator() { + foreach ($this->events as $event) { + yield $event; + } + } +} diff --git a/calendar/tests/event_test.php b/calendar/tests/event_test.php index 28b780ab6a1..cbf85b5178f 100644 --- a/calendar/tests/event_test.php +++ b/calendar/tests/event_test.php @@ -56,7 +56,7 @@ class core_calendar_event_testcase extends advanced_testcase { $constructorparams['type'], $constructorparams['times'], $constructorparams['visible'], - $constructorparams['subscription_id'] + $constructorparams['subscription'] ); foreach ($constructorparams as $name => $value) { @@ -95,7 +95,7 @@ class core_calendar_event_testcase extends advanced_testcase { (new \DateTimeImmutable())->setTimestamp(time()) ), 'visible' => true, - 'subscription_id' => 3 + 'subscription' => new std_proxy(1, $lamecallable) ] ], ]; diff --git a/calendar/tests/repeat_event_collection_test.php b/calendar/tests/repeat_event_collection_test.php index 95561d36e05..635b82b7792 100644 --- a/calendar/tests/repeat_event_collection_test.php +++ b/calendar/tests/repeat_event_collection_test.php @@ -149,46 +149,28 @@ class core_calendar_repeat_event_collection_testcase extends advanced_testcase { * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class core_calendar_repeat_event_collection_event_test_factory implements event_factory_interface { - public function create_instance( - $id, - $name, - $descriptionvalue, - $descriptionformat, - $courseid, - $groupid, - $userid, - $repeatid, - $modulename, - $moduleinstance, - $type, - $timestart, - $timeduration, - $timemodified, - $timesort, - $visible, - $subscriptionid - ) { + public function create_instance(\stdClass $dbrow) { $identity = function($id) { return $id; }; return new event( - $id, - $name, - new event_description($descriptionvalue, $descriptionformat), - new std_proxy($courseid, $identity), - new std_proxy($groupid, $identity), - new std_proxy($userid, $identity), - new repeat_event_collection($id, $this), - new std_proxy($moduleinstance, $identity), - $type, + $dbrow->id, + $dbrow->name, + new event_description($dbrow->description, $dbrow->format), + new std_proxy($dbrow->courseid, $identity), + new std_proxy($dbrow->groupid, $identity), + new std_proxy($dbrow->userid, $identity), + new repeat_event_collection($dbrow->id, $this), + new std_proxy($dbrow->instance, $identity), + $dbrow->type, new event_times( - (new \DateTimeImmutable())->setTimestamp($timestart), - (new \DateTimeImmutable())->setTimestamp($timestart + $timeduration), - (new \DateTimeImmutable())->setTimestamp($timesort ? $timesort : $timestart), - (new \DateTimeImmutable())->setTimestamp($timemodified) + (new \DateTimeImmutable())->setTimestamp($dbrow->timestart), + (new \DateTimeImmutable())->setTimestamp($dbrow->timestart + $dbrow->timeduration), + (new \DateTimeImmutable())->setTimestamp($dbrow->timesort ? $dbrow->timesort : $dbrow->timestart), + (new \DateTimeImmutable())->setTimestamp($dbrow->timemodified) ), - !empty($visible), - $subscriptionid + !empty($dbrow->visible), + new std_proxy($dbrow->subscriptionid, $identity) ); } } diff --git a/calendar/tests/std_proxy_test.php b/calendar/tests/std_proxy_test.php index 3a4a7af1b96..93ab0fde1c5 100644 --- a/calendar/tests/std_proxy_test.php +++ b/calendar/tests/std_proxy_test.php @@ -99,6 +99,7 @@ class core_calendar_std_proxy_testcase extends advanced_testcase { * * @dataProvider test_get_set_testcases() * @expectedException \core_calendar\local\event\exceptions\member_does_not_exist_exception + * @param int $id ID of the object being proxied. */ public function test_get_invalid_member($id) { $proxy = new std_proxy($id, function($id) { @@ -113,6 +114,7 @@ class core_calendar_std_proxy_testcase extends advanced_testcase { * * @dataProvider test_get_set_testcases() * @expectedException \core_calendar\local\event\exceptions\member_does_not_exist_exception + * @param int $id ID of the object being proxied. */ public function test_set_invalid_member($id) { $proxy = new std_proxy($id, function($id) { diff --git a/mod/assign/lib.php b/mod/assign/lib.php index 9b17e3b28ca..19f34f1c641 100644 --- a/mod/assign/lib.php +++ b/mod/assign/lib.php @@ -1706,3 +1706,15 @@ function assign_check_updates_since(cm_info $cm, $from, $filter = array()) { return $updates; } + +//XXX: Rubbish implementation +function mod_assign_core_calendar_provide_event_action( + \core_calendar\event $event, + \core_calendar\action_factory $factory +) { + return $factory->create_instance( + 'chef', + new \moodle_url('http://example.com'), + 3 + ); +}