/** * Overwrite save to set the uri if it's not already set and recalculate the minutes. */ public function save() { // Prevent http://jira.opensource.mayflower.de/jira/browse/PHPROJEKT-450 if (is_null($this->notes)) { $this->notes = ''; } if (empty($this->endTime)) { $this->minutes = null; } else { $start = new Datetime($this->startDatetime); $end = new Datetime(substr($this->startDatetime, 0, 11) . $this->endTime); $this->minutes = floor(($end->getTimestamp() - $start->getTimestamp()) / 60); } if (empty($this->uid)) { $this->uid = Phprojekt::generateUniqueIdentifier(); } if (empty($this->uri)) { $this->uri = $this->uid; } if (!$this->projectId) { $this->projectId = 1; } return parent::save(); }
/** * Overwrite save function. Writes the data in this object into the * database. * * @return int The id of the saved object */ public function save() { if (!$this->recordValidate()) { $errors = $this->getError(); $error = array_pop($errors); throw new Zend_Controller_Action_Exception($error['label'] . ': ' . $error['message'], 400); } if ($this->_isFirst) { $endOfLast = $this->getRruleHelper()->getUpperTimeBoundary(); if ($endOfLast) { $this->lastEnd = $endOfLast->format('Y-m-d H:i:s'); } else { // I hate to do this, but item casts null to '1970-01-01 00;00:00'. $this->_data['lastEnd'] = null; } if (!self::isValidVisibility($this->visibility)) { throw new Zend_Controller_Action_Exception("Invalid visibility {$this->visibility}", 400); } $this->_fetchParticipantData(); // We need to check this before we call parent::save() as it will be // set after. $isNew = empty($this->_storedId); $now = new Datetime('now', new DateTimeZone('UTC')); $this->lastModified = $now->format('Y-m-d H:i:s'); if (!$this->uri) { $this->uri = $this->uid; } $start = new Datetime('@' . Phprojekt_Converter_Time::userToUtc($this->start)); // This is here to fix a special case where P6 interprets things different from iCalendar. Assume a event // starts on tuesdays, has bi-weekly recurrence and BYDAY monday and wednesday. P6 will have the tuesday, // the wednesday after that and monday on the next week, wednesday the week after that, etc. Caldav will // have one week pause and then monday and wednesday in the same week. // TODO: Remove this after we changed to a predicate-based generation of events. if (strpos($this->rrule, ';BYDAY=') && !strpos($this->rrule, ';WKST=')) { $this->rrule = $this->rrule . ';WKST=' . strtoupper(substr($start->format('D'), 0, 2)); } parent::save(); $this->_saveParticipantData(); $this->_updateRights(); // If the start time has changed, we have to adjust all the excluded // dates. if (!$isNew && $start != $this->_originalStart) { $delta = $this->_originalStart->diff($start); $db = $this->getAdapter(); foreach ($this->getExcludedDates() as $date) { $where = $db->quoteInto('calendar2_id = ?', $this->id); $where .= $db->quoteInto('AND date = ?', $date->format('Y-m-d H:i:s')); $date->add($delta); $db->update('calendar2_excluded_dates', array('date' => $date->format('Y-m-d H:i:s')), $where); } } } else { // Split the series into two parts. $this will be the second part. $new = $this; $old = $this->create(); $old->find($this->id); $splitDate = new Datetime('@' . Phprojekt_Converter_Time::userToUtc($new->start)); $helper = $old->getRruleHelper(); $rrules = $helper->splitRrule($splitDate); $old->rrule = $rrules['old']; // Only overwrite the new rrule if the user didn't change it if ($new->rrule == $old->rrule) { $new->rrule = $rrules['new']; } // Regenerate the uid if the new event has multiple occurrences, see // http://jira.opensource.mayflower.de/jira/browse/PHPROJEKT-298 // As they don't belong together anymore, we also need to set a new uri. if ($new->rrule) { $this->uid = Phprojekt::generateUniqueIdentifier(); $new->uri = $new->uid; } $old->save(); $new->_saveToNewRow(); // Update the excluded occurences $where = "id = {$old->id} "; $where .= "AND date >= '{$splitDate->format('Y-m-d H:i:s')}'"; $this->getAdapter()->update('calendar2_excluded_dates', array('id' => $new->id), $where); } $this->_originalStart = new Datetime('@' . Phprojekt_Converter_Time::userToUtc($this->start)); return $this->id; }
/** * Update a group of events with a common parent id */ private function _updateSingleChangedEventGroup($events) { $parent = $this->_db->select()->from('calendar')->where('id = ?', $events[0]['parent_id'])->query()->fetch(); $start = new Datetime($parent['start_datetime']); $duration = $start->diff(new Datetime($parent['end_datetime'])); $helper = new Calendar2_Helper_Rrule($start, $duration, $parent['rrule']); $last = new Datetime($events[count($events) - 1]['end_datetime']); $occurrences = $helper->getDatesInPeriod($start, $last); $deleted = array(); $added = array(); while (!empty($events) && $events[0]['start_datetime'] == $parent['start_datetime']) { array_shift($events); } $addedTimes = array(); $regularTimes = array(); foreach ($events as $e) { // At this point we throw away confirmation information, mostly because I'm too tired and it's too // complicated to retrieve them. if ($e['participant_id'] != $parent['owner_id']) { continue; } if (empty($occurrences)) { $addedTimes[] = $e['start_datetime']; $added[] = $e; continue; } $cmp = $this->_compareDatetimeWithEvent($occurrences[0], $e); if ($cmp < 0) { // occurrence is before $deleted[] = array_shift($occurrences); } else { if ($cmp === 0) { $regularTimes[] = array_shift($occurrences); if ($this->_eventDataDiffers($parent, $e)) { $addedTimes[] = $e['start_datetime']; $deleted[] = new Datetime($e['start_datetime']); $added[] = $e; } } else { // event is before occurrence $added[] = $e; } } } $addedEventsParticipants = array(); foreach ($events as $e) { if ($e['participant_id'] == $parent['owner_id']) { continue; } if (in_array($e['start_datetime'], $addedTimes)) { if (!array_key_exists($e['start_datetime'], $addedEventsParticipants)) { $addedEventsParticipants[$e['start_datetime']] = array(); } $addedEventsParticipants[$e['start_datetime']][] = array('id' => $e['participant_id'], 'status' => $e['status']); } else { if (!in_array($e['start_datetime'], $regularTimes)) { // This event doesn't really belong here. We just create a new one for the user independent of $parent. $uid = Phprojekt::generateUniqueIdentifier(); $this->_db->insert('calendar2', array('project_id' => $e['project_id'], 'summary' => $e['title'], 'description' => $e['notes'], 'location' => $e['place'], 'comments' => "", 'start' => $e['start_datetime'], 'last_end' => $e['end_datetime'], 'end' => $e['end_datetime'], 'owner_id' => $e['participant_id'], 'rrule' => '', 'visibility' => $e['visibility'] + 1, 'uri' => $uid, 'uid' => $uid)); $newCalendarId = $this->_db->lastInsertId(); $this->_db->insert('calendar2_user_relation', array('calendar2_id' => $newCalendarId, 'user_id' => $e['participant_id'], 'confirmation_status' => $e['status'])); } } } if (!empty($deleted)) { $this->_deletedOccurrences($parent, $deleted); } if (!empty($added)) { $this->_addedOccurrences($parent, $added, $addedEventsParticipants); } }