Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
calendar_event.inc
1 <?php
17 require_once SQ_INCLUDE_PATH.'/asset.inc';
18 require_once SQ_FUDGE_PATH.'/datetime_field/datetime_field.inc';
19 require_once SQ_FUDGE_PATH.'/general/datetime.inc';
20 require_once dirname(__FILE__).'/../lib/calendar_common.inc';
21 
35 class Calendar_Event extends Asset
36 {
37 
38 
45  function Calendar_Event($assetid=0)
46  {
47  $this->Asset($assetid);
48 
49  }//end constructor
50 
51 
62  function _preCreateCheck(&$link)
63  {
64  if (!parent::_preCreateCheck($link)) return FALSE;
65 
66  $name = $this->attr('name');
67  if ($GLOBALS['SQ_SYSTEM']->runLevelEnables(SQ_SECURITY_INTEGRITY) && ($name == '')) {
68  trigger_localised_error('CAL0008', E_USER_WARNING, $GLOBALS['SQ_SYSTEM']->am->getTypeInfo($this->type(), 'name'));
69  return FALSE;
70  }
71 
72  return TRUE;
73 
74  }//end _preCreateCheck()
75 
76 
87  function _createAdditional(&$link)
88  {
89  if (!parent::_createAdditional($link)) return FALSE;
90  $result = $this->cacheCalendarData(FALSE);
91  // set an initial web path
92  $initial_path = strtolower($this->attr('name'));
93  require_once SQ_INCLUDE_PATH.'/general_occasional.inc';
94  $valid_paths = make_valid_web_paths(Array($initial_path));
95  $good_paths = $GLOBALS['SQ_SYSTEM']->am->webPathsInUse($link['asset'], $valid_paths, $this->id, TRUE);
96  $result_paths = $this->saveWebPaths($good_paths);
97  return ($result && $result_paths);
98 
99  }//end _createAdditional()
100 
101 
112  function delete($release_lock=TRUE)
113  {
114  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
115  $db = MatrixDAL::getDb();
116  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
117 
118  try {
119  $bind_vars = Array (
120  'assetid' => $this->id,
121  );
122  $result = MatrixDAL::executeQuery('calendar_event', 'deleteCalendarEvent', $bind_vars);
123  } catch (Exception $e) {
124  throw new Exception('Unable to delete the eventid #:'.$this->id.' from the trash due to the following database error:'.$e->getMessage());
125  }//end try catch
126 
127  if (!parent::delete($release_lock)) {
128  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
129  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
130  return FALSE;
131  }
132 
133  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
134  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
135  return TRUE;
136 
137  }//end delete()
138 
139 
150  protected function _getName($short_name=FALSE, $contextid=NULL)
151  {
152  // No context specified, using the current context
153  if ($contextid === NULL) {
154  $contextid = $GLOBALS['SQ_SYSTEM']->getContextId();
155  }//end if
156 
157  // Obtain the attribute value for Name from the specified Context
158  $values = $GLOBALS['SQ_SYSTEM']->am->getAttributeValuesByName('name', $this->type(), Array($this->id), $contextid);
159  if (empty($values) === TRUE) {
160  return parent::_getName($short_name, $contextid);
161  } else {
162  return $values[$this->id];
163  }
164 
165  }//end _getName()
166 
167 
183  {
184  $keywords = parent::getAvailableKeywords();
185 
186  $our_keywords = Array();
187  $our_keywords[] = 'asset_attribute_start_date'; // = translate('start_date_iso'); //'Start date (iso8601)';
188  $our_keywords[] = 'asset_attribute_end_date'; // = translate('end_date_iso'); //'End date (iso8601)';
189  $our_keywords[] = 'event_start_date'; // = translate('start_date_only_readable'); //'Event Start Date';
190  $our_keywords[] = 'event_end_date'; // = tralsate('end_date_only_readable'); //'Event End Date';
191  $our_keywords[] = 'event_start_datetime'; // = translate('Event start date/time';
192  $our_keywords[] = 'event_end_datetime'; // = 'Event end date/time';
193  $our_keywords[] = 'event_start_time_12h'; // = 'Start time (12 hour)';
194  $our_keywords[] = 'event_end_time_12h'; // = 'End time (12 hour)';
195  $our_keywords[] = 'event_start_time_24h'; // = 'Start time (24 hour)';
196  $our_keywords[] = 'event_end_time_24h'; // = 'End time (24 hour)';
197  $our_keywords[] = 'event_short_start_time'; // = 'Short start time (12 hour)';
198  $our_keywords[] = 'event_short_end_time'; // = 'Short end time (12 hour)';
199  $our_keywords[] = 'event_start_time_ical'; // = 'Start time (iCalendar)';
200  $our_keywords[] = 'event_end_time_ical'; // = 'End time (iCalendar)';
201  $our_keywords[] = 'event_datetime_summary'; // = 'Friendly description of event dates and times';
202  $our_keywords[] = 'event_duration'; // = 'Duration of the Event';
203  $our_keywords[] = 'edit_link'; // = 'Link to edit this event in Limbo (if user has permission)';
204  $our_keywords[] = 'delete_link'; // = 'Link to delete this event altogether (if user has permission)';
205  $our_keywords[] = 'event_start_datetime_'; // = dynamic keyword to print start date and time
206  $our_keywords[] = 'event_end_datetime_'; // = dynamic keyword to print end date and time
207  $our_keywords[] = 'event_calendar_date_'; // = dynamic keyword to print calendar date
208 
209 
210  foreach ($our_keywords as $keyword) {
211  $keywords[$keyword] = translate('cal_evt_keyword_'.$keyword);
212  }
213 
214  return $keywords;
215 
216  }//end getAvailableKeywords()
217 
218 
232  function _getAllowedLinks()
233  {
234  return Array(
235  SQ_LINK_TYPE_1 => Array(
236  'file' => Array('card' => 'M', 'exclusive' => FALSE),
237  'page' => Array('card' => 'M', 'exclusive' => FALSE),
238  ),
239  SQ_LINK_TYPE_2 => Array(
240  'file' => Array('card' => 'M', 'exclusive' => FALSE),
241  'page' => Array('card' => 'M', 'exclusive' => FALSE),
242  ),
243  SQ_LINK_TYPE_3 => Array(),
244  SQ_LINK_NOTICE => Array(
245  'image' => Array('card' => 1, 'exclusive' => FALSE),
246  'design' => Array('card' => 'M', 'exclusive' => FALSE),
247  'paint_layout_page' => Array('card' => 'M', 'exclusive' => FALSE),
248  ),
249  );
250 
251  }//end _getAllowedLinks()
252 
253 
260  function _getDeleteLink()
261  {
262  if (TRUE === ($msg = $GLOBALS['SQ_SYSTEM']->am->couldTrashAsset($this->id))) {
263  $res = '<a href="?SQ_CALENDAR_EVENT_ID='.$this->id.'&amp;SQ_CALENDAR_EVENT_ACTION=delete';
264  if (isset($_REQUEST['SQ_CALENDAR_DATE'])) {
265  $res .= '&amp;SQ_CALENDAR_DATE='.$_REQUEST['SQ_CALENDAR_DATE'];
266  }
267  $res .= '" onclick="return confirm(js_translate(\'confirm_delete_event\'));">'.translate('delete').'</a>';
268  return $res;
269  } else {
270  return '';
271  }
272 
273  }//end _getDeleteLink()
274 
275 
286  function saveAttributes($dont_run_updated=FALSE)
287  {
288  $start_date = $this->attr('start_date');
289  $end_date = $this->attr('end_date');
290 
291  // work out if we have any 'null date' or 'null time' sections
292  $start_has_time = $this->getStartTime();
293  $end_has_time = $this->getEndTime();
294  $start_has_date = $this->getStartDate();
295  $end_has_date = $this->getEndDate();
296 
297  if ($GLOBALS['SQ_SYSTEM']->runLevelEnables(SQ_SECURITY_INTEGRITY)) {
298 
299  // All events must have a starting date at least!
300  if (!$start_has_date) {
301  trigger_localised_error('CAL0009', E_USER_WARNING);
302  return FALSE;
303  }
304 
305  // cannot have End Date being like '---------- 11:00:00'
306  if (!$end_has_date && $end_has_time) {
307  trigger_localised_error('CAL0010', E_USER_WARNING);
308  return FALSE;
309  }
310 
311  // Cannot have an end time if you have no start time
312  if ($end_has_time && (!$start_has_time)) {
313  trigger_localised_error('CAL0011', E_USER_WARNING);
314  return FALSE;
315  }
316 
317  // Cannot have an end date and start time if you have no end time
318  if ($end_has_date && $start_has_time && (!$end_has_time)) {
319  trigger_localised_error('CAL0012', E_USER_WARNING);
320  return FALSE;
321  }
322 
323  // If an End Date is specified (and we need date component so we can use that to check),
324  // the End Date must be no earlier than the start Date
325  if ($end_has_date) {
326  if (iso8601_ts($end_date) < iso8601_ts($start_date)) {
327  trigger_localised_error('CAL0013', E_USER_WARNING, $GLOBALS['SQ_SYSTEM']->am->getTypeInfo($this->type(), 'name'));
328  return FALSE;
329  }
330  }
331 
332  }//end if
333 
334  // oh no, we're not using this to display anything... just to use its units extraction :-)
335  $params = Array();
336  $value = '';
337  $datetime = new Datetime_Field('', $value, $params);
338 
339  // check individual sections to make sure we can't commit part dates like '16th, 2005 48'
340  $start_components = $datetime->strToUnitsArray($start_date);
341  $end_components = $datetime->strToUnitsArray($end_date);
342 
343  // don't need to check Start Date's date component as it is required!
344  // must check other parts of both Start and End Date so a meaningful date is stored
345 
346  // For dates, this means all three parts of the date have a value
347  if ($end_has_date && (($end_components['d'] == -1) || ($end_components['m'] == -1) || ($end_components['y'] == -1))) {
348  trigger_localised_error('CAL0014', E_USER_WARNING);
349  return FALSE;
350  }
351 
352  // For times, at least hour and minute must be specified. You can get away with not specifying
353  // seconds, it's optional.
354  if ($start_has_time && (($start_components['h'] == -1) || ($start_components['i'] == -1))) {
355  trigger_localised_error('CAL0015', E_USER_WARNING);
356  return FALSE;
357  }
358 
359  if ($end_has_time && (($end_components['h'] == -1) || ($end_components['i'] == -1))) {
360  trigger_localised_error('CAL0016', E_USER_WARNING);
361  return FALSE;
362  }
363 
364  // cache all the calendar data into another table so the queries for the calendar
365  // page go super-mega-hyperturbo (but only if already created)
366  if (!empty($this->id) && !$dont_run_updated) {
367  if (!$this->cacheCalendarData()) return FALSE;
368  }
369  $treeid = Array();
370 
371  // bug fix #5364 Recurring Calendar Event: Time Changes don't get sent to child Event Modifications
372  // we need to make ssure to cascade the changes to and children of the recurring event,if thats the
373  // asset type we are updating.
374  // also make sure "THIS" asset does have the valid treeid before we try to get its children
375  if ($this->id) $treeid = $GLOBALS['SQ_SYSTEM']->am->getAssetTreeids($this->id);
376  if (($this->id) && $this->type() == 'calendar_event_recurring' && $GLOBALS['SQ_SYSTEM']->runLevelEnables(SQ_SECURITY_INTEGRITY) && !empty($treeid)) {
377  $events_to_update = $GLOBALS['SQ_SYSTEM']->am->getChildren($this->id, 'calendar_event_modification');
378  // because we do not have locks on the child modofication assets
379  // we need to set the run level so that we can update these assets
380  $GLOBALS['SQ_SYSTEM']->setRunLevel(SQ_RUN_LEVEL_FORCED);
381  foreach ($events_to_update as $event_id => $info) {
382  $modification_event = $GLOBALS['SQ_SYSTEM']->am->getAsset($event_id);
383  if (!$modification_event->saveAttributes()) {
384  $GLOBALS['SQ_SYSTEM']->restoreRunLevel();
385  return FALSE;
386  }
387  }
388  $GLOBALS['SQ_SYSTEM']->restoreRunLevel();
389  }
390 
391  // all sweet, so it seems
392  return parent::saveAttributes($dont_run_updated);
393 
394  }//end saveAttributes()
395 
396 
419  function cloneComponents(&$clone, $components, $override=FALSE)
420  {
421  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
422  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
423 
424  if (!parent::cloneComponents($clone, $components, $override)) {
425  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
426  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
427  return FALSE;
428  }
429 
430  if (in_array('all', $components) || in_array('attributes', $components)) {
431  if (!$clone->cacheCalendarData(FALSE)) {
432  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
433  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
434  return FALSE;
435  }
436  }
437 
438  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
439  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
440  return TRUE;
441 
442  }//end cloneComponents()
443 
444 
454  function getStartDate()
455  {
456  $res = substr($this->attr('start_date'), 0, 10);
457  return ($res == '----------') ? FALSE : $res;
458 
459  }//end getStartDate()
460 
461 
471  function getEndDate()
472  {
473  $res = substr($this->attr('end_date'), 0, 10);
474  return ($res == '----------') ? FALSE : $res;
475 
476  }//end getEndDate()
477 
478 
488  function getStartTime()
489  {
490  $res = substr($this->attr('start_date'), 11, 5);
491  return ($res == '--:--') ? FALSE : $res;
492 
493  }//end getStartTime()
494 
495 
505  function getEndTime()
506  {
507  $res = substr($this->attr('end_date'), 11, 5);
508  return ($res == '--:--') ? FALSE : $res;
509 
510  }//end getEndTime()
511 
512 
524  function getDuration()
525  {
526  $seconds_per_day = 24 * 60 * 60;
527 
528  $start_date = $this->attr('start_date');
529  $end_date = $this->attr('end_date');
530 
531  // work out if we have any 'null date' or 'null time' sections
532  $start_has_time = $this->getStartTime();
533  $end_has_time = $this->getEndTime();
534  $start_has_date = $this->getStartDate();
535  $end_has_date = $this->getEndDate();
536 
537  if (!$start_has_date) return NULL;
538 
539  if (!$end_has_date) {
540  // single point in time, and so it has no duration
541  return 0;
542  }
543 
544  // NOTE: no need to replace null time fields with 'midnight' (00:00:00) because the
545  // ISO-to-timestamp conversion function already recognises that it's not a full datetime
546  // if that's the case
547 
548  if (!$start_has_time && !$end_has_time) {
549  // in a multiple day event without times it's assumed to be the start of the start date
550  // (ie. 00:00) to the end of the end date (ie. 00:00 the day after end date).
551  return iso8601_ts($end_date) - iso8601_ts($start_date) + $seconds_per_day;
552 
553  } else {
554  // all fields specified, from one time point to another
555  return iso8601_ts($end_date) - iso8601_ts($start_date);
556 
557  }
558 
559  }//end getDuration()
560 
561 
570  function getFriendlyStart()
571  {
572  if ($this->getStartTime() !== FALSE) {
573  return readable_datetime(iso8601_ts($this->attr('start_date')));
574  } else {
575  return date('jS M Y', iso8601_ts($this->attr('start_date')));
576  }
577 
578  }//end getFriendlyStart()
579 
580 
589  function getFriendlyEnd()
590  {
591  if ($this->getEndTime() !== FALSE) {
592  return readable_datetime(iso8601_ts($this->attr('end_date')));
593  } else if (iso8601_ts($this->attr('end_date')) == -1) {
594  return '';
595  } else {
596  return date('jS M Y', iso8601_ts($this->attr('end_date')));
597  }
598 
599  }//end getFriendlyEnd()
600 
601 
624  {
625  if (substr($this->attr('start_date'), 0, 10) == substr($this->attr('end_date'), 0, 10)) {
626  // start and end dates are the same
627  if (!$this->getStartTime()) {
628  // no start time, so must be an all day event
629  return $this->getFriendlyStart().' (all day)';
630  } else if (($this->getStartTime() == $this->getEndTime())) {
631  // show start date and time only
632  return $this->getFriendlyStart();
633  } else {
634  // show date and start/end times
635  return $this->getFriendlyStart().'-'.date('g:ia', iso8601_ts($this->attr('end_date')));
636  }
637  } else if (iso8601_ts($this->attr('end_date')) == -1) {
638  return $this->getFriendlyStart();
639  } else {
640  return $this->getFriendlyStart().' - '.$this->getFriendlyEnd();
641  }
642 
643  }//end getFriendlyDatesAndTimes()
644 
645 
652  function printBody()
653  {
654  require_once SQ_FUDGE_PATH.'/general/datetime.inc';
655  ?>
656  <table border="0" cellspacing="2" cellpadding="2">
657  <tr>
658  <td><b>Event Name</b></td>
659  <td><?php echo $this->attr('name'); ?></td>
660  </tr>
661  <tr>
662  <td><b>Start Date</b></td>
663  <td><?php echo $this->getFriendlyStart(); ?></td>
664  </tr>
665  <tr>
666  <td><b>End Date</b></td>
667  <td><?php echo $this->getFriendlyEnd(); ?></td>
668  </tr>
669  <tr>
670  <td><b>Duration</b></td>
671  <td><?php
672  // give useful info if no duration - easy_time_total returns empty string
673  $total_time = easy_time_total($this->getDuration(), TRUE);
674  echo (empty($total_time) ? 'N/A' : $total_time);
675  ?></td>
676  </tr>
677  <tr>
678  <td><b>Description</b></td>
679  <td><?php echo $this->getKeywordReplacement('asset_attribute_description'); ?></td>
680  </tr>
681  </table>
682  <?php
683 
684  }//end printBody()
685 
686 
698  function processEventAction($action_name)
699  {
700  switch ($action_name) {
701  case 'move':
702  if (isset($_REQUEST['SQ_CALENDAR_OLD_LOC']) && !empty($_REQUEST['SQ_CALENDAR_OLD_LOC'])) {
703  $old_link = $GLOBALS['SQ_SYSTEM']->am->getLinkByAsset($_REQUEST['SQ_CALENDAR_OLD_LOC'], $this->id);
704  if (empty($old_link)) {
705  trigger_localised_error('CAL0017', E_USER_WARNING, $_REQUEST['SQ_CALENDAR_OLD_LOC'], $this->id);
706  return '';
707  }
708  if (!$GLOBALS['SQ_SYSTEM']->am->moveLink($old_link['linkid'], $_REQUEST['SQ_CALENDAR_NEW_LOC'], $old_link['link_type'], -1)) {
709  trigger_localised_error('CAL0018', E_USER_WARNING, $_REQUEST['SQ_CALENDAR_OLD_LOC'], $_REQUEST['SQ_CALENDAR_NEW_LOC']);
710  return '';
711  }
712  }
713  if (!isset($_REQUEST['SQ_CALENDAR_NEW_DATE'])) {
714  trigger_localised_error('CAL0019', E_USER_WARNING);
715  return '';
716  }
717  $duration = $this->getDuration();
718  if (!isset($_REQUEST['SQ_CALENDAR_NEW_TIME']) || empty($_REQUEST['SQ_CALENDAR_NEW_TIME'])) {
719  $_REQUEST['SQ_CALENDAR_NEW_TIME'] = '--:--';
720  }
721  $this->setAttrValue('start_date', $_REQUEST['SQ_CALENDAR_NEW_DATE'].' '.$_REQUEST['SQ_CALENDAR_NEW_TIME'].':--');
722  $current_end_date = $this->getEndDate();
723  if ($current_end_date) {
724  $new_end_date_ts = iso8601_ts($this->attr('start_date')) + $duration;
725  $new_end_date = date('Y-m-d', $new_end_date_ts);
726  $new_end_time = $this->getEndTime() ? date('H:i:00', $new_end_date_ts) : '--:--:--';
727  $this->setAttrValue('end_date', $new_end_date.' '.$new_end_time);
728  }
729  if (!$GLOBALS['SQ_SYSTEM']->am->acquireLock($this->id, 'attributes')) {
730  trigger_localised_error('CAL0020', E_USER_WARNING, $this->name, $this->id);
731  return '';
732  }
733  $this->saveAttributes();
734  $GLOBALS['SQ_SYSTEM']->am->releaseLock($this->id, 'attributes');
735  break;
736 
737  case 'delete':
738  $GLOBALS['SQ_SYSTEM']->am->trashAsset($this->id);
739  $this->updateLookups();
740  break;
741 
742  default:
743  trigger_localised_error('CAL0021', E_USER_WARNING, $action_name);
744  return '';
745  break;
746  }//end switch
747 
748  }//end processEventAction()
749 
750 
762  function cacheCalendarData($updating=TRUE)
763  {
764  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
765  $db = MatrixDal::getDb();
766 
767  $date_values = Array();
768 
769  foreach (Array('start_date', 'end_date') as $date_comp) {
770  $iso = $this->attr($date_comp);
771 
772  if (iso8601_time_component($iso) === FALSE) {
773  if (($date_comp == 'end_date') && (iso8601_date_component($iso) !== FALSE)) {
774  $iso = substr($iso, 0, 10).' 24:00:00';
775  }
776  } else {
777  // we know the seconds aren't going to be there, so zero them so we can
778  // use the getDate() niceness
779  $iso = substr($iso, 0, 16).':00';
780  }
781 
782  // we have the best, now get the rest
783  $date_values += Calendar_Common::getDateComponents($iso, $date_comp.'_');
784  }
785 
786  // frequency field => blank for standard events, overridden in recurring
787  $date_values['frequency'] = '';
788 
789  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
790 
791  if (!$updating) {
792  // set the asset ids
793  $date_values['assetid'] = $this->id;
794 
795  for (reset($date_values); NULL !== ($key = key($date_values)); next($date_values)) {
796  if (is_null($date_values[$key]))
797  $date_values[$key] = 'NULL';
798  else
799  $date_values[$key] = MatrixDAL::quote($date_values[$key]);
800  }
801  $val_string = implode(',', $date_values);
802 
803  $sql = 'INSERT INTO
804  sq_cal_date_val
805  (
806  '.implode(',', array_keys($date_values)).'
807  )
808  VALUES
809  (
810  '.$val_string.'
811  )';
812 
813  try {
814  $query = MatrixDAL::preparePdoQuery($sql);
815  MatrixDAL::execPdoQuery($query);
816  } catch (Exception $e) {
817  throw new Exception($e->getMessage());
818  }
819  } else {
820  // asset id becomes a where condition
821  $sql = 'UPDATE
822  sq_cal_date_val
823  SET ';
824 
825  $set_array = Array();
826  foreach ($date_values as $key => $value) {
827  $set_array[] = $key.' = '.((is_null($value)) ? 'null' : MatrixDAL::quote($value));
828  }
829  $sql .= implode(',', $set_array);
830  $sql .=' WHERE
831  assetid = :assetid';
832 
833  try {
834  $query = MatrixDAL::preparePdoQuery($sql);
835  MatrixDAL::bindValueToPdo($query, 'assetid', $this->id);
836  MatrixDAL::execPdoQuery($query);
837  } catch (Exception $e) {
838  throw new Exception($e->getMessage());
839  }
840  }
841 
842  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
843  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
844 
845  return TRUE;
846 
847  }//end cacheCalendarData()
848 
849 
864  function getKeywordReplacement($keyword)
865  {
866  $end_date_not_set = ($this->getEndDate() === FALSE);
867  $start_time_not_set = ($this->getStartTime() === FALSE);
868  $end_time_not_set = ($this->getEndTime() === FALSE);
869 
870  $keyword = parse_keyword($keyword, $modifiers);
871 
872  switch ($keyword) {
873  case 'event_name':
874  $replacement = $this->name;
875  break;
876 
877  case 'event_start_date':
878  $replacement = date('jS M Y', iso8601_ts($this->attr('start_date')));
879  break;
880 
881  case 'event_start_time_12h':
882  $replacement = $start_time_not_set ? '' : date('h:i a', iso8601_ts($this->attr('start_date')));
883  break;
884 
885  case 'event_start_time_24h':
886  $replacement = $start_time_not_set ? '' : date('H:i', iso8601_ts($this->attr('start_date')));
887  break;
888 
889  case 'event_start_time_ical':
890  // If theres no time bit, then only use the date portion to get the correct iCal timestamp
891  if (preg_match("/^(.*?) (--):(--):(--)$/", $this->attr('start_date'))) {
892  $replacement = date('Ymd', iso8601_ts($this->attr('start_date')));
893  } else {
894  $replacement = date('Ymd\THis', iso8601_ts($this->attr('start_date')));
895  }
896  break;
897 
898  case 'event_end_date':
899  // In the case of 'end_date' of the first instance is not set
900  $replacement = $end_date_not_set ? '' : date('jS M Y', iso8601_ts($this->attr('end_date')));
901  break;
902 
903  case 'event_end_time_12h':
904  $replacement = $end_time_not_set ? '' : date('h:i a', iso8601_ts($this->attr('end_date')));
905  break;
906 
907  case 'event_end_time_24h':
908  $replacement = $end_time_not_set ? '' : date('H:i', iso8601_ts($this->attr('end_date')));
909  break;
910 
911  case 'event_short_start_time':
912  if ($start_time_not_set) {
913  $replacement = '';
914  } else {
915  $mins = date('i', iso8601_ts($this->attr('start_date')));
916  if ($mins == '00') {
917  $replacement = date('ga', iso8601_ts($this->attr('start_date')));
918  } else {
919  $replacement = date('g:ia', iso8601_ts($this->attr('start_date')));
920  }
921  }
922  break;
923 
924  case 'event_short_end_time':
925  if ($start_time_not_set) {
926  $replacement = '';
927  } else {
928  $mins = date('i', iso8601_ts($this->attr('end_date')));
929  if ($mins == '00') {
930  $replacement = date('ga', iso8601_ts($this->attr('end_date')));
931  } else {
932  $replacement = date('g:ia', iso8601_ts($this->attr('end_date')));
933  }
934  }
935  break;
936 
937  case 'event_end_time_ical':
938  if ($end_date_not_set) {
939  $replacement = '';
940  } else {
941  // If theres no end time for given end date then accourding to iCal
942  // standards this means end date is next day without time bit but
943  // this is confusing and misleading for the users so as a fix to
944  // issue reported on #5359 iCal date keyword prints incorrected if
945  // end date has no time, we will let the end date be according to
946  // hCalendar standards. More information on bug report's comments
947  $no_endtime_pattern = "/^(....)-(..)-([0-9]{2}) (--:--:--)$/";
948  $replacement = "$1-$2-$3";
949  if (preg_match($no_endtime_pattern, $this->attr('end_date'), $matches)) {
950  $end_date = preg_replace($no_endtime_pattern, $replacement, $this->attr('end_date'));
951  } else {
952  $end_date = $this->attr('end_date');
953  }
954 
955  // Don't worry about possibility of invalid date resulting from incrementing
956  // the day bit above; php's date() will handle it correctly
957  $replacement = preg_match("/..:..:..$/",$end_date) ? date('Ymd\THis', iso8601_ts($end_date)) : date('Ymd', iso8601_ts($end_date));
958  }
959  break;
960 
961  case 'event_start_datetime':
962  $replacement = $this->getFriendlyStart();
963  break;
964 
965  case 'event_end_datetime':
966  $replacement = $this->getFriendlyEnd();
967  break;
968 
969  case 'event_datetime_summary':
970  $replacement = $this->getFriendlyDatesAndTimes();
971  break;
972 
973  case 'event_duration':
974  // give useful info if no duration (single point in time) - easy_time_total returns empty string
975  $total_time = easy_time_total($this->getDuration(), TRUE);
976  if (empty($total_time)) $total_time = 'N/A';
977  $replacement = $total_time;
978  break;
979 
980  case 'edit_link':
981  $replacement = $this->writeAccess('') ? '<a href="'.htmlentities(replace_query_string_vars(Array('SQ_CALENDAR_VIEW'=>'edit', 'SQ_CALENDAR_EVENT_ID'=>$this->id))).'">'.translate('cal_event_edit_link_text').'</a>' : '';
982  break;
983 
984  case 'delete_link':
985  $replacement = $this->_getDeleteLink();
986  break;
987 
988  case 'instance_start_datetime':
989 
990  $start_ts = isset($this->vars['start_date_ts']) ? $this->attr('start_date_ts') : '';
991  if (!empty($start_ts)) {
992  $replacement = date('Y-m-d H:i', $start_ts);
993  }
994  break;
995 
996  case 'instance_end_datetime':
997  $end_ts = isset($this->vars['end_date_ts']) ? $this->attr('end_date_ts') : '';
998  if (!empty($end_ts)) {
999  $replacement = empty($end_ts) ? '' : date('Y-m-d H:i', $end_ts);
1000  }
1001  break;
1002 
1003  default:
1004  // if the keyword at this point starts with event_start_datetime_ or event_end_datetime_
1005  // it means this is a dynamic keyword to display a date
1006  preg_match('/^event_start_datetime_(.+)/', $keyword, $matches);
1007  if (!empty($matches)) {
1008  $replacement = date($matches[1], iso8601_ts($this->attr('start_date')));
1009  }
1010  preg_match('/^event_end_datetime_(.+)/', $keyword, $matches);
1011  if (!empty($matches)) {
1012  $replacement = $end_date_not_set ? '' : date($matches[1], iso8601_ts($this->attr('end_date')));
1013  }
1014 
1015  preg_match('/^event_calendar_date_(.+)/', $keyword, $matches);
1016  if (!empty($matches) && !empty($_REQUEST['SQ_CALENDAR_DATE'])) {
1017  $replacement = date($matches[1], strtotime($_REQUEST['SQ_CALENDAR_DATE']));
1018  }
1019 
1020  // Event instance keywords
1021  if (isset($this->vars['start_date_ts'])) {
1022  $start_ts = $this->attr('start_date_ts');
1023  preg_match('/^instance_start_datetime_(.+)/', $keyword, $matches);
1024  if (!empty($matches)) {
1025  if ($matches[1] == 'ical') {
1026  $replacement = empty($start_ts) ? '' : date('Ymd\THis', $start_ts);
1027  } else {
1028  $replacement = empty($start_ts) ? '' : date($matches[1], $start_ts);
1029  }
1030  }//end if
1031  }
1032  if (isset($this->vars['end_date_ts'])) {
1033  $end_ts = $this->attr('end_date_ts');
1034  preg_match('/^instance_end_datetime_(.+)/', $keyword, $matches);
1035  if (!empty($matches)) {
1036  if ($matches[1] == 'ical') {
1037  $replacement = empty($end_ts) ? '' : date('Ymd\THis', $end_ts);
1038  } else {
1039  $replacement = empty($end_ts) ? '' : date($matches[1], $end_ts);
1040  }
1041  }//end if
1042  }
1043 
1044  if (empty($replacement)) $replacement = parent::getKeywordReplacement($keyword);
1045  break;
1046 
1047  }//end switch
1048 
1049  apply_keyword_modifiers($replacement, $modifiers, Array('assetid' => $this->id));
1050 
1051  return $replacement;
1052 
1053  }//end getKeywordReplacement()
1054 
1055 
1065  public function getAsset($whole_assetid)
1066  {
1067  $asset = NULL;
1068  $assetid_parts = explode(':', $whole_assetid);
1069 
1070  $assetid = $assetid_parts[0];
1071  if (empty($assetid_parts[1])) {
1072  return $asset;
1073  } else {
1074  $shdw_part_data = explode(',', $assetid_parts[1]);
1075  $instance_data = Array();
1076  foreach($shdw_part_data as $data) {
1077  list($key, $val) = explode("=", $data);
1078  $instance_data[$key] = $val;
1079  }
1080  if (!$GLOBALS['SQ_SYSTEM']->am->getAssetInfo($assetid)) {
1081  return $asset;
1082  }
1083  $event_asset = clone $GLOBALS['SQ_SYSTEM']->am->getAsset($assetid);
1084 
1085  $event_asset->full_id = $whole_assetid;
1086  foreach($instance_data as $attr => $value) {
1087  $event_asset->vars[$attr]['attrid'] = 0;
1088  $event_asset->vars[$attr]['type'] = 'text';
1089  $event_asset->vars[$attr]['value'] = $value;
1090  $event_asset->vars[$attr]['is_contextable'] = 0;
1091  }
1092  }
1093 
1094  return $event_asset;
1095 
1096  }//end getAsset()
1097 
1098 
1113  public function getAssetInfo(Array $assetids, $type_code=Array(), $strict_type_code=TRUE, $field='')
1114  {
1115  $info = Array();
1116  foreach ($assetids as $whole_assetid) {
1117  $assetid_parts = explode(':', $whole_assetid);
1118  $assetid = $assetid_parts[0];
1119  if (empty($assetid_parts[1])) {
1120  $asset_type = $this->type();
1121  } else {
1122  $event_data_raw = explode(',', $assetid_parts[1]);
1123  $event_data = Array();
1124  foreach($event_data_raw as $event) {
1125  list($key, $val) = explode("=", $event);
1126  $event_data[$key] = $val;
1127  }
1128  $asset_type = $event_data['type_code'];
1129  }
1130 
1131  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($assetid);
1132  // if a sort field is specified then return only that field value else return all of the fields
1133  if (!empty($field)) {
1134  if (isset($event_data[$field])) {
1135  $info[$whole_assetid] = $event_data[$field];
1136  } else if (isset($asset->{$field})) {
1137  $info[$whole_assetid] = $asset->{$field};
1138  } else {
1139  trigger_error('Invalid field for the asset type Calendar Event asset', E_USER_ERROR);
1140  }
1141  } else {
1142  $info[$whole_assetid] = Array(
1143  'type_code' => $asset_type,
1144  'version' => $asset->version,
1145  'name' => $asset->name,
1146  'short_name' => $asset->short_name,
1147  'status' => $asset->status,
1148  'languages' => '',
1149  'charset' => '',
1150  'force_secure' => '0',
1151  'created' => $asset->getKeywordReplacement('asset_created'),
1152  'created_userid' => $asset->created_userid,
1153  'updated' => $asset->getKeywordReplacement('asset_updated'),
1154  'updated_userid' => $asset->updated_userid,
1155  'published' => $asset->getKeywordReplacement('asset_published'),
1156  'published_userid' => $asset->published_userid,
1157  'status_changed' => $asset->getKeywordReplacement('asset_status_changed'),
1158  'status_changed_userid' => $asset->status_changed_userid,
1159  );
1160  }//end if field not empty
1161  }//end foreach of assetids
1162 
1163  return $info;
1164 
1165  }//end getAssetInfo()
1166 
1167 
1183  public function getAttributeValuesByName($attr_name, $asset_type, $assetids, $contextid=NULL)
1184  {
1185  if (empty($assetids)) return Array();
1186 
1187  $real_assetids = Array();
1188  foreach($assetids as $full_assetid) {
1189  if (strpos($full_assetid, ':') !== FALSE) {
1190  list($real_assetids[]) = explode(':', $full_assetid);
1191  } else {
1192  $real_assetids[] = $full_assetid;
1193  }
1194  }//end foreach
1195 
1196  $real_res = $GLOBALS['SQ_SYSTEM']->am->getAttributeValuesByName($attr_name, $asset_type, $real_assetids, $contextid);
1197 
1198  $res = Array();
1199  foreach($assetids as $full_assetid) {
1200  list($real_assetid) = explode(':', $full_assetid);
1201  $res[$full_assetid] = isset($real_res[$real_assetid]) ? $real_res[$real_assetid] : '';
1202  }//end foreach
1203 
1204  return $res;
1205 
1206  }//end getAttributeValuesByName()
1207 
1208 
1209 }//end class
1210 
1211 ?>