first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
+208
View File
@@ -0,0 +1,208 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Action event tests.
*
* @package core_calendar
* @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_calendar;
use core_calendar\local\event\entities\action_event;
use core_calendar\local\event\value_objects\action;
use core_calendar\local\event\value_objects\event_description;
use core_calendar\local\event\value_objects\event_times;
use core_calendar\local\event\entities\event_collection_interface;
use core_calendar\local\event\entities\event_interface;
defined('MOODLE_INTERNAL') || die;
/**
* Action event testcase.
*
* @package core_calendar
* @category test
* @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class action_event_test extends \advanced_testcase {
/**
* Test event class getters.
*
* @dataProvider getters_testcases()
* @param array $constructorparams Associative array of constructor parameters.
*/
public function test_getters($constructorparams): void {
$event = new action_event(
$constructorparams['event'],
$constructorparams['action']
);
foreach ($constructorparams as $name => $value) {
if ($name !== 'event') {
$this->assertEquals($event->{'get_' . $name}(), $value);
}
}
}
/**
* Test cases for getters test.
*/
public function getters_testcases() {
return [
'Dataset 1' => [
'constructorparams' => [
'event' => new core_calendar_action_event_test_event(),
'action' => new action(
'action 1',
new \moodle_url('http://example.com'),
2,
true
)
]
],
'Dataset 2' => [
'constructorparams' => [
'event' => new core_calendar_action_event_test_event(),
'action' => new action(
'action 2',
new \moodle_url('http://example.com'),
5,
false
)
]
],
];
}
}
/**
* Test event.
*
* @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class core_calendar_action_event_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_location() {
return 'Cube office';
}
public function get_category() {
return new \stdClass();
}
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(-386380800),
(new \DateTimeImmutable())->setTimestamp(115776000),
(new \DateTimeImmutable())->setTimestamp(115776000),
(new \DateTimeImmutable())->setTimestamp(time())
);
}
public function get_repeats() {
return new core_calendar_action_event_test_event_collection();
}
public function get_subscription() {
return new \stdClass();
}
public function is_visible() {
return true;
}
/**
* Component
* @return string|null
*/
public function get_component() {
return null;
}
}
/**
* Test event collection.
*
* @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class core_calendar_action_event_test_event_collection implements event_collection_interface {
/**
* @var array
*/
protected $events;
/**
* core_calendar_action_event_test_event_collection 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(): \Traversable {
foreach ($this->events as $event) {
yield $event;
}
}
}
+43
View File
@@ -0,0 +1,43 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_calendar;
use core_calendar\local\event\entities\action_interface;
/**
* Action factory testcase.
*
* @package core_calendar
* @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class action_factory_test extends \advanced_testcase {
/**
* Test action factory.
*/
public function test_action_factory(): void {
$factory = new action_factory();
$instance = $factory->create_instance(
'test',
new \moodle_url('http://example.com'),
1729,
true
);
$this->assertInstanceOf(action_interface::class, $instance);
}
}
+75
View File
@@ -0,0 +1,75 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_calendar;
use core_calendar\local\event\value_objects\action;
/**
* Action testcase.
*
* @package core_calendar
* @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class action_test extends \advanced_testcase {
/**
* Test action class getters.
*
* @dataProvider getters_testcases()
* @param array $constructorparams Associative array of constructor parameters.
*/
public function test_getters($constructorparams): void {
$action = new action(
$constructorparams['name'],
$constructorparams['url'],
$constructorparams['item_count'],
$constructorparams['actionable']
);
foreach ($constructorparams as $name => $value) {
if ($name == 'actionable') {
$this->assertEquals($action->is_actionable(), $value);
} else {
$this->assertEquals($action->{'get_' . $name}(), $value);
}
}
}
/**
* Test cases for getters test.
*/
public function getters_testcases() {
return [
'Dataset 1' => [
'constructorparams' => [
'name' => 'Hello',
'url' => new \moodle_url('http://example.com'),
'item_count' => 1,
'actionable' => true
]
],
'Dataset 2' => [
'constructorparams' => [
'name' => 'Goodbye',
'url' => new \moodle_url('http://example.com'),
'item_count' => 2,
'actionable' => false
]
]
];
}
}
+268
View File
@@ -0,0 +1,268 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Behat calendar-related steps definitions.
*
* @package core_calendar
* @category test
* @copyright 2013 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// NOTE: no MOODLE_INTERNAL used, this file may be required by behat before including /config.php.
require_once(__DIR__ . '/../../../lib/behat/behat_base.php');
use Behat\Gherkin\Node\TableNode as TableNode;
/**
* Contains functions used by behat to test functionality.
*
* @package core_calendar
* @category test
* @copyright 2013 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_calendar extends behat_base {
/**
* Return the list of partial named selectors.
*
* @return array
*/
public static function get_partial_named_selectors(): array {
return [
new behat_component_named_selector('mini calendar block', [".//*[@data-block='calendar_month']"]),
new behat_component_named_selector('full calendar page', [".//*[@id='page-calendar-view']"]),
new behat_component_named_selector('calendar day', [".//*[@data-region='day'][@data-day=%locator%]"]),
new behat_component_named_selector(
'calendar day detail',
[".//*[@data-region='day'][@data-day=%locator%]//a[@data-action='view-day-link']"]
),
new behat_component_named_selector(
'responsive calendar day',
[".//*[@data-region='day'][@data-day=%locator%]/div[contains(@class, 'hidden-desktop')]"]
),
new behat_component_named_selector(
'responsive calendar day detail',
[".//*[@data-region='day'][@data-day=%locator%]" .
"/div[contains(@class, 'hidden-desktop')]//a[@data-action='view-day-link']"]
),
];
}
/**
* Create event when starting on the front page.
*
* @Given /^I create a calendar event with form data:$/
* @param TableNode $data
*/
public function i_create_a_calendar_event_with_form_data($data) {
// Go to current month page.
$this->execute("behat_general::click_link", get_string('fullcalendar', 'calendar'));
// Create event.
$this->i_create_a_calendar_event($data);
}
/**
* Create event.
*
* @Given /^I create a calendar event:$/
* @param TableNode $data
*/
public function i_create_a_calendar_event($data) {
// Get the event name.
$eventname = $data->getRow(1);
$eventname = $eventname[1];
$this->execute("behat_general::wait_until_the_page_is_ready");
if ($this->running_javascript()) {
// Click to create new event.
$this->execute("behat_general::i_click_on", array(get_string('newevent', 'calendar'), "button"));
// Set form fields.
$this->execute("behat_forms::i_set_the_following_fields_to_these_values", $data);
// Save event.
$this->execute("behat_forms::press_button", get_string('save'));
}
}
/**
* Hover over a specific day in the mini-calendar.
*
* @Given /^I hover over day "(?P<dayofmonth>\d+)" of this month in the mini-calendar block(?P<responsive> responsive view|)$/
* @param int $day The day of the current month
* @param string $responsive If not null, find the responsive version of the link.
*/
public function i_hover_over_day_of_this_month_in_mini_calendar_block(int $day, string $responsive = ''): void {
$this->execute(
"behat_general::i_hover_in_the",
[
$day,
empty($responsive) ? 'core_calendar > calendar day' : 'core_calendar > responsive calendar day',
'',
'core_calendar > mini calendar block',
],
);
}
/**
* Hover over a specific day in the full calendar page.
*
* @Given /^I hover over day "(?P<dayofmonth>\d+)" of this month in the full calendar page(?P<responsive> responsive view|)$/
* @param int $day The day of the current month
* @param string $responsive If not empty, use the repsonsive view.
*/
public function i_hover_over_day_of_this_month_in_full_calendar_page(int $day, string $responsive = ''): void {
$this->execute(
"behat_general::i_hover_in_the",
[
$day,
empty($responsive) ? 'core_calendar > calendar day' : 'core_calendar > responsive calendar day',
'',
'core_calendar > full calendar page',
],
);
}
/**
* Click on a specific day in the mini-calendar.
*
* @Given /^I click on day "(?P<dayofmonth>\d+)" of this month in the mini-calendar block(?P<responsive> responsive view|)$/
*
* @param int $day The day of the current month.
* @param string $responsive If not null, find the responsive version of the link.
* @param string $detail If not null, find the detail version of the link.
*/
public function i_click_on_day_of_this_month_in_mini_calendar_block(
int $day,
string $responsive = '',
string $detail = '',
): void {
$selectortype = 'core_calendar >';
if (!empty($responsive)) {
$selectortype .= ' responsive';
}
$selectortype .= ' calendar day';
if (!empty($detail)) {
$selectortype .= ' detail';
}
$this->execute(
contextapi: "behat_general::i_click_on_in_the",
params: [
$day,
$selectortype,
'',
'core_calendar > mini calendar block',
],
);
}
/**
* Hover over today in the mini-calendar.
*
* @Given /^I hover over today in the mini-calendar block( responsive view|)$/
*
* @param string $responsive If not empty, use the responsive calendar link.
*/
public function i_hover_over_today_in_mini_calendar_block(string $responsive = ''): void {
$todaysday = date('j');
$this->i_hover_over_day_of_this_month_in_mini_calendar_block($todaysday, $responsive);
}
/**
* Click on today in the mini-calendar.
*
* @Given /^I click on today in the mini-calendar block( responsive view|)( to view the detail|)$/
*
* @param string $responsive If not empty, use the responsive calendar link.
* @param string $detail If not empty, use the detail view calendar link.
*/
public function i_click_on_today_in_mini_calendar_block(string $responsive = '', string $detail = ''): void {
$this->i_click_on_day_of_this_month_in_mini_calendar_block(
day: date('j'),
responsive: $responsive,
detail: $detail,
);
}
/**
* Navigate to a specific month in the calendar.
*
* @Given /^I view the calendar for "(?P<month>\d+)" "(?P<year>\d+)"$/
* @param int $month the month selected as a number
* @param int $year the four digit year
*/
public function i_view_the_calendar_for($month, $year) {
$this->view_the_calendar('month', 1, $month, $year);
}
/**
* Navigate to a specific date in the calendar.
*
* @Given /^I view the calendar for "(?P<day>\d+)" "(?P<month>\d+)" "(?P<year>\d+)"$/
* @param int $day the day selected as a number
* @param int $month the month selected as a number
* @param int $year the four digit year
*/
public function i_view_the_calendar_day_view(int $day, int $month, int $year) {
$this->view_the_calendar('day', $day, $month, $year);
}
/**
* View the correct calendar view with specific day
*
* @param string $type type of calendar view: month or day
* @param int $day the day selected as a number
* @param int $month the month selected as a number
* @param int $year the four digit year
*/
private function view_the_calendar(string $type, int $day, int $month, int $year) {
$time = make_timestamp($year, $month, $day);
$this->execute('behat_general::i_visit', ['/calendar/view.php?view=' . $type . '&course=1&time=' . $time]);
}
/**
* Navigate to site calendar.
*
* @Given /^I am viewing site calendar$/
* @throws coding_exception
* @return void
*/
public function i_am_viewing_site_calendar() {
$this->i_am_viewing_calendar_in_view('month');
}
/**
* Navigate to a specific view in the calendar.
*
* @Given /^I am viewing calendar in "([^"]+)" view$/
* @param string $view The calendar view ('month', 'day' and 'upcoming') to navigate to.
* @return void
*/
public function i_am_viewing_calendar_in_view(string $view): void {
if (!in_array($view, ['month', 'day', 'upcoming'])) {
throw new Exception("Invalid calendar view. Allowed values are: 'month', 'day' and 'upcoming'");
}
$url = new moodle_url('/calendar/view.php', ['view' => $view]);
$this->execute('behat_general::i_visit', [$url]);
}
}
@@ -0,0 +1,59 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
require_once(__DIR__ . '/../../../lib/behat/behat_deprecated_base.php');
/**
* Steps definitions that are now deprecated and will be removed in the next releases.
*
* This file only contains the steps that previously were in the behat_*.php files in the SAME DIRECTORY.
* When deprecating steps from other components or plugins, create a behat_COMPONENT_deprecated.php
* file in the same directory where the steps were defined.
*
* @package core_calendar
* @category test
* @copyright 2024 Mathew May <mathew.solutions>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_calendar_deprecated extends behat_deprecated_base {
/**
* Hover over today in the calendar.
*
* @Given /^I hover over today in the calendar$/
*
* @deprecated since 4.4 MDL-73117.
* @TODO MDL-79721: This will be deleted in Moodle 4.8.
*/
public function i_hover_over_today_in_the_calendar() {
$this->deprecated_message('behat_calendar::i_hover_over_today_in_the_calendar');
$todaysday = date('j');
$summarytitle = userdate(time(), get_string('strftimemonthyear'));
// The current month table.
$currentmonth = "table[descendant::*[self::caption[contains(concat(' ', normalize-space(.), ' '), ' {$summarytitle} ')]]]";
// Strings for the class cell match.
$cellclasses = "contains(concat(' ', normalize-space(@class), ' '), ' day ')";
$daycontains = "text()[contains(concat(' ', normalize-space(.), ' '), ' {$todaysday} ')]";
$daycell = "td[{$cellclasses}]";
$dayofmonth = "a[{$daycontains}]";
$xpath = '//' . $currentmonth . '/descendant::' . $daycell . '/' . $dayofmonth;
$this->execute("behat_general::i_hover", [$xpath, "xpath_element"]);
}
}
+456
View File
@@ -0,0 +1,456 @@
@core @core_calendar
Feature: Perform basic calendar functionality
In order to ensure the calendar works as expected
As an admin
I need to create calendar data
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
| student3 | Student | 3 | student3@example.com |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "categories" exist:
| name | category | idnumber |
| CatA | 0 | cata |
And the following "courses" exist:
| fullname | shortname | format | category |
| Course 1 | C1 | topics | cata |
| Course 2 | C2 | topics | cata |
| Course 3 | C3 | topics | cata |
| Course 4 | C4 | topics | cata |
And the following "course enrolments" exist:
| user | course | role |
| student1 | C1 | student |
| student3 | C1 | student |
| teacher1 | C1 | teacher |
| admin | C1 | editingteacher |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C1 | G1 |
And the following "group members" exist:
| user | group |
| student1 | G1 |
| teacher1 | G1 |
And the following "blocks" exist:
| blockname | contextlevel | reference | pagetypepattern | defaultregion |
| calendar_month | Course | C1 | course-view-* | side-pre |
| calendar_upcoming | Course | C4 | course-view-* | side-pre |
@javascript
Scenario: Create a site event
Given I log in as "admin"
And I create a calendar event with form data:
| Type of event | site |
| Event title | Really awesome event! |
| Description | Come join this awesome event, sucka! |
And I log out
When I am on the "Course 1" course page logged in as student1
And I follow "Course calendar"
And I should see "Really awesome event!"
And I log out
And I log in as "student2"
And I follow "Full calendar"
Then I should see "Really awesome event!"
@javascript
Scenario: Create a course event
Given I log in as "teacher1"
And I create a calendar event with form data:
| Type of event | course |
| Course | Course 1 |
| Event title | Really awesome event! |
| Description | Come join this awesome event, sucka! |
And I log out
When I am on the "Course 1" course page logged in as student1
And I follow "Course calendar"
And I click on "Really awesome event!" "link"
And "Course 1" "link" should exist in the "Really awesome event!" "dialogue"
And I click on "Close" "button" in the "Really awesome event!" "dialogue"
And I log out
And I log in as "student2"
And I follow "Full calendar"
Then I should not see "Really awesome event!"
@javascript
Scenario: Create a group event
Given I log in as "teacher1"
And I follow "Full calendar"
And I set the field "course" to "C1"
And I create a calendar event:
| Type of event | group |
| Group | Group 1 |
| Event title | Really awesome event! |
| Description | Come join this awesome event |
And I log out
When I am on the "Course 1" course page logged in as student1
And I follow "Course calendar"
Then I follow "Really awesome event!"
@javascript
Scenario: Create a user event
Given I log in as "teacher1"
And I create a calendar event with form data:
| Type of event | user |
| Event title | Really awesome event! |
| Description | Come join this awesome event, sucka! |
And I log out
When I am on the "Course 1" course page logged in as student1
And I follow "Course calendar"
Then I should not see "Really awesome event!"
@javascript
Scenario: Create an event containing URL as location
Given I log in as "admin"
And I create a calendar event with form data:
| Type of event | site |
| Event title | Important webinar |
| Location | https://moodle.org |
When I click on "Important webinar" "link"
Then "https://moodle.org" "link" should exist in the "Important webinar" "dialogue"
@javascript
Scenario: Delete an event
Given I log in as "teacher1"
And I create a calendar event with form data:
| Type of event | user |
| Event title | Really awesome event! |
| Description | Come join this awesome event, sucka! |
And I am on "Course 1" course homepage
When I follow "Course calendar"
And I click on "Really awesome event!" "link"
And I click on "Delete" "button" in the "Really awesome event!" "dialogue"
And I click on "Delete event" "button"
And I wait to be redirected
Then I should not see "Really awesome event!"
@javascript
Scenario: Edit an event
Given I log in as "teacher1"
And I create a calendar event with form data:
| Type of event | user |
| Event title | Really awesome event! |
| Description | Come join this awesome event, sucka! |
| Location | Cube office |
And I am on "Course 1" course homepage
When I follow "Course calendar"
And I click on "Really awesome event!" "link"
And ".location-content" "css_element" should exist
And I should see "Cube office"
And I click on "Edit" "button"
And I set the following fields to these values:
| Event title | Mediocre event :( |
| Description | Wait, this event isn't that great. |
| Location | |
And I press "Save"
And I should see "Mediocre event"
And I click on "Mediocre event :(" "link"
Then I should see "Mediocre event"
And ".location-content" "css_element" should not exist
@javascript @editor_tiny
Scenario: Edit a newly created event using TinyMCE editor
Given I log in as "teacher1"
And I follow "Dashboard"
And I click on "New event" "button"
And I set the field "Event title" to "Newly created event"
When I press "Save"
Then I should see "Newly created event"
And I click on "Newly created event" "link"
And I click on "Edit" "button" in the "Newly created event" "dialogue"
And I click on "Show more..." "link"
And I click on the "Link" button for the "Description" TinyMCE editor
And I set the field "Text to display" to "Read more..."
And I set the field "Enter a URL" to "https://moodle.org/"
And I click on "Create link" "button" in the "Create link" "dialogue"
And I press "Save"
And I click on "Newly created event" "link"
And I should see "Read more..."
@javascript
Scenario: Module events editing
Given I log in as "teacher1"
And I am on "Course 1" course homepage
And the following "activities" exist:
| activity | course | idnumber | name | intro | timeopen | timeclose |
| choice | C1 | choice1 | Test choice | Test choice description | ##today## | ##today## |
When I follow "Course calendar"
Then I should see "Test choice opens"
And I should see "Test choice closes"
When I click on "Test choice opens" "link"
Then "Delete" "button" should not exist in the "Test choice opens" "dialogue"
And "Edit" "button" should not exist in the "Test choice opens" "dialogue"
And I should see "Course event"
When I click on "Go to activity" "link"
And I wait to be redirected
Then I should see "Test choice"
And I am on "Course 1" course homepage
And I follow "Course calendar"
When I click on "Test choice closes" "link"
Then "Delete" "button" should not exist in the "Test choice closes" "dialogue"
And "Edit" "button" should not exist in the "Test choice closes" "dialogue"
And I should see "Course event"
When I click on "Go to activity" "link"
And I wait to be redirected
Then I should see "Test choice"
@javascript
Scenario: Attempt to create event without fill required fields should display validation errors
Given I am on the "Course 1" course page logged in as teacher1
And I follow "Course calendar"
And I click on "New event" "button"
When I click on "Save" "button"
Then I should see "Required" in the "Event title" "form_row"
And I am on homepage
And I follow "Full calendar"
And I click on "New event" "button"
And I set the field "Event title" to "Really awesome event!"
And I set the field "Type of event" to "Course"
And I click on "Save" "button"
And I should see "Select a course" in the "Course" "form_row"
@javascript
Scenario: Default event type selection in the event form
Given I log in as "teacher1"
When I am viewing site calendar
And I click on "New event" "button"
Then the field "Type of event" matches value "User"
And I click on "Close" "button" in the "New event" "dialogue"
And I set the field "course" to "C1"
When I click on "New event" "button"
Then the field "Type of event" matches value "Course"
@javascript
Scenario: Admin can only see all courses if calendar_adminseesall setting is enabled.
Given I am on the "Course 1" course page logged in as admin
And I am viewing site calendar
And I click on "New event" "button"
And I set the field "Type of event" to "Course"
When I expand the "Course" autocomplete
Then "Course 1" "autocomplete_suggestions" should exist
And "Course 2" "autocomplete_suggestions" should not exist
And "Course 3" "autocomplete_suggestions" should not exist
And I click on "Close" "button" in the "New event" "dialogue"
And I am on site homepage
And I navigate to "Appearance > Calendar" in site administration
And I set the field "Admins see all" to "1"
And I press "Save changes"
And I am viewing site calendar
And I click on "New event" "button"
And I set the field "Type of event" to "Course"
When I expand the "Course" autocomplete
Then "Course 1" "autocomplete_suggestions" should exist
And "Course 2" "autocomplete_suggestions" should exist
And "Course 3" "autocomplete_suggestions" should exist
@javascript
Scenario: Students can not see event type field by default.
Given I log in as "student1"
And I am viewing site calendar
When I click on "New event" "button"
# Only "user" event type is available, so "Type of event" field should not be displayed.
Then "Type of event" "select" should not exist
@javascript
Scenario: "Student 2" has "manageentries" capability assigned but it's not enrolled in any course.
Given the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/calendar:manageentries | Allow | student | System | |
And I log in as "student2"
And I am viewing site calendar
When I click on "New event" "button"
# Only "user" event type is available, so "Type of event" field should not be displayed.
Then "Type of event" "select" should not exist
@javascript
Scenario: "Student 1" has "manageentries" capability assigned and it's enrolled in a course.
Given the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/calendar:manageentries | Allow | student | System | |
And I log in as "student1"
And I am viewing site calendar
When I click on "New event" "button"
# Student 1 is enrolled in a course and have the capability assigned.
# Then, the "Type of event" select box should be visible.
Then "Type of event" "select" should exist
And I should see "User" in the "Type of event" "select"
And I should see "Course" in the "Type of event" "select"
@javascript @accessibility
Scenario: The calendar page must be accessible
Given I am on the "Course 1" course page logged in as student1
When I follow "Course calendar"
Then the page should meet accessibility standards
And the page should meet "wcag131, wcag143, wcag412" accessibility standards
And the page should meet accessibility standards with "wcag131, wcag143, wcag412" extra tests
@javascript
Scenario: The calendar page should be responsive
Given I log in as "admin"
And I am viewing site calendar
And I create a calendar event:
| Type of event | site |
| Event title | Event 1:1 |
| timestart[day] | 1 |
When I change viewport size to "1200x1000"
Then I should see "Event 1:1"
And I change viewport size to "600x1000"
# We need to give the browser a couple seconds to re-render the page after the screen has been resized.
And I wait "1" seconds
And I should not see "Event 1:1"
And I hover over day "1" of this month in the full calendar page responsive view
And I should see "Event 1:1"
@javascript
Scenario: Admin can create and edit course events if calendar_adminseesall setting is disabled
Given I log in as "admin"
And the following config values are set as admin:
| calendar_adminseesall | 0 |
And I am on "Course 4" course homepage with editing mode on
And I click on "Go to calendar..." "link" in the "Upcoming events" "block"
And I click on "New event" "button"
And I should see "Course" in the "Type of event" "select"
And "Course 4" "autocomplete_selection" should exist
And I set the field "Event title" to "Test course event"
And I click on "Save" "button"
And I should see "Test course event"
When I click on "Edit" "link" in the "region-main" "region"
Then the field "Event title" matches value "Test course event"
And the field "Type of event" matches value "Course"
And "Course 4" "autocomplete_selection" should exist
@javascript
Scenario: Changing the event type should clear previous data
Given I am on the "Course 1" course page logged in as admin
And I follow "Course calendar"
And I press "New event"
And I set the following fields to these values:
| Event title | Group 1 event |
| Type of event | Group |
And I press "Save"
And I am on "Course 1" course homepage
And I follow "Course calendar"
And I click on "Group 1 event" "link"
And I should see "Group event"
And I should see "Group 1"
When I click on "Edit" "button" in the "Group 1 event" "dialogue"
And I set the following fields to these values:
| Event title | My own user event |
| Type of event | user |
And I press "Save"
And I click on "My own user event" "link"
Then I should see "User event"
And I should not see "Group 1"
And I click on "Edit" "button" in the "My own user event" "dialogue"
And I set the following fields to these values:
| Event title | Site event |
| Type of event | site |
And I press "Save"
And I click on "Site event" "link"
And I should see "Site event"
And I click on "Edit" "button" in the "Site event" "dialogue"
And I set the following fields to these values:
| Event title | Course 1 event |
| Type of event | course |
And I expand the "Course" autocomplete
And I click on "Course 1" item in the autocomplete list
And I press "Save"
And I click on "Course 1 event" "link"
And I should see "Course event"
And I click on "Edit" "button" in the "Course 1 event" "dialogue"
And I set the following fields to these values:
| Event title | Category event |
| Type of event | category |
| Category | CatA |
And I press "Save"
And I click on "Category event" "link"
And I should see "Category event"
@javascript
Scenario: Changing the event type from user to anything else should work
Given I log in as "teacher1"
# We need this so we can see the groups.
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And the following "role assigns" exist:
| user | role | contextlevel | reference |
| teacher1 | manager | Category | cata |
And I am on "Course 1" course homepage
And I follow "Course calendar"
And I press "New event"
And I set the following fields to these values:
| Event title | type change test event |
| Type of event | User |
And I press "Save"
And I am on "Course 1" course homepage
And I follow "Course calendar"
And I click on "type change test event" "link"
And I should see "User event"
When I click on "Edit" "button"
And I set the following fields to these values:
| Event title | type change test event |
| Type of event | Course |
And I expand the "Course" autocomplete
And I click on "Course 1" item in the autocomplete list
And I press "Save"
And I click on "type change test event" "link"
Then I should see "Course event"
# Reset to user event
And I click on "Edit" "button" in the "type change test event" "dialogue"
And I set the following fields to these values:
| Event title | type change test event |
| Type of event | User |
And I press "Save"
And I click on "type change test event" "link"
And I should see "User event"
# Now test changing from user to group event.
And I am on "Course 1" course homepage
And I follow "Course calendar"
And I click on "type change test event" "link"
And I click on "Edit" "button"
And I set the following fields to these values:
| Event title | type change test event |
| Type of event | Group |
And I click on "#fitem_id_groupcourseid .form-autocomplete-downarrow" "css_element"
And I click on "Course 1" item in the autocomplete list
And I set the following fields to these values:
| Group | Group 1 |
And I press "Save"
And I click on "type change test event" "link"
And I should see "Group event"
# Reset to user event
And I click on "Edit" "button" in the "type change test event" "dialogue"
And I set the following fields to these values:
| Event title | type change test event |
| Type of event | User |
And I press "Save"
And I click on "type change test event" "link"
And I should see "User event"
# Now test changing from user to course event.
And I click on "Edit" "button" in the "type change test event" "dialogue"
And I set the following fields to these values:
| Event title | Course 1 event |
| Type of event | Course |
And I expand the "Course" autocomplete
And I click on "Course 1" item in the autocomplete list
And I press "Save"
And I click on "Course 1 event" "link"
And I should see "Course event"
# Reset to user event
And I click on "Edit" "button" in the "Course 1 event" "dialogue"
And I set the following fields to these values:
| Event title | type change test event |
| Type of event | User |
And I press "Save"
And I click on "type change test event" "link"
And I should see "User event"
# Now test changing from user to category event.
And I click on "Edit" "button" in the "type change test event" "dialogue"
And I set the following fields to these values:
| Event title | type change test event |
| Type of event | Category |
And I press "Save"
And I click on "type change test event" "link"
And I should see "Category event"
@@ -0,0 +1,104 @@
@core @core_calendar @_file_upload @javascript
Feature: Import and edit calendar events
In order to manipulate imported calendar events
As an user
I need to import calendar events then edit them.
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | topics |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
Scenario: Import then edit a calendar event.
Given I log in as "teacher1"
And I view the calendar for "1" "2016"
And I click on "Import or export calendars" "link"
And "Calendar" "link" should exist in the ".breadcrumb" "css_element"
And "Import or export calendars" "text" should exist in the ".breadcrumb" "css_element"
And I press "Import calendar"
And "Calendar" "link" should exist in the ".breadcrumb" "css_element"
And "Import or export calendars" "link" should exist in the ".breadcrumb" "css_element"
And "Import calendar" "text" should exist in the ".breadcrumb" "css_element"
And I set the following fields to these values:
| Calendar name | Test Import |
| Import from | Calendar file (.ics) |
| Type of event | User |
And I upload "calendar/tests/fixtures/import.ics" file to "Calendar file (.ics)" filemanager
And I press "Import calendar"
And I should see "2 events were imported"
And I view the calendar for "2" "2017"
And I should see "February 2017"
And I should see "Event on 2-15-2017"
And I should see "Event on 2-25-2017"
And I click on "Event on 2-15-2017" "link"
And I should see "Some place"
And I click on "Edit" "button"
And I set the following fields to these values:
| Event title | Event on 2-20-2017 |
| Description | Event on 2-20-2017 |
| timestart[day] | 20 |
And I press "Save"
When I view the calendar for "2" "2017"
Then I should see "Event on 2-20-2017"
And I should see "Event on 2-25-2017"
And I should not see "Event on 2-15-2017"
And I click on "Import or export calendars" "link"
And I click on "Delete" "link"
And I should see "Are you sure you want to delete the \"Test Import\" calendar subscription?" in the ".modal .modal-body" "css_element"
And I click on "Yes" "button" in the ".modal.show" "css_element"
And I view the calendar for "2" "2017"
And I should not see "Event on 2-25-2017"
And I should not see "Event on 2-20-2017"
Scenario: Import events using different event types.
Given I log in as "admin"
And I view the calendar for "1" "2016"
And I click on "Import or export calendars" "link"
And I press "Import calendar"
And I set the following fields to these values:
| Calendar name | Test Import |
| Import from | Calendar file (.ics) |
| Type of event | User |
And I upload "calendar/tests/fixtures/import.ics" file to "Calendar file (.ics)" filemanager
And I press "Import calendar"
And I should see "User events"
And I press "Import calendar"
And I set the following fields to these values:
| Calendar name | Test Import |
| Import from | Calendar file (.ics) |
| Type of event | Category |
| Category | Category 1 |
And I upload "calendar/tests/fixtures/import.ics" file to "Calendar file (.ics)" filemanager
And I press "Import calendar"
And I should see "Category events"
And I press "Import calendar"
And I set the following fields to these values:
| Calendar name | Test Import |
| Import from | Calendar file (.ics) |
| Type of event | Site |
And I upload "calendar/tests/fixtures/import.ics" file to "Calendar file (.ics)" filemanager
And I press "Import calendar"
And I should see "Site events"
Scenario: Import iCalendar file with parameter.
Given I log in as "admin"
And I view the calendar for "7" "2022"
And I click on "Import or export calendars" "link"
And I press "Import calendar"
And I set the following fields to these values:
| Calendar name | Test Import |
| Import from | Calendar file (.ics) |
| Type of event | User |
And I upload "calendar/tests/fixtures/import_with_parameters.ics" file to "Calendar file (.ics)" filemanager
And I press "Import calendar"
When I view the calendar for "1" "7" "2022"
Then I should see "First event"
And I should see "Description of the first event"
And I should see "Second event"
And I should see "Description of the second event"
@@ -0,0 +1,42 @@
@core @core_calendar @javascript
Feature: Limit displayed upcoming events
In order to filter what is displayed on the calendar
As a user
I need to interact with the calendar
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | topics |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And the following "blocks" exist:
| blockname | contextlevel | reference | pagetypepattern | defaultregion |
| calendar_month | Course | C1 | course-view-* | side-pre |
| calendar_upcoming | Course | C1 | course-view-* | side-pre |
And I log in as "teacher1"
Scenario: I view calendar details for a future event
Given I am on "Course 1" course homepage with editing mode on
And I follow "Course calendar"
And I click on "a.next" "css_element"
And I click on "a.next" "css_element"
When I create a calendar event:
| Type of event | course |
| Course | Course 1 |
| Event title | Two months away event |
And I am on "Course 1" course homepage
Then I should not see "Two months away event"
And I am on site homepage
And I follow "Preferences" in the user menu
And I follow "Calendar preferences"
When I set the following fields to these values:
| Upcoming events look-ahead | 3 months |
And I press "Save changes"
And I wait to be redirected
And I am on "Course 1" course homepage
Then I should see "Two months away event"
@@ -0,0 +1,27 @@
@core @core_calendar
Feature: Verify that the day and month names are displayed using UTF-8
In order to be able to use the calendar using different languages
As a user
I need to see the day and month names displayed properly
Background:
Given remote langimport tests are enabled
Scenario Outline: View the calendar for December 2012 with correct UTF-8
Given the following "language pack" exists:
| language | <lang> |
And I log in as "admin"
And I follow "Preferences" in the user menu
And I follow "Preferred language"
And I set the field "Preferred language" to "<lang>"
And I press "Save changes"
When I view the calendar for "12" "2022"
Then I should see "<month>"
And I should see "<day>"
Examples:
| lang | month | day |
| en_ar | December | Sat |
| es | diciembre | Sáb |
| fr | décembre | Sa |
| ru | декабря | Сб |
@@ -0,0 +1,75 @@
@core @core_calendar @javascript
Feature: Perform calendar filter actions
In order to test the calendar filters with preselected options
As a user
I need to filter calendar events by certain criteria
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "categories" exist:
| name | idnumber | category |
| Year | year | |
| Department C1 | department-c1 | year |
And the following "courses" exist:
| fullname | shortname | format | category |
| Course 1 | C1 | topics | department-c1 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C1 | G1 |
And the following "group members" exist:
| user | group |
| teacher1 | G1 |
And the following "events" exist:
| name | eventtype |
| Site event | site |
And the following "events" exist:
| name | eventtype | course |
| C1 event | course | C1 |
And the following "events" exist:
| name | eventtype | category |
| Dep1a event | category | department-c1 |
And the following "events" exist:
| name | eventtype | group | course |
| Group1 event | group | G1 | C1 |
Scenario: Teacher of a Course can see his events and filter them
Given I log in as "teacher1"
When I follow "Calendar" in the user menu
Then I should see "C1 event"
And I should see "Dep1a event"
And I should see "Group1 event"
And I click on "Hide category events" "link"
And I should see "C1 event"
And I should not see "Dep1a event"
And I should see "Group1 event"
And I click on "Hide course events" "link"
And I should not see "C1 event"
And I should not see "Dep1a event"
And I should see "Group1 event"
Scenario: Teacher of a Course can see only non filtered events from user preferences calendar_savedflt
Given I log in as "teacher1"
And the following "user preferences" exist:
| user | preference | value |
| teacher1 | calendar_persistflt | 1 |
| teacher1 | calendar_savedflt | 13 |
When I follow "Calendar" in the user menu
Then I should not see "C1 event"
And I should see "Dep1a event"
And I should not see "Group1 event"
Scenario: Teacher of a Course can see all events because session is used and not user preference calendar_savedflt
Given I log in as "teacher1"
And the following "user preferences" exist:
| user | preference | value |
| teacher1 | calendar_persistflt | 0 |
| teacher1 | calendar_savedflt | 13 |
When I follow "Calendar" in the user menu
Then I should see "C1 event"
And I should see "Dep1a event"
And I should see "Group1 event"
@@ -0,0 +1,100 @@
@core @core_calendar
Feature: Course Category Events
In order to inform multiple courses of shared events
As a manager
I need to create catgory events
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| managera | Manager | A | managera@example.com |
| managera1 | Manager | A1 | managera1@example.com |
| managera2 | Manager | A2 | managera2@example.com |
| teachera1i | Teacher | A1i | teachera1i@example.com |
| managerb | Manager | B | managerb@example.com |
| managerb1 | Manager | B1 | managerb1@example.com |
| managerb2 | Manager | B2 | managerb2@example.com |
| teacherb1i | Teacher | B1i | teacherb1i@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
And the following "categories" exist:
| name | idnumber | category |
| Year | year | |
| Faculty A | faculty-a | year |
| Faculty B | faculty-b | year |
| Department A1 | department-a1 | faculty-a |
| Department A2 | department-a2 | faculty-a |
| Department B1 | department-b1 | faculty-b |
| Department B2 | department-b2 | faculty-b |
And the following "courses" exist:
| fullname | shortname | idnumber | format | category |
| Course A1i | A1i | A1i | topics | department-a1 |
| Course A2i | A2i | A2i | topics | department-a2 |
| Course B1i | B1i | B1i | topics | department-b1 |
| Course B2i | B2i | B2i | topics | department-b2 |
And the following "role assigns" exist:
| user | role | contextlevel | reference |
| managera | manager | Category | faculty-a |
| managera1 | manager | Category | department-a1 |
| managerb | manager | Category | faculty-b |
| managerb1 | manager | Category | department-b1 |
And the following "course enrolments" exist:
| user | course | role |
| teachera1i | A1i | editingteacher |
| teacherb1i | B1i | editingteacher |
| student1 | A1i | student |
| student1 | A2i | student |
| student2 | B1i | student |
| student2 | B2i | student |
And the following "events" exist:
| name | eventtype |
| Site event | site |
And the following "events" exist:
| name | eventtype | course |
| CA1i event | course | A1i |
| CA2i event | course | A2i |
| CB1i event | course | B1i |
| CB2i event | course | B2i |
And the following "events" exist:
| name | eventtype | category |
| FA event | category | faculty-a |
| DA1 event | category | department-a1 |
| DA2 event | category | department-a1 |
| FB event | category | faculty-b |
| DB1 event | category | department-b1 |
| DB2 event | category | department-b1 |
@javascript
Scenario: Manager of a Category can see all child and parent events in their category
Given I log in as "managera"
When I follow "Calendar" in the user menu
Then I should see "FA event"
And I should see "DA1 event"
And I should see "DA2 event"
And I should not see "FB event"
And I should not see "DB1 event"
And I should not see "DB2 event"
And I log out
Given I log in as "managerb"
And I follow "Calendar" in the user menu
Then I should see "FB event"
And I should see "DB1 event"
And I should see "DB2 event"
And I should not see "FA event"
And I should not see "DA1 event"
And I should not see "DA2 event"
@javascript
Scenario: Users enrolled in a course can see all child and parent events in their category
Given I log in as "student1"
When I follow "Calendar" in the user menu
Then I should see "FA event"
And I should see "DA1 event"
And I should see "DA2 event"
And I should see "CA1i event"
And I should see "CA2i event"
And I should not see "FB event"
And I should not see "DB1 event"
And I should not see "DB2 event"
And I should not see "CB1i event"
And I should not see "CB2i event"
+95
View File
@@ -0,0 +1,95 @@
@core @core_calendar
Feature: Export calendar events
In order to be able to use my calendar events outside of Moodle
As a user
I need to export calendar events in iCalendar format
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| student1 | Student | 1 | student1@example.com |
And the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | topics |
And the following "course enrolments" exist:
| user | course | role |
| student1 | C1 | student |
And I log in as "student1"
Scenario: Viewing calendar export options
Given I follow "Full calendar"
When I click on "Import or export calendars" "link"
And "Calendar" "link" should exist in the ".breadcrumb" "css_element"
And "Import or export calendars" "text" should exist in the ".breadcrumb" "css_element"
And I click on "Export calendar" "button"
And "Calendar" "link" should exist in the ".breadcrumb" "css_element"
And "Import or export calendars" "link" should exist in the ".breadcrumb" "css_element"
And "Export calendar" "text" should exist in the ".breadcrumb" "css_element"
Then I should see "All events"
And I should see "Events related to courses"
And I should see "Events related to groups"
And I should see "My personal events"
@javascript
Scenario: Export calendar in ics format
And I follow "Full calendar"
And I press "New event"
And I set the following fields to these values:
| Event title | My event |
| id_timestart_hour | 13 |
| id_timestart_minute | 00 |
And I press "Save"
When I click on "Import or export calendars" "link"
And I click on "Export calendar" "button"
And I set the field "All events" to "1"
And I set the field "Recent and next 60 days" to "1"
And I press "Export"
And I should see "SUMMARY:My event"
# We need to split the step in two because Bennu library use days with leading zero and moodle removes it.
And I should see "##today##DTSTART:%Y%m##"
And I should see "##today##%dT050000Z##"
Scenario: Generating calendar URL for all events
Given I follow "Full calendar"
And I click on "Import or export calendars" "link"
And I click on "Export calendar" "button"
And I set the field "All events" to "1"
And I set the field "Recent and next 60 days" to "1"
When I click on "Get calendar URL" "button"
Then the "value" attribute of "Calendar URL" "field" should contain "&preset_what=all&"
Scenario: Generating calendar URL for course events
Given I follow "Full calendar"
And I click on "Import or export calendars" "link"
And I click on "Export calendar" "button"
And I set the field "Events related to courses" to "1"
And I set the field "Recent and next 60 days" to "1"
When I click on "Get calendar URL" "button"
Then the "value" attribute of "Calendar URL" "field" should contain "&preset_what=courses&"
Scenario: Generating calendar URL for group events
Given I follow "Full calendar"
And I click on "Import or export calendars" "link"
And I click on "Export calendar" "button"
And I set the field "Events related to groups" to "1"
And I set the field "Recent and next 60 days" to "1"
When I click on "Get calendar URL" "button"
Then the "value" attribute of "Calendar URL" "field" should contain "&preset_what=groups&"
Scenario: Generating calendar URL for category events
Given I follow "Full calendar"
And I click on "Import or export calendars" "link"
And I click on "Export calendar" "button"
And I set the field "Events related to categories" to "1"
And I set the field "Recent and next 60 days" to "1"
When I click on "Get calendar URL" "button"
Then the "value" attribute of "Calendar URL" "field" should contain "&preset_what=categories&"
Scenario: Generating calendar URL for user events
Given I follow "Full calendar"
And I click on "Import or export calendars" "link"
And I click on "Export calendar" "button"
And I set the field "My personal events" to "1"
And I set the field "Recent and next 60 days" to "1"
When I click on "Get calendar URL" "button"
Then the "value" attribute of "Calendar URL" "field" should contain "&preset_what=user&"
+47
View File
@@ -0,0 +1,47 @@
@core @core_calendar
Feature: Open calendar popup
In order to view calendar information
As a user
I need to interact with the calendar
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| student1 | Student | 1 | student1@example.com |
And the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | topics |
And the following "course enrolments" exist:
| user | course | role |
| student1 | C1 | student |
And I log in as "admin"
@javascript
Scenario: I view calendar details of a day with multiple events
Given I follow "Full calendar"
And I create a calendar event:
| Type of event | site |
| Event title | Event 1:1 |
| timestart[day] | 1 |
And I create a calendar event:
| Type of event | site |
| Event title | Event 1:2 |
| timestart[day] | 1 |
When I reload the page
Then I should see "Event 1:1"
And I should see "Event 1:2"
And I am on homepage
When I hover over day "1" of this month in the mini-calendar block
And I should see "Event 1:1"
And I should see "Event 1:2"
@javascript
Scenario: I view calendar details for today
Given I follow "Full calendar"
When I create a calendar event:
| Type of event | site |
| Event title | Today's event |
Then I should see "Today's event"
And I am on homepage
And I hover over today in the mini-calendar block
And I should see "Today's event"
@@ -0,0 +1,302 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_calendar;
use core_calendar\external\calendar_event_exporter;
use core_calendar\local\event\container;
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__ . '/helpers.php');
/**
* Calendar event exporter testcase.
*
* @package core_calendar
* @copyright 2017 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class calendar_event_exporter_test extends \advanced_testcase {
/**
* Data provider for the timestamp min limit test case to confirm
* that the minimum time limit is set correctly on the boundary cases.
*/
public function get_timestamp_min_limit_test_cases() {
$now = time();
$todaymidnight = usergetmidnight($now);
$tomorrowmidnight = $todaymidnight + DAYSECS;
$eightam = $todaymidnight + (60 * 60 * 8);
$starttime = (new \DateTime())->setTimestamp($eightam);
return [
'before min' => [
$starttime,
[
($starttime->getTimestamp() + 1),
'some error'
],
$tomorrowmidnight
],
'equal min' => [
$starttime,
[
$starttime->getTimestamp(),
'some error'
],
$todaymidnight
],
'after min' => [
$starttime,
[
($starttime->getTimestamp() - 1),
'some error'
],
$todaymidnight
]
];
}
/**
* @dataProvider get_timestamp_min_limit_test_cases()
*/
public function test_get_timestamp_min_limit($starttime, $min, $expected): void {
$class = calendar_event_exporter::class;
$mock = $this->getMockBuilder($class)
->disableOriginalConstructor()
->onlyMethods([])
->getMock();
$reflector = new \ReflectionClass($class);
$method = $reflector->getMethod('get_timestamp_min_limit');
$result = $method->invoke($mock, $starttime, $min);
$this->assertEquals($expected, $result['mindaytimestamp']);
$this->assertEquals($min[1], $result['mindayerror']);
}
/**
* Data provider for the timestamp max limit test case to confirm
* that the maximum time limit is set correctly on the boundary cases.
*/
public function get_timestamp_max_limit_test_cases() {
$now = time();
$todaymidnight = usergetmidnight($now);
$yesterdaymidnight = $todaymidnight - DAYSECS;
$eightam = $todaymidnight + (60 * 60 * 8);
$starttime = (new \DateTime())->setTimestamp($eightam);
return [
'before max' => [
$starttime,
[
($starttime->getTimestamp() + 1),
'some error'
],
$todaymidnight
],
'equal max' => [
$starttime,
[
$starttime->getTimestamp(),
'some error'
],
$todaymidnight
],
'after max' => [
$starttime,
[
($starttime->getTimestamp() - 1),
'some error'
],
$yesterdaymidnight
]
];
}
/**
* @dataProvider get_timestamp_max_limit_test_cases()
*/
public function test_get_timestamp_max_limit($starttime, $max, $expected): void {
$class = calendar_event_exporter::class;
$mock = $this->getMockBuilder($class)
->disableOriginalConstructor()
->onlyMethods([])
->getMock();
$reflector = new \ReflectionClass($class);
$method = $reflector->getMethod('get_timestamp_max_limit');
$result = $method->invoke($mock, $starttime, $max);
$this->assertEquals($expected, $result['maxdaytimestamp']);
$this->assertEquals($max[1], $result['maxdayerror']);
}
/**
* Exporting a course event should generate the course URL.
*/
public function test_calendar_event_exporter_course_url_course_event(): void {
global $CFG, $PAGE;
require_once($CFG->dirroot . '/course/lib.php');
$this->resetAfterTest(true);
$this->setAdminUser();
$generator = $this->getDataGenerator();
$user = $generator->create_user();
$course = $generator->create_course();
$context = \context_course::instance($course->id);
$now = time();
$mapper = container::get_event_mapper();
$legacyevent = create_event([
'courseid' => $course->id,
'userid' => 1,
'eventtype' => 'course',
'timestart' => $now
]);
$event = $mapper->from_legacy_event_to_event($legacyevent);
$exporter = new calendar_event_exporter($event, [
'context' => $context,
'course' => $course,
'moduleinstance' => null,
'daylink' => new \moodle_url(''),
'type' => type_factory::get_calendar_instance(),
'today' => $now
]);
$courseurl = course_get_url($course->id);
$expected = $courseurl->out(false);
$renderer = $PAGE->get_renderer('core_calendar');
$exportedevent = $exporter->export($renderer);
// The exported URL should be for the course.
$this->assertEquals($expected, $exportedevent->url);
}
/**
* Exporting a user event should generate the site course URL.
*/
public function test_calendar_event_exporter_course_url_user_event(): void {
global $CFG, $PAGE;
require_once($CFG->dirroot . '/course/lib.php');
$this->resetAfterTest(true);
$this->setAdminUser();
$generator = $this->getDataGenerator();
$user = $generator->create_user();
$context = \context_user::instance($user->id);
$now = time();
$mapper = container::get_event_mapper();
$legacyevent = create_event([
'courseid' => 0,
'userid' => $user->id,
'eventtype' => 'user',
'timestart' => $now
]);
$event = $mapper->from_legacy_event_to_event($legacyevent);
$exporter = new calendar_event_exporter($event, [
'context' => $context,
'course' => null,
'moduleinstance' => null,
'daylink' => new \moodle_url(''),
'type' => type_factory::get_calendar_instance(),
'today' => $now
]);
$courseurl = course_get_url(SITEID);
$expected = $courseurl->out(false);
$renderer = $PAGE->get_renderer('core_calendar');
$exportedevent = $exporter->export($renderer);
// The exported URL should be for the site course.
$this->assertEquals($expected, $exportedevent->url);
}
/**
* Popup name respects filters for course shortname.
*/
public function test_calendar_event_exporter_popupname_course_shortname_strips_links(): void {
global $CFG, $PAGE;
$this->resetAfterTest(true);
$this->setAdminUser();
$generator = $this->getDataGenerator();
$user = $generator->create_user();
$rawshortname = 'Shortname <a href="#">link</a>';
$nolinkshortname = strip_links($rawshortname);
$course = $generator->create_course(['shortname' => $rawshortname]);
$coursecontext = \context_course::instance($course->id);
$now = time();
$mapper = container::get_event_mapper();
$renderer = $PAGE->get_renderer('core_calendar');
$legacyevent = create_event([
'courseid' => $course->id,
'userid' => 1,
'eventtype' => 'course',
'timestart' => $now
]);
$event = $mapper->from_legacy_event_to_event($legacyevent);
$exporter = new calendar_event_exporter($event, [
'context' => $coursecontext,
'course' => $course,
'moduleinstance' => null,
'daylink' => new \moodle_url(''),
'type' => type_factory::get_calendar_instance(),
'today' => $now
]);
$exportedevent = $exporter->export($renderer);
// Links should always be stripped from the course short name.
$this->assertMatchesRegularExpression("/$nolinkshortname/", $exportedevent->popupname);
}
/**
* Exported event contains the exported course.
*/
public function test_calendar_event_exporter_exports_course(): void {
global $CFG, $PAGE;
$this->resetAfterTest(true);
$this->setAdminUser();
$generator = $this->getDataGenerator();
$user = $generator->create_user();
$rawshortname = 'Shortname <a href="#">link</a>';
$nolinkshortname = strip_links($rawshortname);
$course = $generator->create_course(['shortname' => $rawshortname]);
$coursecontext = \context_course::instance($course->id);
$now = time();
$mapper = container::get_event_mapper();
$renderer = $PAGE->get_renderer('core_calendar');
$legacyevent = create_event([
'courseid' => $course->id,
'userid' => 1,
'eventtype' => 'course',
'timestart' => $now
]);
$event = $mapper->from_legacy_event_to_event($legacyevent);
$exporter = new calendar_event_exporter($event, [
'context' => $coursecontext,
'course' => $course,
'moduleinstance' => null,
'daylink' => new \moodle_url(''),
'type' => type_factory::get_calendar_instance(),
'today' => $now
]);
$exportedevent = $exporter->export($renderer);
$courseexporter = new \core_course\external\course_summary_exporter($course, [
'context' => $coursecontext
]);
$exportedcourse = $courseexporter->export($renderer);
$this->assertEquals($exportedevent->course, $exportedcourse);
}
}
File diff suppressed because it is too large Load Diff
+331
View File
@@ -0,0 +1,331 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains the class that handles testing the calendar type system.
*
* @package core_calendar
* @copyright 2013 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_calendar;
defined('MOODLE_INTERNAL') || die();
global $CFG;
// The test calendar type.
require_once($CFG->dirroot . '/calendar/tests/calendartype_test_example.php');
// Used to test the dateselector elements.
require_once($CFG->libdir . '/form/dateselector.php');
require_once($CFG->libdir . '/form/datetimeselector.php');
// Used to test the user datetime profile field.
require_once($CFG->dirroot . '/user/profile/lib.php');
require_once($CFG->dirroot . '/user/profile/definelib.php');
/**
* Unit tests for the calendar type system.
*
* @package core_calendar
* @copyright 2013 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 2.6
*/
class calendartype_test extends \advanced_testcase {
/** @var MoodleQuickForm Keeps reference of dummy form object */
private $mform;
/**
* The test user.
*/
private $user;
/**
* Test set up.
*/
protected function setUp(): void {
// The user we are going to test this on.
$this->user = self::getDataGenerator()->create_user();
self::setUser($this->user);
// Get form data.
$form = new temp_form_calendartype();
$this->mform = $form->getform();
}
/**
* Test that setting the calendar type works.
*/
public function test_calendar_type_set(): void {
// We want to reset the test data after this run.
$this->resetAfterTest();
// Test setting it as the 'Test' calendar type.
$this->set_calendar_type('test_example');
$this->assertEquals('test_example', \core_calendar\type_factory::get_calendar_type());
// Test setting it as the 'Gregorian' calendar type.
$this->set_calendar_type('gregorian');
$this->assertEquals('gregorian', \core_calendar\type_factory::get_calendar_type());
}
/**
* Test that calling core Moodle functions responsible for displaying the date
* have the same results as directly calling the same function in the calendar type.
*/
public function test_calendar_type_core_functions(): void {
// We want to reset the test data after this run.
$this->resetAfterTest();
// Test that the core functions reproduce the same results as the Gregorian calendar.
$this->core_functions_test('gregorian');
// Test that the core functions reproduce the same results as the test calendar.
$this->core_functions_test('test_example');
}
/**
* Test that dates selected using the date selector elements are being saved as unixtime, and that the
* unixtime is being converted back to a valid date to display in the date selector elements for
* different calendar types.
*/
public function test_calendar_type_dateselector_elements(): void {
// We want to reset the test data after this run.
$this->resetAfterTest();
$this->setTimezone('UTC');
// Note: this test is pretty useless because it does not test current user timezones.
// Check converting dates to Gregorian when submitting a date selector element works. Note: the test
// calendar is 2 years, 2 months, 2 days, 2 hours and 2 minutes ahead of the Gregorian calendar.
$date1 = array();
$date1['day'] = 4;
$date1['month'] = 7;
$date1['year'] = 2013;
$date1['hour'] = 0;
$date1['minute'] = 0;
$date1['timestamp'] = 1372896000;
$this->convert_dateselector_to_unixtime_test('dateselector', 'gregorian', $date1);
$date2 = array();
$date2['day'] = 7;
$date2['month'] = 9;
$date2['year'] = 2015;
$date2['hour'] = 0; // The dateselector element does not have hours.
$date2['minute'] = 0; // The dateselector element does not have minutes.
$date2['timestamp'] = 1372896000;
$this->convert_dateselector_to_unixtime_test('dateselector', 'test_example', $date2);
$date3 = array();
$date3['day'] = 4;
$date3['month'] = 7;
$date3['year'] = 2013;
$date3['hour'] = 23;
$date3['minute'] = 15;
$date3['timestamp'] = 1372979700;
$this->convert_dateselector_to_unixtime_test('datetimeselector', 'gregorian', $date3);
$date4 = array();
$date4['day'] = 7;
$date4['month'] = 9;
$date4['year'] = 2015;
$date4['hour'] = 1;
$date4['minute'] = 17;
$date4['timestamp'] = 1372979700;
$this->convert_dateselector_to_unixtime_test('datetimeselector', 'test_example', $date4);
// The date selector element values are set by using the function usergetdate, here we want to check that
// the unixtime passed is being successfully converted to the correct values for the calendar type.
$this->convert_unixtime_to_dateselector_test('gregorian', $date3);
$this->convert_unixtime_to_dateselector_test('test_example', $date4);
}
/**
* Test that the user profile field datetime minimum and maximum year settings are saved as the
* equivalent Gregorian years.
*/
public function test_calendar_type_datetime_field_submission(): void {
// We want to reset the test data after this run.
$this->resetAfterTest();
// Create an array with the input values and expected values once submitted.
$date = array();
$date['inputminyear'] = '1970';
$date['inputmaxyear'] = '2013';
$date['expectedminyear'] = '1970';
$date['expectedmaxyear'] = '2013';
$this->datetime_field_submission_test('gregorian', $date);
// The test calendar is 2 years, 2 months, 2 days in the future, so when the year 1970 is submitted,
// the year 1967 should be saved in the DB, as 1/1/1970 converts to 30/10/1967 in Gregorian.
$date['expectedminyear'] = '1967';
$date['expectedmaxyear'] = '2010';
$this->datetime_field_submission_test('test_example', $date);
}
/**
* Test all the core functions that use the calendar type system.
*
* @param string $type the calendar type we want to test
*/
private function core_functions_test($type) {
$this->set_calendar_type($type);
// Get the calendar.
$calendar = \core_calendar\type_factory::get_calendar_instance();
// Test the userdate function.
$this->assertEquals($calendar->timestamp_to_date_string($this->user->timecreated, '', 99, true, true),
userdate($this->user->timecreated));
// Test the calendar/lib.php functions.
$this->assertEquals($calendar->get_weekdays(), calendar_get_days());
$this->assertEquals($calendar->get_starting_weekday(), calendar_get_starting_weekday());
$this->assertEquals($calendar->get_num_days_in_month('1986', '9'), calendar_days_in_month('9', '1986'));
$this->assertEquals($calendar->get_next_month('1986', '9'), calendar_add_month('9', '1986'));
$this->assertEquals($calendar->get_prev_month('1986', '9'), calendar_sub_month('9', '1986'));
// Test the lib/moodle.php functions.
$this->assertEquals($calendar->get_num_days_in_month('1986', '9'), days_in_month('9', '1986'));
$this->assertEquals($calendar->get_weekday('1986', '9', '16'), dayofweek('16', '9', '1986'));
}
/**
* Simulates submitting a form with a date selector element and tests that the chosen dates
* are converted into unixtime before being saved in DB.
*
* @param string $element the form element we are testing
* @param string $type the calendar type we want to test
* @param array $date the date variables
*/
private function convert_dateselector_to_unixtime_test($element, $type, $date) {
$this->set_calendar_type($type);
static $counter = 0;
$counter++;
if ($element == 'dateselector') {
$el = $this->mform->addElement('date_selector',
'dateselector' . $counter, null, array('timezone' => 0.0));
} else {
$el = $this->mform->addElement('date_time_selector',
'dateselector' . $counter, null, array('timezone' => 0.0, 'optional' => false));
}
$submitvalues = array('dateselector' . $counter => $date);
$this->assertSame(array('dateselector' . $counter => $date['timestamp']), $el->exportValue($submitvalues, true));
}
/**
* Test converting dates from unixtime to a date for the calendar type specified.
*
* @param string $type the calendar type we want to test
* @param array $date the date variables
*/
private function convert_unixtime_to_dateselector_test($type, $date) {
$this->set_calendar_type($type);
// Get the calendar.
$calendar = \core_calendar\type_factory::get_calendar_instance();
$usergetdate = $calendar->timestamp_to_date_array($date['timestamp'], 0.0);
$comparedate = array(
'minute' => $usergetdate['minutes'],
'hour' => $usergetdate['hours'],
'day' => $usergetdate['mday'],
'month' => $usergetdate['mon'],
'year' => $usergetdate['year'],
'timestamp' => $date['timestamp']
);
$this->assertEquals($comparedate, $date);
}
/**
* Test saving the minimum and max year settings for the user datetime field.
*
* @param string $type the calendar type we want to test
* @param array $date the date variables
*/
private function datetime_field_submission_test($type, $date) {
$this->set_calendar_type($type);
// Get the data we are submitting for the form.
$formdata = array();
$formdata['id'] = 0;
$formdata['shortname'] = 'Shortname';
$formdata['name'] = 'Name';
$formdata['param1'] = $date['inputminyear'];
$formdata['param2'] = $date['inputmaxyear'];
$formdata['datatype'] = 'datetime';
// Mock submitting this.
\core_user\form\profile_field_form::mock_submit($formdata);
// Create the user datetime form.
$form = new \core_user\form\profile_field_form();
// Get the data from the submission.
$submissiondata = $form->get_data();
// On the user profile field page after get_data, the function define_save is called
// in the field base class, which then calls the field's function define_save_preprocess.
$field = new \profile_define_datetime();
$submissiondata = $field->define_save_preprocess($submissiondata);
// Create an array we want to compare with the date passed.
$comparedate = $date;
$comparedate['expectedminyear'] = $submissiondata->param1;
$comparedate['expectedmaxyear'] = $submissiondata->param2;
$this->assertEquals($comparedate, $date);
}
/**
* Set the calendar type for this user.
*
* @param string $type the calendar type we want to set
*/
private function set_calendar_type($type) {
$this->user->calendartype = $type;
\core\session\manager::set_user($this->user);
}
}
/**
* Form object to be used in test case.
*/
class temp_form_calendartype extends \moodleform {
/**
* Form definition.
*/
public function definition() {
// No definition required.
}
/**
* Returns form reference
* @return MoodleQuickForm
*/
public function getform() {
$mform = $this->_form;
// Set submitted flag, to simulate submission.
$mform->_flagSubmitted = true;
return $mform;
}
}
@@ -0,0 +1,317 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace calendartype_test_example;
use \core_calendar\type_base;
/**
* Handles calendar functions for the test calendar.
*
* The test calendar is going to be 2 years, 2 days, 2 hours and 2 minutes
* in the future of the Gregorian calendar.
*
* @package core_calendar
* @copyright 2013 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class structure extends type_base {
/**
* Returns the name of the calendar.
*
* @return string the calendar name
*/
public function get_name() {
return 'test_example';
}
/**
* Returns a list of all the possible days for all months.
*
* This is used to generate the select box for the days
* in the date selector elements. Some months contain more days
* than others so this function should return all possible days as
* we can not predict what month will be chosen (the user
* may have JS turned off and we need to support this situation in
* Moodle).
*
* @return array the days
*/
public function get_days() {
$days = array();
for ($i = 1; $i <= 31; $i++) {
$days[$i] = $i;
}
return $days;
}
/**
* Returns a list of all the names of the months.
*
* @return array the month names
*/
public function get_months() {
$months = array();
for ($i = 1; $i <= 12; $i++) {
$months[$i] = $i;
}
return $months;
}
/**
* Returns the minimum year for the calendar.
*
* @return int The minimum year
*/
public function get_min_year() {
return 1900;
}
/**
* Returns the maximum year for the calendar
*
* @return int The maximum year
*/
public function get_max_year() {
return 2050;
}
/**
* Returns an array of years.
*
* @param int $minyear
* @param int $maxyear
* @return array the years.
*/
public function get_years($minyear = null, $maxyear = null) {
if (is_null($minyear)) {
$minyear = $this->get_min_year();
}
if (is_null($maxyear)) {
$maxyear = $this->get_max_year();
}
$years = array();
for ($i = $minyear; $i <= $maxyear; $i++) {
$years[$i] = $i;
}
return $years;
}
/**
* Returns a multidimensional array with information for day, month, year
* and the order they are displayed when selecting a date.
* The order in the array will be the order displayed when selecting a date.
* Override this function to change the date selector order.
*
* @param int $minyear The year to start with.
* @param int $maxyear The year to finish with.
* @return array Full date information.
*/
public function get_date_order($minyear = null, $maxyear = null) {
$dateinfo = array();
$dateinfo['day'] = $this->get_days();
$dateinfo['month'] = $this->get_months();
$dateinfo['year'] = $this->get_years($minyear, $maxyear);
return $dateinfo;
}
/**
* Returns the number of days in a week.
*
* @return int the number of days
*/
public function get_num_weekdays() {
return 7;
}
/**
* Returns an indexed list of all the names of the weekdays.
*
* The list starts with the index 0. Each index, representing a
* day, must be an array that contains the indexes 'shortname'
* and 'fullname'.
*
* @return array array of days
*/
public function get_weekdays() {
return '';
}
/**
* Returns the index of the starting week day.
*
* @return int
*/
public function get_starting_weekday() {
return '';
}
/**
* Returns the index of the weekday for a specific calendar date.
*
* @param int $year
* @param int $month
* @param int $day
* @return int
*/
public function get_weekday($year, $month, $day) {
return '';
}
/**
* Returns the number of days in a given month.
*
* @param int $year
* @param int $month
* @return int the number of days
*/
public function get_num_days_in_month($year, $month) {
return '';
}
/**
* Get the previous month.
*
* If the current month is January, it will get the last month of the previous year.
*
* @param int $year
* @param int $month
* @return array previous month and year
*/
public function get_prev_month($year, $month) {
return '';
}
/**
* Get the next month.
*
* If the current month is December, it will get the first month of the following year.
*
* @param int $year
* @param int $month
* @return array the following month and year
*/
public function get_next_month($year, $month) {
return '';
}
/**
* Returns a formatted string that represents a date in user time.
*
* @param int $time the timestamp in UTC, as obtained from the database
* @param string $format strftime format
* @param int|float|string $timezone the timezone to use
* {@link https://moodledev.io/docs/apis/subsystems/time#timezone}
* @param bool $fixday if true then the leading zero from %d is removed,
* if false then the leading zero is maintained
* @param bool $fixhour if true then the leading zero from %I is removed,
* if false then the leading zero is maintained
* @return string the formatted date/time
*/
public function timestamp_to_date_string($time, $format, $timezone, $fixday, $fixhour) {
return '';
}
/**
* Given a $time timestamp in GMT (seconds since epoch), returns an array that represents
* the date in user time.
*
* @param int $time timestamp in GMT
* @param float|int|string $timezone the timezone to use to calculate the time
* {@link https://moodledev.io/docs/apis/subsystems/time#timezone}
* @return array an array that represents the date in user time
*/
public function timestamp_to_date_array($time, $timezone = 99) {
$gregoriancalendar = \core_calendar\type_factory::get_calendar_instance('gregorian');
$date = $gregoriancalendar->timestamp_to_date_array($time, $timezone);
$newdate = $this->convert_from_gregorian($date['year'], $date['mon'], $date['mday'],
$date['hours'], $date['minutes']);
$date['year'] = $newdate['year'];
$date['mon'] = $newdate['month'];
$date['mday'] = $newdate['day'];
$date['hours'] = $newdate['hour'];
$date['minutes'] = $newdate['minute'];
return $date;
}
/**
* Provided with a day, month, year, hour and minute
* convert it into the equivalent Gregorian date.
*
* @param int $year
* @param int $month
* @param int $day
* @param int $hour
* @param int $minute
* @return array the converted day, month, year, hour and minute.
*/
public function convert_to_gregorian($year, $month, $day, $hour = 0, $minute = 0) {
$timestamp = make_timestamp($year, $month, $day, $hour, $minute);
$date = date('Y/n/j/H/i', strtotime('-2 year, -2 months, -2 days, -2 hours, -2 minutes', $timestamp));
list($year, $month, $day, $hour, $minute) = explode('/', $date);
return array('year' => (int) $year,
'month' => (int) $month,
'day' => (int) $day,
'hour' => (int) $hour,
'minute' => (int) $minute);
}
/**
* Provided with a day, month, year, hour and minute in a Gregorian date
* convert it into the specific calendar type date.
*
* @param int $year
* @param int $month
* @param int $day
* @param int $hour
* @param int $minute
* @return array the converted day, month, year, hour and minute.
*/
public function convert_from_gregorian($year, $month, $day, $hour = 0, $minute = 0) {
$timestamp = make_timestamp($year, $month, $day, $hour, $minute);
$date = date('Y/n/j/H/i', strtotime('+2 year, +2 months, +2 days, +2 hours, +2 minutes', $timestamp));
list($year, $month, $day, $hour, $minute) = explode('/', $date);
return array('year' => (int) $year,
'month' => (int) $month,
'day' => (int) $day,
'hour' => (int) $hour,
'minute' => (int) $minute);
}
/**
* This return locale for windows os.
*
* @return string locale
*/
public function locale_win_charset() {
return get_string('localewincharset', 'langconfig');
}
}
+52
View File
@@ -0,0 +1,52 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_calendar;
use core_calendar\local\event\proxies\cm_info_proxy;
/**
* cm_info_proxy testcase.
*
* @package core_calendar
* @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cm_info_proxy_test extends \advanced_testcase {
/**
* Test creating cm_info_std_proxy, using getter and setter.
*/
public function test_proxy(): void {
$this->resetAfterTest(true);
$course = $this->getDataGenerator()->create_course();
$module = $this->getDataGenerator()->create_module('forum',
['course' => $course->id, 'idnumber' => '123456']);
$proxy = new cm_info_proxy(
'forum',
$module->id,
$course->id
);
$this->assertEquals('forum', $proxy->get('modname'));
$this->assertEquals($module->id, $proxy->get('instance'));
$this->assertEquals($course->id, $proxy->get('course'));
$this->assertEquals('123456', $proxy->get('idnumber'));
$this->assertEquals($module->cmid, $proxy->get('id'));
$this->assertEquals('123456', $proxy->get_proxied_instance()->idnumber);
}
}
+616
View File
@@ -0,0 +1,616 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_calendar;
use core_calendar\local\event\entities\action_event;
use core_calendar\local\event\entities\event;
use core_calendar\local\event\entities\event_interface;
use core_calendar\local\event\factories\event_factory;
use core_calendar\local\event\factories\event_factory_interface;
use core_calendar\local\event\mappers\event_mapper;
use core_calendar\local\event\mappers\event_mapper_interface;
use core_completion\api;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/calendar/lib.php');
/**
* Event container test..
*
* @package core_calendar
* @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class container_test extends \advanced_testcase {
/**
* Test setup.
*/
public function setUp(): void {
$this->resetAfterTest();
$this->setAdminUser();
}
/**
* Test getting the event factory.
*/
public function test_get_event_factory(): void {
$factory = \core_calendar\local\event\container::get_event_factory();
// Test that the container is returning the right type.
$this->assertInstanceOf(event_factory_interface::class, $factory);
// Test that the container is returning the right implementation.
$this->assertInstanceOf(event_factory::class, $factory);
// Test that getting the factory a second time returns the same instance.
$factory2 = \core_calendar\local\event\container::get_event_factory();
$this->assertTrue($factory === $factory2);
}
/**
* Test that the event factory correctly creates instances of events.
*
* @dataProvider get_event_factory_testcases()
* @param \stdClass $dbrow Row from the "database".
*/
public function test_event_factory_create_instance($dbrow): void {
$legacyevent = $this->create_event($dbrow);
$factory = \core_calendar\local\event\container::get_event_factory();
$course = $this->getDataGenerator()->create_course();
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$moduleinstance = $generator->create_instance(['course' => $course->id]);
// Set some of the fake dbrow properties to match real data in the DB
// this is necessary as the factory hides things that modinfo doesn't
// know about.
$dbrow->id = $legacyevent->id;
$dbrow->courseid = $course->id;
$dbrow->instance = $moduleinstance->id;
$dbrow->modulename = 'assign';
$event = $factory->create_instance($dbrow);
// Test that the factory is returning the right type.
$this->assertInstanceOf(event_interface::class, $event);
// Test that the factory is returning the right implementation.
$this->assertTrue($event instanceof event || $event instanceof action_event);
// Test that the event created has the correct properties.
$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'));
$this->assertEquals($dbrow->location, $event->get_location());
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(null, $event->get_repeats());
$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 that the event factory deals with invisible modules properly as admin.
*
* @dataProvider get_event_factory_testcases()
* @param \stdClass $dbrow Row from the "database".
*/
public function test_event_factory_when_module_visibility_is_toggled_as_admin($dbrow): void {
$legacyevent = $this->create_event($dbrow);
$factory = \core_calendar\local\event\container::get_event_factory();
$course = $this->getDataGenerator()->create_course();
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$moduleinstance = $generator->create_instance(['course' => $course->id]);
$dbrow->id = $legacyevent->id;
$dbrow->courseid = $course->id;
$dbrow->instance = $moduleinstance->id;
$dbrow->modulename = 'assign';
set_coursemodule_visible($moduleinstance->cmid, 0);
$event = $factory->create_instance($dbrow);
// Test that the factory is returning an event as the admin can see hidden course modules.
$this->assertInstanceOf(event_interface::class, $event);
}
/**
* Test that the event factory deals with invisible modules properly as a guest.
*
* @dataProvider get_event_factory_testcases()
* @param \stdClass $dbrow Row from the "database".
*/
public function test_event_factory_when_module_visibility_is_toggled_as_guest($dbrow): void {
$legacyevent = $this->create_event($dbrow);
$factory = \core_calendar\local\event\container::get_event_factory();
$course = $this->getDataGenerator()->create_course();
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$moduleinstance = $generator->create_instance(['course' => $course->id]);
$dbrow->id = $legacyevent->id;
$dbrow->courseid = $course->id;
$dbrow->instance = $moduleinstance->id;
$dbrow->modulename = 'assign';
set_coursemodule_visible($moduleinstance->cmid, 0);
// Set to a user who can not view hidden course modules.
$this->setGuestUser();
$event = $factory->create_instance($dbrow);
// Module is invisible to guest users so this should return null.
$this->assertNull($event);
}
/**
* Test that the event factory deals with invisible courses as an admin.
*
* @dataProvider get_event_factory_testcases()
* @param \stdClass $dbrow Row from the "database".
*/
public function test_event_factory_when_course_visibility_is_toggled_as_admin($dbrow): void {
$legacyevent = $this->create_event($dbrow);
$factory = \core_calendar\local\event\container::get_event_factory();
// Create a hidden course with an assignment.
$course = $this->getDataGenerator()->create_course(['visible' => 0]);
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$moduleinstance = $generator->create_instance(['course' => $course->id]);
$dbrow->id = $legacyevent->id;
$dbrow->courseid = $course->id;
$dbrow->instance = $moduleinstance->id;
$dbrow->modulename = 'assign';
$event = $factory->create_instance($dbrow);
// Module is still visible to admins even if the course is invisible.
$this->assertInstanceOf(event_interface::class, $event);
}
/**
* Test that the event factory deals with invisible courses as a student.
*
* @dataProvider get_event_factory_testcases()
* @param \stdClass $dbrow Row from the "database".
*/
public function test_event_factory_when_course_visibility_is_toggled_as_student($dbrow): void {
$legacyevent = $this->create_event($dbrow);
$factory = \core_calendar\local\event\container::get_event_factory();
// Create a hidden course with an assignment.
$course = $this->getDataGenerator()->create_course(['visible' => 0]);
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$moduleinstance = $generator->create_instance(['course' => $course->id]);
// Enrol a student into this course.
$student = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->enrol_user($student->id, $course->id);
// Set the user to the student.
$this->setUser($student);
$dbrow->id = $legacyevent->id;
$dbrow->courseid = $course->id;
$dbrow->instance = $moduleinstance->id;
$dbrow->modulename = 'assign';
$event = $factory->create_instance($dbrow);
// Module is invisible to students if the course is invisible.
$this->assertNull($event);
}
/**
* Test that the event factory deals with invisible categorys as an admin.
*/
public function test_event_factory_when_category_visibility_is_toggled_as_admin(): void {
// Create a hidden category.
$category = $this->getDataGenerator()->create_category(['visible' => 0]);
$eventdata = [
'categoryid' => $category->id,
'eventtype' => 'category',
];
$legacyevent = $this->create_event($eventdata);
$dbrow = $this->get_dbrow_from_skeleton((object) $eventdata);
$dbrow->id = $legacyevent->id;
$factory = \core_calendar\local\event\container::get_event_factory();
$event = $factory->create_instance($dbrow);
// Module is still visible to admins even if the category is invisible.
$this->assertInstanceOf(event_interface::class, $event);
}
/**
* Test that the event factory deals with invisible categorys as an user.
*/
public function test_event_factory_when_category_visibility_is_toggled_as_user(): void {
// Create a hidden category.
$category = $this->getDataGenerator()->create_category(['visible' => 0]);
$eventdata = [
'categoryid' => $category->id,
'eventtype' => 'category',
];
$legacyevent = $this->create_event($eventdata);
$dbrow = $this->get_dbrow_from_skeleton((object) $eventdata);
$dbrow->id = $legacyevent->id;
// Use a standard user.
$user = $this->getDataGenerator()->create_user();
// Set the user to the student.
$this->setUser($user);
$factory = \core_calendar\local\event\container::get_event_factory();
$event = $factory->create_instance($dbrow);
// Module is invisible to non-privileged users.
$this->assertNull($event);
}
/**
* Test that the event factory deals with invisible categorys as an guest.
*/
public function test_event_factory_when_category_visibility_is_toggled_as_guest(): void {
// Create a hidden category.
$category = $this->getDataGenerator()->create_category(['visible' => 0]);
$eventdata = [
'categoryid' => $category->id,
'eventtype' => 'category',
];
$legacyevent = $this->create_event($eventdata);
$dbrow = $this->get_dbrow_from_skeleton((object) $eventdata);
$dbrow->id = $legacyevent->id;
// Set the user to the student.
$this->setGuestUser();
$factory = \core_calendar\local\event\container::get_event_factory();
$event = $factory->create_instance($dbrow);
// Module is invisible to guests.
$this->assertNull($event);
}
/**
* Test that the event factory deals with completion related events properly.
*/
public function test_event_factory_with_completion_related_event(): void {
global $CFG;
$CFG->enablecompletion = true;
// Create the course we will be using.
$course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
// Add the assignment.
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$assign = $generator->create_instance(array('course' => $course->id), array('completion' => 1));
// Create a completion event.
$event = new \stdClass();
$event->name = 'An event';
$event->description = 'Event description';
$event->location = 'Event location';
$event->format = FORMAT_HTML;
$event->eventtype = \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED;
$event->userid = 1;
$event->modulename = 'assign';
$event->instance = $assign->id;
$event->categoryid = 0;
$event->courseid = $course->id;
$event->groupid = 0;
$event->timestart = time();
$event->timesort = time();
$event->timemodified = time();
$event->timeduration = 0;
$event->subscriptionid = null;
$event->repeatid = 0;
$legacyevent = $this->create_event($event);
// Update the id of the event that was created.
$event->id = $legacyevent->id;
// Create the factory we are going to be testing the behaviour of.
$factory = \core_calendar\local\event\container::get_event_factory();
// Check that we get the correct instance.
$this->assertInstanceOf(event_interface::class, $factory->create_instance($event));
// Now, disable completion.
$CFG->enablecompletion = false;
// The result should now be null since we have disabled completion.
$this->assertNull($factory->create_instance($event));
}
/**
* Checks that completed activities events do not show.
* @covers \core_calendar\local\event::init
*/
public function test_event_factory_with_completed_module_related_event(): void {
global $CFG, $DB;
$this->setAdminUser();
// Create a course.
$course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]);
$user = $this->getDataGenerator()->create_and_enrol($course);
// Create an assign activity with a time set.
$time = time();
$assign = $this->getDataGenerator()->create_module(
'assign', ['course' => $course->id, 'completion' => COMPLETION_TRACKING_MANUAL]);
// Create the event but set it to tomorrow.
$CFG->enablecompletion = true;
api::update_completion_date_event($assign->cmid, 'assign', $assign,
$time + DAYSECS);
$this->setUser($user);
// Check that we get should be completed event.
$this->assertCount(1, \core_calendar\local\event\container::get_event_vault()->get_events());
// Then Complete the activity.
$completion = new \completion_info($course);
$cmassign = get_coursemodule_from_id('assign', $assign->cmid);
// This should trigger another call to the update_completion_date_event.
$completion->update_state($cmassign, COMPLETION_COMPLETE, $user->id);
// Check that we do not see the event anymore.
$this->assertCount(0, \core_calendar\local\event\container::get_event_vault()->get_events());
}
/**
* Test that the event factory only returns an event if the logged in user
* is enrolled in the course.
*/
public function test_event_factory_unenrolled_user(): void {
$user = $this->getDataGenerator()->create_user();
// Create the course we will be using.
$course = $this->getDataGenerator()->create_course();
// Add the assignment.
$generator = $this->getDataGenerator()->get_plugin_generator('mod_lesson');
$lesson = $generator->create_instance(array('course' => $course->id));
// Create a user override event for the lesson.
$event = new \stdClass();
$event->name = 'An event';
$event->description = 'Event description';
$event->location = 'Event location';
$event->format = FORMAT_HTML;
$event->eventtype = 'close';
$event->userid = $user->id;
$event->modulename = 'lesson';
$event->instance = $lesson->id;
$event->categoryid = 0;
$event->courseid = $course->id;
$event->groupid = 0;
$event->timestart = time();
$event->timesort = time();
$event->timemodified = time();
$event->timeduration = 0;
$event->subscriptionid = null;
$event->repeatid = 0;
$legacyevent = $this->create_event($event);
// Update the id of the event that was created.
$event->id = $legacyevent->id;
// Set the logged in user to the one we created.
$this->setUser($user);
// Create the factory we are going to be testing the behaviour of.
$factory = \core_calendar\local\event\container::get_event_factory();
// The result should be null since the user is not enrolled in the
// course the event is for.
$this->assertNull($factory->create_instance($event));
// Now enrol the user in the course.
$this->getDataGenerator()->enrol_user($user->id, $course->id);
// Check that we get the correct instance.
$this->assertInstanceOf(event_interface::class, $factory->create_instance($event));
}
/**
* Test that when course module is deleted all events are also deleted.
*/
public function test_delete_module_delete_events(): void {
global $DB;
$user = $this->getDataGenerator()->create_user();
// Create the course we will be using.
$course = $this->getDataGenerator()->create_course();
$group = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
foreach (\core_component::get_plugin_list('mod') as $modname => $unused) {
try {
$generator = $this->getDataGenerator()->get_plugin_generator('mod_'.$modname);
} catch (\coding_exception $e) {
// Module generator is not implemented.
continue;
}
$module = $generator->create_instance(['course' => $course->id]);
// Create bunch of events of different type (user override, group override, module event).
$this->create_event(['userid' => $user->id, 'modulename' => $modname, 'instance' => $module->id]);
$this->create_event(['groupid' => $group->id, 'modulename' => $modname, 'instance' => $module->id]);
$this->create_event(['modulename' => $modname, 'instance' => $module->id]);
$this->create_event(['modulename' => $modname, 'instance' => $module->id, 'courseid' => $course->id]);
// Delete module and make sure all events are deleted.
course_delete_module($module->cmid);
$this->assertEmpty($DB->get_record('event', ['modulename' => $modname, 'instance' => $module->id]));
}
}
/**
* Test getting the event mapper.
*/
public function test_get_event_mapper(): void {
$mapper = \core_calendar\local\event\container::get_event_mapper();
$this->assertInstanceOf(event_mapper_interface::class, $mapper);
$this->assertInstanceOf(event_mapper::class, $mapper);
$mapper2 = \core_calendar\local\event\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,
'categoryid' => 0,
'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,
'location' => 'Test location',
]
],
'Data set 2' => [
'dbrow' => (object)[
'name' => 'Test event',
'description' => 'Hello',
'format' => 1,
'categoryid' => 0,
'courseid' => 1,
'groupid' => 1,
'userid' => 1,
'repeatid' => 0,
'modulename' => 'assign',
'instance' => 2,
'eventtype' => 'due',
'timestart' => 1486396800,
'timeduration' => 0,
'timesort' => 1486396800,
'visible' => 1,
'timemodified' => 1485793098,
'subscriptionid' => null,
'location' => 'Test location',
]
]
];
}
/**
* Helper function to create calendar events using the old code.
*
* @param array $properties A list of calendar event properties to set
* @return calendar_event|bool
*/
protected function create_event($properties = []) {
$record = new \stdClass();
$record->name = 'event name';
$record->eventtype = 'site';
$record->timestart = time();
$record->timeduration = 0;
$record->timesort = 0;
$record->type = 1;
$record->courseid = 0;
$record->categoryid = 0;
foreach ($properties as $name => $value) {
$record->$name = $value;
}
$event = new \calendar_event($record);
return $event->create($record, false);
}
/**
* Pad out a basic DB row with basic information.
*
* @param \stdClass $skeleton the current skeleton
* @return \stdClass
*/
protected function get_dbrow_from_skeleton($skeleton) {
$dbrow = (object) [
'name' => 'Name',
'description' => 'Description',
'format' => 1,
'categoryid' => 0,
'courseid' => 0,
'groupid' => 0,
'userid' => 0,
'repeatid' => 0,
'modulename' => '',
'instance' => 0,
'eventtype' => 'user',
'timestart' => 1486396800,
'timeduration' => 0,
'timesort' => 1486396800,
'visible' => 1,
'timemodified' => 1485793098,
'subscriptionid' => null,
'location' => 'Test location',
];
foreach ((array) $skeleton as $key => $value) {
$dbrow->$key = $value;
}
return $dbrow;
}
}
+57
View File
@@ -0,0 +1,57 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_calendar;
use core_calendar\local\event\proxies\coursecat_proxy;
/**
* coursecat_proxy testcase.
*
* @package core_calendar
* @copyright 2017 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class coursecat_proxy_test extends \advanced_testcase {
public function test_valid_coursecat(): void {
global $DB;
$this->resetAfterTest();
$name = '2027-2028 Academic Year';
$generator = $this->getDataGenerator();
$category = $generator->create_category([
'name' => $name,
]);
\cache_helper::purge_by_event('changesincoursecat');
// Fetch the proxy.
$startreads = $DB->perf_get_reads();
$proxy = new coursecat_proxy($category->id);
$this->assertInstanceOf(coursecat_proxy::class, $proxy);
$this->assertEquals(0, $DB->perf_get_reads() - $startreads);
// Fetch the ID - this is known and doesn't require a cache read.
$this->assertEquals($category->id, $proxy->get('id'));
$this->assertEquals(0, $DB->perf_get_reads() - $startreads);
// Fetch the name - not known, and requires a read.
$this->assertEquals($name, $proxy->get('name'));
$this->assertEquals(1, $DB->perf_get_reads() - $startreads);
$this->assertInstanceOf('core_course_category', $proxy->get_proxied_instance());
}
}
+820
View File
@@ -0,0 +1,820 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains the class that handles testing of the calendar events.
*
* @package core_calendar
* @copyright 2014 Ankit Agarwal <ankit.agrr@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_calendar\event;
use core_calendar_externallib_testcase;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/calendar/tests/externallib_test.php');
/**
* This file contains the class that handles testing of the calendar events.
*
* @package core_calendar
* @copyright 2014 Ankit Agarwal <ankit.agrr@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class events_test extends \advanced_testcase {
/**
* The test user.
*/
private $user;
/**
* The test course.
*/
private $course;
/**
* Test set up.
*/
protected function setUp(): void {
global $USER;
// The user we are going to test this on.
$this->setAdminUser();
$this->user = $USER;
$this->course = self::getDataGenerator()->create_course();
}
/**
* Tests for calendar_event_created event.
*/
public function test_calendar_event_created(): void {
$this->resetAfterTest();
// Catch the events.
$sink = $this->redirectEvents();
// Create a calendar event.
$record = new \stdClass();
$record->courseid = 0;
$time = time();
$calevent = \core_calendar\externallib_test::create_calendar_event('event', $this->user->id, 'user', 0, $time,
$record); // User event.
// Capture the event.
$events = $sink->get_events();
$sink->clear();
// Validate the event.
$event = $events[0];
$this->assertInstanceOf('\core\event\calendar_event_created', $event);
$this->assertEquals('event', $event->objecttable);
$this->assertEquals(0, $event->courseid);
$this->assertEquals($calevent->context, $event->get_context());
$other = array('repeatid' => 0, 'timestart' => $time, 'name' => 'event');
$this->assertEquals($other, $event->other);
$this->assertEventContextNotUsed($event);
// Now we create a repeated course event.
$record = new \stdClass();
$record->courseid = $this->course->id;
$calevent = \core_calendar\externallib_test::create_calendar_event('course', $this->user->id, 'course', 10, $time,
$record);
$events = $sink->get_events();
$sink->close();
$this->assertEquals(10, count($events));
foreach ($events as $event) {
$this->assertInstanceOf('\core\event\calendar_event_created', $event);
$this->assertEquals('event', $event->objecttable);
$this->assertEquals($this->course->id, $event->courseid);
$this->assertEquals($calevent->context, $event->get_context());
}
}
/**
* Tests for event validations related to calendar_event_created event.
*/
public function test_calendar_event_created_validations(): void {
$this->resetAfterTest();
$context = \context_user::instance($this->user->id);
// Test not setting other['repeatid'].
try {
\core\event\calendar_event_created::create(array(
'context' => $context,
'objectid' => 2,
'other' => array(
'timestart' => time(),
'name' => 'event'
)
));
$this->fail("Event validation should not allow \\core\\event\\calendar_event_created to be triggered without
other['repeatid']");
} catch (\coding_exception $e) {
$this->assertStringContainsString('The \'repeatid\' value must be set in other.', $e->getMessage());
}
// Test not setting other['name'].
try {
\core\event\calendar_event_created::create(array(
'context' => $context,
'objectid' => 2,
'other' => array(
'repeatid' => 0,
'timestart' => time(),
)
));
$this->fail("Event validation should not allow \\core\\event\\calendar_event_created to be triggered without
other['name']");
} catch (\coding_exception $e) {
$this->assertStringContainsString('The \'name\' value must be set in other.', $e->getMessage());
}
// Test not setting other['timestart'].
try {
\core\event\calendar_event_created::create(array(
'context' => $context,
'objectid' => 2,
'other' => array(
'name' => 'event',
'repeatid' => 0,
)
));
$this->fail("Event validation should not allow \\core\\event\\calendar_event_deleted to be triggered without
other['timestart']");
} catch (\coding_exception $e) {
$this->assertStringContainsString('The \'timestart\' value must be set in other.', $e->getMessage());
}
}
/**
* Tests for calendar_event_updated event.
*/
public function test_calendar_event_updated(): void {
$this->resetAfterTest();
// Create a calendar event.
$record = new \stdClass();
$record->courseid = 0;
$time = time();
$calevent = \core_calendar\externallib_test::create_calendar_event('event', $this->user->id, 'user', 0, $time,
$record); // User event.
// Catch the events.
$sink = $this->redirectEvents();
$prop = new \stdClass();
$prop->name = 'new event';
$calevent->update($prop); // Update calender event.
// Capture the event.
$events = $sink->get_events();
// Validate the event.
$event = $events[0];
$this->assertInstanceOf('\core\event\calendar_event_updated', $event);
$this->assertEquals('event', $event->objecttable);
$this->assertEquals(0, $event->courseid);
$this->assertEquals($calevent->context, $event->get_context());
$other = array('repeatid' => 0, 'timestart' => $time, 'name' => 'new event');
$this->assertEquals($other, $event->other);
$this->assertEventContextNotUsed($event);
// Now we create a repeated course event and update it.
$record = new \stdClass();
$record->courseid = $this->course->id;
$calevent = \core_calendar\externallib_test::create_calendar_event('course', $this->user->id, 'course', 10, time(),
$record);
$sink->clear();
$prop = new \stdClass();
$prop->name = 'new event';
$prop->repeateditall = true;
$calevent->update($prop); // Update calender event.
$events = $sink->get_events();
$sink->close();
$this->assertEquals(10, count($events));
foreach ($events as $event) {
$this->assertInstanceOf('\core\event\calendar_event_updated', $event);
$this->assertEquals('event', $event->objecttable);
$this->assertEquals($this->course->id, $event->courseid);
$this->assertEquals($calevent->context, $event->get_context());
}
}
/**
* Tests for calendar_event_updated event.
*/
public function test_calendar_event_updated_toggle_visibility(): void {
global $DB;
$siteid = 0;
$this->resetAfterTest();
// Create a calendar event.
$time = time();
$calevent = \core_calendar\externallib_test::create_calendar_event('Some wickedly awesome event yo!',
$this->user->id, 'user', 0, $time);
// Updated the visibility of the calendar event.
$sink = $this->redirectEvents();
$calevent->toggle_visibility();
$dbrecord = $DB->get_record('event', array('id' => $calevent->id), '*', MUST_EXIST);
$events = $sink->get_events();
// Validate the calendar_event_updated event.
$event = $events[0];
$this->assertInstanceOf('\core\event\calendar_event_updated', $event);
$this->assertEquals('event', $event->objecttable);
$this->assertEquals($siteid, $event->courseid);
$this->assertEquals($calevent->context, $event->get_context());
$other = array('repeatid' => 0, 'timestart' => $time, 'name' => 'Some wickedly awesome event yo!');
$this->assertEquals($other, $event->other);
$this->assertEventContextNotUsed($event);
$this->assertEquals($dbrecord, $event->get_record_snapshot('event', $event->objectid));
}
/**
* Tests for event validations related to calendar_event_created event.
*/
public function test_calendar_event_updated_validations(): void {
$this->resetAfterTest();
$context = \context_user::instance($this->user->id);
// Test not setting other['repeatid'].
try {
\core\event\calendar_event_updated::create(array(
'context' => $context,
'objectid' => 2,
'other' => array(
'timestart' => time(),
'name' => 'event'
)
));
$this->fail("Event validation should not allow \\core\\event\\calendar_event_updated to be triggered without
other['repeatid']");
} catch (\coding_exception $e) {
$this->assertStringContainsString('The \'repeatid\' value must be set in other.', $e->getMessage());
}
// Test not setting other['name'].
try {
\core\event\calendar_event_updated::create(array(
'context' => $context,
'objectid' => 2,
'other' => array(
'repeatid' => 0,
'timestart' => time(),
)
));
$this->fail("Event validation should not allow \\core\\event\\calendar_event_updated to be triggered without
other['name']");
} catch (\coding_exception $e) {
$this->assertStringContainsString('The \'name\' value must be set in other.', $e->getMessage());
}
// Test not setting other['timestart'].
try {
\core\event\calendar_event_updated::create(array(
'context' => $context,
'objectid' => 2,
'other' => array(
'name' => 'event',
'repeatid' => 0,
)
));
$this->fail("Event validation should not allow \\core\\event\\calendar_event_deleted to be triggered without
other['timestart']");
} catch (\coding_exception $e) {
$this->assertStringContainsString('The \'timestart\' value must be set in other.', $e->getMessage());
}
}
/**
* Tests for calendar_event_deleted event.
*/
public function test_calendar_event_deleted(): void {
global $DB;
$this->resetAfterTest();
// Create a calendar event.
$record = new \stdClass();
$record->courseid = 0;
$record->repeatid = 0;
$time = time();
$calevent = \core_calendar\externallib_test::create_calendar_event('event', $this->user->id, 'user', 0, $time,
$record); // User event.
$dbrecord = $DB->get_record('event', array('id' => $calevent->id), '*', MUST_EXIST);
// Catch the events.
$sink = $this->redirectEvents();
$calevent->delete(false);
$events = $sink->get_events();
// Validate the event.
$event = $events[0];
$this->assertInstanceOf('\core\event\calendar_event_deleted', $event);
$this->assertEquals('event', $event->objecttable);
$this->assertEquals(0, $event->courseid);
$this->assertEquals($calevent->context, $event->get_context());
$other = array('repeatid' => 0, 'timestart' => $time, 'name' => 'event');
$this->assertEquals($other, $event->other);
$this->assertEventContextNotUsed($event);
$this->assertEquals($dbrecord, $event->get_record_snapshot('event', $event->objectid));
// Now we create a repeated course event and delete it.
$record = new \stdClass();
$record->courseid = $this->course->id;
$calevent = \core_calendar\externallib_test::create_calendar_event('course', $this->user->id, 'course', 10, time(),
$record);
$sink->clear();
$prop = new \stdClass();
$prop->name = 'new event';
$prop->repeateditall = true;
$calevent->delete(true);
$events = $sink->get_events();
$sink->close();
$this->assertEquals(10, count($events));
foreach ($events as $event) {
$this->assertInstanceOf('\core\event\calendar_event_deleted', $event);
$this->assertEquals('event', $event->objecttable);
$this->assertEquals($this->course->id, $event->courseid);
$this->assertEquals($calevent->context, $event->get_context());
}
}
/**
* Tests for event validations related to calendar_event_deleted event.
*/
public function test_calendar_event_deleted_validations(): void {
$this->resetAfterTest();
$context = \context_user::instance($this->user->id);
// Test not setting other['repeatid'].
try {
\core\event\calendar_event_deleted::create(array(
'context' => $context,
'objectid' => 2,
'other' => array(
'timestart' => time(),
'name' => 'event'
)
));
$this->fail("Event validation should not allow \\core\\event\\calendar_event_deleted to be triggered without
other['repeatid']");
} catch (\coding_exception $e) {
$this->assertStringContainsString('The \'repeatid\' value must be set in other.', $e->getMessage());
}
// Test not setting other['name'].
try {
\core\event\calendar_event_deleted::create(array(
'context' => $context,
'objectid' => 2,
'other' => array(
'repeatid' => 0,
'timestart' => time(),
)
));
$this->fail("Event validation should not allow \\core\\event\\calendar_event_deleted to be triggered without
other['name']");
} catch (\coding_exception $e) {
$this->assertStringContainsString('The \'name\' value must be set in other.', $e->getMessage());
}
// Test not setting other['timestart'].
try {
\core\event\calendar_event_deleted::create(array(
'context' => $context,
'objectid' => 2,
'other' => array(
'name' => 'event',
'repeatid' => 0,
)
));
$this->fail("Event validation should not allow \\core\\event\\calendar_event_deleted to be triggered without
other['timestart']");
} catch (\coding_exception $e) {
$this->assertStringContainsString('The \'timestart\' value must be set in other.', $e->getMessage());
}
}
/**
* Tests for calendar_subscription_added event for a site subscription.
*/
public function test_calendar_subscription_created_site(): void {
global $CFG;
require_once($CFG->dirroot . '/calendar/lib.php');
$this->resetAfterTest(true);
// Create a mock subscription.
$subscription = new \stdClass();
$subscription->eventtype = 'site';
$subscription->name = 'test';
$subscription->courseid = $this->course->id;
// Trigger and capture the event.
$sink = $this->redirectEvents();
$id = calendar_add_subscription($subscription);
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\core\event\calendar_subscription_created', $event);
$this->assertEquals($id, $event->objectid);
$this->assertEquals($subscription->courseid, $event->other['courseid']);
$this->assertEquals($subscription->eventtype, $event->other['eventtype']);
$this->assertArrayNotHasKey('categoryid', $event->other);
$this->assertArrayNotHasKey('groupid', $event->other);
$this->assertDebuggingNotCalled();
$sink->close();
}
/**
* Tests for calendar_subscription_added event for a category subscription.
*/
public function test_calendar_subscription_created_category(): void {
global $CFG;
require_once($CFG->dirroot . '/calendar/lib.php');
$this->resetAfterTest(true);
$categoryid = $this->course->category;
// Create a mock subscription.
$subscription = new \stdClass();
$subscription->eventtype = 'category';
$subscription->name = 'test';
$subscription->categoryid = $categoryid;
// Trigger and capture the event.
$sink = $this->redirectEvents();
$id = calendar_add_subscription($subscription);
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\core\event\calendar_subscription_created', $event);
$this->assertEquals($id, $event->objectid);
$this->assertEquals($categoryid, $event->other['categoryid']);
$this->assertEquals($subscription->eventtype, $event->other['eventtype']);
$this->assertArrayNotHasKey('courseid', $event->other);
$this->assertArrayNotHasKey('groupid', $event->other);
$this->assertDebuggingNotCalled();
$sink->close();
}
/**
* Tests for calendar_subscription_added event for a course subscription.
*/
public function test_calendar_subscription_created_course(): void {
global $CFG;
require_once($CFG->dirroot . '/calendar/lib.php');
$this->resetAfterTest(true);
// Create a mock subscription.
$subscription = new \stdClass();
$subscription->eventtype = 'course';
$subscription->name = 'test';
$subscription->courseid = $this->course->id;
// Trigger and capture the event.
$sink = $this->redirectEvents();
$id = calendar_add_subscription($subscription);
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\core\event\calendar_subscription_created', $event);
$this->assertEquals($id, $event->objectid);
$this->assertEquals($subscription->courseid, $event->other['courseid']);
$this->assertEquals($subscription->eventtype, $event->other['eventtype']);
$this->assertArrayNotHasKey('categoryid', $event->other);
$this->assertArrayNotHasKey('groupid', $event->other);
$this->assertDebuggingNotCalled();
$sink->close();
}
/**
* Tests for calendar_subscription_added event for a group subscription.
*/
public function test_calendar_subscription_created_group(): void {
global $CFG;
require_once($CFG->dirroot . '/calendar/lib.php');
$this->resetAfterTest(true);
$courseid = $this->course->id;
$groupid = 42;
// Create a mock subscription.
$subscription = new \stdClass();
$subscription->eventtype = 'group';
$subscription->name = 'test';
$subscription->courseid = $courseid;
$subscription->groupid = $groupid;
// Trigger and capture the event.
$sink = $this->redirectEvents();
$id = calendar_add_subscription($subscription);
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\core\event\calendar_subscription_created', $event);
$this->assertEquals($id, $event->objectid);
$this->assertEquals($courseid, $event->other['courseid']);
$this->assertEquals($groupid, $event->other['groupid']);
$this->assertEquals($subscription->eventtype, $event->other['eventtype']);
$this->assertArrayNotHasKey('categoryid', $event->other);
$this->assertDebuggingNotCalled();
$sink->close();
}
/**
* Tests for calendar_subscription_updated event for a site subscription.
*/
public function test_calendar_subscription_updated_site(): void {
global $CFG;
require_once($CFG->dirroot . '/calendar/lib.php');
$this->resetAfterTest(true);
// Create a mock subscription.
$subscription = new \stdClass();
$subscription->eventtype = 'site';
$subscription->name = 'test';
$subscription->courseid = $this->course->id;
$subscription->id = calendar_add_subscription($subscription);
// Now edit it.
$subscription->name = 'awesome';
// Trigger and capture the event.
$sink = $this->redirectEvents();
calendar_update_subscription($subscription);
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\core\event\calendar_subscription_updated', $event);
$this->assertEquals($subscription->id, $event->objectid);
$this->assertEquals($subscription->courseid, $event->other['courseid']);
$this->assertEquals($subscription->eventtype, $event->other['eventtype']);
$this->assertArrayNotHasKey('categoryid', $event->other);
$this->assertArrayNotHasKey('groupid', $event->other);
$this->assertDebuggingNotCalled();
$sink->close();
}
/**
* Tests for calendar_subscription_updated event for a category subscription.
*/
public function test_calendar_subscription_updated_category(): void {
global $CFG;
require_once($CFG->dirroot . '/calendar/lib.php');
$this->resetAfterTest(true);
$categoryid = $this->course->category;
// Create a mock subscription.
$subscription = new \stdClass();
$subscription->eventtype = 'category';
$subscription->name = 'test';
$subscription->categoryid = $categoryid;
$subscription->id = calendar_add_subscription($subscription);
// Now edit it.
$subscription->name = 'awesome';
// Trigger and capture the event.
$sink = $this->redirectEvents();
calendar_update_subscription($subscription);
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\core\event\calendar_subscription_updated', $event);
$this->assertEquals($subscription->id, $event->objectid);
$this->assertEquals($categoryid, $event->other['categoryid']);
$this->assertEquals($subscription->eventtype, $event->other['eventtype']);
$this->assertArrayNotHasKey('courseid', $event->other);
$this->assertArrayNotHasKey('groupid', $event->other);
$this->assertDebuggingNotCalled();
$sink->close();
}
/**
* Tests for calendar_subscription_updated event for a group subscription.
*/
public function test_calendar_subscription_updated_course(): void {
global $CFG;
require_once($CFG->dirroot . '/calendar/lib.php');
$this->resetAfterTest(true);
// Create a mock subscription.
$subscription = new \stdClass();
$subscription->eventtype = 'course';
$subscription->name = 'test';
$subscription->courseid = $this->course->id;
$subscription->id = calendar_add_subscription($subscription);
// Now edit it.
$subscription->name = 'awesome';
// Trigger and capture the event.
$sink = $this->redirectEvents();
calendar_update_subscription($subscription);
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\core\event\calendar_subscription_updated', $event);
$this->assertEquals($subscription->id, $event->objectid);
$this->assertEquals($this->course->id, $event->other['courseid']);
$this->assertEquals($subscription->eventtype, $event->other['eventtype']);
$this->assertArrayNotHasKey('categoryid', $event->other);
$this->assertArrayNotHasKey('groupid', $event->other);
$this->assertDebuggingNotCalled();
$sink->close();
}
/**
* Tests for calendar_subscription_updated event for a course subscription.
*/
public function test_calendar_subscription_updated_group(): void {
global $CFG;
require_once($CFG->dirroot . '/calendar/lib.php');
$this->resetAfterTest(true);
$courseid = $this->course->id;
$groupid = 42;
// Create a mock subscription.
$subscription = new \stdClass();
$subscription->eventtype = 'group';
$subscription->name = 'test';
$subscription->courseid = $courseid;
$subscription->groupid = $groupid;
$subscription->id = calendar_add_subscription($subscription);
// Now edit it.
$subscription->name = 'awesome';
// Trigger and capture the event.
$sink = $this->redirectEvents();
calendar_update_subscription($subscription);
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\core\event\calendar_subscription_updated', $event);
$this->assertEquals($subscription->id, $event->objectid);
$this->assertEquals($this->course->id, $event->other['courseid']);
$this->assertEquals($groupid, $event->other['groupid']);
$this->assertEquals($subscription->eventtype, $event->other['eventtype']);
$this->assertArrayNotHasKey('categoryid', $event->other);
$this->assertDebuggingNotCalled();
$sink->close();
}
/**
* Tests for calendar_subscription_deleted event for a site subscription.
*/
public function test_calendar_subscription_deleted_site(): void {
global $CFG;
require_once($CFG->dirroot . '/calendar/lib.php');
$this->resetAfterTest(true);
// Create a mock subscription.
$subscription = new \stdClass();
$subscription->eventtype = 'site';
$subscription->name = 'test';
$subscription->courseid = $this->course->id;
$subscription->id = calendar_add_subscription($subscription);
// Trigger and capture the event.
$sink = $this->redirectEvents();
calendar_delete_subscription($subscription);
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\core\event\calendar_subscription_deleted', $event);
$this->assertEquals($subscription->id, $event->objectid);
$this->assertEquals($subscription->courseid, $event->other['courseid']);
$this->assertDebuggingNotCalled();
$sink->close();
}
/**
* Tests for calendar_subscription_deleted event for a category subscription.
*/
public function test_calendar_subscription_deleted_category(): void {
global $CFG;
require_once($CFG->dirroot . '/calendar/lib.php');
$this->resetAfterTest(true);
$categoryid = $this->course->category;
// Create a mock subscription.
$subscription = new \stdClass();
$subscription->eventtype = 'category';
$subscription->name = 'test';
$subscription->categoryid = $categoryid;
$subscription->id = calendar_add_subscription($subscription);
// Trigger and capture the event.
$sink = $this->redirectEvents();
calendar_delete_subscription($subscription);
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\core\event\calendar_subscription_deleted', $event);
$this->assertEquals($subscription->id, $event->objectid);
$this->assertEquals($categoryid, $event->other['categoryid']);
$this->assertEquals($subscription->eventtype, $event->other['eventtype']);
$this->assertArrayNotHasKey('courseid', $event->other);
$this->assertArrayNotHasKey('groupid', $event->other);
$this->assertDebuggingNotCalled();
$sink->close();
}
/**
* Tests for calendar_subscription_deleted event for a course.
*/
public function test_calendar_subscription_deleted_course(): void {
global $CFG;
require_once($CFG->dirroot . '/calendar/lib.php');
$this->resetAfterTest(true);
// Create a mock subscription.
$subscription = new \stdClass();
$subscription->eventtype = 'course';
$subscription->name = 'test';
$subscription->courseid = $this->course->id;
$subscription->id = calendar_add_subscription($subscription);
// Trigger and capture the event.
$sink = $this->redirectEvents();
calendar_delete_subscription($subscription);
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\core\event\calendar_subscription_deleted', $event);
$this->assertEquals($subscription->id, $event->objectid);
$this->assertEquals($this->course->id, $event->other['courseid']);
$this->assertEquals($subscription->eventtype, $event->other['eventtype']);
$this->assertArrayNotHasKey('categoryid', $event->other);
$this->assertArrayNotHasKey('groupid', $event->other);
$this->assertDebuggingNotCalled();
$sink->close();
}
/**
* Tests for calendar_subscription_deleted event for a group.
*/
public function test_calendar_subscription_deleted_group(): void {
global $CFG;
require_once($CFG->dirroot . '/calendar/lib.php');
$this->resetAfterTest(true);
$courseid = $this->course->id;
$groupid = 42;
// Create a mock subscription.
$subscription = new \stdClass();
$subscription->eventtype = 'group';
$subscription->name = 'test';
$subscription->groupid = $groupid;
$subscription->courseid = $courseid;
$subscription->id = calendar_add_subscription($subscription);
// Trigger and capture the event.
$sink = $this->redirectEvents();
calendar_delete_subscription($subscription);
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\core\event\calendar_subscription_deleted', $event);
$this->assertEquals($subscription->id, $event->objectid);
$this->assertEquals($this->course->id, $event->other['courseid']);
$this->assertEquals($groupid, $event->other['groupid']);
$this->assertEquals($subscription->eventtype, $event->other['eventtype']);
$this->assertArrayNotHasKey('categoryid', $event->other);
$this->assertDebuggingNotCalled();
$sink->close();
}
}
+64
View File
@@ -0,0 +1,64 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_calendar;
use core_calendar\local\event\value_objects\event_description;
/**
* Action testcase.
*
* @package core_calendar
* @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class event_description_test extends \advanced_testcase {
/**
* Test event description class getters.
*
* @dataProvider getters_testcases()
* @param array $constructorparams Associative array of constructor parameters.
*/
public function test_getters($constructorparams): void {
$eventdescription = new event_description(
$constructorparams['value'],
$constructorparams['format']
);
foreach ($constructorparams as $name => $value) {
$this->assertEquals($eventdescription->{'get_' . $name}(), $value);
}
}
/**
* Test cases for getters test.
*/
public function getters_testcases() {
return [
'Dataset 1' => [
'constructorparams' => [
'value' => 'Hello',
'format' => 1
]
],
'Dataset 2' => [
'constructorparams' => [
'value' => 'Goodbye',
'format' => 2
]
]
];
}
}
+480
View File
@@ -0,0 +1,480 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_calendar;
use core_calendar\local\event\factories\event_factory;
use core_calendar\local\event\entities\event_interface;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/calendar/lib.php');
/**
* Event factory test.
*
* @package core_calendar
* @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class event_factory_test extends \advanced_testcase {
/**
* Test event class getters.
*
* @dataProvider create_instance_testcases()
* @param \stdClass $dbrow Row from the event table.
* @param callable $actioncallbackapplier Action callback applier.
* @param callable $visibilitycallbackapplier Visibility callback applier.
* @param callable $bailoutcheck Early bail out check function.
* @param string $expectedclass Class the factory is expected to produce.
* @param mixed $expectedattributevalue Expected value of the modified attribute.
*/
public function test_create_instance(
$dbrow,
callable $actioncallbackapplier,
callable $visibilitycallbackapplier,
callable $bailoutcheck,
$expectedclass,
$expectedattributevalue
): void {
$this->resetAfterTest(true);
$this->setAdminUser();
$event = $this->create_event();
$coursecache = [];
$modulecache = [];
$factory = new event_factory(
$actioncallbackapplier,
$visibilitycallbackapplier,
$bailoutcheck,
$coursecache,
$modulecache
);
$dbrow->id = $event->id;
$instance = $factory->create_instance($dbrow);
if ($expectedclass) {
$this->assertInstanceOf($expectedclass, $instance);
}
if (is_null($expectedclass)) {
$this->assertNull($instance);
}
if ($expectedattributevalue) {
$this->assertEquals(
$instance->get_description()->get_value(),
$expectedattributevalue
);
}
}
/**
* Test invalid callback exception.
*/
public function test_invalid_action_callback(): void {
$this->resetAfterTest(true);
$this->setAdminUser();
$event = $this->create_event();
$coursecache = [];
$modulecache = [];
$factory = new event_factory(
function () {
return 'hello';
},
function () {
return true;
},
function () {
return false;
},
$coursecache,
$modulecache
);
$this->expectException('\core_calendar\local\event\exceptions\invalid_callback_exception');
$factory->create_instance(
(object)[
'id' => $event->id,
'name' => 'test',
'description' => 'Test description',
'format' => 2,
'categoryid' => 0,
'courseid' => 1,
'groupid' => 1,
'userid' => 1,
'repeatid' => 0,
'modulename' => 'assign',
'instance' => 1,
'eventtype' => 'due',
'type' => CALENDAR_EVENT_TYPE_ACTION,
'timestart' => 123456789,
'timeduration' => 12,
'timemodified' => 123456789,
'timesort' => 123456789,
'visible' => 1,
'subscriptionid' => 1,
'location' => 'Test location',
]
);
}
/**
* Test invalid callback exception.
*/
public function test_invalid_visibility_callback(): void {
$this->resetAfterTest(true);
$this->setAdminUser();
$event = $this->create_event();
$coursecache = [];
$modulecache = [];
$factory = new event_factory(
function ($event) {
return $event;
},
function () {
return 'asdf';
},
function () {
return false;
},
$coursecache,
$modulecache
);
$this->expectException('\core_calendar\local\event\exceptions\invalid_callback_exception');
$factory->create_instance(
(object)[
'id' => $event->id,
'name' => 'test',
'description' => 'Test description',
'format' => 2,
'categoryid' => 0,
'courseid' => 1,
'groupid' => 1,
'userid' => 1,
'repeatid' => 0,
'modulename' => 'assign',
'instance' => 1,
'eventtype' => 'due',
'type' => CALENDAR_EVENT_TYPE_ACTION,
'timestart' => 123456789,
'timeduration' => 12,
'timemodified' => 123456789,
'timesort' => 123456789,
'visible' => 1,
'subscriptionid' => 1,
'location' => 'Test location',
]
);
}
/**
* Test invalid callback exception.
*/
public function test_invalid_bail_callback(): void {
$this->resetAfterTest(true);
$this->setAdminUser();
$event = $this->create_event();
$coursecache = [];
$modulecache = [];
$factory = new event_factory(
function ($event) {
return $event;
},
function () {
return true;
},
function () {
return 'asdf';
},
$coursecache,
$modulecache
);
$this->expectException('\core_calendar\local\event\exceptions\invalid_callback_exception');
$factory->create_instance(
(object)[
'id' => $event->id,
'name' => 'test',
'description' => 'Test description',
'format' => 2,
'categoryid' => 0,
'courseid' => 1,
'groupid' => 1,
'userid' => 1,
'repeatid' => 0,
'modulename' => 'assign',
'instance' => 1,
'eventtype' => 'due',
'type' => CALENDAR_EVENT_TYPE_ACTION,
'timestart' => 123456789,
'timeduration' => 12,
'timemodified' => 123456789,
'timesort' => 123456789,
'visible' => 1,
'subscriptionid' => 1,
'location' => 'Test location',
]
);
}
/**
* Test the factory's course cache.
*/
public function test_course_cache(): void {
$this->resetAfterTest(true);
$this->setAdminUser();
$course = self::getDataGenerator()->create_course();
$event = $this->create_event(['courseid' => $course->id]);
$coursecache = [];
$modulecache = [];
$factory = new event_factory(
function ($event) {
return $event;
},
function () {
return true;
},
function () {
return false;
},
$coursecache,
$modulecache
);
$instance = $factory->create_instance(
(object)[
'id' => $event->id,
'name' => 'test',
'description' => 'Test description',
'format' => 2,
'categoryid' => 0,
'courseid' => $course->id,
'groupid' => 1,
'userid' => 1,
'repeatid' => 0,
'modulename' => 'assign',
'instance' => 1,
'eventtype' => 'due',
'type' => CALENDAR_EVENT_TYPE_ACTION,
'timestart' => 123456789,
'timeduration' => 12,
'timemodified' => 123456789,
'timesort' => 123456789,
'visible' => 1,
'subscriptionid' => 1,
'location' => 'Test location',
]
);
$instance->get_course()->get('fullname');
$this->assertArrayHasKey($course->id, $coursecache);
}
/**
* Test the factory's module cache.
*/
public function test_module_cache(): void {
$this->resetAfterTest(true);
$this->setAdminUser();
$course = self::getDataGenerator()->create_course();
$event = $this->create_event(['courseid' => $course->id]);
$plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$assigninstance = $plugingenerator->create_instance(['course' => $course->id]);
$coursecache = [];
$modulecache = [];
$factory = new event_factory(
function ($event) {
return $event;
},
function () {
return true;
},
function () {
return false;
},
$coursecache,
$modulecache
);
$instance = $factory->create_instance(
(object)[
'id' => $event->id,
'name' => 'test',
'description' => 'Test description',
'format' => 2,
'categoryid' => 0,
'courseid' => 0,
'groupid' => 1,
'userid' => 1,
'repeatid' => 0,
'modulename' => 'assign',
'instance' => $assigninstance->id,
'eventtype' => 'due',
'type' => CALENDAR_EVENT_TYPE_ACTION,
'timestart' => 123456789,
'timeduration' => 12,
'timemodified' => 123456789,
'timesort' => 123456789,
'visible' => 1,
'subscriptionid' => 1,
'location' => 'Test location',
]
);
$instance->get_course_module()->get('course');
$this->assertArrayHasKey('assign' . '_' . $assigninstance->id, $modulecache);
}
/**
* Testcases for the create instance test.
*
* @return array Array of testcases.
*/
public function create_instance_testcases() {
return [
'Sample event record with event exposed' => [
'dbrow' => (object)[
'name' => 'Test event',
'description' => 'Hello',
'format' => 1,
'categoryid' => 0,
'courseid' => 1,
'groupid' => 1,
'userid' => 1,
'repeatid' => 0,
'modulename' => 'Test module',
'instance' => 1,
'eventtype' => 'Due',
'type' => CALENDAR_EVENT_TYPE_ACTION,
'timestart' => 123456789,
'timeduration' => 123456789,
'timemodified' => 123456789,
'timesort' => 123456789,
'visible' => true,
'subscriptionid' => 1,
'location' => 'Test location',
],
'actioncallbackapplier' => function(event_interface $event) {
return $event;
},
'visibilitycallbackapplier' => function(event_interface $event) {
return true;
},
'bailoutcheck' => function() {
return false;
},
event_interface::class,
'Hello'
],
'Sample event record with event hidden' => [
'dbrow' => (object)[
'name' => 'Test event',
'description' => 'Hello',
'format' => 1,
'categoryid' => 0,
'courseid' => 1,
'groupid' => 1,
'userid' => 1,
'repeatid' => 0,
'modulename' => 'Test module',
'instance' => 1,
'eventtype' => 'Due',
'type' => CALENDAR_EVENT_TYPE_ACTION,
'timestart' => 123456789,
'timeduration' => 123456789,
'timemodified' => 123456789,
'timesort' => 123456789,
'visible' => true,
'subscriptionid' => 1,
'location' => 'Test location',
],
'actioncallbackapplier' => function(event_interface $event) {
return $event;
},
'visibilitycallbackapplier' => function(event_interface $event) {
return false;
},
'bailoutcheck' => function() {
return false;
},
null,
null
],
'Sample event record with early bail' => [
'dbrow' => (object)[
'name' => 'Test event',
'description' => 'Hello',
'format' => 1,
'categoryid' => 0,
'courseid' => 1,
'groupid' => 1,
'userid' => 1,
'repeatid' => 0,
'modulename' => 'Test module',
'instance' => 1,
'eventtype' => 'Due',
'type' => CALENDAR_EVENT_TYPE_ACTION,
'timestart' => 123456789,
'timeduration' => 123456789,
'timemodified' => 123456789,
'timesort' => 123456789,
'visible' => true,
'subscriptionid' => 1,
'location' => 'Test location',
],
'actioncallbackapplier' => function(event_interface $event) {
return $event;
},
'visibilitycallbackapplier' => function(event_interface $event) {
return true;
},
'bailoutcheck' => function() {
return true;
},
null,
null
]
];
}
/**
* Helper function to create calendar events using the old code.
*
* @param array $properties A list of calendar event properties to set
* @return calendar_event
*/
protected function create_event($properties = []) {
$record = new \stdClass();
$record->name = 'event name';
$record->eventtype = 'site';
$record->timestart = time();
$record->timeduration = 0;
$record->timesort = 0;
$record->type = 1;
$record->courseid = 0;
$record->categoryid = 0;
foreach ($properties as $name => $value) {
$record->$name = $value;
}
$event = new \calendar_event($record);
return $event->create($record, false);
}
}
+472
View File
@@ -0,0 +1,472 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Event mapper test.
*
* @package core_calendar
* @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_calendar;
use core_calendar\local\event\mappers\event_mapper;
use core_calendar\local\event\value_objects\action;
use core_calendar\local\event\value_objects\event_description;
use core_calendar\local\event\value_objects\event_times;
use core_calendar\local\event\factories\action_factory_interface;
use core_calendar\local\event\entities\event_collection_interface;
use core_calendar\local\event\factories\event_factory_interface;
use core_calendar\local\event\entities\event_interface;
use core_calendar\local\event\entities\action_event_interface;
use core_calendar\local\event\proxies\proxy_interface;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/calendar/lib.php');
/**
* Event mapper test.
*
* @package core_calendar
* @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class event_mapper_test extends \advanced_testcase {
/**
* Test legacy event -> event.
*/
public function test_from_legacy_event_to_event(): void {
$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(): void {
$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(\calendar_event::class, $legacyevent);
}
/**
* Test event -> stdClass.
*/
public function test_from_event_to_stdclass(): void {
$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()
);
$obj = $mapper->from_event_to_stdClass($event);
$this->assertInstanceOf(\stdClass::class, $obj);
$this->assertEquals($obj->name, $event->get_name());
$this->assertEquals($obj->eventtype, $event->get_type());
$this->assertEquals($obj->timestart, $event->get_times()->get_start_time()->getTimestamp());
}
/**
* Test event -> array.
*/
public function test_from_event_to_assoc_array(): void {
$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()
);
$arr = $mapper->from_event_to_assoc_array($event);
$this->assertTrue(is_array($arr));
$this->assertEquals($arr['name'], $event->get_name());
$this->assertEquals($arr['eventtype'], $event->get_type());
$this->assertEquals($arr['timestart'], $event->get_times()->get_start_time()->getTimestamp());
}
/**
* Test for action event -> legacy event.
*/
public function test_from_action_event_to_legacy_event(): void {
$this->resetAfterTest(true);
$this->setAdminUser();
$legacyevent = $this->create_event(['modname' => 'assign', 'instance' => 1]);
$event = new event_mapper_test_action_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(\calendar_event::class, $legacyevent);
$this->assertEquals($legacyevent->actionname, 'test action');
$this->assertInstanceOf(\moodle_url::class, $legacyevent->actionurl);
$this->assertEquals($legacyevent->actionnum, 1729);
$this->assertEquals($legacyevent->actionactionable, $event->get_action()->is_actionable());
}
/**
* Helper function to create calendar events using the old code.
*
* @param array $properties A list of calendar event properties to set
* @return calendar_event
*/
protected function create_event($properties = []) {
$record = new \stdClass();
$record->name = 'event name';
$record->eventtype = 'site';
$record->timestart = time();
$record->timeduration = 0;
$record->timesort = 0;
$record->type = 1;
$record->courseid = 0;
$record->categoryid = 0;
foreach ($properties as $name => $value) {
$record->$name = $value;
}
$event = new \calendar_event($record);
return $event->create($record, false);
}
}
/**
* A test event factory.
*
* @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
* @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 action event
*
* @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class event_mapper_test_action_event implements action_event_interface {
/**
* @var event_interface $event The event to delegate to.
*/
protected $event;
/**
* event_mapper_test_action_event constructor.
* @param event_interface $event
*/
public function __construct(event_interface $event) {
$this->event = $event;
}
public function get_id() {
return $this->event->get_id();
}
public function get_name() {
return $this->event->get_name();
}
public function get_description() {
return $this->event->get_description();
}
public function get_location() {
return $this->event->get_location();
}
public function get_category() {
return $this->event->get_category();
}
public function get_course() {
return $this->event->get_course();
}
public function get_course_module() {
return $this->event->get_course_module();
}
public function get_group() {
return $this->event->get_group();
}
public function get_user() {
return $this->event->get_user();
}
public function get_type() {
return $this->event->get_type();
}
public function get_times() {
return $this->event->get_times();
}
public function get_repeats() {
return $this->event->get_repeats();
}
public function get_subscription() {
return $this->event->get_subscription();
}
public function is_visible() {
return $this->event->is_visible();
}
public function get_action() {
return new action(
'test action',
new \moodle_url('http://example.com'),
1729,
true
);
}
/**
* Component
* @return string|null
*/
public function get_component() {
return $this->event->get_component();
}
}
/**
* A test event.
*
* @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class event_mapper_test_event implements event_interface {
/**
* @var proxy_interface $categoryproxy Category proxy.
*/
protected $categoryproxy;
/**
* @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 calendar_event $legacyevent Legacy event to extract 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_location() {
return 'Cube office';
}
public function get_category() {
return $this->categoryproxy;
}
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(-386380800),
(new \DateTimeImmutable())->setTimestamp(115776000),
(new \DateTimeImmutable())->setTimestamp(115776000),
(new \DateTimeImmutable())->setTimestamp(time()),
(new \DateTimeImmutable())->setTimestamp(115776000)
);
}
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;
}
/**
* Component
* @return string|null
*/
public function get_component() {
return null;
}
}
/**
* A test proxy.
*
* @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
* @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) {
if ($member === 'id') {
return $this->id;
}
return isset($params[$member]) ? $params[$member] : null;
}
public function get_proxied_instance() {
}
}
/**
* A test event.
*
* @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
* @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(): \Traversable {
foreach ($this->events as $event) {
yield $event;
}
}
}
+144
View File
@@ -0,0 +1,144 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_calendar;
use core_calendar\local\event\entities\event;
use core_calendar\local\event\proxies\std_proxy;
use core_calendar\local\event\proxies\coursecat_proxy;
use core_calendar\local\event\value_objects\event_description;
use core_calendar\local\event\value_objects\event_times;
use core_calendar\local\event\entities\event_collection_interface;
defined('MOODLE_INTERNAL') || die();
/**
* Calendar event tests..
*
* @package core_calendar
* @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class event_test extends \advanced_testcase {
/**
* Test event class getters.
*
* @dataProvider getters_testcases()
* @param array $constructorparams Associative array of constructor parameters.
*/
public function test_getters($constructorparams): void {
$event = new event(
$constructorparams['id'],
$constructorparams['name'],
$constructorparams['description'],
$constructorparams['category'],
$constructorparams['course'],
$constructorparams['group'],
$constructorparams['user'],
$constructorparams['repeats'],
$constructorparams['course_module'],
$constructorparams['type'],
$constructorparams['times'],
$constructorparams['visible'],
$constructorparams['subscription'],
$constructorparams['location'],
$constructorparams['component']
);
foreach ($constructorparams as $name => $value) {
if ($name !== 'visible' && $name !== 'component') {
$this->assertEquals($event->{'get_' . $name}(), $value);
}
}
$this->assertEquals($event->is_visible(), $constructorparams['visible']);
$this->assertEquals('mod_' . $event->get_course_module()->get('modname'), $event->get_component());
}
/**
* Test cases for getters test.
*/
public function getters_testcases() {
$lamecallable = function($id) {
return (object)['id' => $id, 'modname' => 'assign'];
};
return [
'Dataset 1' => [
'constructorparams' => [
'id' => 1,
'name' => 'Test event 1',
'description' => new event_description('asdf', 1),
'category' => new coursecat_proxy(0),
'course' => new std_proxy(1, $lamecallable),
'group' => new std_proxy(1, $lamecallable),
'user' => new std_proxy(1, $lamecallable),
'repeats' => new core_calendar_event_test_event_collection(),
'course_module' => new std_proxy(1, $lamecallable),
'type' => 'dunno what this actually is meant to be',
'times' => new event_times(
(new \DateTimeImmutable())->setTimestamp(-386380800),
(new \DateTimeImmutable())->setTimestamp(115776000),
(new \DateTimeImmutable())->setTimestamp(115776000),
(new \DateTimeImmutable())->setTimestamp(time()),
(new \DateTimeImmutable())->setTimestamp(115776000)
),
'visible' => true,
'subscription' => new std_proxy(1, $lamecallable),
'location' => 'Test',
'component' => null
]
],
];
}
}
/**
* Test event class.
*
* @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class core_calendar_event_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(): \Traversable {
foreach ($this->events as $event) {
yield $event;
}
}
}
+76
View File
@@ -0,0 +1,76 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_calendar;
use core_calendar\local\event\value_objects\event_times;
/**
* Event times tests.
*
* @package core_calendar
* @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class event_times_test extends \advanced_testcase {
/**
* Test event times class getters.
*
* @dataProvider getters_testcases()
* @param array $constructorparams Associative array of constructor parameters.
*/
public function test_getters($constructorparams): void {
$eventtimes = new event_times(
$constructorparams['start_time'],
$constructorparams['end_time'],
$constructorparams['sort_time'],
$constructorparams['modified_time'],
$constructorparams['usermidnight_time']
);
foreach ($constructorparams as $name => $value) {
$this->assertEquals($eventtimes->{'get_' . $name}(), $value);
}
$this->assertEquals($eventtimes->get_duration(), $constructorparams['end_time']->diff($constructorparams['start_time']));
}
/**
* Test cases for getters test.
*/
public function getters_testcases() {
return [
'Dataset 1' => [
'constructorparams' => [
'start_time' => (new \DateTimeImmutable())->setTimestamp(-386380800),
'end_time' => (new \DateTimeImmutable())->setTimestamp(115776000),
'sort_time' => (new \DateTimeImmutable())->setTimestamp(115776000),
'modified_time' => (new \DateTimeImmutable())->setTimestamp(time()),
'usermidnight_time' => (new \DateTimeImmutable())->setTimestamp(115776000),
]
],
'Dataset 2' => [
'constructorparams' => [
'start_time' => (new \DateTimeImmutable())->setTimestamp(123456),
'end_time' => (new \DateTimeImmutable())->setTimestamp(12345678),
'sort_time' => (new \DateTimeImmutable())->setTimestamp(1111),
'modified_time' => (new \DateTimeImmutable())->setTimestamp(time()),
'usermidnight_time' => (new \DateTimeImmutable())->setTimestamp(1111),
]
]
];
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,134 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_calendar;
use core_calendar\external\events_related_objects_cache;
use core_calendar\local\event\container;
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__ . '/helpers.php');
/**
* Tests for the events_related_objects_cache.
*
* @package core_calendar
* @copyright 2017 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class events_related_objects_cache_test extends \advanced_testcase {
/**
* Tests set up
*/
protected function setUp(): void {
$this->resetAfterTest();
}
/**
* An event with no module should return null when trying to retrieve
* the module instance.
*/
public function test_get_module_instance_no_module(): void {
$this->setAdminUser();
$mapper = container::get_event_mapper();
$legacyevent = create_event([
'modulename' => '',
'instance' => 0
]);
$event = $mapper->from_legacy_event_to_event($legacyevent);
$cache = new events_related_objects_cache([$event]);
$this->assertNull($cache->get_module_instance($event));
}
/**
* The get_module_instance should return the correct module instances
* for the given set of events in the cache.
*/
public function test_get_module_instance_with_modules(): void {
$this->setAdminUser();
$mapper = container::get_event_mapper();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$plugingenerator = $generator->get_plugin_generator('mod_assign');
$instance1 = $plugingenerator->create_instance(['course' => $course->id]);
$instance2 = $plugingenerator->create_instance(['course' => $course->id]);
unset($instance1->cmid);
unset($instance2->cmid);
$params = [
'type' => CALENDAR_EVENT_TYPE_ACTION,
'courseid' => $course->id,
'modulename' => 'assign',
'userid' => 0,
'eventtype' => 'due',
'repeats' => 0,
'timestart' => 1,
];
$legacyevent1 = create_event(array_merge($params, ['name' => 'Event 1', 'instance' => $instance1->id]));
$legacyevent2 = create_event(array_merge($params, ['name' => 'Event 2', 'instance' => $instance1->id]));
$legacyevent3 = create_event(array_merge($params, ['name' => 'Event 3', 'instance' => $instance2->id]));
$event1 = $mapper->from_legacy_event_to_event($legacyevent1);
$event2 = $mapper->from_legacy_event_to_event($legacyevent2);
$event3 = $mapper->from_legacy_event_to_event($legacyevent3);
$cache = new events_related_objects_cache([$event1, $event2, $event3]);
$eventinstance1 = $cache->get_module_instance($event1);
$eventinstance2 = $cache->get_module_instance($event2);
$eventinstance3 = $cache->get_module_instance($event3);
$this->assertEquals($instance1, $eventinstance1);
$this->assertEquals($instance1, $eventinstance2);
$this->assertEquals($instance2, $eventinstance3);
}
/**
* Trying to load the course module of an event that isn't in
* the cache should return null.
*/
public function test_module_instance_unknown_event(): void {
$this->setAdminUser();
$mapper = container::get_event_mapper();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$plugingenerator = $generator->get_plugin_generator('mod_assign');
$instance1 = $plugingenerator->create_instance(['course' => $course->id]);
$instance2 = $plugingenerator->create_instance(['course' => $course->id]);
unset($instance1->cmid);
unset($instance2->cmid);
$params = [
'type' => CALENDAR_EVENT_TYPE_ACTION,
'courseid' => $course->id,
'modulename' => 'assign',
'userid' => 0,
'eventtype' => 'due',
'repeats' => 0,
'timestart' => 1,
];
$legacyevent1 = create_event(array_merge($params, ['name' => 'Event 1', 'instance' => $instance1->id]));
$legacyevent2 = create_event(array_merge($params, ['name' => 'Event 2', 'instance' => $instance2->id]));
$event1 = $mapper->from_legacy_event_to_event($legacyevent1);
$event2 = $mapper->from_legacy_event_to_event($legacyevent2);
$cache = new events_related_objects_cache([$event1]);
$this->assertNull($cache->get_module_instance($event2));
}
}
File diff suppressed because it is too large Load Diff
+26
View File
@@ -0,0 +1,26 @@
BEGIN:VCALENDAR
METHOD:PUBLISH
PRODID:-//John Papaioannou/NONSGML Bennu 0.1//EN
VERSION:2.0
BEGIN:VEVENT
UID:198001@127.0.0.1:8888/moodle32
SUMMARY:Event on 2-15-2017
DESCRIPTION:Event on 2-15-2017
CLASS:PUBLIC
LAST-MODIFIED:20170226T014326Z
LOCATION:Some place
DTSTAMP:20170226T014355Z
DTSTART;VALUE=DATE:20170214
DTEND;VALUE=DATE:20170215
END:VEVENT
BEGIN:VEVENT
UID:198000@127.0.0.1:8888/moodle32
SUMMARY:Event on 2-25-2017
DESCRIPTION:Event on 2-25-2017
CLASS:PUBLIC
LAST-MODIFIED:20170226T014258Z
DTSTAMP:20170226T014355Z
DTSTART;VALUE=DATE:20170224
DTEND;VALUE=DATE:20170225
END:VEVENT
END:VCALENDAR
+27
View File
@@ -0,0 +1,27 @@
BEGIN:VCALENDAR
METHOD:PUBLISH
PRODID:-//Huong Nguyen/NONSGML Moodle//EN
VERSION:2.0
BEGIN:VEVENT
UID:special_import_moodle_1
SUMMARY:First event
DESCRIPTION:Description of the first event\n
CLASS:PUBLIC
LAST-MODIFIED:20220728T034015Z
LOCATION:Vietnam
DTSTAMP:20220728T034031Z
DTSTART:20220701T070000Z
DTEND:20220701T070000Z
END:VEVENT
BEGIN:VEVENT
UID:special_import_moodle_2
SUMMARY:Second event
DESCRIPTION;ALTREP="http://moodle.com/":Description of the second event\n
CLASS:PUBLIC
LAST-MODIFIED:20220728T034021Z
LOCATION:Vietnam
DTSTAMP:20220728T034031Z
DTSTART:20220701T080000Z
DTEND:20220701T080000Z
END:VEVENT
END:VCALENDAR
+256
View File
@@ -0,0 +1,256 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains helper classes and functions for testing.
*
* @package core_calendar
* @copyright 2017 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/calendar/lib.php');
use core_calendar\local\event\entities\action_event;
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\proxies\coursecat_proxy;
use core_calendar\local\event\proxies\cm_info_proxy;
use core_calendar\local\event\value_objects\action;
use core_calendar\local\event\value_objects\event_description;
use core_calendar\local\event\value_objects\event_times;
use core_calendar\local\event\factories\event_factory_interface;
/**
* Create a calendar event with the given properties.
*
* @param array $properties The properties to set on the event
* @return \calendar_event
*/
function create_event($properties) {
$record = new \stdClass();
$record->name = 'event name';
$record->eventtype = 'site';
$record->repeat = 0;
$record->repeats = 0;
$record->timestart = time();
$record->timeduration = 0;
$record->timesort = 0;
$record->type = CALENDAR_EVENT_TYPE_STANDARD;
$record->courseid = 0;
$record->categoryid = 0;
foreach ($properties as $name => $value) {
$record->$name = $value;
}
$event = new \calendar_event($record);
return $event->create($record);
}
/**
* Helper function to create a x number of events for each event type.
*
* @param int $quantity The quantity of events to be created.
* @return array List of created events.
*/
function create_standard_events(int $quantity): array {
$types = ['site', 'category', 'course', 'group', 'user'];
$events = [];
foreach ($types as $eventtype) {
// Create five events of each event type.
for ($i = 0; $i < $quantity; $i++) {
$events[] = create_event(['eventtype' => $eventtype]);
}
}
return $events;
}
/**
* Helper function to create an action event.
*
* @param array $data The event data.
* @return bool|calendar_event
*/
function create_action_event(array $data) {
global $CFG;
require_once($CFG->dirroot . '/calendar/lib.php');
if (!isset($data['modulename']) || !isset($data['instance'])) {
throw new coding_exception('Module and instance should be specified when creating an action event.');
}
$isuseroverride = isset($data->priority) && $data->priority == CALENDAR_EVENT_USER_OVERRIDE_PRIORITY;
if ($isuseroverride) {
if (!in_array($data['modulename'], ['assign', 'lesson', 'quiz'])) {
throw new coding_exception('Only assign, lesson and quiz modules supports overrides');
}
}
$event = array_merge($data, [
'eventtype' => isset($data['eventtype']) ? $data['eventtype'] : 'open',
'courseid' => isset($data['courseid']) ? $data['courseid'] : 0,
'instance' => $data['instance'],
'modulename' => $data['modulename'],
'type' => CALENDAR_EVENT_TYPE_ACTION,
]);
return create_event($event);
}
/**
* Helper function to create an user override calendar event.
*
* @param string $modulename The modulename.
* @param int $instanceid The instance id.
* @param int $userid The user id.
* @return calendar_event|false
*/
function create_user_override_event(string $modulename, int $instanceid, int $userid) {
if (!isset($userid)) {
throw new coding_exception('Must specify userid when creating a user override.');
}
return create_action_event([
'modulename' => $modulename,
'instance' => $instanceid,
'userid' => $userid,
'priority' => CALENDAR_EVENT_USER_OVERRIDE_PRIORITY,
]);
}
/**
* Helper function to create an group override calendar event.
*
* @param string $modulename The modulename.
* @param int $instanceid The instance id.
* @param int $courseid The course id.
* @param int $groupid The group id.
* @return calendar_event|false
*/
function create_group_override_event(string $modulename, int $instanceid, int $courseid, int $groupid) {
if (!isset($groupid)) {
throw new coding_exception('Must specify groupid when creating a group override.');
}
return create_action_event([
'groupid' => $groupid,
'courseid' => $courseid,
'modulename' => $modulename,
'instance' => $instanceid,
]);
}
/**
* A test factory that will create action events.
*
* @copyright 2017 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or late
*/
class action_event_test_factory implements event_factory_interface {
/**
* @var callable $callback.
*/
private $callback;
/**
* A test factory that will create action events. The factory accepts a callback
* that will be used to determine if the event should be returned or not.
*
* The callback will be given the event and should return true if the event
* should be returned and false otherwise.
*
* @param callable $callback The callback.
*/
public function __construct($callback = null) {
$this->callback = $callback;
}
public function create_instance(\stdClass $record) {
$module = null;
$subscription = null;
if ($record->instance && $record->modulename) {
$module = new cm_info_proxy($record->instance, $record->modulename, $record->courseid);
}
if ($record->subscriptionid) {
$subscription = new std_proxy($record->subscriptionid, function($id) {
return (object)['id' => $id];
});
}
$event = new event(
$record->id,
$record->name,
new event_description($record->description, $record->format),
new coursecat_proxy($record->categoryid),
new std_proxy($record->courseid, function($id) {
$course = new \stdClass();
$course->id = $id;
return $course;
}),
new std_proxy($record->groupid, function($id) {
$group = new \stdClass();
$group->id = $id;
return $group;
}),
new std_proxy($record->userid, function($id) {
$user = new \stdClass();
$user->id = $id;
return $user;
}),
!empty($record->repeatid) ? new repeat_event_collection($record, $this) : null,
$module,
$record->eventtype,
new event_times(
(new \DateTimeImmutable())->setTimestamp($record->timestart),
(new \DateTimeImmutable())->setTimestamp($record->timestart + $record->timeduration),
(new \DateTimeImmutable())->setTimestamp($record->timesort ? $record->timesort : $record->timestart),
(new \DateTimeImmutable())->setTimestamp($record->timemodified),
(new \DateTimeImmutable())->setTimestamp($record->timesort ? usergetmidnight($record->timesort) : 0)
),
!empty($record->visible),
$subscription,
$record->location,
!empty($record->component) ? $record->component : null
);
$action = new action(
'Test action',
new \moodle_url('/'),
1,
true
);
$actionevent = new action_event($event, $action);
if ($callback = $this->callback) {
return $callback($actionevent) ? $actionevent : false;
} else {
return $actionevent;
}
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+835
View File
@@ -0,0 +1,835 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy tests for core_calendar.
*
* @package core_calendar
* @category test
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_calendar\privacy;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/calendar/lib.php');
require_once($CFG->dirroot . '/calendar/tests/externallib_test.php');
use core_calendar\privacy\provider;
use core_privacy\local\metadata\collection;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\writer;
use core_privacy\tests\provider_testcase;
use core_privacy\local\request\approved_userlist;
/**
* Unit tests for calendar/classes/privacy/provider
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \core_calendar\privacy\provider
*/
class provider_test extends provider_testcase {
/**
* Overriding setUp() function to always reset after tests.
*/
public function setUp(): void {
$this->resetAfterTest(true);
}
/**
* Test for provider::get_contexts_for_userid().
*
* @throws coding_exception
*/
public function test_get_contexts_for_userid(): void {
// Create test user to create Calendar Events and Subscriptions.
$user = $this->getDataGenerator()->create_user();
$this->setUser($user);
// Create a Category and Courses to assign Calendar Events and Subscriptions.
$category = $this->getDataGenerator()->create_category();
$course1 = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$course3 = $this->getDataGenerator()->create_course();
$grouprecord = (object)[
'courseid' => $course3->id,
'name' => 'test_group'
];
$course3group = $this->getDataGenerator()->create_group($grouprecord);
// Get contexts.
$usercontext = \context_user::instance($user->id);
$categorycontext = \context_coursecat::instance($category->id);
$course1context = \context_course::instance($course1->id);
$course2context = \context_course::instance($course2->id);
$course3context = \context_course::instance($course3->id);
// Add Category Calendar Events for Category.
$this->create_test_standard_calendar_event('category', $user->id, time(), '', $category->id);
$this->create_test_standard_calendar_event('category', $user->id, time(), '', $category->id);
// Add User Calendar Events for User.
$this->create_test_standard_calendar_event('user', $user->id, time(), '');
$this->create_test_standard_calendar_event('user', $user->id, time(), '', 0, $course1->id);
$this->create_test_standard_calendar_event('user', $user->id, time(), '', 0, $course2->id);
// Add a Course Calendar Event for Course 1.
$this->create_test_standard_calendar_event('course', $user->id, time(), '', 0, $course1->id);
// Add a Course Assignment Action Calendar Event for Course 2.
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$params['course'] = $course2->id;
$params['assignsubmission_onlinetext_enabled'] = 1;
$instance = $generator->create_instance($params);
$cm = get_coursemodule_from_instance('assign', $instance->id);
$modulecontext = \context_module::instance($cm->id);
$assign = new \assign($modulecontext, $cm, $course2);
$this->create_test_action_calendar_event('duedate', $course2->id, $instance->id, 'assign', $user->id, time());
$this->create_test_action_calendar_event('gradingduedate', $course2->id, $instance->id, 'assign', $user->id, time());
// Add a Calendar Subscription and Group Calendar Event to Course 3.
$this->create_test_calendar_subscription('course', 'https://calendar.google.com/', $user->id, 0, $course3->id);
$this->create_test_standard_calendar_event('group', $user->id, time(), '', 0, $course3->id, $course3group->id);
// The user will be in these contexts.
$usercontextids = [
$usercontext->id,
$categorycontext->id,
$course1context->id,
$modulecontext->id,
$course3context->id
];
// Retrieve the user's context ids.
$contextids = provider::get_contexts_for_userid($user->id);
// Check the user context list and retrieved user context lists contains the same number of records.
$this->assertEquals(count($usercontextids), count($contextids->get_contextids()));
// There should be no difference between the contexts.
$this->assertEmpty(array_diff($usercontextids, $contextids->get_contextids()));
}
/**
* Test for provider::export_user_data().
*
* @throws coding_exception
*/
public function test_export_user_data(): void {
global $DB;
// Create test user to create Calendar Events and Subscriptions with.
$user = $this->getDataGenerator()->create_user();
$this->setUser($user);
// Create a Category to test creating a Category Calendar Event.
$category = $this->getDataGenerator()->create_category();
$course1 = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$course3 = $this->getDataGenerator()->create_course();
$grouprecord = (object)[
'courseid' => $course3->id,
'name' => 'test_group'
];
$course3group = $this->getDataGenerator()->create_group($grouprecord);
// Add User Calendar Events for User.
$event1 = $this->create_test_standard_calendar_event('user', $user->id, time(), '');
// Add Category Calendar Events for Category.
$event2 = $this->create_test_standard_calendar_event('category', $user->id, time(), '', $category->id);
// Add two Course Calendar Event for Course 1 and set the same time (1 day a head).
$time = strtotime('+1 day', time());
$event3 = $this->create_test_standard_calendar_event('course', $user->id, $time, 'ABC', 0, $course1->id);
$event4 = $this->create_test_standard_calendar_event('course', $user->id, $time, 'DEF', 0, $course1->id);
// Add a Course Assignment Action Calendar Event for Course 2.
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$params['course'] = $course2->id;
$params['assignsubmission_onlinetext_enabled'] = 1;
$instance = $generator->create_instance($params);
$cm = get_coursemodule_from_instance('assign', $instance->id);
$modulecontext = \context_module::instance($cm->id);
$assign = new \assign($modulecontext, $cm, $course2);
$event5 = $this->create_test_action_calendar_event('duedate', $course2->id, $instance->id, 'assign', $user->id, time());
// Add a Calendar Subscription and Group Calendar Event to Course 3.
$subscription1 = $this->create_test_calendar_subscription('course', 'https://calendar.google.com/', $user->id, 0, $course3->id);
$event6 = $this->create_test_standard_calendar_event('group', $user->id, time(), '', 0, $course3->id, $course3group->id);
// Retrieve the user's context ids.
$contextlist = provider::get_contexts_for_userid($user->id);
$approvedcontextlist = new approved_contextlist($user, 'core_calendar', $contextlist->get_contextids());
// Retrieve Calendar Event and Subscriptions data only for this user.
provider::export_user_data($approvedcontextlist);
foreach ($contextlist as $context) {
/** @var \core_privacy\tests\request\content_writer $writer */
$writer = writer::with_context($context);
$this->assertTrue($writer->has_any_data());
// Test event 1 that was created for the test User.
if ($context->instanceid == $user->id && $context->contextlevel == CONTEXT_USER) {
// Test the content contains Calendar Event user data.
$subcontexts = [
get_string('calendar', 'calendar'),
get_string('events', 'calendar'),
date('c', $event1->timestart)
];
$name = "user-event";
$data = $writer->get_related_data($subcontexts, $name);
$this->assertEquals('Standard Calendar Event user', $data->name);
}
// Test event 2 that was created for the test Category.
if ($context->instanceid == $category->id && $context->contextlevel == CONTEXT_COURSECAT) {
// Test the content contains Calendar Event category data.
$subcontexts = [
get_string('calendar', 'calendar'),
get_string('events', 'calendar'),
date('c', $event2->timestart)
];
$name = "category-event";
$data = $writer->get_related_data($subcontexts, $name);
$this->assertEquals('Standard Calendar Event category', $data->name);
}
// Test events 3, 4, and 5 that were created for the test Course 1.
if ($context->instanceid == $course1->id && $context->contextlevel == CONTEXT_COURSE) {
// Test the content contains Calendar Event course data set with the same time, and the exported files are uniquely identified.
$subcontext1 = [
get_string('calendar', 'calendar'),
get_string('events', 'calendar'),
date('c', $event3->timestart)
];
$name1 = "course-event-1";
$data1 = $writer->get_related_data($subcontext1, $name1);
$this->assertEquals('Standard Calendar Event course -- ABC', $data1->name);
$subcontext2 = [
get_string('calendar', 'calendar'),
get_string('events', 'calendar'),
date('c', $event4->timestart)
];
$name2 = "course-event-2";
$data2 = $writer->get_related_data($subcontext2, $name2);
$this->assertEquals('Standard Calendar Event course -- DEF', $data2->name);
}
// Test action event that were created for the test Course 2.
if ($context->instanceid == $cm->id && $context->contextlevel == CONTEXT_MODULE) {
// Test the content contains Calendar Action Event course data.
$subcontexts = [
get_string('calendar', 'calendar'),
get_string('events', 'calendar'),
date('c', $event5->timestart)
];
$name = "duedate-event";
$data = $writer->get_related_data($subcontexts, $name);
$this->assertEquals('Action Calendar Event duedate -- assign', $data->name);
}
// Test Calendar Subscription and Event that were created for the test Course 3.
if ($context->instanceid == $course3->id && $context->contextlevel == CONTEXT_COURSE) {
// Test the content contains Calendar Subscription data also created for the test Course 3.
$subcontexts = [
get_string('calendar', 'calendar'),
get_string('subscriptions', 'calendar')
];
$name = "course-subscription";
$data = $writer->get_related_data($subcontexts, $name);
$this->assertEquals('Calendar Subscription course', $data->name);
// Test the content contains Calendar Event group data also created for the test Course 3.
$subcontexts = [
get_string('calendar', 'calendar'),
get_string('events', 'calendar'),
date('c', $event6->timestart)
];
$name = "group-event";
$data = $writer->get_related_data($subcontexts, $name);
$this->assertEquals('Standard Calendar Event group', $data->name);
}
}
}
/**
* Test for provider::test_export_user_preferences().
*/
public function test_export_user_preferences(): void {
global $DB;
// Test setup.
$user = $this->getDataGenerator()->create_user();
$this->setUser($user);
// Add a user home page preference for the User.
set_user_preference('calendar_savedflt', 'true', $user);
// Test the user preference exists.
$params = [
'userid' => $user->id,
'name' => 'calendar_savedflt'
];
// Test the user preferences export contains 1 user preference record for the User.
provider::export_user_preferences($user->id);
$contextuser = \context_user::instance($user->id);
$writer = writer::with_context($contextuser);
$this->assertTrue($writer->has_any_data());
$exportedpreferences = $writer->get_user_preferences('core_calendar');
$this->assertCount(1, (array) $exportedpreferences);
$this->assertEquals('true', $exportedpreferences->calendarsavedflt->value);
}
/**
* Test for provider::delete_data_for_all_users_in_context().
*
* @throws dml_exception
*/
public function test_delete_data_for_all_users_in_context(): void {
global $DB;
// Create test user to create Calendar Events and Subscriptions with.
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
// Create a Course to test creating a Category Calendar Event.
$course1 = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
// Get contexts.
$course1context = \context_course::instance($course1->id);
$course2context = \context_course::instance($course2->id);
// Add a Course Calendar Event by User 1 for Course 1 and Course 2.
$this->setUser($user1);
$this->create_test_standard_calendar_event('course', $user1->id, time(), '', 0, $course1->id);
$this->create_test_standard_calendar_event('course', $user1->id, time(), '', 0, $course2->id);
// Add a Calendar Subscription by User 1 for Course 1.
$this->create_test_calendar_subscription('course', 'https://calendar.google.com/', $user1->id, 0, $course1->id);
// Add a Course Calendar Event by User 2 for Course 1 and Course 2.
$this->setUser($user2);
$this->create_test_standard_calendar_event('course', $user2->id, time(), '', 0, $course1->id);
$this->create_test_standard_calendar_event('course', $user2->id, time(), '', 0, $course2->id);
// Add a Calendar Subscription by User 2 for Course 2.
$this->create_test_calendar_subscription('course', 'https://calendar.google.com/', $user2->id, 0, $course2->id);
// Add a Course Assignment Action Calendar Event by User 2 for Course 2.
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$params['course'] = $course2->id;
$params['assignsubmission_onlinetext_enabled'] = 1;
$instance = $generator->create_instance($params);
$cm = get_coursemodule_from_instance('assign', $instance->id);
$modulecontext = \context_module::instance($cm->id);
$assign = new \assign($modulecontext, $cm, $course2);
$this->create_test_action_calendar_event('duedate', $course2->id, $instance->id, 'assign', $user2->id, time());
$this->create_test_action_calendar_event('gradingduedate', $course2->id, $instance->id, 'assign', $user2->id, time());
// Delete all Calendar Events for all Users by Context for Course 1.
provider::delete_data_for_all_users_in_context($course1context);
// Verify all Calendar Events for Course 1 were deleted.
$events = $DB->get_records('event', array('courseid' => $course1->id));
$this->assertCount(0, $events);
// Verify all Calendar Subscriptions for Course 1 were deleted.
$subscriptions = $DB->get_records('event_subscriptions', array('courseid' => $course1->id));
$this->assertCount(0, $subscriptions);
// Verify all Calendar Events for Course 2 exists still.
$events = $DB->get_records('event', array('courseid' => $course2->id));
$this->assertCount(4, $events);
// Verify all Calendar Subscriptions for Course 2 exists still.
$subscriptions = $DB->get_records('event_subscriptions', array('courseid' => $course2->id));
$this->assertCount(1, $subscriptions);
// Delete all Calendar Events for all Users by Context for Course 2.
provider::delete_data_for_all_users_in_context($course2context);
// Verify all Calendar Events for Course 2 context were deleted.
$events = $DB->get_records('event', array('courseid' => $course2->id, 'modulename' => '0'));
$this->assertCount(0, $events);
// Verify all Calendar Subscriptions for Course 2 were deleted.
$subscriptions = $DB->get_records('event_subscriptions', array('courseid' => $course2->id));
$this->assertCount(0, $subscriptions);
// Verify all Calendar Events for the assignment exists still.
$events = $DB->get_records('event', array('modulename' => 'assign'));
$this->assertCount(2, $events);
// Delete all Calendar Events for all Users by Context for the assignment.
provider::delete_data_for_all_users_in_context($modulecontext);
// Verify all Calendar Events for the assignment context were deleted.
$events = $DB->get_records('event', array('modulename' => 'assign'));
$this->assertCount(0, $events);
}
/**
* Test for provider::delete_data_for_user().
*
* @throws dml_exception
*/
public function test_delete_data_for_user(): void {
global $DB;
// Create test user to create Calendar Events and Subscriptions with.
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
// Create a Category and Courses to test creating a Category Calendar Event.
$category = $this->getDataGenerator()->create_category();
$course1 = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
// Add 5 Calendar Events for User 1 for various contexts.
$this->setUser($user1);
$this->create_test_standard_calendar_event('user', $user1->id, time(), '');
$this->create_test_standard_calendar_event('site', $user1->id, time(), '', 0, 1);
$this->create_test_standard_calendar_event('category', $user1->id, time(), '', $category->id);
$this->create_test_standard_calendar_event('course', $user1->id, time(), '', 0, $course1->id);
$this->create_test_standard_calendar_event('course', $user1->id, time(), '', 0, $course2->id);
// Add 1 Calendar Subscription for User 1 at course context.
$this->create_test_calendar_subscription('course', 'https://calendar.google.com/', $user1->id, 0, $course2->id);
// Add 3 Calendar Events for User 2 for various contexts.
$this->setUser($user2);
$this->create_test_standard_calendar_event('user', $user2->id, time(), '');
$this->create_test_standard_calendar_event('category', $user2->id, time(), '', $category->id);
$this->create_test_standard_calendar_event('course', $user2->id, time(), '', 0, $course1->id);
// Add 1 Calendar Subscription for User 2 at course context.
$this->create_test_calendar_subscription('course', 'https://calendar.google.com/', $user2->id, 0, $course2->id);
// Retrieve the user's context ids.
$contextlist = provider::get_contexts_for_userid($user1->id);
$approvedcontextlist = new approved_contextlist($user1, 'core_calendar', $contextlist->get_contextids());
// Delete all Calendar data for User 1.
provider::delete_data_for_user($approvedcontextlist);
// Test all Calendar Events and Subscriptions for User 1 equals zero.
$events = $DB->get_records('event', ['userid' => $user1->id]);
$this->assertCount(0, $events);
$eventsubscriptions = $DB->get_records('event_subscriptions', ['userid' => $user1->id]);
$this->assertCount(0, $eventsubscriptions);
// Test all Calendar Events and Subscriptions for User 2 still exists and matches the same number created.
$events = $DB->get_records('event', ['userid' => $user2->id]);
$this->assertCount(3, $events);
$eventsubscriptions = $DB->get_records('event_subscriptions', ['userid' => $user2->id]);
$this->assertCount(1, $eventsubscriptions);
}
/**
* Test that only users with a user context are fetched.
*/
public function test_get_users_in_context(): void {
$component = 'core_calendar';
// Create user1 to create Calendar Events and Subscriptions.
$user1 = $this->getDataGenerator()->create_user();
$usercontext1 = \context_user::instance($user1->id);
// Create user2 to create Calendar Events and Subscriptions.
$user2 = $this->getDataGenerator()->create_user();
$usercontext2 = \context_user::instance($user2->id);
// Create user3 to create Calendar Events and Subscriptions.
$user3 = $this->getDataGenerator()->create_user();
$usercontext3 = \context_user::instance($user3->id);
// Create a Category and Courses to assign Calendar Events and Subscriptions.
$category = $this->getDataGenerator()->create_category();
$categorycontext = \context_coursecat::instance($category->id);
$course1 = $this->getDataGenerator()->create_course();
$course1context = \context_course::instance($course1->id);
$course2 = $this->getDataGenerator()->create_course();
$course2context = \context_course::instance($course2->id);
$course3 = $this->getDataGenerator()->create_course();
$course3context = \context_course::instance($course3->id);
$grouprecord = (object)[
'courseid' => $course3->id,
'name' => 'test_group'
];
$course3group = $this->getDataGenerator()->create_group($grouprecord);
// Add Category Calendar Events for Category.
$this->setUser($user1);
$this->create_test_standard_calendar_event('category', $user1->id, time(), '',
$category->id);
$this->setUser($user2);
$this->create_test_standard_calendar_event('category', $user2->id, time(), '',
$category->id);
// Add User Calendar Events for user1 and user2.
$this->setUser($user1);
$this->create_test_standard_calendar_event('user', $user1->id, time(), '');
$this->create_test_standard_calendar_event('user', $user1->id, time(), '',
0, $course1->id);
$this->create_test_standard_calendar_event('user', $user1->id, time(), '',
0, $course2->id);
$this->setUser($user2);
$this->create_test_standard_calendar_event('user', $user2->id, time(), '',
0, $course1->id);
// Add a Course Calendar Events for Course 1.
$this->setUser($user1);
$this->create_test_standard_calendar_event('course', $user1->id, time(), '',
0, $course1->id);
$this->setUser($user2);
$this->create_test_standard_calendar_event('course', $user2->id, time(), '',
0, $course1->id);
// Add a Course Assignment Action Calendar Event for Course 2.
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$params['course'] = $course2->id;
$params['assignsubmission_onlinetext_enabled'] = 1;
$instance = $generator->create_instance($params);
$cm = get_coursemodule_from_instance('assign', $instance->id);
$modulecontext = \context_module::instance($cm->id);
$assign = new \assign($modulecontext, $cm, $course2);
$this->setUser($user2);
$this->create_test_action_calendar_event('duedate', $course2->id, $instance->id,
'assign', $user2->id, time());
$this->create_test_action_calendar_event('gradingduedate', $course2->id, $instance->id,
'assign', $user2->id, time());
// Add a Calendar Subscription and Group Calendar Event to Course 3.
$this->create_test_standard_calendar_event('group', $user2->id, time(), '', 0,
$course3->id, $course3group->id);
$this->setUser($user3);
$this->create_test_calendar_subscription('course', 'https://calendar.google.com/', $user3->id,
0, $course3->id);
// The user list for usercontext1 should return user1.
$userlist1 = new \core_privacy\local\request\userlist($usercontext1, $component);
provider::get_users_in_context($userlist1);
$this->assertCount(1, $userlist1);
$this->assertTrue(in_array($user1->id, $userlist1->get_userids()));
// The user list for usercontext2 should return user2.
$userlist2 = new \core_privacy\local\request\userlist($usercontext2, $component);
provider::get_users_in_context($userlist2);
$this->assertCount(1, $userlist2);
$this->assertTrue(in_array($user2->id, $userlist2->get_userids()));
// The user list for course1context should return user1 and user2.
$userlist3 = new \core_privacy\local\request\userlist($course1context, $component);
provider::get_users_in_context($userlist3);
$this->assertCount(2, $userlist3);
$this->assertTrue(in_array($user1->id, $userlist3->get_userids()));
$this->assertTrue(in_array($user2->id, $userlist3->get_userids()));
// The user list for course2context should not return any users.
$userlist4 = new \core_privacy\local\request\userlist($course2context, $component);
provider::get_users_in_context($userlist4);
$this->assertCount(0, $userlist4);
// The user list for course3context should return user2 and user3.
$userlist5 = new \core_privacy\local\request\userlist($course3context, $component);
provider::get_users_in_context($userlist5);
$this->assertCount(2, $userlist5);
$this->assertTrue(in_array($user2->id, $userlist5->get_userids()));
$this->assertTrue(in_array($user3->id, $userlist5->get_userids()));
// The user list for categorycontext should return user1 and user2.
$userlist6 = new \core_privacy\local\request\userlist($categorycontext, $component);
provider::get_users_in_context($userlist6);
$this->assertCount(2, $userlist6);
$this->assertTrue(in_array($user1->id, $userlist6->get_userids()));
$this->assertTrue(in_array($user2->id, $userlist6->get_userids()));
// The user list for modulecontext should return user2.
$userlist7 = new \core_privacy\local\request\userlist($modulecontext, $component);
provider::get_users_in_context($userlist7);
$this->assertCount(1, $userlist7);
$this->assertTrue(in_array($user2->id, $userlist7->get_userids()));
// The user list for usercontext3 should not return any users.
$userlist8 = new \core_privacy\local\request\userlist($usercontext3, $component);
provider::get_users_in_context($userlist8);
$this->assertCount(0, $userlist8);
}
/**
* Test that data for users in approved userlist is deleted.
*/
public function test_delete_data_for_users(): void {
$component = 'core_calendar';
// Create user1 to create Calendar Events and Subscriptions.
$user1 = $this->getDataGenerator()->create_user();
$usercontext1 = \context_user::instance($user1->id);
// Create user2 to create Calendar Events and Subscriptions.
$user2 = $this->getDataGenerator()->create_user();
$usercontext2 = \context_user::instance($user2->id);
// Create user3 to create Calendar Events and Subscriptions.
$user3 = $this->getDataGenerator()->create_user();
$usercontext3 = \context_user::instance($user3->id);
// Create a Category and Courses to assign Calendar Events and Subscriptions.
$category = $this->getDataGenerator()->create_category();
$categorycontext = \context_coursecat::instance($category->id);
$course1 = $this->getDataGenerator()->create_course();
$course1context = \context_course::instance($course1->id);
$course2 = $this->getDataGenerator()->create_course();
$course2context = \context_course::instance($course2->id);
$course3 = $this->getDataGenerator()->create_course();
$course3context = \context_course::instance($course3->id);
$grouprecord = (object)[
'courseid' => $course3->id,
'name' => 'test_group'
];
$course3group = $this->getDataGenerator()->create_group($grouprecord);
// Add Category Calendar Events for Category.
$this->setUser($user1);
$this->create_test_standard_calendar_event('category', $user1->id, time(), '',
$category->id);
$this->setUser($user2);
$this->create_test_standard_calendar_event('category', $user2->id, time(), '',
$category->id);
// Add User Calendar Events for user1 and user2.
$this->setUser($user1);
$this->create_test_standard_calendar_event('user', $user1->id, time(), '');
$this->create_test_standard_calendar_event('user', $user1->id, time(), '',
0, $course1->id);
$this->create_test_standard_calendar_event('user', $user1->id, time(), '',
0, $course2->id);
$this->setUser($user2);
$this->create_test_standard_calendar_event('user', $user2->id, time(), '',
0, $course1->id);
// Add a Course Calendar Events for Course 1.
$this->setUser($user1);
$this->create_test_standard_calendar_event('course', $user1->id, time(), '',
0, $course1->id);
$this->setUser($user2);
$this->create_test_standard_calendar_event('course', $user2->id, time(), '',
0, $course1->id);
// Add a Course Assignment Action Calendar Event for Course 2.
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$params['course'] = $course2->id;
$params['assignsubmission_onlinetext_enabled'] = 1;
$instance = $generator->create_instance($params);
$cm = get_coursemodule_from_instance('assign', $instance->id);
$modulecontext = \context_module::instance($cm->id);
$assign = new \assign($modulecontext, $cm, $course2);
$this->setUser($user2);
$this->create_test_action_calendar_event('duedate', $course2->id, $instance->id,
'assign', $user2->id, time());
$this->create_test_action_calendar_event('gradingduedate', $course2->id, $instance->id,
'assign', $user2->id, time());
// Add a Calendar Subscription and Group Calendar Event to Course 3.
$this->create_test_standard_calendar_event('group', $user2->id, time(), '', 0,
$course3->id, $course3group->id);
$this->setUser($user3);
$this->create_test_calendar_subscription('course', 'https://calendar.google.com/', $user3->id,
0, $course3->id);
// The user list for usercontext1 should return user1.
$userlist1 = new \core_privacy\local\request\userlist($usercontext1, $component);
provider::get_users_in_context($userlist1);
$this->assertCount(1, $userlist1);
// The user list for usercontext2 should return user2.
$userlist2 = new \core_privacy\local\request\userlist($usercontext2, $component);
provider::get_users_in_context($userlist2);
$this->assertCount(1, $userlist2);
// The user list for course1context should return user1 and user2.
$userlist3 = new \core_privacy\local\request\userlist($course1context, $component);
provider::get_users_in_context($userlist3);
$this->assertCount(2, $userlist3);
// The user list for course2context should not return any users.
$userlist4 = new \core_privacy\local\request\userlist($course2context, $component);
provider::get_users_in_context($userlist4);
$this->assertCount(0, $userlist4);
// The user list for course3context should return user2 and user3.
$userlist5 = new \core_privacy\local\request\userlist($course3context, $component);
provider::get_users_in_context($userlist5);
$this->assertCount(2, $userlist5);
// The user list for categorycontext should return user1 and user2.
$userlist6 = new \core_privacy\local\request\userlist($categorycontext, $component);
provider::get_users_in_context($userlist6);
$this->assertCount(2, $userlist6);
// The user list for modulecontext should return user2.
$userlist7 = new \core_privacy\local\request\userlist($modulecontext, $component);
provider::get_users_in_context($userlist7);
$this->assertCount(1, $userlist7);
// The user list for usercontext3 should not return any users.
$userlist8 = new \core_privacy\local\request\userlist($usercontext3, $component);
provider::get_users_in_context($userlist8);
$this->assertCount(0, $userlist8);
// Convert $userlist1 into an approved_contextlist.
$approvedlist1 = new approved_userlist($usercontext1, $component, $userlist1->get_userids());
// Delete using delete_data_for_user.
provider::delete_data_for_users($approvedlist1);
// The user list for usercontext1 should not return any users.
$userlist1 = new \core_privacy\local\request\userlist($usercontext1, $component);
provider::get_users_in_context($userlist1);
$this->assertCount(0, $userlist1);
// The user list for usercontext2 should still return users2.
$userlist2 = new \core_privacy\local\request\userlist($usercontext2, $component);
provider::get_users_in_context($userlist2);
$this->assertCount(1, $userlist2);
// Convert $userlist3 into an approved_contextlist.
// Pass an empty array as a value for the approved user list.
$approvedlist2 = new approved_userlist($course1context, $component, []);
// Delete using delete_data_for_user.
provider::delete_data_for_users($approvedlist2);
// The user list for course1context should return user1 and user2.
$userlist3 = new \core_privacy\local\request\userlist($course1context, $component);
provider::get_users_in_context($userlist3);
$this->assertCount(2, $userlist3);
$this->assertTrue(in_array($user1->id, $userlist3->get_userids()));
$this->assertTrue(in_array($user2->id, $userlist3->get_userids()));
// Convert $userlist3 into an approved_contextlist.
// Pass the ID of user1 as a value for the approved user list.
$approvedlist2 = new approved_userlist($course1context, $component, [$user1->id]);
// Delete using delete_data_for_user.
provider::delete_data_for_users($approvedlist2);
// The user list for course1context should return user2.
$userlist3 = new \core_privacy\local\request\userlist($course1context, $component);
provider::get_users_in_context($userlist3);
$this->assertCount(1, $userlist3);
$this->assertTrue(in_array($user2->id, $userlist3->get_userids()));
// The user list for course3context should still return user2 and user3.
$userlist5 = new \core_privacy\local\request\userlist($course3context, $component);
provider::get_users_in_context($userlist5);
$this->assertCount(2, $userlist5);
// Convert $userlist6 into an approved_contextlist.
$approvedlist3 = new approved_userlist($categorycontext, $component, $userlist6->get_userids());
// Delete using delete_data_for_user.
provider::delete_data_for_users($approvedlist3);
// The user list for categorycontext should not return any users.
$userlist6 = new \core_privacy\local\request\userlist($categorycontext, $component);
provider::get_users_in_context($userlist6);
$this->assertCount(0, $userlist6);
// Convert $userlist7 into an approved_contextlist.
$approvedlist4 = new approved_userlist($modulecontext, $component, $userlist7->get_userids());
// Delete using delete_data_for_user.
provider::delete_data_for_users($approvedlist4);
// The user list for modulecontext should not return any users.
$userlist7 = new \core_privacy\local\request\userlist($modulecontext, $component);
provider::get_users_in_context($userlist7);
$this->assertCount(0, $userlist7);
}
// Start of helper functions.
/**
* Helper function to create a Standard Calendar Event.
*
* @param string $eventtype Calendar event type
* @param int $userid User Id
* @param int $time Timestamp value
* @param string $customname Custom name
* @param int $categoryid Course Category Id
* @param int $courseid Course Id
* @param int $groupid Group Id
* @return bool|calendar_event Standard Calendar Event created.
* @throws coding_exception
*/
protected function create_test_standard_calendar_event($eventtype, $userid, $time, $customname = '', $categoryid = 0, $courseid = 0, $groupid = 0) {
// Create a standard calendar event.
$name = "Standard Calendar Event $eventtype";
if ($customname != '') {
$name .= " -- $customname";
}
$event = (object)[
'name' => $name,
'categoryid' => $categoryid,
'courseid' => $courseid,
'groupid' => $groupid,
'userid' => $userid,
'modulename' => 0,
'instance' => 0,
'eventtype' => $eventtype,
'type' => CALENDAR_EVENT_TYPE_STANDARD,
'timestart' => $time,
'visible' => 1
];
return \calendar_event::create($event, false);
}
/**
* Helper function to create an Action Calendar Event.
*
* @param string $eventtype Calendar event type
* @param int $courseid Course Id
* @param int $instanceid Activity Module instance id
* @param string $modulename Activity Module name
* @param int $userid User Id
* @param int $time Timestamp value
* @return bool|calendar_event Action Calendar Event created.
* @throws coding_exception
*/
protected function create_test_action_calendar_event($eventtype, $courseid, $instanceid, $modulename, $userid, $time) {
// Create an action calendar event.
$event = (object)[
'name' => "Action Calendar Event $eventtype -- $modulename",
'categoryid' => 0,
'courseid' => $courseid,
'groupid' => 0,
'userid' => $userid,
'modulename' => $modulename,
'instance' => $instanceid,
'eventtype' => $eventtype,
'type' => CALENDAR_EVENT_TYPE_ACTION,
'timestart' => $time,
'visible' => 1
];
return \calendar_event::create($event, false);
}
/**
* Helper function to create a Calendar Subscription.
*
* @param string $eventtype Calendar Subscription event type
* @param string $url Calendar Subscription URL
* @param int $userid User Id
* @param int $categoryid Category Id
* @param int $courseid Course Id
* @param int $groupid Group Id
* @return int Calendar Subscription Id
*/
protected function create_test_calendar_subscription($eventtype, $url, $userid, $categoryid = 0, $courseid = 0, $groupid = 0) {
// Create a subscription calendar event.
$subscription = (object)[
'name' => "Calendar Subscription " . $eventtype,
'url' => $url,
'categoryid' => $categoryid,
'courseid' => $courseid,
'groupid' => $groupid,
'userid' => $userid,
'eventtype' => $eventtype
];
return calendar_add_subscription($subscription);
}
}
@@ -0,0 +1,454 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_calendar;
use core_calendar\local\event\strategies\raw_event_retrieval_strategy;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/calendar/tests/helpers.php');
/**
* Raw event retrieval strategy tests.
*
* @package core_calendar
* @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class raw_event_retrieval_strategy_test extends \advanced_testcase {
/**
* Test retrieval strategy when module is disabled.
*/
public function test_get_raw_events_with_disabled_module(): void {
global $DB;
$this->resetAfterTest();
$retrievalstrategy = new raw_event_retrieval_strategy();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$student = $generator->create_user();
$generator->enrol_user($student->id, $course->id, 'student');
$this->setUser($student);
$events = [
[
'name' => 'Start of assignment',
'description' => '',
'location' => 'Test',
'format' => 1,
'courseid' => $course->id,
'groupid' => 0,
'userid' => 2,
'modulename' => 'assign',
'instance' => 1,
'eventtype' => 'due',
'timestart' => time(),
'timeduration' => 86400,
'visible' => 1
], [
'name' => 'Start of lesson',
'description' => '',
'location' => 'Test',
'format' => 1,
'courseid' => $course->id,
'groupid' => 0,
'userid' => 2,
'modulename' => 'lesson',
'instance' => 1,
'eventtype' => 'end',
'timestart' => time(),
'timeduration' => 86400,
'visible' => 1
]
];
foreach ($events as $event) {
\calendar_event::create($event, false);
}
// Get all events.
$events = $retrievalstrategy->get_raw_events(null, [0], null);
$this->assertCount(2, $events);
// Disable the lesson module.
$DB->set_field('modules', 'visible', 0, ['name' => 'lesson']);
// Check that we only return the assign event.
$events = $retrievalstrategy->get_raw_events(null, [0], null);
$this->assertCount(1, $events);
$event = reset($events);
$this->assertEquals('assign', $event->modulename);
// Now, log out and repeat the above test in the reverse order.
$this->setUser();
// Check that we only return the assign event (given that the lesson module is still disabled).
$events = $retrievalstrategy->get_raw_events([$student->id], [0], null);
$this->assertCount(1, $events);
$event = reset($events);
$this->assertEquals('assign', $event->modulename);
// Enable the lesson module.
$DB->set_field('modules', 'visible', 1, ['name' => 'lesson']);
// Get all events.
$events = $retrievalstrategy->get_raw_events(null, [0], null);
$this->assertCount(2, $events);
}
/**
* Test retrieval strategy when there are overrides.
*/
public function test_get_raw_event_strategy_with_overrides(): void {
$this->resetAfterTest();
$retrievalstrategy = new raw_event_retrieval_strategy();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$instance = $plugingenerator->create_instance(['course' => $course->id]);
// Create users.
$useroverridestudent = $generator->create_user();
$group1student = $generator->create_user();
$group2student = $generator->create_user();
$group12student = $generator->create_user();
$nogroupstudent = $generator->create_user();
// Enrol users.
$generator->enrol_user($useroverridestudent->id, $course->id, 'student');
$generator->enrol_user($group1student->id, $course->id, 'student');
$generator->enrol_user($group2student->id, $course->id, 'student');
$generator->enrol_user($group12student->id, $course->id, 'student');
$generator->enrol_user($nogroupstudent->id, $course->id, 'student');
// Create groups.
$group1 = $generator->create_group(['courseid' => $course->id, 'name' => 'Group 1']);
$group2 = $generator->create_group(['courseid' => $course->id, 'name' => 'Group 2']);
// Add members to groups.
$generator->create_group_member(['groupid' => $group1->id, 'userid' => $group1student->id]);
$generator->create_group_member(['groupid' => $group2->id, 'userid' => $group2student->id]);
$generator->create_group_member(['groupid' => $group1->id, 'userid' => $group12student->id]);
$generator->create_group_member(['groupid' => $group2->id, 'userid' => $group12student->id]);
$now = time();
// Events with the same module name, instance and event type.
$events = [
[
'name' => 'Assignment 1 due date',
'description' => '',
'location' => 'Test',
'format' => 0,
'courseid' => $course->id,
'groupid' => 0,
'userid' => 2,
'modulename' => 'assign',
'instance' => $instance->id,
'eventtype' => 'due',
'timestart' => $now,
'timeduration' => 0,
'visible' => 1
], [
'name' => 'Assignment 1 due date - User override',
'description' => '',
'location' => 'Test',
'format' => 1,
'courseid' => 0,
'groupid' => 0,
'userid' => $useroverridestudent->id,
'modulename' => 'assign',
'instance' => $instance->id,
'eventtype' => 'due',
'timestart' => $now + 86400,
'timeduration' => 0,
'visible' => 1,
'priority' => CALENDAR_EVENT_USER_OVERRIDE_PRIORITY
], [
'name' => 'Assignment 1 due date - Group A override',
'description' => '',
'location' => 'Test',
'format' => 1,
'courseid' => $course->id,
'groupid' => $group1->id,
'userid' => 2,
'modulename' => 'assign',
'instance' => $instance->id,
'eventtype' => 'due',
'timestart' => $now + (2 * 86400),
'timeduration' => 0,
'visible' => 1,
'priority' => 1,
], [
'name' => 'Assignment 1 due date - Group B override',
'description' => '',
'location' => 'Test',
'format' => 1,
'courseid' => $course->id,
'groupid' => $group2->id,
'userid' => 2,
'modulename' => 'assign',
'instance' => $instance->id,
'eventtype' => 'due',
'timestart' => $now + (3 * 86400),
'timeduration' => 0,
'visible' => 1,
'priority' => 2,
],
];
foreach ($events as $event) {
\calendar_event::create($event, false);
}
$groups = [$group1->id, $group2->id];
// Do the following tests multiple times when logged in with different users. Also run the whole set when logged out.
// In any cases, the tests should not depend on the logged-in user.
foreach ([$useroverridestudent, $nogroupstudent, $group12student, $group1student, null] as $login) {
$this->setUser($login);
// Get user override events.
$events = $retrievalstrategy->get_raw_events([$useroverridestudent->id], $groups, [$course->id]);
$this->assertCount(1, $events);
$event = reset($events);
$this->assertEquals('Assignment 1 due date - User override', $event->name);
// Get events for user that does not belong to any group and has no user override events.
$events = $retrievalstrategy->get_raw_events([$nogroupstudent->id], $groups, [$course->id]);
$this->assertCount(1, $events);
$event = reset($events);
$this->assertEquals('Assignment 1 due date', $event->name);
// Get events for user that belongs to groups A and B and has no user override events.
$events = $retrievalstrategy->get_raw_events([$group12student->id], $groups, [$course->id]);
$this->assertCount(1, $events);
$event = reset($events);
$this->assertEquals('Assignment 1 due date - Group A override', $event->name);
// Get events for user that belongs to group A and has no user override events.
$events = $retrievalstrategy->get_raw_events([$group1student->id], $groups, [$course->id]);
$this->assertCount(1, $events);
$event = reset($events);
$this->assertEquals('Assignment 1 due date - Group A override', $event->name);
}
// Add repeating events.
$repeatingevents = [
[
'name' => 'Repeating site event',
'description' => '',
'location' => 'Test',
'format' => 1,
'courseid' => SITEID,
'groupid' => 0,
'userid' => 2,
'repeatid' => 1,
'modulename' => '0',
'instance' => 0,
'eventtype' => 'site',
'timestart' => $now + 86400,
'timeduration' => 0,
'visible' => 1,
],
[
'name' => 'Repeating site event',
'description' => '',
'location' => 'Test',
'format' => 1,
'courseid' => SITEID,
'groupid' => 0,
'userid' => 2,
'repeatid' => 1,
'modulename' => '0',
'instance' => 0,
'eventtype' => 'site',
'timestart' => $now + (2 * 86400),
'timeduration' => 0,
'visible' => 1,
],
];
foreach ($repeatingevents as $event) {
\calendar_event::create($event, false);
}
// Make sure repeating events are not filtered out.
$events = $retrievalstrategy->get_raw_events();
$this->assertCount(3, $events);
}
/**
* Test retrieval strategy with category specifications.
*/
public function test_get_raw_events_category(): void {
$this->resetAfterTest();
$retrievalstrategy = new raw_event_retrieval_strategy();
$generator = $this->getDataGenerator();
$category1 = $generator->create_category();
$category2 = $generator->create_category();
$events = [
[
'name' => 'E1',
'eventtype' => 'category',
'description' => '',
'location' => 'Test',
'format' => 1,
'categoryid' => $category1->id,
'userid' => 2,
'timestart' => time(),
],
[
'name' => 'E2',
'eventtype' => 'category',
'description' => '',
'location' => 'Test',
'format' => 1,
'categoryid' => $category2->id,
'userid' => 2,
'timestart' => time() + 1,
],
];
foreach ($events as $event) {
\calendar_event::create($event, false);
}
// Get all events.
$events = $retrievalstrategy->get_raw_events(null, null, null, null);
$this->assertCount(2, $events);
$event = array_shift($events);
$this->assertEquals('E1', $event->name);
$event = array_shift($events);
$this->assertEquals('E2', $event->name);
// Get events for C1 events.
$events = $retrievalstrategy->get_raw_events(null, null, null, [$category1->id]);
$this->assertCount(1, $events);
$event = array_shift($events);
$this->assertEquals('E1', $event->name);
// Get events for C2 events.
$events = $retrievalstrategy->get_raw_events(null, null, null, [$category2->id]);
$this->assertCount(1, $events);
$event = array_shift($events);
$this->assertEquals('E2', $event->name);
// Get events for several categories.
$events = $retrievalstrategy->get_raw_events(null, null, null, [$category1->id, $category2->id]);
$this->assertCount(2, $events);
}
public function test_get_raw_events_for_multiple_users(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
// Create users.
$user1 = $generator->create_user();
$user2 = $generator->create_user();
$user3 = $generator->create_user();
// Create user events.
$events = [
[
'name' => 'User1 Event',
'eventtype' => 'user',
'userid' => $user1->id,
'timestart' => time(),
], [
'name' => 'User2 Event',
'eventtype' => 'user',
'userid' => $user2->id,
'timestart' => time(),
], [
'name' => 'User3 Event',
'eventtype' => 'user',
'userid' => $user3->id,
'timestart' => time(),
]
];
foreach ($events as $event) {
\calendar_event::create($event, false);
}
$retrievalstrategy = new raw_event_retrieval_strategy();
// Get all events.
$events = $retrievalstrategy->get_raw_events([$user1->id, $user2->id]);
$this->assertCount(2, $events);
$this->assertEqualsCanonicalizing(
['User1 Event', 'User2 Event'],
array_column($events, 'name'));
}
public function test_get_raw_events_for_groups_with_no_members(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
// Create groups.
$group1 = $generator->create_group(['courseid' => $course->id, 'name' => 'Group 1']);
$group2 = $generator->create_group(['courseid' => $course->id, 'name' => 'Group 2']);
// Create group events.
$events = [
[
'name' => 'Group 1 Event',
'eventtype' => 'group',
'groupid' => $group1->id,
'timestart' => time(),
], [
'name' => 'Group 2 Event',
'eventtype' => 'group',
'groupid' => $group2->id,
'timestart' => time(),
]
];
foreach ($events as $event) {
\calendar_event::create($event, false);
}
$retrievalstrategy = new raw_event_retrieval_strategy;
// Get group eventsl.
$events = $retrievalstrategy->get_raw_events(null, [$group1->id, $group2->id]);
$this->assertCount(2, $events);
$this->assertEqualsCanonicalizing(
['Group 1 Event', 'Group 2 Event'],
array_column($events, 'name'));
}
/**
* Test retrieval strategy with empty filters.
* This covers a edge case not covered elsewhere to ensure its SQL is cross
* db compatible. The test is ensuring we don't get a DML Exception with
* the filters setup this way.
*/
public function test_get_raw_events_with_empty_user_and_category_lists(): void {
$retrievalstrategy = new raw_event_retrieval_strategy;
$retrievalstrategy->get_raw_events([], null, null, []);
}
}
@@ -0,0 +1,216 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Repeat event collection tests.
*
* @package core_calendar
* @copyright 2017 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_calendar;
use core_calendar\local\event\entities\event;
use core_calendar\local\event\entities\repeat_event_collection;
use core_calendar\local\event\proxies\coursecat_proxy;
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\event\factories\event_factory_interface;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/calendar/lib.php');
/**
* Repeat event collection tests.
*
* @package core_calendar
* @copyright 2017 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class repeat_event_collection_test extends \advanced_testcase {
/**
* Test that the collection id is set to the parent id if the repeat id
* is falsey.
*/
public function test_parent_id_no_repeat_id(): void {
$this->resetAfterTest(true);
$dbrow = (object) [
'id' => 123122131,
'repeatid' => null
];
$factory = new core_calendar_repeat_event_collection_event_test_factory();
$collection = new repeat_event_collection($dbrow, $factory);
$this->assertEquals($dbrow->id, $collection->get_id());
}
/**
* Test that the repeat id is set to the parent id if the repeat id
* is not falsey (even if the parent id is provided).
*/
public function test_parent_id_and_repeat_id(): void {
$this->resetAfterTest(true);
$dbrow = (object) [
'id' => 123122131,
'repeatid' => 5647839
];
$factory = new core_calendar_repeat_event_collection_event_test_factory();
$collection = new repeat_event_collection($dbrow, $factory);
$this->assertEquals($dbrow->repeatid, $collection->get_id());
}
/**
* Test that an empty collection is valid.
*/
public function test_empty_collection(): void {
$this->resetAfterTest(true);
$this->setAdminUser();
$event = $this->create_event([
// This causes the code to set the repeat id on this record
// but not create any repeat event records.
'repeat' => 1,
'repeats' => 0
]);
$dbrow = (object) [
'id' => $event->id,
'repeatid' => null
];
$factory = new core_calendar_repeat_event_collection_event_test_factory();
// Event collection with no repeats.
$collection = new repeat_event_collection($dbrow, $factory);
$this->assertEquals($event->id, $collection->get_id());
$this->assertEquals(0, $collection->get_num());
$this->assertNull($collection->getIterator()->next());
}
/**
* Test that a collection with values behaves correctly.
*/
public function test_values_collection(): void {
$this->resetAfterTest(true);
$this->setAdminUser();
$factory = new core_calendar_repeat_event_collection_event_test_factory();
$event = $this->create_event([
// This causes the code to set the repeat id on this record
// but not create any repeat event records.
'repeat' => 1,
'repeats' => 0
]);
$parentid = $event->id;
$dbrow = (object) [
'id' => $parentid,
'repeatid' => null
];
$repeats = [];
for ($i = 1; $i < 4; $i++) {
$record = $this->create_event([
'name' => sprintf('repeat %d', $i),
'repeatid' => $parentid
]);
// Index by name so that we don't have to rely on sorting
// when doing the comparison later.
$repeats[$record->name] = $record;
}
// Event collection with no repeats.
$collection = new repeat_event_collection($dbrow, $factory);
$this->assertEquals($parentid, $collection->get_id());
$this->assertEquals(count($repeats), $collection->get_num());
foreach ($collection as $index => $event) {
$name = $event->get_name();
$this->assertEquals($repeats[$name]->name, $name);
}
}
/**
* Helper function to create calendar events using the old code.
*
* @param array $properties A list of calendar event properties to set
* @return calendar_event
*/
protected function create_event($properties = []) {
$record = new \stdClass();
$record->name = 'event name';
$record->eventtype = 'site';
$record->repeat = 0;
$record->repeats = 0;
$record->timestart = time();
$record->timeduration = 0;
$record->timesort = 0;
$record->type = 1;
$record->courseid = 0;
$record->categoryid = 0;
foreach ($properties as $name => $value) {
$record->$name = $value;
}
$event = new \calendar_event($record);
return $event->create($record, false);
}
}
/**
* Test event factory.
*
* @copyright 2017 Ryan Wyllie <ryan@moodle.com>
* @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(\stdClass $dbrow) {
$identity = function($id) {
return $id;
};
return new event(
$dbrow->id,
$dbrow->name,
new event_description($dbrow->description, $dbrow->format),
new coursecat_proxy($dbrow->categoryid),
new std_proxy($dbrow->courseid, $identity),
new std_proxy($dbrow->groupid, $identity),
new std_proxy($dbrow->userid, $identity),
$dbrow->repeatid ? new repeat_event_collection($dbrow, $this) : null,
new std_proxy($dbrow->instance, $identity),
$dbrow->type,
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),
(new \DateTimeImmutable())->setTimestamp(usergetmidnight($dbrow->timesort))
),
!empty($dbrow->visible),
new std_proxy($dbrow->subscriptionid, $identity),
$dbrow->location,
$dbrow->component
);
}
}
File diff suppressed because it is too large Load Diff
+162
View File
@@ -0,0 +1,162 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_calendar;
use core_calendar\local\event\proxies\std_proxy;
/**
* std_proxy testcase.
*
* @package core_calendar
* @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class std_proxy_test extends \advanced_testcase {
/**
* @var \stdClass[] $objects Array of objects to proxy.
*/
public $objects;
public function setUp(): void {
$this->objects = [
1 => (object) [
'member1' => 'Hello',
'member2' => 1729,
'member3' => 'Something else'
],
5 => (object) [
'member1' => 'Hej',
'member2' => 87539319,
'member3' => 'nagot annat'
]
];
}
/**
* Test proxying.
*
* @dataProvider proxy_testcases
* @param int $id Object ID.
* @param string $member Object member to retrieve.
* @param mixed $expected Expected value of member.
*/
public function test_proxy($id, $member, $expected): void {
$proxy = new std_proxy($id, function($id) {
return $this->objects[$id];
});
$this->assertEquals($proxy->get($member), $expected);
}
/**
* Test setting values with a base class.
*
* @dataProvider proxy_testcases
* @param int $id Object ID.
* @param string $member Object member to retrieve.
* @param mixed $storedvalue Value as would be stored externally.
*/
public function test_base_values($id, $member, $storedvalue): void {
$proxy = new std_proxy(
$id,
function($id) {
return $this->objects[$id];
},
(object)['member1' => 'should clobber 1']
);
$expected = $member == 'member1' ? 'should clobber 1' : $storedvalue;
$this->assertEquals($proxy->get($member), $expected);
}
/**
* Test getting a non existant member.
*
* @dataProvider get_set_testcases
* @param int $id ID of the object being proxied.
*/
public function test_get_invalid_member($id): void {
$proxy = new std_proxy($id, function($id) {
return $this->objects[$id];
});
$this->expectException('\core_calendar\local\event\exceptions\member_does_not_exist_exception');
$proxy->get('thisdoesnotexist');
}
/**
* Test get proxied instance.
*
* @dataProvider get_set_testcases
* @param int $id Object ID.
*/
public function test_get_proxied_instance($id): void {
$proxy = new std_proxy($id, function($id) {
return $this->objects[$id];
});
$this->assertEquals($proxy->get_proxied_instance(), $this->objects[$id]);
}
/**
* Test cases for proxying test.
*/
public function proxy_testcases() {
return [
'Object 1 member 1' => [
1,
'member1',
'Hello'
],
'Object 1 member 2' => [
1,
'member2',
1729
],
'Object 1 member 3' => [
1,
'member3',
'Something else'
],
'Object 2 member 1' => [
5,
'member1',
'Hej'
],
'Object 2 member 2' => [
5,
'member2',
87539319
],
'Object 3 member 3' => [
5,
'member3',
'nagot annat'
]
];
}
/**
* Test cases for getting and setting tests.
*/
public function get_set_testcases() {
return [
'Object 1' => [1],
'Object 2' => [5]
];
}
}