17 require_once dirname(__FILE__).
'/../../calendar_event/calendar_event.inc';
18 require_once dirname(__FILE__).
'/../../lib/calendar_common.inc';
19 require_once SQ_FUDGE_PATH.
'/datetime_field/datetime_field.inc';
20 require_once SQ_FUDGE_PATH.
'/general/general.inc';
21 require_once SQ_FUDGE_PATH.
'/general/datetime.inc';
36 var $parent_links = Array();
62 parent::load($assetid);
64 $this->parent_links = $GLOBALS[
'SQ_SYSTEM']->am->getLinks($assetid, SQ_SC_LINK_ALL,
'calendar_event_multi_date', FALSE,
'minor');
91 $freq = $this->
attr(
'frequency');
93 trigger_localised_error(
'CAL0047', E_USER_WARNING);
96 return parent::_preCreateCheck($link);
111 return $timestamp - strtotime(gmdate(
'Y-m-d 00:00:00', $timestamp).
' GMT');
139 if (is_null($after)) $after = date(
'Y-m-d');
142 if ((!(isset($this) && is_a($this,
'Calendar_Event_Recurring'))) && (func_num_args() < 5)) {
143 trigger_localised_error(
'CAL0030', E_USER_ERROR);
146 if (is_null($start)) {
148 $freq_type = substr($this->
attr(
'frequency'), 0, 3);
149 $interval = substr($this->
attr(
'frequency'), 3);
150 if (!$interval) $interval = 1;
151 $start = substr($this->
attr(
'start_date'),0,10);
152 $stop = $this->
attr(
'stop_date');
154 if ($stop ==
'---------- --:--:--') $stop = NULL;
157 $seconds_per_day = 60 * 60 * 24;
158 if ($after <= $start)
return $start;
161 while ($result ==
'') {
162 list($res_year,$res_month,$res_day) = sscanf($after,
'%04d-%02d-%02d');
163 list($after_year,$after_month,$after_day) = sscanf($after,
'%04d-%02d-%02d');
164 list($start_year,$start_month,$start_day) = sscanf($start,
'%04d-%02d-%02d');
165 $month_diff = (12 * ($after_year - $start_year)) + $after_month - $start_month;
167 switch ($freq_type) {
169 $periods_so_far = ceil(days_between_isos($after, $start) / $interval);
170 $result = add_days_to_iso($start, $interval * $periods_so_far);
174 $periods_so_far = ceil(days_between_isos($after, $start) / $interval);
175 $result = add_days_to_iso($start, $interval * $periods_so_far);
176 while (in_array(date(
'D', iso8601_ts($result)), Array(
'Sat',
'Sun'))) {
177 $result = add_days_to_iso($result, 1);
182 $periods_so_far = ceil(days_between_isos($after, $start) / $interval);
183 $result = add_days_to_iso($start, $interval * $periods_so_far);
184 while (!in_array(date(
'D', iso8601_ts($result)), Array(
'Sat',
'Sun'))) {
185 $result = add_days_to_iso($result, 1);
190 $periods_so_far = ceil(days_between_isos($after, $start) / ($interval*7));
191 $result = add_days_to_iso($start, $interval * 7 * $periods_so_far);
196 if (($month_diff % $interval) != 0) {
197 increment_month($res_month, $res_year, ($interval - ($month_diff % $interval)));
198 }
else if ($res_day > $start_day) {
199 increment_month($res_month, $res_year, $interval);
201 while ($start_day > days_in_month($res_month, $res_year)) {
202 increment_month($res_month, $res_year, $interval);
204 $result = sprintf(
'%04d-%02d-%02d',$res_year,$res_month,$start_day);
209 $target_week_of_month = (int)(($start_day - 1) / 7);
210 $target_day_of_week = date(
'w', iso8601_ts($start));
211 $res_day = ($target_week_of_month * 7) + 1;
213 if (($month_diff % $interval) != 0) {
215 increment_month($res_month, $res_year, $interval - ($month_diff % $interval));
216 }
else if ((
int)($after_day / 7) > $target_week_of_month) {
218 increment_month($res_month, $res_year, $interval);
219 }
else if ((
int)($after_day / 7) == $target_week_of_month) {
220 $res_day = max($res_day, $after_day);
223 $month_length = days_in_month($res_month, $res_year);
225 $result = sprintf(
'%04d-%02d-%02d',$res_year,$res_month,$res_day);
226 while (date(
'w', iso8601_ts($result)) != $target_day_of_week) {
227 $res_day += (7 + $target_day_of_week - date(
'w', iso8601_ts($result)) - 1) % 7 + 1;
229 $result = sprintf(
'%04d-%02d-%02d',$res_year,$res_month,$res_day);
230 if (($res_day > $month_length) || ($res_day > (($target_week_of_month+1) * 7))) {
233 increment_month($res_month, $res_year, $interval);
234 $month_length = days_in_month($res_month, $res_year);
235 $res_day = ($target_week_of_month * 7)+1;
237 $result = sprintf(
'%04d-%02d-%02d',$res_year,$res_month,$res_day);
243 $target_days_from_end = days_in_month($start_month, $start_year) - $start_day;
245 if (($month_diff % $interval) != 0) {
246 increment_month($res_month, $res_year, $interval - ($month_diff % $interval));
247 }
else if ((days_in_month($res_month, $res_year) - $after_day) < $target_days_from_end) {
248 increment_month($res_month, $res_year, $interval);
251 $result = sprintf(
'%04d-%02d-%02d',$res_year,$res_month,days_in_month($res_month, $res_year) - $target_days_from_end);
253 while ((days_in_month($res_month, $res_year) - $target_days_from_end) < 0) {
254 increment_month($res_month, $res_year, $interval);
256 $result = sprintf(
'%04d-%02d-%02d',$res_year,$res_month,days_in_month($res_month, $res_year) - $target_days_from_end);
263 $target_weeks_from_end = (int)((days_in_month($start_month, $start_year) - $start_day) / 7);
264 $target_day_of_week = (date(
'w', iso8601_ts($start)));
266 if (($month_diff % $interval) != 0) {
268 increment_month($res_month, $res_year, $interval - ($month_diff % $interval));
269 }
else if ((
int)((days_in_month($after_month, $after_year) - $after_day) / 7) < $target_weeks_from_end) {
271 increment_month($res_month, $res_year, $interval);
272 }
else if ((
int)((days_in_month($after_month, $after_year) - $after_day) / 7) == $target_weeks_from_end) {
275 $min_day = $after_day;
277 $res_day = days_in_month($res_month, $res_year) - ($target_weeks_from_end * 7);
278 $result = sprintf(
'%04d-%02d-%02d',$res_year,$res_month,$res_day);
280 while (date(
'w', iso8601_ts($result)) != $target_day_of_week) {
282 $res_day -= (7 + date(
'w', iso8601_ts($result)) - $target_day_of_week) % 7;
284 if (($res_day < $min_day) || ($result < $after)) {
287 increment_month($res_month, $res_year, $interval);
288 $res_day = days_in_month($res_month, $res_year) - ($target_weeks_from_end * 7);
292 $result = sprintf(
'%04d-%02d-%02d',$res_year,$res_month,$res_day);
297 if (isset($this) && is_a($this,
'Calendar_Event_Recurring') && $exception_link = $this->
getExceptionLink($result, $this->
id)) {
298 $after = add_days_to_iso($result);
303 if (!empty($stop) && ($result > $stop)) {
334 if (is_null($this) && (func_num_args() < 5)) {
335 trigger_localised_error(
'CAL0031', E_USER_ERROR);
339 if (is_null($start)) {
341 $freq_type = substr($this->
attr(
'frequency'), 0, 3);
342 $interval = substr($this->
attr(
'frequency'), 3);
343 $start = substr($this->
attr(
'start_date'),0,10);
344 $stop = $this->
attr(
'stop_date');
346 if (is_null($date)) $date = date(
'Y-m-d');
347 if (strpos($stop,
'----------') !== FALSE) {
352 if ($start > $date)
return FALSE;
353 if ((!is_null($stop)) && ($stop < $date)) {
361 if (!$interval) $interval = 1;
362 if ($interval > 1) $freq_type .=
'x';
364 switch ($freq_type) {
372 return (($date_components[
'ds'] - $start_components[
'ds']) % $interval == 0);
377 return !in_array($date_components[
'wday'], Array(0, 6));
382 return in_array($date_components[
'wday'], Array(0, 6));
387 return ($date_components[
'wday'] == $start_components[
'wday']);
393 return ($date_components[
'wday'] == $start_components[
'wday'])
394 && (((($date_components[
'ds'] - $start_components[
'ds']) / 7) % $interval) == 0);
399 return ($date_components[
'mday'] == $start_components[
'mday']);
405 return ($date_components[
'mday'] == $start_components[
'mday'])
406 && ((($date_components[
'ms'] - $start_components[
'ms']) % $interval) == 0);
412 return ($date_components[
'wday'] == $start_components[
'wday'])
413 && ($date_components[
'wdom'] == $start_components[
'wdom']);
420 return ($date_components[
'wday'] == $start_components[
'wday'])
421 && ($date_components[
'wdom'] == $start_components[
'wdom'])
422 && ((($date_components[
'ms'] - $start_components[
'ms']) % $interval) == 0);
427 return ($start_components[
'rmday'] == $date_components[
'rmday']);
433 return ($start_components[
'rmday'] == $date_components[
'rmday'])
434 && ((($date_components[
'ms'] - $start_components[
'ms']) % $interval) == 0);
440 return ($date_components[
'wday'] == $start_components[
'wday'])
441 && ($date_components[
'rwdom'] == $start_components[
'rwdom']);
448 return ($date_components[
'wday'] == $start_components[
'wday'])
449 && ($date_components[
'rwdom'] == $start_components[
'rwdom'])
450 && ((($date_components[
'ms'] - $start_components[
'ms']) % $interval) == 0);
474 if (empty($this->_tmp[
'instance_dates'][$date])) {
477 $res[
'start'] = $date;
481 $period = substr($this->
attr(
'frequency'), 3);
482 if (!$period) $period = 1;
483 switch (substr($this->
attr(
'frequency'), 0, 1)) {
485 $first_occur = add_days_to_iso($date, -$period);
489 $first_occur = add_days_to_iso($date, -$period*7);
493 $first_occur = add_months_to_iso($date, -$period).
'-'.date(
'd', iso8601_ts($date));
500 if ($this->
getStartTime()) $res[
'start'] .=
' '.$this->getStartTime();
503 $res[
'end'] = date(
'Y-m-d', iso8601_ts($res[
'start']) + $duration);
505 if ($date > $res[
'end']){
507 if ($this->
getStartTime()) $res[
'start'] .=
' '.$this->getStartTime();
508 $res[
'end'] = date(
'Y-m-d', iso8601_ts($res[
'start']) + $duration);
511 if ($this->
getEndTime()) $res[
'end'] .=
' '.$this->getEndTime();
513 $this->_tmp[
'instance_dates'][$date] = $res;
515 return $this->_tmp[
'instance_dates'][$date];
528 $freq_type = substr($this->
attr(
'frequency'), 0, 3);
529 $interval = substr($this->
attr(
'frequency'), 3);
531 switch ($freq_type) {
535 $rule .=
'FREQ=DAILY;INTERVAL='.$interval;
537 $rule .=
'FREQ=DAILY;INTERVAL=1';
544 $rule .=
'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR;INTERVAL='.$interval;
546 $rule .=
'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR;INTERVAL=1';
553 $rule .=
'FREQ=WEEKLY;BYDAY=SA,SU;INTERVAL='.$interval;
555 $rule .=
'FREQ=WEEKLY;BYDAY=SA,SU;INTERVAL=1';
562 $rule .=
'FREQ=WEEKLY;INTERVAL='.$interval;
564 $rule .=
'FREQ=WEEKLY;INTERVAL=1';
571 $day = (int)substr($this->
attr(
'start_date'), 8, 2);
573 $rule .=
'FREQ=MONTHLY;INTERVAL='.$interval;
575 $rule .=
'FREQ=MONTHLY;INTERVAL=1';
581 $day = (int)substr($this->
attr(
'start_date'), 8, 2);
582 $counter = (int)(($day-1) / 7) + 1;
583 $day_of_week = strtoupper(substr(date(
'l', iso8601_ts($this->
attr(
'start_date'))), 0, 2));
586 $rule .=
'FREQ=MONTHLY;BYDAY='.$counter.$day_of_week.
';INTERVAL='.$interval;
588 $rule .=
'FREQ=MONTHLY;BYDAY='.$counter.$day_of_week.
';INTERVAL=1';
594 $day = (int)substr($this->
attr(
'start_date'), 8, 2);
595 $month = (int)substr($this->
attr(
'start_date'), 5, 2);
596 $year = (int)substr($this->
attr(
'start_date'), 0, 4);
597 $month_length = date(
'j', strtotime(
'yesterday', iso8601_ts($year.
'-'.($month+1).
'-01')));
598 $day_of_month = (int) $month_length - $day + 1;
601 $rule .=
'FREQ=MONTHLY;INTERVAL='.$interval.
';BYMONTHDAY=-'.$day_of_month;
603 $rule .=
'FREQ=MONTHLY;BYMONTHDAY=-'.$day_of_month;
609 $day = (int)substr($this->
attr(
'start_date'), 8, 2);
610 $day_of_week = strtoupper(substr(date(
'l', iso8601_ts($this->
attr(
'start_date'))), 0, 2));
611 $month = (int)substr($this->
attr(
'start_date'), 5, 2);
612 $year = (int)substr($this->
attr(
'start_date'), 0, 4);
613 $month_length = date(
'j', strtotime(
'yesterday', iso8601_ts($year.
'-'.($month+1).
'-01')));
614 $day_of_month = (int)((($month_length - $day + 1) / 7) + 1);
617 $rule .=
'FREQ=MONTHLY;INTERVAL='.$interval.
';BYDAY=-'.$day_of_month.$day_of_week;
619 $rule .=
'FREQ=MONTHLY;INTERVAL=1;BYDAY=-'.$day_of_month.$day_of_week;
627 if ($stop_date_attr->value !=
'---------- --:--:--') {
628 $rule .=
';UNTIL='.date(
'Ymd\THis', iso8601_ts($stop_date_attr->value));
643 $freq_type = substr($this->
attr(
'frequency'), 0, 3);
644 $interval = substr($this->
attr(
'frequency'), 3);
646 switch ($freq_type) {
650 $res = translate(
'cal_event_every_x_days', $interval);
652 $res = translate(
'cal_event_every_day');
658 $res = translate(
'cal_event_every_weekday');
663 $res = translate(
'cal_event_every_weekend');
668 $dow = date(
'l', iso8601_ts($this->
attr(
'start_date')));
670 $res = translate(
'cal_event_every_x_weeks', $interval, $dow);
672 $res = translate(
'cal_event_every_week', $dow);
678 $day = (int)substr($this->
attr(
'start_date'), 8, 2);
680 $res = translate(
'cal_event_every_x_months_first_day', $interval, add_ordinal_suffix($day));
682 $res = translate(
'cal_event_every_month_first_day', add_ordinal_suffix($day));
688 $day = (int)substr($this->
attr(
'start_date'), 8, 2);
689 $day_of_week = date(
'l', iso8601_ts($this->
attr(
'start_date')));
691 $res = translate(
'cal_event_every_x_months_first_weekday', $interval, add_ordinal_suffix((
int)((($day-1) / 7) + 1)), $day_of_week);
693 $res = translate(
'cal_event_every_month_first_weekday', add_ordinal_suffix((
int)((($day-1) / 7) + 1)), $day_of_week);
699 $day = (int)substr($this->
attr(
'start_date'), 8, 2);
700 $month = (int)substr($this->
attr(
'start_date'), 5, 2);
701 $year = (int)substr($this->
attr(
'start_date'), 0, 4);
702 $month_length = date(
'j', strtotime(
'yesterday', iso8601_ts($year.
'-'.($month+1).
'-01')));
704 $res = translate(
'cal_event_every_x_months_last_day', $interval, add_reverse_ordinal_suffix($month_length - $day + 1));
706 $res = translate(
'cal_event_every_month_last_day', add_reverse_ordinal_suffix($month_length - $day + 1));
712 $day = (int)substr($this->
attr(
'start_date'), 8, 2);
713 $day_of_week = date(
'l', iso8601_ts($this->
attr(
'start_date')));
714 $month = (int)substr($this->
attr(
'start_date'), 5, 2);
715 $year = (int)substr($this->
attr(
'start_date'), 0, 4);
716 $month_length = date(
'j', strtotime(
'yesterday', iso8601_ts($year.
'-'.($month+1).
'-01')));
718 $res = translate(
'cal_event_every_x_months_last_weekday', $interval, add_reverse_ordinal_suffix((
int)((($month_length - $day + 1) / 7) + 1)), $day_of_week);
720 $res = translate(
'cal_event_every_month_last_weekday', add_reverse_ordinal_suffix((
int)((($month_length - $day + 1) / 7) + 1)), $day_of_week);
726 $res = translate(
'cal_event_unknown_frequency', $this->
attr(
'frequency'));
730 if (($stop_timestamp = $stop_date_attr->getTimestamp()) == -1) {
731 return $res.
', '.translate(
'cal_event_recur_until_further_notice');
733 return $res.
', '.translate(
'cal_event_recur_until_date', date(
'jS M Y', $stop_timestamp));
750 if (isset($this) && is_a($this,
'Calendar_Event_Recurring')) {
751 $freq_type = substr($this->
attr(
'frequency'), 0, 3);
752 $interval = substr($this->
attr(
'frequency'), 3);
754 if (is_null($event)) {
757 $freq_type = array_get_index($event,
'frequency',
'');;
758 $interval = array_get_index($event,
'period',
'');
762 if (empty($interval)) {
767 switch ($freq_type) {
769 $frequency = 1*$interval;
773 $frequency = 2*$interval;
777 $frequency = 5*$interval;
781 $frequency = 7*$interval;
788 $frequency = 30*$interval;
808 $exception_string =
'';
809 if ($this->id <> 0) {
810 $cancellations = $GLOBALS[
'SQ_SYSTEM']->am->getLinks($this->
id, SQ_SC_LINK_ALL, Array(
'calendar_event_cancellation'), FALSE,
'major');
812 foreach ($cancellations as $cancelled_event) {
813 $event = $GLOBALS[
'SQ_SYSTEM']->am->getAsset($cancelled_event[
'minorid'], $cancelled_event[
'minor_type_code']);
814 if ($event->readAccess()) {
815 $exception_string .= date(
'Ymd\THis', iso8601_ts($event->attr(
'start_date'))).
',';
818 if (substr($exception_string, -1) ==
',') {
819 $exception_string = substr($exception_string, 0, -1);
822 return $exception_string;
836 <table border=
"0" cellspacing=
"2" cellpadding=
"2">
838 <td><b><?php echo translate(
'name'); ?></b></td>
839 <td><?php echo $this->
attr(
'name'); ?></td>
842 <td><b><?php echo translate(
'cal_event_first_start'); ?></b></td>
846 <td><b><?php echo translate(
'cal_event_first_end'); ?></b></td>
850 <td><b><?php echo translate(
'cal_event_instance_duration'); ?></b></td>
853 $total_time = easy_time_total($this->
getDuration(), TRUE);
854 echo (empty($total_time) ?
'N/A' : $total_time);
858 <td><b><?php echo translate(
'frequency'); ?></b></td>
862 <td><b><?php echo translate(
'description'); ?></b></td>
879 $links = parent::_getAllowedLinks();
880 $links[SQ_LINK_TYPE_2][
'calendar_event_modification'] = Array(
'card' =>
'M',
'exclusive' => FALSE);
881 $links[SQ_LINK_TYPE_2][
'calendar_event_cancellation'] = Array(
'card' =>
'M',
'exclusive' => FALSE);
907 function prepareLink(&$asset, $side_of_link, &$link_type, &$value, &$sort_order, &$dependant, &$exclusive)
909 if (is_a($asset,
'calendar_event_modification') || is_a($asset,
'calendar_event_cancellation')) {
910 $link_type = SQ_LINK_TYPE_2;
933 $keyword = parse_keyword($keyword, $modifiers);
937 $replacement = $this->
writeAccess(
'') ?
'<a href="'.htmlspecialchars(replace_query_string_vars(Array(
'SQ_CALENDAR_VIEW'=>
'edit',
'SQ_CALENDAR_EVENT_ID'=>$this->
id))).
'">'.translate(
'cal_event_recurring_edit_link_text').
'</a>' :
'';
940 case 'event_frequency':
944 case 'event_frequency_summary':
945 $frequency_threshold = $GLOBALS[
'SQ_SYSTEM']->getUserPrefs(
'calendar_event_recurring',
'SQ_CALENDAR_EVENTS_FREQUENCY');
951 case 'event_ical_frequency':
955 case 'event_ical_exceptions':
960 if (in_array($keyword, Array(
'instance_start_datetime',
'instance_end_datetime',
'cancel_link',
'modify_link'))) {
961 if (isset($_REQUEST[
'SQ_CALENDAR_DATE'])) {
962 if ($exception_link = $this->
getExceptionLink($_REQUEST[
'SQ_CALENDAR_DATE'])) {
969 case 'instance_start_datetime':
970 if (!isset($this->vars[
'start_date_ts'])) {
971 $replacement = $instance_dates[
'start'];
974 $replacement = parent::getKeywordReplacement($keyword);
978 case 'instance_end_datetime':
979 if (!isset($this->vars[
'start_end_ts'])) {
980 $replacement = $instance_dates[
'end'];
983 $replacement = parent::getKeywordReplacement($keyword);
989 $replacement = $write_access ? $this->
_getCancelLink() : translate(
'cal_event_cancel_link_default');
994 $replacement = $write_access ? $this->
_getModifyLink() : translate(
'cal_event_modify_link_default');
998 }
else if ($keyword ==
'instance_start_datetime' || $keyword ==
'instance_end_datetime') {
1000 $replacement = parent::getKeywordReplacement($keyword);
1012 preg_match(
'/^instance_start_datetime_(.+)/', $keyword, $matches);
1013 if (!empty($matches)) {
1014 if (!empty($_REQUEST[
'SQ_CALENDAR_DATE'])) {
1015 if ($exception_link = $this->
getExceptionLink($_REQUEST[
'SQ_CALENDAR_DATE'])) {
1021 switch ($matches[1]){
1024 if (preg_match(
"/^(.*?) (--):(--):(--)$/", $instance_dates[
'start'])) {
1025 $replacement = date(
'Ymd', iso8601_ts($instance_dates[
'start']));
1027 $replacement = date(
'Ymd\THis', iso8601_ts($instance_dates[
'start']));
1031 $replacement = date($matches[1], iso8601_ts($instance_dates[
'start']));
1036 $replacement = parent::getKeywordReplacement($keyword);
1042 preg_match(
'/^instance_end_datetime_(.+)/', $keyword, $matches);
1043 if (!empty($matches)) {
1044 if (!empty($_REQUEST[
'SQ_CALENDAR_DATE'])) {
1045 if ($exception_link = $this->
getExceptionLink($_REQUEST[
'SQ_CALENDAR_DATE'])) {
1051 switch ($matches[1]){
1053 if (preg_match(
"/^(.*?) (--):(--):(--)$/", $instance_dates[
'end'])) {
1054 $replacement = date(
'Ymd', iso8601_ts($instance_dates[
'end']));
1056 $replacement = date(
'Ymd\THis', iso8601_ts($instance_dates[
'end']));
1060 $replacement = date($matches[1], iso8601_ts($instance_dates[
'end']));
1065 $replacement = parent::getKeywordReplacement($keyword);
1071 preg_match(
'/^event_stop_date_(.+)/', $keyword, $matches);
1072 $stop_date = $this->
attr(
'stop_date');
1073 if ((!empty($matches)) && !empty($stop_date) && (FALSE === strpos(
'----', $stop_date))) {
1074 $replacement = date($matches[1], iso8601_ts($stop_date));
1079 if (in_array($keyword, Array(
'asset_url',
'asset_href'))) {
1080 $res = parent::getKeywordReplacement($keyword);
1081 if (!empty($_REQUEST[
'SQ_CALENDAR_DATE'])) {
1082 $res = replace_query_string_vars(Array(
'SQ_CALENDAR_DATE' => $_REQUEST[
'SQ_CALENDAR_DATE']), $res);
1086 $replacement = htmlentities($res);
1092 $replacement = parent::getKeywordReplacement($keyword);
1093 $empty_replacement = (((string)$replacement) ==
'%'.$keyword.
'%');
1096 if ($empty_replacement && (count($this->parent_links) > 0)) {
1098 $parent_link = reset($this->parent_links);
1100 $parent_asset = $GLOBALS[
'SQ_SYSTEM']->am->getAsset($parent_link[
'majorid']);
1101 $replacement = $parent_asset->getKeywordReplacement($keyword);
1102 $GLOBALS[
'SQ_SYSTEM']->am->forgetAsset($parent_asset);
1107 apply_keyword_modifiers($replacement, $modifiers, Array(
'assetid' => $this->
id));
1109 return $replacement;
1130 if (is_null($id) && isset($this->_tmp[
'exception_link'])) {
1131 return $this->_tmp[
'exception_link'];
1133 $search_id = is_null($id) ? $this->
id : $id;
1134 $child_links = $GLOBALS[
'SQ_SYSTEM']->am->getLinks($search_id, SQ_SC_LINK_ALL, Array(
'calendar_event_cancellation',
'calendar_event_modification'), FALSE,
'major', $date);
1135 $res = current($child_links);
1136 if ($res[
'minor_type_code'] ==
'calendar_event_cancellation') {
1137 $replacement_links = $GLOBALS[
'SQ_SYSTEM']->am->getLinks($res[
'minorid'], SQ_SC_LINK_ALL,
'calendar_event_single', FALSE);
1138 if (!empty($replacement_links)) {
1139 $res = current($replacement_links);
1143 $this->_tmp[
'exception_link'] = $res;
1158 if (isset($_REQUEST[
'SQ_CALENDAR_DATE'])) {
1159 return '<a href="?SQ_CALENDAR_VIEW=event&SQ_CALENDAR_EVENT_ID='.$this->id.
'&SQ_CALENDAR_EVENT_ACTION=cance11&SQ_CALENDAR_DATE='.$_REQUEST[
'SQ_CALENDAR_DATE'].
'" onclick="return confirm(\''.translate(
'cal_event_cancel_this_instance_confirm').
'\');
">'.translate('cal_event_cancel_this_instance').'</a>';
1161 return translate('cal_event_cancel_link_default');
1164 }//end _getCancelLink()
1173 function _getModifyLink()
1175 if (isset($_REQUEST['SQ_CALENDAR_DATE'])) {
1176 return '<a href="?SQ_CALENDAR_VIEW=
event&SQ_CALENDAR_EVENT_ID=
'.$this->id.'&SQ_CALENDAR_EVENT_ACTION=modify1&SQ_CALENDAR_DATE=
'.$_REQUEST['SQ_CALENDAR_DATE
'].'">'.translate('cal_event_modify_this_instance').'</a>';
1178 return translate('cal_event_modify_link_default');
1181 }//end _getModifyLink()
1192 function processEventAction($action_name)
1195 switch ($action_name) {
1197 if (!isset($_REQUEST['SQ_CALENDAR_DATE'])) {
1198 trigger_localised_error('CAL0032', E_USER_WARNING);
1201 $res = '<form method="POST
" action="?SQ_CALENDAR_VIEW=
event&SQ_CALENDAR_EVENT_ID=
'.$this->id.'&SQ_CALENDAR_EVENT_ACTION=cancel2&SQ_CALENDAR_DATE=
'.$_REQUEST['SQ_CALENDAR_DATE
'].'"><table cellpadding="4
" border="0
">';
1202 $res .= '<tr><td style="vertical-align: top
">'.translate('cal_event_reason_for_cancellation').':</td><td><textarea rows="4
" cols="40
" name="event_cancellation_reason
"></textarea></td></tr>';
1203 $res .= '<tr><td colspan="2
"><input type="submit
" value="'.translate('cal_event_add_cancellation
').'" /> <input type="button
" value="'.translate('go_back
').'" onclick="document.location=\
''.$_SERVER[
'HTTP_REFERER'].
'\'" /></td></tr></table></form>';
1207 if ((!isset($_REQUEST['SQ_CALENDAR_DATE'])) || (!isset($_REQUEST['event_cancellation_reason']))) {
1208 trigger_localised_error('CAL0033', E_USER_WARNING);
1212 $cancel_event = $this->addCancellation($_REQUEST['SQ_CALENDAR_DATE'], $_REQUEST['event_cancellation_reason']);
1214 $res = '<p>'.translate('cal_event_cancel_rep_invite_message_1', $this->attr('name'), date('jS M Y', strtotime($_REQUEST['SQ_CALENDAR_DATE'].' 12:00:00 GMT'))).'</p>';
1215 $res .= '<p style="margin: 0px;
">'.translate('cal_event_cancel_rep_invite_message_2').'<p>';
1216 $res .= '<form style="margin: 0px;
float: left
" method="POST
" action="?SQ_CALENDAR_VIEW=
event&SQ_CALENDAR_EVENT_ID=
'.$cancel_event->id.'&SQ_CALENDAR_EVENT_ACTION=addreplacement&SQ_CALENDAR_DATE=
'.$_REQUEST['SQ_CALENDAR_DATE
'].'"><input type="submit
" value="'.translate('yes
').'" /></form><form style="margin: 0px 1ex;
float: left
" method="POST
" action="?SQ_CALENDAR_VIEW=
event&SQ_CALENDAR_EVENT_ID=
'.$this->id.'&SQ_CALENDAR_DATE=
'.$_REQUEST['SQ_CALENDAR_DATE
'].'"><input type="submit
" value="'.translate('no
').'" /></form>';
1220 if (!isset($_REQUEST['SQ_CALENDAR_DATE'])) {
1221 trigger_localised_error('CAL0034', E_USER_WARNING);
1224 $res = '<form method="POST
" action="?SQ_CALENDAR_VIEW=
event&SQ_CALENDAR_EVENT_ID=
'.$this->id.'&SQ_CALENDAR_EVENT_ACTION=modify2&SQ_CALENDAR_DATE=
'.$_REQUEST['SQ_CALENDAR_DATE
'].'"><table cellpadding="4
" border="0
">';
1226 $res .= '<tr><td style="vertical-align: top
">'.translate('cal_event_start_and_end').'</td><td>';
1228 $edit_fns = $this->getEditFns();
1229 $edit_fns->paintStartEndChooser($this, 'event');
1230 $res .= ob_get_contents();
1232 $res .= '</td></tr>';
1234 $res .= '<tr><td style="vertical-align: top
">'.translate('description').':</td><td><textarea name="event_description
">';
1235 $res .= $this->attr('description');
1236 $res .= '</textarea></td></tr>';
1238 $res .= '<tr><td colspan="2
"><input type="submit
" value="'.translate('cal_event_add_modification
').'" /> <input type="button
" value="'.translate('cancel
').'" onclick="document.location=\
''.$_SERVER[
'HTTP_REFERER'].
'\'" /></td></tr></table></form>';
1243 // Figure out the original details of the occurrence we're modifying
1244 $occurrence_start = '';
1245 $occurrence_end = '---------- --:--:--';
1246 if ($this->hasOccurrenceOnDate($_REQUEST['SQ_CALENDAR_DATE'])) {
1247 $occurrence_start_date = $_REQUEST['SQ_CALENDAR_DATE'];
1249 $occurrence_start_date = $this->getFirstOccurrenceAfter(date('Y-m-d', iso8601_ts($_REQUEST['SQ_CALENDAR_DATE']) - $this->getDuration()));
1251 $occurrence_start = $occurrence_start_date.' ';
1252 $occurrence_start .= ($this->getStartTime() ? $this->getStartTime().':00' : '--:--:--');
1254 if ($duration = $this->getDuration()) {
1255 $occurrence_end = date('Y-m-d', iso8601_ts($occurrence_start) + $duration).' ';
1256 $occurrence_end .= ($this->getEndTime() ? $this->getEndTime().':00' : '--:--:--');
1259 // Get the new details
1260 $edit_fns = $this->getEditFns();
1261 $new_details = $edit_fns->getStartEndChooserResult('event');
1263 // Compare old and new details
1264 if (($new_details['start'] == $occurrence_start) && ($new_details['end'] == $occurrence_end)) {
1265 // because the dates and times have not changed, we can just add a modification
1266 // with the new description
1267 $this->addModification($occurrence_start_date, $_REQUEST['event_description']);
1268 $res = '<p>'.translate('cal_event_instance_modified').'</p>';
1270 // dates/times have changed, so we have to cancel and then reschedule
1271 $cancellation_event =& $this->addCancellation($occurrence_start_date, translate('cal_event_rescheduled_note'));
1273 $replacement =& $cancellation_event->addReplacement($new_details['start'], $new_details['end'] , $_REQUEST['event_description']);
1275 $res = '<p>Event rescheduled</p>';
1276 $new_query_string_vars = Array(
1277 'SQ_CALENDAR_EVENT_ID' => $replacement->id,
1278 'SQ_CALENDAR_DATE' => $replacement->getStartDate(),
1279 'SQ_CALENDAR_EVENT_ACTION' => NULL,
1281 $res .= '<p><a href="'.htmlspecialchars(replace_query_string_vars($new_query_string_vars)).'">'.translate('cal_event_view_replacement_event').'</a></p>';
1286 $res = parent::processEventAction($action_name);
1291 }//end processEventAction()
1303 function &addCancellation($date, $reason)
1305 if (!$this->writeAccess('')) {
1306 trigger_localised_error('CAL0035', E_USER_WARNING);
1309 $GLOBALS['SQ_SYSTEM']->am->includeAsset('calendar_event_cancellation');
1310 if ($existing_link = $this->getExceptionLink($date)) {
1311 if ($existing_link['minor_type_code'] == 'calendar_event_cancellation') {
1312 $cancellation_event = $GLOBALS['SQ_SYSTEM']->am->getAsset($existing_link['minorid']);
1314 $GLOBALS['SQ_SYSTEM']->am->deleteAssetLink($existing_link['linkid']);
1315 $cancellation_event = new Calendar_Event_Cancellation();
1318 $cancellation_event = new Calendar_Event_Cancellation();
1320 $cancellation_event->setAttrValue('start_date', $date.' '.($this->getStartTime() ? $this->getStartTime().':00' : '--:--:--'));
1321 $end_date = date('Y-m-d', iso8601_ts($cancellation_event->attr('start_date')) + $this->getDuration());
1322 $cancellation_event->setAttrValue('end_date', $end_date.' '.($this->getEndTime() ? $this->getEndTime().':00' : '--:--:--'));
1323 $cancellation_event->setAttrValue('description', $reason);
1324 if (!$cancellation_event->id) {
1325 $link = Array('asset' => &$this, 'link_type' => SQ_LINK_TYPE_2, 'is_dependant' => 1, 'is_exclusive' => 0, 'value' => $date);
1326 $cancellation_event->create($link);
1328 if (!$GLOBALS['SQ_SYSTEM']->am->acquireLock($cancellation_event->id, 'attributes')) {
1329 trigger_localised_error('CAL0036', E_USER_WARNING, $cancellation_event->name);
1332 $cancellation_event->saveAttributes();
1333 $GLOBALS['SQ_SYSTEM']->am->releaseLock($cancellation_event->id, 'attributes');
1335 $cancellation_event->processStatusChange($this->status);
1336 return $cancellation_event;
1338 }//end addCancellation()
1350 function &addModification($date, $description)
1352 if (!$this->writeAccess('')) {
1353 trigger_localised_error('CAL0037', E_USER_WARNING);
1356 $GLOBALS['SQ_SYSTEM']->am->includeAsset('calendar_event_modification');
1358 if ($existing_link = $this->getExceptionLink($date)) {
1359 if ($existing_link['minor_type_code'] == 'calendar_event_modification') {
1360 $modification_event = $GLOBALS['SQ_SYSTEM']->am->getAsset($existing_link['minorid']);
1362 $GLOBALS['SQ_SYSTEM']->am->deleteAssetLink($existing_link['linkid']);
1363 $modification_event = new Calendar_Event_Modification();
1366 $modification_event = new Calendar_Event_Modification();
1368 $modification_event->setAttrValue('start_date', $date.' --:--:--');
1369 $modification_event->setAttrValue('description', $description);
1370 if (!$modification_event->id) {
1371 $link = Array('asset' => &$this, 'link_type' => SQ_LINK_TYPE_2, 'is_dependant' => 1, 'is_exclusive' => 0, 'value' => $date);
1372 $modification_event->create($link);
1374 if (!$GLOBALS['SQ_SYSTEM']->am->acquireLock($modification_event->id, 'attributes')) {
1375 trigger_localised_error('CAL0038', E_USER_WARNING, $modification_event->name);
1378 $modification_event->saveAttributes();
1379 $GLOBALS['SQ_SYSTEM']->am->releaseLock($modification_event->id, 'attributes');
1381 return $modification_event;
1383 }//end addModification()
1395 function cacheCalendarData($updating=TRUE)
1397 $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
1398 $db = MatrixDAL::getDb();
1400 $date_values = Array();
1401 foreach (Array('start_date', 'end_date') as $date_comp) {
1402 $date_values += Calendar_Common::getDateComponents($this->attr($date_comp), $date_comp.'_');
1405 // frequency field => as thy will be set in the standard attribute value table
1406 $date_values['frequency'] = substr($this->attr('frequency'),0,3);
1407 if (strlen($this->attr('frequency')) > 3) {
1408 $date_values['period'] = intval(substr($this->attr('frequency'),3));
1410 $date_values['period'] = 1;
1414 if (strtotime(substr($this->attr('stop_date'),0,10)) != -1) {
1415 $date_values['stop_date'] = substr($this->attr('stop_date'),0,10);
1418 $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
1421 // set the asset ids
1422 $date_values['assetid'] = $this->id;
1424 for (reset($date_values); NULL !== ($key = key($date_values)); next($date_values)) {
1425 if (is_null($date_values[$key]))
1426 $date_values[$key] = 'NULL';
1428 $date_values[$key] = MatrixDAL::quote($date_values[$key]);
1430 $val_string = implode(',', $date_values);
1435 '.implode(',', array_keys($date_values)).'
1443 $query = MatrixDAL::preparePdoQuery($sql);
1444 MatrixDAL::execPdoQuery($query);
1445 } catch (Exception $e) {
1446 throw new Exception($e->getMessage());
1450 // asset id becomes a where condition
1455 $set_array = Array();
1456 foreach ($date_values as $key => $value) {
1457 $set_array[] = $key.' = '.((is_null($value)) ? 'null' : MatrixDAL::quote($value));
1459 $sql .= implode(',', $set_array);
1461 assetid = :assetid';
1464 $query = MatrixDAL::preparePdoQuery($sql);
1465 MatrixDAL::bindValueToPdo($query, 'assetid', $this->id);
1466 MatrixDAL::execPdoQuery($query);
1467 } catch (Exception $e) {
1468 throw new Exception($e->getMessage());
1472 $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
1473 $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
1476 }//end cacheCalendarData()
1493 function getAvailableKeywords()
1495 $res = parent::getAvailableKeywords();
1497 $our_keywords[] = 'asset_attribute_start_date'; // = translate('start_date_iso'); //'Start date (iso8601)';
1498 $our_keywords[] = 'asset_attribute_end_date'; // = translate('end_date_iso'); //'End date (iso8601)';
1499 $our_keywords[] = 'event_start_date'; // = translate('start_date_only_readable'); //'Event Start Date';
1500 $our_keywords[] = 'event_end_date'; // = tralsate('end_date_only_readable'); //'Event End Date';
1501 $our_keywords[] = 'event_start_datetime'; // = translate('Event start date/time';
1502 $our_keywords[] = 'event_end_datetime'; // = 'Event end date/time';
1503 $our_keywords[] = 'event_start_time_12h'; // = 'Start time (12 hour)';
1504 $our_keywords[] = 'event_end_time_12h'; // = 'End time (12 hour)';
1505 $our_keywords[] = 'event_start_time_24h'; // = 'Start time (24 hour)';
1506 $our_keywords[] = 'event_end_time_24h'; // = 'End time (24 hour)';
1507 $our_keywords[] = 'event_start_time_ical'; // = 'Start time (iCalendar)';
1508 $our_keywords[] = 'event_end_time_ical'; // = 'End time (iCalendar)';
1509 $our_keywords[] = 'event_duration'; // = 'Duration of the Event';
1510 $our_keywords[] = 'event_start_datetime_'; // = dynamic keyword to print start date and time
1511 $our_keywords[] = 'event_end_datetime_'; // = dynamic keyword to print end date and time
1512 $our_keywords[] = 'event_frequency';
1513 $our_keywords[] = 'instance_end_datetime';
1514 $our_keywords[] = 'instance_start_datetime';
1515 $our_keywords[] = 'instance_start_datetime_';
1516 $our_keywords[] = 'instance_end_datetime_';
1517 $our_keywords[] = 'event_stop_date_';
1518 $our_keywords[] = 'event_ical_frequency';
1519 $our_keywords[] = 'event_ical_exceptions';
1520 $our_keywords[] = 'event_frequency_summary';
1522 foreach ($our_keywords as $keyword) {
1523 $res[$keyword] = translate('cal_evt_recur_keyword_'.$keyword);
1528 }//end getAvailableKeywords()