/** * 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 (!calendar_add_event_allowed($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: // Ewww 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->properties); $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(); } } // Hook for tracking added events self::calendar_event_hook('add_event', array($this->properties, $repeatedids)); return true; } else { if ($checkcapability) { if (!calendar_edit_event_allowed($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}\n SET name = ?,\n description = ?,\n timestart = timestart + ?,\n timeduration = ?,\n timemodified = ?\n 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), '', 'id,timestart'); foreach ($events as $event) { $eventargs['objectid'] = $event->id; $eventargs['other']['timestart'] = $event->timestart; $event = \core\event\calendar_event_updated::create($eventargs); $event->trigger(); } } else { $DB->update_record('event', $this->properties); $event = calendar_event::load($this->properties->id); $this->properties = $event->properties(); // Trigger an update event. $event = \core\event\calendar_event_updated::create($eventargs); $event->trigger(); } // Hook for tracking event updates self::calendar_event_hook('update_event', array($this->properties, $updaterepeated)); return true; } }
/** * Tests for event validations related to calendar_event_created event. */ public function test_calendar_event_created_validations() { $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\n other['repeatid']"); } catch (coding_exception $e) { $this->assertContains('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\n other['name']"); } catch (coding_exception $e) { $this->assertContains('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\n other['timestart']"); } catch (coding_exception $e) { $this->assertContains('The \'timestart\' value must be set in other.', $e->getMessage()); } }