Merge branch 'wip-MDL-58911-master' of git://github.com/marinaglancy/moodle

This commit is contained in:
Jun Pataleta 2017-06-20 16:33:15 +08:00
commit 88720416ba
3 changed files with 90 additions and 98 deletions

View File

@ -71,11 +71,6 @@ class container {
*/
protected static $eventretrievalstrategy;
/**
* @var array A list of callbacks to use.
*/
protected static $callbacks = array();
/**
* @var \stdClass[] An array of cached courses to use with the event factory.
*/
@ -91,16 +86,6 @@ class container {
*/
private static function init() {
if (empty(self::$eventfactory)) {
// When testing the container's components, we need to make sure
// the callback implementations in modules are not executed, since
// we cannot control their output from PHPUnit. To do this we have
// a set of 'testing' callbacks that the factory can use. This way
// we know exactly how the factory behaves when being tested.
$getcallback = function($which) {
return self::$callbacks[PHPUNIT_TEST ? 'testing' : 'production'][$which];
};
self::initcallbacks();
self::$actionfactory = new action_factory();
self::$eventmapper = new event_mapper(
// The event mapper we return from here needs to know how to
@ -129,8 +114,8 @@ class container {
);
self::$eventfactory = new event_factory(
$getcallback('action'),
$getcallback('visibility'),
[self::class, 'apply_component_provide_event_action'],
[self::class, 'apply_component_is_event_visible'],
function ($dbrow) {
// At present we only have a bail-out check for events in course modules.
if (empty($dbrow->modulename)) {
@ -183,6 +168,19 @@ class container {
}
}
/**
* Reset all static caches, called between tests.
*/
public static function reset_caches() {
self::$eventfactory = null;
self::$eventmapper = null;
self::$eventvault = null;
self::$actionfactory = null;
self::$eventretrievalstrategy = null;
self::$coursecache = [];
self::$modulecache = [];
}
/**
* Gets the event factory.
*
@ -214,88 +212,74 @@ class container {
}
/**
* Initialises the callbacks.
* Calls callback 'core_calendar_provide_event_action' from the component responsible for the event
*
* There are two sets here, one is used during PHPUnit runs.
* See the comment at the start of the init method for more
* detail.
* If no callback is present or callback returns null, there is no action on the event
* and it will not be displayed on the dashboard.
*
* @param event_interface $event
* @return action_event|event_interface
*/
private static function initcallbacks() {
self::$callbacks = array(
'testing' => array(
// Always return an action event.
'action' => function (event_interface $event) {
return new action_event(
$event,
new \core_calendar\local\event\value_objects\action(
'test',
new \moodle_url('http://example.com'),
420,
true
));
},
// Always be visible.
'visibility' => function (event_interface $event) {
return true;
}
),
'production' => array(
// This function has type event_interface -> event_interface.
// This is enforced by the event_factory.
'action' => function (event_interface $event) {
// Callbacks will get supplied a "legacy" version
// of the event class.
$mapper = self::$eventmapper;
$action = null;
if ($event->get_course_module()) {
// TODO MDL-58866 Only activity modules currently support this callback.
// Any other event will not be displayed on the dashboard.
$action = component_callback(
'mod_' . $event->get_course_module()->get('modname'),
'core_calendar_provide_event_action',
[
$mapper->from_event_to_legacy_event($event),
self::$actionfactory
]
);
}
public static function apply_component_provide_event_action(event_interface $event) {
// Callbacks will get supplied a "legacy" version
// of the event class.
$mapper = self::$eventmapper;
$action = null;
if ($event->get_course_module()) {
// TODO MDL-58866 Only activity modules currently support this callback.
// Any other event will not be displayed on the dashboard.
$action = component_callback(
'mod_' . $event->get_course_module()->get('modname'),
'core_calendar_provide_event_action',
[
$mapper->from_event_to_legacy_event($event),
self::$actionfactory
]
);
}
// If we get an action back, return an action event, otherwise
// continue piping through the original event.
//
// If a module does not implement the callback, component_callback
// returns null.
return $action ? new action_event($event, $action) : $event;
},
// This function has type event_interface -> bool.
// This is enforced by the event_factory.
'visibility' => function (event_interface $event) {
$mapper = self::$eventmapper;
$eventvisible = null;
if ($event->get_course_module()) {
// TODO MDL-58866 Only activity modules currently support this callback.
$eventvisible = component_callback(
'mod_' . $event->get_course_module()->get('modname'),
'core_calendar_is_event_visible',
[
$mapper->from_event_to_legacy_event($event)
]
);
}
// If we get an action back, return an action event, otherwise
// continue piping through the original event.
//
// If a module does not implement the callback, component_callback
// returns null.
return $action ? new action_event($event, $action) : $event;
}
// Do not display the event if there is nothing to action.
if ($event instanceof action_event_interface && $event->get_action()->get_item_count() === 0) {
return false;
}
/**
* Calls callback 'core_calendar_is_event_visible' from the component responsible for the event
*
* The visibility callback is optional, if not present it is assumed as visible.
* If it is an actionable event but the get_item_count() returns 0 the visibility
* is set to false.
*
* @param event_interface $event
* @return bool
*/
public static function apply_component_is_event_visible(event_interface $event) {
$mapper = self::$eventmapper;
$eventvisible = null;
if ($event->get_course_module()) {
// TODO MDL-58866 Only activity modules currently support this callback.
$eventvisible = component_callback(
'mod_' . $event->get_course_module()->get('modname'),
'core_calendar_is_event_visible',
[
$mapper->from_event_to_legacy_event($event)
]
);
}
// Module does not implement the callback, event should be visible.
if (is_null($eventvisible)) {
return true;
}
// Do not display the event if there is nothing to action.
if ($event instanceof action_event_interface && $event->get_action()->get_item_count() === 0) {
return false;
}
return $eventvisible ? true : false;
}
),
);
// Module does not implement the callback, event should be visible.
if (is_null($eventvisible)) {
return true;
}
return $eventvisible ? true : false;
}
}

View File

@ -674,13 +674,15 @@ class core_calendar_externallib_testcase extends externallib_advanced_testcase {
*/
public function test_get_calendar_events_override() {
$user = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$teacher = $this->getDataGenerator()->create_user();
$anotheruser = $this->getDataGenerator()->create_user();
$course = $this->getDataGenerator()->create_course();
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$moduleinstance = $generator->create_instance(['course' => $course->id]);
$this->getDataGenerator()->enrol_user($user->id, $course->id);
$this->getDataGenerator()->enrol_user($user->id, $course->id, 'student');
$this->getDataGenerator()->enrol_user($user2->id, $course->id, 'student');
$this->getDataGenerator()->enrol_user($teacher->id, $course->id, 'editingteacher');
$this->resetAfterTest(true);
$this->setAdminUser();
@ -692,11 +694,12 @@ class core_calendar_externallib_testcase extends externallib_advanced_testcase {
];
$now = time();
// Create two events - one for everybody in the course and one only for the first student.
$event1 = $this->create_calendar_event('Base event', 0, 'due', 0, $now + DAYSECS, $params + ['courseid' => $course->id]);
$event2 = $this->create_calendar_event('User event', $user->id, 'due', 0, $now + 2*DAYSECS, $params + ['courseid' => 0]);
// Retrieve course events for teacher - only one "Base event" is returned.
$this->setUser($teacher);
// Retrieve course events for the second student - only one "Base event" is returned.
$this->setUser($user2);
$paramevents = array('courseids' => array($course->id));
$options = array ('siteevents' => true, 'userevents' => true);
$events = core_calendar_external::get_calendar_events($paramevents, $options);
@ -705,7 +708,7 @@ class core_calendar_externallib_testcase extends externallib_advanced_testcase {
$this->assertEquals(0, count($events['warnings']));
$this->assertEquals('Base event', $events['events'][0]['name']);
// Retrieve events for user - both events are returned.
// Retrieve events for the first student - both events are returned.
$this->setUser($user);
$events = core_calendar_external::get_calendar_events($paramevents, $options);
$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);

View File

@ -229,6 +229,11 @@ class phpunit_util extends testing_util {
// Reset internal users.
core_user::reset_internal_users();
// Clear static caches in calendar container.
if (class_exists('\core_calendar\local\event\container', false)) {
core_calendar\local\event\container::reset_caches();
}
//TODO MDL-25290: add more resets here and probably refactor them to new core function
// Reset course and module caches.