function src_event_edit() { if (!CheckPermissions($this->mPermission)) { return; } // Get data from uri resolution. $source_id = $this->mData['SourceId']; $event_id = $this->mData['EventId']; $occurrence_specified = array_key_exists('OccurrenceId', $this->mData); if ($occurrence_specified) { $occurrence_id = $this->mData['OccurrenceId']; } else { $occurrence_id = NULL; } // Validate the source if (!$this->_GetSource()) { return; } $this->load->library('calendar_view_edit_simple'); $this->pages_model->SetPageCode('calendar_event_edit'); // Get the redirect url tail $args = func_get_args(); $tail = implode('/', $args); $get_action = ''; if (isset($_GET['action'])) { $get_action = $_GET['action']; } // Fetch the specified event $calendar_data = new CalendarData(); $this->mMainSource->FetchEvent($calendar_data, $source_id, $event_id); $events = $calendar_data->GetEvents(); if (array_key_exists(0, $events)) { $event = $events[0]; // Find the occurrence $found_occurrence = NULL; if (NULL !== $occurrence_id) { foreach ($event->Occurrences as $key => $occurrence) { if ($occurrence->SourceOccurrenceId == $occurrence_id) { $found_occurrence =& $event->Occurrences[$key]; break; } } if (NULL === $found_occurrence) { $this->messages->AddMessage('warning', 'The event occurrence with id ' . $occurrence_id . ' does not belong to the event with id ' . $event_id . '.'); redirect($this->mPaths->EventInfo($event) . '/' . $tail); return; } } if (NULL === $occurrence_id) { // default to the only occurrence if there is only one. if (count($event->Occurrences) == 1) { $found_occurrence =& $event->Occurrences[0]; $occurrence_id = $found_occurrence->SourceOccurrenceId; } } // Get the buttons from post data $prefix = 'eved'; $return_button = isset($_POST[$prefix . '_return']); if (false !== $event && $event->ReadOnly) { $return_button = TRUE; $this->messages->AddMessage('error', 'You do not have permission to make changes to this event.'); } if ($return_button) { // REDIRECT if ($occurrence_specified) { $path = $this->mPaths->OccurrenceInfo($found_occurrence); } else { $path = $this->mPaths->EventInfo($event); } return redirect($path . '/' . $tail); } $input_summary = $this->input->post($prefix . '_summary'); $errors = array(); $process_input = false; // Read the recurrence data if (isset($_POST[$prefix . '_recur_simple']) and isset($_POST[$prefix . '_start']) and isset($_POST[$prefix . '_duration']) and isset($_POST[$prefix . '_inex'])) { $rset_arr = $_POST[$prefix . '_recur_simple']; $rset = Calendar_view_edit_simple::validate_recurrence_set_data(!(isset($_POST[$prefix . '_allday']) && $_POST[$prefix . '_allday']), $_POST[$prefix . '_start'], $_POST[$prefix . '_duration'], $_POST[$prefix . '_recur_simple'], $_POST[$prefix . '_inex'], $errors); } // Fill it in if none supplied /// @todo Fix that the new rset doesn't have the same rrule ids, so theres a deletion/insertion instead of update. if (!isset($rset_arr)) { $rset = $event->GetRecurrenceSet(); if ((isset($_POST['evview_delete']) || 'delete' == $get_action) && NULL !== $found_occurrence) { $inex_date = array($found_occurrence->StartTime->Format('Ymd') => array(NULL => NULL)); $rset->RemoveRDates($inex_date); $rset->AddExDates($inex_date); $process_input = true; $_POST[$prefix . '_save'] = true; $input_valid = true; } elseif (isset($_POST['evview_delete_all']) || 'delete_all' == $get_action) { $rset->ClearRecurrence(); $process_input = true; $_POST[$prefix . '_save'] = true; $input_valid = true; } elseif ((isset($_POST['evview_restore']) || 'restore' == $get_action) && NULL !== $found_occurrence) { $inex_date = array($found_occurrence->StartTime->Format('Ymd') => array(NULL => NULL)); $rset->RemoveExDates($inex_date); $rset->AddRDates($inex_date); $process_input = true; $_POST[$prefix . '_save'] = true; $input_valid = true; } $rset_arr = Calendar_view_edit_simple::transform_recur_for_view($rset, $errors); } // Always fill in the inex info again, ignoring input from form. $inex_arr = Calendar_view_edit_simple::transform_inex_for_view($rset, $errors); list($start, $end) = $rset->GetStartEnd(); $categories = $this->mSource->GetAllCategories(); $input = array('name' => $event->Name, 'description' => $event->Description, 'location_name' => $event->LocationDescription, 'category' => 0, 'time_associated' => $event->TimeAssociated); if (isset($categories[$event->Category])) { $input['category'] = $categories[$event->Category]['id']; } $input_summary = $this->input->post($prefix . '_summary'); $confirm_list = NULL; if (false !== $input_summary) { $input_valid = true; $process_input = true; // Get more post data $input['name'] = $input_summary; if (strlen($input['name']) <= 3 or strlen($input['name']) >= 256) { $input_valid = false; $this->messages->AddMessage('error', 'Event summary is too long or too short.'); } $input_description = $this->input->post($prefix . '_description'); if (false !== $input_description) { $input['description'] = $input_description; if (strlen($input['name']) > 65535) { $input_valid = false; $this->messages->AddMessage('error', 'Event description is too long.'); } } $input_category = $this->input->post($prefix . '_category'); if (false !== $input_category) { $input['category'] = $input_category; } $input_location = $this->input->post($prefix . '_location'); if (false !== $input_location) { $input['location_name'] = $input_location; if (strlen($input['location_name']) > 50) { $input_valid = false; $this->messages->AddMessage('error', 'Event location is too long.'); } } $input['time_associated'] = $this->input->post($prefix . '_allday') === false; } if ($process_input) { // at this point $start and $end are still plain timestamps $input['recur'] = $rset; if ($input_valid && empty($errors)) { if (isset($_POST[$prefix . '_save'])) { $confirm_list = $this->mMainSource->GetEventRecurChanges($event, $rset); if (isset($confirm_list['draft']) && !$this->mMainSource->IsSupported('publish')) { unset($confirm_list['draft']); } if (empty($confirm_list)) { $_POST[$prefix . '_confirm']['confirm_btn'] = 'Confirm'; } } if (isset($_POST[$prefix . '_confirm']['confirm_btn'])) { if (NULL === $confirm_list) { $confirm_list = $this->mMainSource->GetEventRecurChanges($event, $rset); } // Make the change $messages = $this->mMainSource->AmmendEvent($event, $input); $this->messages->AddMessages($messages); if (!array_key_exists('error', $messages) || empty($messages['error'])) { // Success $this->messages->AddMessage('success', 'Event updated'); // Publish the specified occurrences. $publish_occurrences = array(); foreach (array('create', 'draft') as $namespace) { if (isset($_POST[$prefix . '_confirm'][$namespace . '_publish'])) { foreach ($_POST[$prefix . '_confirm'][$namespace . '_publish'] as $day => $dummy) { if (isset($confirm_list[$namespace][$day])) { $publish_occurrences[] = $confirm_list[$namespace][$day]['start_time']; } } } } if (!empty($publish_occurrences)) { $published = $this->mSource->PublishOccurrences($event, $publish_occurrences); $desired = count($publish_occurrences); if ($published < $desired) { $message_type = 'warning'; } else { $message_type = 'success'; } $this->messages->Addmessage($message_type, "{$published} out of {$desired} occurrences were published."); } // changes have been made including possible deletion. // if the redirection results in event not found, we // want it to redirect straight back to the tail. $_SESSION['calendar']['modded'][$event_id] = 1; // REDIRECT if ($occurrence_specified) { $path = $this->mPaths->OccurrenceInfo($found_occurrence); } else { $path = $this->mPaths->EventInfo($event); } return redirect($path . '/' . $tail); } } } } // Ready output data $start = new Academic_time($start); $end = new Academic_time($end); $eventinfo = array('summary' => $input['name'], 'description' => $input['description'], 'location' => $input['location_name'], 'category' => $input['category'], 'allday' => !$input['time_associated'], 'start' => array('monthday' => $start->DayOfMonth(), 'month' => $start->Month(), 'year' => $start->Year(), 'time' => $start->Hour() . ':' . $start->Minute(), 'yearday' => $start->DayOfYear(), 'day' => $start->DayOfWeek(), 'monthweek' => (int) (($start->DayOfMonth() + 6) / 7)), 'duration' => Calendar_view_edit_simple::calculate_duration($start, $end)); if ($this->events_model->IsVip()) { $help_xhtml = $this->pages_model->GetPropertyWikitext('help_vip'); } else { $help_xhtml = $this->pages_model->GetPropertyWikitext('help_personal'); } $data = array('SimpleRecur' => $rset_arr, 'InExDates' => $inex_arr, 'FailRedirect' => '/' . $tail, 'Path' => $this->mPaths, 'EventCategories' => $categories, 'FormPrefix' => $prefix, 'EventInfo' => $eventinfo, 'Help' => $help_xhtml, 'CanPublish' => $this->mMainSource->IsSupported('publish'), 'Create' => false, 'SuccessRedirect' => false); if (is_array($confirm_list)) { $data['Confirms'] = $confirm_list; if (isset($_POST[$prefix . '_confirm'])) { $data['Confirm'] = $_POST[$prefix . '_confirm']; } else { $data['Confirm'] = NULL; } } foreach ($errors as $error) { $this->messages->AddMessage('error', $error['text']); } $this->SetupTabs('', $start); $this->main_frame->SetTitleParameters(array('source' => $this->mSource->GetSourceName(), 'event' => $event->Name)); $this->main_frame->IncludeCss('stylesheets/calendar.css'); $this->main_frame->IncludeJs('javascript/simple_ajax.js'); $this->main_frame->IncludeJs('javascript/css_classes.js'); $this->main_frame->IncludeJs('javascript/calendar_edit.js'); $this->main_frame->SetContent(new FramesView('calendar/event_edit', $data)); } else { // Event not in list $this->ErrorNotAccessible($tail); } $this->main_frame->Load(); }
/** * @return array,NULL,FALSE: NULL if no recurrence, FALSE if too complicated. */ static function transform_recur_for_view(&$recur, &$errors) { if (NULL === $recur) { return NULL; } /* * check in following order: * daily, interval, no bys * weekly, interval, byday multiple * monthly, interval * bymonthday singular * bydayn singular / byday singular, setpos / byday multiple special, setpos * yearly, interval * bymonthday singular, bymonth singular * bydayn singular, bymonth singular * byyearday */ /// @TODO allow implicit monthly/yearly bymonthday[, bymonth] $rrule = $recur->GetSimpleRrule(); if (NULL !== $rrule) { $fields = $rrule->GetUsedFields(); $freq = $rrule->GetFrequency(); $result = array('enable' => 'on', 'freq' => $freq, 'interval' => $rrule->GetInterval()); if (isset($fields['count'])) { $result['range_method'] = 'count'; $result['count'] = $rrule->GetCount(); } elseif (isset($fields['until'])) { $result['range_method'] = 'until'; $until = $rrule->GetUntil(); $result['until'] = array('monthday' => (int) date('d', $until), 'month' => (int) date('n', $until), 'year' => (int) date('Y', $until)); } else { $result['range_method'] = 'noend'; } $by_fields = array(); foreach ($fields as $field => $dummy) { if (substr($field, 0, 2) === 'by') { $by_fields[$field] = $dummy; } } $match = true; if ('daily' === $freq) { if (!empty($by_fields)) { $match = false; } } elseif ('weekly' === $freq) { foreach ($fields as $field => $dummy) { if (substr($field, 0, 2) === 'by' && $field !== 'byday') { $errors[] = array('text' => "Recurrence rule too complicated for basic interface ({$field} detected)"); $match = false; break; } } if ($match) { if (isset($fields['byday'])) { $days = $rrule->GetByDayWeekless(); $result['weekly_byday'] = array(); foreach ($days as $day) { $result['weekly_byday'][$day] = 'on'; } } else { $result['weekly_byday'] = array(); } } } elseif ('monthly' === $freq) { if (isset($fields['bymonthday'])) { $monthdays = $rrule->GetByMonthDay(); if (count($monthdays) === 1) { foreach ($fields as $field => $dummy) { if (substr($field, 0, 2) === 'by' && $field !== 'bymonthday') { $errors[] = array('text' => "Recurrence rule too complicated for basic interface ({$field} detected)"); $match = false; break; } } if ($match) { $result['monthly_method'] = 'monthday'; $monthdays_output = array(); $result['monthly_monthday'] = array('monthday' => $monthdays[0]); } } else { // Not one bymonthday field $errors[] = array('text' => "Recurrence rule too complicated for basic interface (not one bymonthday)"); $match = false; } } elseif (isset($fields['byday'])) { $bydays = $rrule->GetByDay(); foreach ($fields as $field => $dummy) { if (substr($field, 0, 2) === 'by' && $field !== 'byday' && $field !== 'bysetpos') { $errors[] = array('text' => "Recurrence rule too complicated for basic interface ({$field} detected)"); $match = false; break; } } if ($match) { // Either: // 1. bydays is individual day with week and no setpos // 2. bydays is individual day without week and setpos // 3. bydays is 1,2,3,4,5 without weeks and setpos $multiple_bydays = count($bydays); $setpos = $rrule->GetBySetPos(); $dayweeks_specified = NULL; $weekdays = array(); $has_setpos = isset($fields['bysetpos']); if (!$has_setpos or count($setpos) == 1) { foreach ($bydays as $day => $weeks) { if (is_array($weeks)) { if (count($weeks) === 1) { $dayweeks_specified = true; $actual_weeks = array_keys($weeks); $result['monthly_weekday'] = array('week' => $actual_weeks[0], 'day' => $day); } else { // Not one week in byday field $errors[] = array('text' => "Recurrence rule too complicated for basic interface (not one week in byday)"); $match = false; } } else { $weekdays[] = $day; } } if ($multiple_bydays == 1) { if ($dayweeks_specified && !$has_setpos) { // case 1 $result['monthly_method'] = 'weekday'; } elseif (!$dayweeks_specified && $has_setpos) { // case 2 $result['monthly_method'] = 'weekday'; $result['monthly_weekday'] = array('week' => $setpos[0], 'day' => $weekdays[0]); // var_dump($result['monthly_weekday']); } else { // Invalid combination of byday and bysetpos $errors[] = array('text' => "Recurrence rule too complicated for basic interface (unknown combination of byday and bysetpos)"); $match = false; } } elseif (!$dayweeks_specified && $has_setpos) { // days = 1,2,3,4,5 sort($weekdays); if (count($weekdays) == 5 and $weekdays[0] == 1 and $weekdays[1] == 2 and $weekdays[2] == 3 and $weekdays[3] == 4 and $weekdays[4] == 5) { // case 3 $result['monthly_method'] = 'weekday'; $result['monthly_weekday'] = array('week' => $setpos[0], 'day' => join(',', $weekdays)); } else { // Not standard combination of days $errors[] = array('text' => "Recurrence rule too complicated for basic interface (using setpos with multiple bydays but not a standard combination of days)"); $match = false; } } else { // Multiple bydays without setpos $errors[] = array('text' => "Recurrence rule too complicated for basic interface (no bysetpos with multiple bydays)"); $match = false; } } else { // Multiple setpos on monthly byday $errors[] = array('text' => "Recurrence rule too complicated for basic interface (multiple bysetpos on monthly byday)"); $match = false; } } } else { // Not a recognised monthly method $errors[] = array('text' => "Recurrence rule too complicated for basic interface (not recognised monthly method)"); $match = false; } } elseif ('yearly' === $freq) { if (empty($by_fields) || isset($fields['bymonthday']) && isset($fields['bymonth'])) { list($start_date) = $recur->GetStartEnd(); $start_date = new Academic_time($start_date); if (empty($by_fields)) { $monthdays = array($start_date->DayOfMonth()); $months = array($start_date->Month()); } else { $monthdays = $rrule->GetByMonthDay(); $months = $rrule->GetByMonth(); } if (count($monthdays) === 1 && count($months) === 1) { foreach ($fields as $field => $dummy) { if (substr($field, 0, 2) === 'by' && $field !== 'bymonthday' && $field !== 'bymonth') { $errors[] = array('text' => "Recurrence rule too complicated for basic interface ({$field} detected)"); $match = false; break; } } if ($match) { $result['yearly_method'] = 'monthday'; $monthdays_output = array(); $result['yearly_monthday'] = array('monthday' => $monthdays[0], 'month' => $months[0]); } } else { // Not one bymonthday field or bymonth field $errors[] = array('text' => "Recurrence rule too complicated for basic interface (not one bymonthday or bymonth)"); $match = false; } } elseif (isset($fields['byday']) && isset($fields['bymonth'])) { $bydays = $rrule->GetByDay(); $months = $rrule->GetByMonth(); if (count($bydays) === 1 && count($months) === 1) { foreach ($fields as $field => $dummy) { if (substr($field, 0, 2) === 'by' && $field !== 'byday' && $field !== 'bymonth') { $match = false; break; } } if ($match) { foreach ($bydays as $day => $weeks) { if (is_array($weeks) && count($weeks) === 1) { $actual_weeks = array_keys($weeks); $result['yearly_method'] = 'weekday'; $result['yearly_weekday'] = array('week' => $actual_weeks[0], 'day' => $day, 'month' => $months[0]); } else { // Not one week in byday field $errors[] = array('text' => "Recurrence rule too complicated for basic interface (not one week in byday)"); $match = false; } } } } else { // Not one byday field or bymonth field $errors[] = array('text' => "Recurrence rule too complicated for basic interface (not one byday or bymonth)"); $match = false; } } elseif (isset($fields['byyearday'])) { $yeardays = $rrule->GetByYearDay(); if (count($yeardays) === 1) { foreach ($fields as $field => $dummy) { if (substr($field, 0, 2) === 'by' && $field !== 'byyearday') { $errors[] = array('text' => "Recurrence rule too complicated for basic interface ({$field} detected)"); $match = false; break; } } if ($match) { $result['yearly_method'] = 'yearday'; $monthdays_output = array(); $result['yearly_yearday'] = array('yearday' => $yeardays[0]); } } else { // Not one byyearday field $errors[] = array('text' => "Recurrence rule too complicated for basic interface (not one byyearday)"); $match = false; } } else { // Not a recognised yearly method $errors[] = array('text' => "Recurrence rule too complicated for basic interface (not recognised yearly method)"); $match = false; } } else { // Not a recognised simple frequency $errors[] = array('text' => "Recurrence rule too complicated for basic interface (not recognised simple frequency)"); $match = false; } if ($match) { return $result; } else { return false; } } else { return false; } }