mirror of
https://github.com/moodle/moodle.git
synced 2025-08-09 02:46:40 +02:00
784 lines
32 KiB
PHP
784 lines
32 KiB
PHP
<?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/>.
|
|
|
|
/**
|
|
* Contains the class for the calendar events.
|
|
*
|
|
* @package core_calendar
|
|
* @copyright 2016 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();
|
|
|
|
require_once($CFG->dirroot . '/calendar/lib.php');
|
|
|
|
/**
|
|
* The class for the calendar events.
|
|
*
|
|
* @package core_calendar
|
|
* @copyright 2016 Mark Nelson <markn@moodle.com>
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
*/
|
|
class event {
|
|
|
|
/** @var array An object containing the event properties can be accessed via the magic __get/set methods */
|
|
protected $properties = null;
|
|
|
|
/** @var string The converted event discription with file paths resolved.
|
|
* This gets populated when someone requests description for the first time */
|
|
protected $_description = null;
|
|
|
|
/** @var array The options to use with this description editor */
|
|
protected $editoroptions = array(
|
|
'subdirs' => false,
|
|
'forcehttps' => false,
|
|
'maxfiles' => -1,
|
|
'maxbytes' => null,
|
|
'trusttext' => false);
|
|
|
|
/** @var object The context to use with the description editor */
|
|
protected $editorcontext = null;
|
|
|
|
/**
|
|
* Instantiates a new event and optionally populates its properties with the data provided.
|
|
*
|
|
* @param \stdClass $data Optional. An object containing the properties to for
|
|
* an event
|
|
*/
|
|
public function __construct($data = null) {
|
|
global $CFG, $USER;
|
|
|
|
// First convert to object if it is not already (should either be object or assoc array).
|
|
if (!is_object($data)) {
|
|
$data = (object) $data;
|
|
}
|
|
|
|
$this->editoroptions['maxbytes'] = $CFG->maxbytes;
|
|
|
|
$data->eventrepeats = 0;
|
|
|
|
if (empty($data->id)) {
|
|
$data->id = null;
|
|
}
|
|
|
|
if (!empty($data->subscriptionid)) {
|
|
$data->subscription = api::get_subscription($data->subscriptionid);
|
|
}
|
|
|
|
// Default to a user event.
|
|
if (empty($data->eventtype)) {
|
|
$data->eventtype = 'user';
|
|
}
|
|
|
|
// Default to the current user.
|
|
if (empty($data->userid)) {
|
|
$data->userid = $USER->id;
|
|
}
|
|
|
|
if (!empty($data->timeduration) && is_array($data->timeduration)) {
|
|
$data->timeduration = make_timestamp(
|
|
$data->timeduration['year'], $data->timeduration['month'], $data->timeduration['day'],
|
|
$data->timeduration['hour'], $data->timeduration['minute']) - $data->timestart;
|
|
}
|
|
|
|
if (!empty($data->description) && is_array($data->description)) {
|
|
$data->format = $data->description['format'];
|
|
$data->description = $data->description['text'];
|
|
} else if (empty($data->description)) {
|
|
$data->description = '';
|
|
$data->format = editors_get_preferred_format();
|
|
}
|
|
|
|
// Ensure form is defaulted correctly.
|
|
if (empty($data->format)) {
|
|
$data->format = editors_get_preferred_format();
|
|
}
|
|
|
|
$this->properties = $data;
|
|
|
|
if (empty($data->context)) {
|
|
$this->properties->context = $this->calculate_context();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Magic set method.
|
|
*
|
|
* Attempts to call a set_$key method if one exists otherwise falls back
|
|
* to simply set the property.
|
|
*
|
|
* @param string $key property name
|
|
* @param mixed $value value of the property
|
|
*/
|
|
public function __set($key, $value) {
|
|
if (method_exists($this, 'set_'.$key)) {
|
|
$this->{'set_'.$key}($value);
|
|
}
|
|
$this->properties->{$key} = $value;
|
|
}
|
|
|
|
/**
|
|
* Magic get method.
|
|
*
|
|
* Attempts to call a get_$key method to return the property and ralls over
|
|
* to return the raw property.
|
|
*
|
|
* @param string $key property name
|
|
* @return mixed property value
|
|
* @throws \coding_exception
|
|
*/
|
|
public function __get($key) {
|
|
if (method_exists($this, 'get_'.$key)) {
|
|
return $this->{'get_'.$key}();
|
|
}
|
|
if (!isset($this->properties->{$key})) {
|
|
throw new \coding_exception('Undefined property requested');
|
|
}
|
|
return $this->properties->{$key};
|
|
}
|
|
|
|
/**
|
|
* Magic isset method.
|
|
*
|
|
* PHP needs an isset magic method if you use the get magic method and
|
|
* still want empty calls to work.
|
|
*
|
|
* @param string $key $key property name
|
|
* @return bool|mixed property value, false if property is not exist
|
|
*/
|
|
public function __isset($key) {
|
|
return !empty($this->properties->{$key});
|
|
}
|
|
|
|
/**
|
|
* Calculate the context value needed for an event.
|
|
*
|
|
* Event's type can be determine by the available value store in $data
|
|
* It is important to check for the existence of course/courseid to determine
|
|
* the course event.
|
|
* Default value is set to CONTEXT_USER
|
|
*
|
|
* @return \stdClass The context object.
|
|
*/
|
|
protected function calculate_context() {
|
|
global $USER, $DB;
|
|
|
|
$context = null;
|
|
if (isset($this->properties->courseid) && $this->properties->courseid > 0) {
|
|
$context = \context_course::instance($this->properties->courseid);
|
|
} else if (isset($this->properties->course) && $this->properties->course > 0) {
|
|
$context = \context_course::instance($this->properties->course);
|
|
} else if (isset($this->properties->groupid) && $this->properties->groupid > 0) {
|
|
$group = $DB->get_record('groups', array('id' => $this->properties->groupid));
|
|
$context = \context_course::instance($group->courseid);
|
|
} else if (isset($this->properties->userid) && $this->properties->userid > 0
|
|
&& $this->properties->userid == $USER->id) {
|
|
$context = \context_user::instance($this->properties->userid);
|
|
} else if (isset($this->properties->userid) && $this->properties->userid > 0
|
|
&& $this->properties->userid != $USER->id &&
|
|
isset($this->properties->instance) && $this->properties->instance > 0) {
|
|
$cm = get_coursemodule_from_instance($this->properties->modulename, $this->properties->instance, 0,
|
|
false, MUST_EXIST);
|
|
$context = \context_course::instance($cm->course);
|
|
} else {
|
|
$context = \context_user::instance($this->properties->userid);
|
|
}
|
|
|
|
return $context;
|
|
}
|
|
|
|
/**
|
|
* Returns an array of editoroptions for this event.
|
|
*
|
|
* @return array event editor options
|
|
*/
|
|
protected function get_editoroptions() {
|
|
return $this->editoroptions;
|
|
}
|
|
|
|
/**
|
|
* Returns an event description: Called by __get
|
|
* Please use $blah = $event->description;
|
|
*
|
|
* @return string event description
|
|
*/
|
|
protected function get_description() {
|
|
global $CFG;
|
|
|
|
require_once($CFG->libdir . '/filelib.php');
|
|
|
|
if ($this->_description === null) {
|
|
// Check if we have already resolved the context for this event.
|
|
if ($this->editorcontext === null) {
|
|
// Switch on the event type to decide upon the appropriate context to use for this event.
|
|
$this->editorcontext = $this->properties->context;
|
|
if ($this->properties->eventtype != 'user' && $this->properties->eventtype != 'course'
|
|
&& $this->properties->eventtype != 'site' && $this->properties->eventtype != 'group') {
|
|
return clean_text($this->properties->description, $this->properties->format);
|
|
}
|
|
}
|
|
|
|
// Work out the item id for the editor, if this is a repeated event
|
|
// then the files will be associated with the original.
|
|
if (!empty($this->properties->repeatid) && $this->properties->repeatid > 0) {
|
|
$itemid = $this->properties->repeatid;
|
|
} else {
|
|
$itemid = $this->properties->id;
|
|
}
|
|
|
|
// Convert file paths in the description so that things display correctly.
|
|
$this->_description = file_rewrite_pluginfile_urls($this->properties->description, 'pluginfile.php',
|
|
$this->editorcontext->id, 'calendar', 'event_description', $itemid);
|
|
// Clean the text so no nasties get through.
|
|
$this->_description = clean_text($this->_description, $this->properties->format);
|
|
}
|
|
|
|
// Finally return the description.
|
|
return $this->_description;
|
|
}
|
|
|
|
/**
|
|
* Return the number of repeat events there are in this events series.
|
|
*
|
|
* @return int number of event repeated
|
|
*/
|
|
public function count_repeats() {
|
|
global $DB;
|
|
if (!empty($this->properties->repeatid)) {
|
|
$this->properties->eventrepeats = $DB->count_records('event',
|
|
array('repeatid' => $this->properties->repeatid));
|
|
// We don't want to count ourselves.
|
|
$this->properties->eventrepeats--;
|
|
}
|
|
return $this->properties->eventrepeats;
|
|
}
|
|
|
|
/**
|
|
* Update or create an event within the database
|
|
*
|
|
* Pass in a object containing the event properties and this function will
|
|
* insert it into the database and deal with any associated files
|
|
*
|
|
* @see self::create()
|
|
* @see self::update()
|
|
*
|
|
* @param \stdClass $data object of event
|
|
* @param bool $checkcapability if moodle should check calendar managing capability or not
|
|
* @return bool event updated
|
|
*/
|
|
public function update($data, $checkcapability=true) {
|
|
global $DB, $USER;
|
|
|
|
foreach ($data as $key => $value) {
|
|
$this->properties->$key = $value;
|
|
}
|
|
|
|
$this->properties->timemodified = time();
|
|
$usingeditor = (!empty($this->properties->description) && is_array($this->properties->description));
|
|
|
|
// Prepare event data.
|
|
$eventargs = array(
|
|
'context' => $this->properties->context,
|
|
'objectid' => $this->properties->id,
|
|
'other' => array(
|
|
'repeatid' => empty($this->properties->repeatid) ? 0 : $this->properties->repeatid,
|
|
'timestart' => $this->properties->timestart,
|
|
'name' => $this->properties->name
|
|
)
|
|
);
|
|
|
|
if (empty($this->properties->id) || $this->properties->id < 1) {
|
|
|
|
if ($checkcapability) {
|
|
if (!\core_calendar\api::can_add_event($this->properties)) {
|
|
print_error('nopermissiontoupdatecalendar');
|
|
}
|
|
}
|
|
|
|
if ($usingeditor) {
|
|
switch ($this->properties->eventtype) {
|
|
case 'user':
|
|
$this->properties->courseid = 0;
|
|
$this->properties->course = 0;
|
|
$this->properties->groupid = 0;
|
|
$this->properties->userid = $USER->id;
|
|
break;
|
|
case 'site':
|
|
$this->properties->courseid = SITEID;
|
|
$this->properties->course = SITEID;
|
|
$this->properties->groupid = 0;
|
|
$this->properties->userid = $USER->id;
|
|
break;
|
|
case 'course':
|
|
$this->properties->groupid = 0;
|
|
$this->properties->userid = $USER->id;
|
|
break;
|
|
case 'group':
|
|
$this->properties->userid = $USER->id;
|
|
break;
|
|
default:
|
|
// We should NEVER get here, but just incase we do lets fail gracefully.
|
|
$usingeditor = false;
|
|
break;
|
|
}
|
|
|
|
// If we are actually using the editor, we recalculate the context because some default values
|
|
// were set when calculate_context() was called from the constructor.
|
|
if ($usingeditor) {
|
|
$this->properties->context = $this->calculate_context();
|
|
$this->editorcontext = $this->properties->context;
|
|
}
|
|
|
|
$editor = $this->properties->description;
|
|
$this->properties->format = $this->properties->description['format'];
|
|
$this->properties->description = $this->properties->description['text'];
|
|
}
|
|
|
|
// Insert the event into the database.
|
|
$this->properties->id = $DB->insert_record('event', $this->properties);
|
|
|
|
if ($usingeditor) {
|
|
$this->properties->description = file_save_draft_area_files(
|
|
$editor['itemid'],
|
|
$this->editorcontext->id,
|
|
'calendar',
|
|
'event_description',
|
|
$this->properties->id,
|
|
$this->editoroptions,
|
|
$editor['text'],
|
|
$this->editoroptions['forcehttps']);
|
|
$DB->set_field('event', 'description', $this->properties->description,
|
|
array('id' => $this->properties->id));
|
|
}
|
|
|
|
// Log the event entry.
|
|
$eventargs['objectid'] = $this->properties->id;
|
|
$eventargs['context'] = $this->properties->context;
|
|
$event = \core\event\calendar_event_created::create($eventargs);
|
|
$event->trigger();
|
|
|
|
$repeatedids = array();
|
|
|
|
if (!empty($this->properties->repeat)) {
|
|
$this->properties->repeatid = $this->properties->id;
|
|
$DB->set_field('event', 'repeatid', $this->properties->repeatid, array('id' => $this->properties->id));
|
|
|
|
$eventcopy = clone($this->properties);
|
|
unset($eventcopy->id);
|
|
|
|
$timestart = new \DateTime('@' . $eventcopy->timestart);
|
|
$timestart->setTimezone(\core_date::get_user_timezone_object());
|
|
|
|
for ($i = 1; $i < $eventcopy->repeats; $i++) {
|
|
|
|
$timestart->add(new \DateInterval('P7D'));
|
|
$eventcopy->timestart = $timestart->getTimestamp();
|
|
|
|
// Get the event id for the log record.
|
|
$eventcopyid = $DB->insert_record('event', $eventcopy);
|
|
|
|
// If the context has been set delete all associated files.
|
|
if ($usingeditor) {
|
|
$fs = get_file_storage();
|
|
$files = $fs->get_area_files($this->editorcontext->id, 'calendar', 'event_description',
|
|
$this->properties->id);
|
|
foreach ($files as $file) {
|
|
$fs->create_file_from_storedfile(array('itemid' => $eventcopyid), $file);
|
|
}
|
|
}
|
|
|
|
$repeatedids[] = $eventcopyid;
|
|
|
|
// Trigger an event.
|
|
$eventargs['objectid'] = $eventcopyid;
|
|
$eventargs['other']['timestart'] = $eventcopy->timestart;
|
|
$event = \core\event\calendar_event_created::create($eventargs);
|
|
$event->trigger();
|
|
}
|
|
}
|
|
|
|
return true;
|
|
} else {
|
|
|
|
if ($checkcapability) {
|
|
if (!api::can_edit_event($this->properties)) {
|
|
print_error('nopermissiontoupdatecalendar');
|
|
}
|
|
}
|
|
|
|
if ($usingeditor) {
|
|
if ($this->editorcontext !== null) {
|
|
$this->properties->description = file_save_draft_area_files(
|
|
$this->properties->description['itemid'],
|
|
$this->editorcontext->id,
|
|
'calendar',
|
|
'event_description',
|
|
$this->properties->id,
|
|
$this->editoroptions,
|
|
$this->properties->description['text'],
|
|
$this->editoroptions['forcehttps']);
|
|
} else {
|
|
$this->properties->format = $this->properties->description['format'];
|
|
$this->properties->description = $this->properties->description['text'];
|
|
}
|
|
}
|
|
|
|
$event = $DB->get_record('event', array('id' => $this->properties->id));
|
|
|
|
$updaterepeated = (!empty($this->properties->repeatid) && !empty($this->properties->repeateditall));
|
|
|
|
if ($updaterepeated) {
|
|
// Update all.
|
|
if ($this->properties->timestart != $event->timestart) {
|
|
$timestartoffset = $this->properties->timestart - $event->timestart;
|
|
$sql = "UPDATE {event}
|
|
SET name = ?,
|
|
description = ?,
|
|
timestart = timestart + ?,
|
|
timeduration = ?,
|
|
timemodified = ?
|
|
WHERE repeatid = ?";
|
|
$params = array($this->properties->name, $this->properties->description, $timestartoffset,
|
|
$this->properties->timeduration, time(), $event->repeatid);
|
|
} else {
|
|
$sql = "UPDATE {event} SET name = ?, description = ?, timeduration = ?, timemodified = ? WHERE repeatid = ?";
|
|
$params = array($this->properties->name, $this->properties->description,
|
|
$this->properties->timeduration, time(), $event->repeatid);
|
|
}
|
|
$DB->execute($sql, $params);
|
|
|
|
// Trigger an update event for each of the calendar event.
|
|
$events = $DB->get_records('event', array('repeatid' => $event->repeatid), '', '*');
|
|
foreach ($events as $calendarevent) {
|
|
$eventargs['objectid'] = $calendarevent->id;
|
|
$eventargs['other']['timestart'] = $calendarevent->timestart;
|
|
$event = \core\event\calendar_event_updated::create($eventargs);
|
|
$event->add_record_snapshot('event', $calendarevent);
|
|
$event->trigger();
|
|
}
|
|
} else {
|
|
$DB->update_record('event', $this->properties);
|
|
$event = self::load($this->properties->id);
|
|
$this->properties = $event->properties();
|
|
|
|
// Trigger an update event.
|
|
$event = \core\event\calendar_event_updated::create($eventargs);
|
|
$event->add_record_snapshot('event', $this->properties);
|
|
$event->trigger();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Deletes an event and if selected an repeated events in the same series
|
|
*
|
|
* This function deletes an event, any associated events if $deleterepeated=true,
|
|
* and cleans up any files associated with the events.
|
|
*
|
|
* @see self::delete()
|
|
*
|
|
* @param bool $deleterepeated delete event repeatedly
|
|
* @return bool succession of deleting event
|
|
*/
|
|
public function delete($deleterepeated = false) {
|
|
global $DB;
|
|
|
|
// If $this->properties->id is not set then something is wrong.
|
|
if (empty($this->properties->id)) {
|
|
debugging('Attempting to delete an event before it has been loaded', DEBUG_DEVELOPER);
|
|
return false;
|
|
}
|
|
$calevent = $DB->get_record('event', array('id' => $this->properties->id), '*', MUST_EXIST);
|
|
// Delete the event.
|
|
$DB->delete_records('event', array('id' => $this->properties->id));
|
|
|
|
// Trigger an event for the delete action.
|
|
$eventargs = array(
|
|
'context' => $this->properties->context,
|
|
'objectid' => $this->properties->id,
|
|
'other' => array(
|
|
'repeatid' => empty($this->properties->repeatid) ? 0 : $this->properties->repeatid,
|
|
'timestart' => $this->properties->timestart,
|
|
'name' => $this->properties->name
|
|
));
|
|
$event = \core\event\calendar_event_deleted::create($eventargs);
|
|
$event->add_record_snapshot('event', $calevent);
|
|
$event->trigger();
|
|
|
|
// If we are deleting parent of a repeated event series, promote the next event in the series as parent.
|
|
if (($this->properties->id == $this->properties->repeatid) && !$deleterepeated) {
|
|
$newparent = $DB->get_field_sql("SELECT id from {event} where repeatid = ? order by id ASC",
|
|
array($this->properties->id), IGNORE_MULTIPLE);
|
|
if (!empty($newparent)) {
|
|
$DB->execute("UPDATE {event} SET repeatid = ? WHERE repeatid = ?",
|
|
array($newparent, $this->properties->id));
|
|
// Get all records where the repeatid is the same as the event being removed.
|
|
$events = $DB->get_records('event', array('repeatid' => $newparent));
|
|
// For each of the returned events trigger an update event.
|
|
foreach ($events as $calendarevent) {
|
|
// Trigger an event for the update.
|
|
$eventargs['objectid'] = $calendarevent->id;
|
|
$eventargs['other']['timestart'] = $calendarevent->timestart;
|
|
$event = \core\event\calendar_event_updated::create($eventargs);
|
|
$event->add_record_snapshot('event', $calendarevent);
|
|
$event->trigger();
|
|
}
|
|
}
|
|
}
|
|
|
|
// If the editor context hasn't already been set then set it now.
|
|
if ($this->editorcontext === null) {
|
|
$this->editorcontext = $this->properties->context;
|
|
}
|
|
|
|
// If the context has been set delete all associated files.
|
|
if ($this->editorcontext !== null) {
|
|
$fs = get_file_storage();
|
|
$files = $fs->get_area_files($this->editorcontext->id, 'calendar', 'event_description', $this->properties->id);
|
|
foreach ($files as $file) {
|
|
$file->delete();
|
|
}
|
|
}
|
|
|
|
// If we need to delete repeated events then we will fetch them all and delete one by one.
|
|
if ($deleterepeated && !empty($this->properties->repeatid) && $this->properties->repeatid > 0) {
|
|
// Get all records where the repeatid is the same as the event being removed.
|
|
$events = $DB->get_records('event', array('repeatid' => $this->properties->repeatid));
|
|
// For each of the returned events populate an event object and call delete.
|
|
// make sure the arg passed is false as we are already deleting all repeats.
|
|
foreach ($events as $event) {
|
|
$event = new event($event);
|
|
$event->delete(false);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Fetch all event properties.
|
|
*
|
|
* This function returns all of the events properties as an object and optionally
|
|
* can prepare an editor for the description field at the same time. This is
|
|
* designed to work when the properties are going to be used to set the default
|
|
* values of a moodle forms form.
|
|
*
|
|
* @param bool $prepareeditor If set to true a editor is prepared for use with
|
|
* the mforms editor element. (for description)
|
|
* @return \stdClass Object containing event properties
|
|
*/
|
|
public function properties($prepareeditor = false) {
|
|
global $DB;
|
|
|
|
// First take a copy of the properties. We don't want to actually change the
|
|
// properties or we'd forever be converting back and forwards between an
|
|
// editor formatted description and not.
|
|
$properties = clone($this->properties);
|
|
// Clean the description here.
|
|
$properties->description = clean_text($properties->description, $properties->format);
|
|
|
|
// If set to true we need to prepare the properties for use with an editor
|
|
// and prepare the file area.
|
|
if ($prepareeditor) {
|
|
|
|
// We may or may not have a property id. If we do then we need to work
|
|
// out the context so we can copy the existing files to the draft area.
|
|
if (!empty($properties->id)) {
|
|
|
|
if ($properties->eventtype === 'site') {
|
|
// Site context.
|
|
$this->editorcontext = $this->properties->context;
|
|
} else if ($properties->eventtype === 'user') {
|
|
// User context.
|
|
$this->editorcontext = $this->properties->context;
|
|
} else if ($properties->eventtype === 'group' || $properties->eventtype === 'course') {
|
|
// First check the course is valid.
|
|
$course = $DB->get_record('course', array('id' => $properties->courseid));
|
|
if (!$course) {
|
|
print_error('invalidcourse');
|
|
}
|
|
// Course context.
|
|
$this->editorcontext = $this->properties->context;
|
|
// We have a course and are within the course context so we had
|
|
// better use the courses max bytes value.
|
|
$this->editoroptions['maxbytes'] = $course->maxbytes;
|
|
} else {
|
|
// If we get here we have a custom event type as used by some
|
|
// modules. In this case the event will have been added by
|
|
// code and we won't need the editor.
|
|
$this->editoroptions['maxbytes'] = 0;
|
|
$this->editoroptions['maxfiles'] = 0;
|
|
}
|
|
|
|
if (empty($this->editorcontext) || empty($this->editorcontext->id)) {
|
|
$contextid = false;
|
|
} else {
|
|
// Get the context id that is what we really want.
|
|
$contextid = $this->editorcontext->id;
|
|
}
|
|
} else {
|
|
|
|
// If we get here then this is a new event in which case we don't need a
|
|
// context as there is no existing files to copy to the draft area.
|
|
$contextid = null;
|
|
}
|
|
|
|
// If the contextid === false we don't support files so no preparing
|
|
// a draft area.
|
|
if ($contextid !== false) {
|
|
// Just encase it has already been submitted.
|
|
$draftiddescription = file_get_submitted_draft_itemid('description');
|
|
// Prepare the draft area, this copies existing files to the draft area as well.
|
|
$properties->description = file_prepare_draft_area($draftiddescription, $contextid, 'calendar',
|
|
'event_description', $properties->id, $this->editoroptions, $properties->description);
|
|
} else {
|
|
$draftiddescription = 0;
|
|
}
|
|
|
|
// Structure the description field as the editor requires.
|
|
$properties->description = array('text' => $properties->description, 'format' => $properties->format,
|
|
'itemid' => $draftiddescription);
|
|
}
|
|
|
|
// Finally return the properties.
|
|
return $properties;
|
|
}
|
|
|
|
/**
|
|
* Toggles the visibility of an event
|
|
*
|
|
* @param null|bool $force If it is left null the events visibility is flipped,
|
|
* If it is false the event is made hidden, if it is true it
|
|
* is made visible.
|
|
* @return bool if event is successfully updated, toggle will be visible
|
|
*/
|
|
public function toggle_visibility($force = null) {
|
|
global $DB;
|
|
|
|
// Set visible to the default if it is not already set.
|
|
if (empty($this->properties->visible)) {
|
|
$this->properties->visible = 1;
|
|
}
|
|
|
|
if ($force === true || ($force !== false && $this->properties->visible == 0)) {
|
|
// Make this event visible.
|
|
$this->properties->visible = 1;
|
|
} else {
|
|
// Make this event hidden.
|
|
$this->properties->visible = 0;
|
|
}
|
|
|
|
// Update the database to reflect this change.
|
|
$success = $DB->set_field('event', 'visible', $this->properties->visible, array('id' => $this->properties->id));
|
|
$calendarevent = $DB->get_record('event', array('id' => $this->properties->id), '*', MUST_EXIST);
|
|
|
|
// Prepare event data.
|
|
$eventargs = array(
|
|
'context' => $this->properties->context,
|
|
'objectid' => $this->properties->id,
|
|
'other' => array(
|
|
'repeatid' => empty($this->properties->repeatid) ? 0 : $this->properties->repeatid,
|
|
'timestart' => $this->properties->timestart,
|
|
'name' => $this->properties->name
|
|
)
|
|
);
|
|
$event = \core\event\calendar_event_updated::create($eventargs);
|
|
$event->add_record_snapshot('event', $calendarevent);
|
|
$event->trigger();
|
|
|
|
return $success;
|
|
}
|
|
|
|
/**
|
|
* Returns an event object when provided with an event id.
|
|
*
|
|
* This function makes use of MUST_EXIST, if the event id passed in is invalid
|
|
* it will result in an exception being thrown.
|
|
*
|
|
* @param int|object $param event object or event id
|
|
* @return event
|
|
*/
|
|
public static function load($param) {
|
|
global $DB;
|
|
if (is_object($param)) {
|
|
$event = new event($param);
|
|
} else {
|
|
$event = $DB->get_record('event', array('id' => (int)$param), '*', MUST_EXIST);
|
|
$event = new event($event);
|
|
}
|
|
return $event;
|
|
}
|
|
|
|
/**
|
|
* Creates a new event and returns an event object
|
|
*
|
|
* @param \stdClass|array $properties An object containing event properties
|
|
* @param bool $checkcapability Check caps or not
|
|
* @throws \coding_exception
|
|
*
|
|
* @return event|bool The event object or false if it failed
|
|
*/
|
|
public static function create($properties, $checkcapability = true) {
|
|
if (is_array($properties)) {
|
|
$properties = (object)$properties;
|
|
}
|
|
if (!is_object($properties)) {
|
|
throw new \coding_exception('When creating an event properties should be either an object or an assoc array');
|
|
}
|
|
$event = new event($properties);
|
|
if ($event->update($properties, $checkcapability)) {
|
|
return $event;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Format the text using the external API.
|
|
*
|
|
* This function should we used when text formatting is required in external functions.
|
|
*
|
|
* @return array an array containing the text formatted and the text format
|
|
*/
|
|
public function format_external_text() {
|
|
|
|
if ($this->editorcontext === null) {
|
|
// Switch on the event type to decide upon the appropriate context to use for this event.
|
|
$this->editorcontext = $this->properties->context;
|
|
|
|
if ($this->properties->eventtype != 'user' && $this->properties->eventtype != 'course'
|
|
&& $this->properties->eventtype != 'site' && $this->properties->eventtype != 'group') {
|
|
// We don't have a context here, do a normal format_text.
|
|
return external_format_text($this->properties->description, $this->properties->format, $this->editorcontext->id);
|
|
}
|
|
}
|
|
|
|
// Work out the item id for the editor, if this is a repeated event then the files will be associated with the original.
|
|
if (!empty($this->properties->repeatid) && $this->properties->repeatid > 0) {
|
|
$itemid = $this->properties->repeatid;
|
|
} else {
|
|
$itemid = $this->properties->id;
|
|
}
|
|
|
|
return external_format_text($this->properties->description, $this->properties->format, $this->editorcontext->id,
|
|
'calendar', 'event_description', $itemid);
|
|
}
|
|
}
|