diff options
Diffstat (limited to 'mod/event_calendar/models')
-rw-r--r-- | mod/event_calendar/models/model.php | 2518 |
1 files changed, 2518 insertions, 0 deletions
diff --git a/mod/event_calendar/models/model.php b/mod/event_calendar/models/model.php new file mode 100644 index 000000000..7b4698f98 --- /dev/null +++ b/mod/event_calendar/models/model.php @@ -0,0 +1,2518 @@ +<?php +/** + * Elgg event model + * + * @package event_calendar + * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU Public License version 2 + * @author Kevin Jardine <kevin@radagast.biz> + * @copyright Radagast Solutions 2008-2011 + * @link http://radagast.biz/ + * + */ + +function event_calendar_get_event_for_edit($event_id) { + if ($event_id && $event = get_entity($event_id)) { + if ($event->canEdit()) { + return $event; + } else { + return false; + } + } else { + return false; + } +} + +// converts to time in minutes since midnight +function event_calendar_convert_to_time($hour,$minute,$meridian) { + if ($meridian) { + if ($meridian == 'am') { + if ($hour == 12) { + $hour = 0; + } + } else { + if ($hour < 12) { + $hour += 12; + } + } + } + return 60*$hour+$minute; +} + +// returns the event or FALSE +function event_calendar_set_event_from_form($event_guid,$group_guid) { + + $event_calendar_times = elgg_get_plugin_setting('times', 'event_calendar'); + $event_calendar_region_display = elgg_get_plugin_setting('region_display', 'event_calendar'); + $event_calendar_type_display = elgg_get_plugin_setting('type_display', 'event_calendar'); + $event_calendar_spots_display = elgg_get_plugin_setting('spots_display', 'event_calendar'); + $event_calendar_hide_end = elgg_get_plugin_setting('hide_end', 'event_calendar'); + $event_calendar_more_required = elgg_get_plugin_setting('more_required', 'event_calendar'); + $event_calendar_personal_manage = elgg_get_plugin_setting('personal_manage', 'event_calendar'); + $event_calendar_repeating_events = elgg_get_plugin_setting('repeating_events', 'event_calendar'); + $schedule_type = get_input('schedule_type'); + + if ($event_calendar_more_required == 'yes') { + $required_fields = array('title','venue','start_date', + 'brief_description','fees','contact','organiser', + 'tags'); + + if ($event_calendar_times != 'no') { + $required_fields[] = 'start_time'; + if ($event_calendar_hide_end != 'yes') { + $required_fields[] = 'end_time'; + } + } + if ($event_calendar_region_display == 'yes') { + $required_fields[] = 'region'; + } + if ($event_calendar_type_display == 'yes') { + $required_fields[] = 'event_type'; + } + if ($event_calendar_spots_display == 'yes') { + $required_fields[] = 'spots'; + } + } else { + $required_fields = array('title'); + } + + if ($event_guid) { + $event = get_entity($event_guid); + if (!elgg_instanceof($event, 'object', 'event_calendar')) { + // do nothing because this is a bad event guid + return FALSE; + } + } else { + $user_guid = elgg_get_logged_in_user_guid(); + $event = new ElggObject(); + $event->subtype = 'event_calendar'; + $event->owner_guid = $user_guid; + if ($group_guid) { + $event->container_guid = $group_guid; + } else { + $event->container_guid = $event->owner_guid; + } + } + $event->access_id = get_input('access_id'); + $event->title = get_input('title'); + $event->description = get_input('description'); + $event->venue = get_input('venue'); + + if ($schedule_type != 'poll') { + $start_date_text = trim(get_input('start_date')); + /*$event->original_start_date = get_input('start_date'); + //$end_date = trim(get_input('end_date','')); + // convert start date from current server time to GMT + $start_date_text = gmdate("Y-m-d",$start_date); + //$event->munged_start_date_string = $start_date_text." ".date_default_timezone_get();*/ + + // TODO: is the timezone bit necessary? + $event->start_date = strtotime($start_date_text." GMT"); + $end_date_text = trim(get_input('end_date','')); + //$event->original_end_date = get_input('end_date'); + if ($end_date_text) { + $event->end_date = strtotime($end_date_text." GMT"); + //$event->munged_end_date_string = $end_date_text." ".date_default_timezone_get(); + } else { + $event->end_date = ''; + } + + if ($event_calendar_times != 'no') { + $hour = get_input('start_time_hour',''); + $minute = get_input('start_time_minute',''); + $meridian = get_input('start_time_meridian',''); + if (is_numeric($hour) && is_numeric($minute)) { + $event->start_time = event_calendar_convert_to_time($hour,$minute,$meridian); + } else { + $event->start_time = ''; + } + $hour = get_input('end_time_hour',''); + $minute = get_input('end_time_minute',''); + $meridian = get_input('end_time_meridian',''); + if (is_numeric($hour) && is_numeric($minute)) { + $event->end_time = event_calendar_convert_to_time($hour,$minute,$meridian); + } else { + $event->end_time = ''; + } + if (is_numeric($event->start_date) && is_numeric($event->start_time)) { + // Set start date to the Unix start time, if set. + // This allows sorting by date *and* time. + $event->start_date += $event->start_time*60; + } + } + } + if ($event_calendar_spots_display == 'yes') { + $event->spots = trim(get_input('spots')); + } + if ($event_calendar_region_display == 'yes') { + $event->region = get_input('region'); + } + if ($event_calendar_type_display == 'yes') { + $event->event_type = get_input('event_type'); + } + if ($event_calendar_personal_manage == 'by_event') { + $event->personal_manage = get_input('personal_manage'); + } + + if ($event_calendar_repeating_events != 'no') { + $repeats = get_input('repeats'); + $event->repeats = $repeats; + if ($repeats == 'yes') { + $event->repeat_interval = get_input('repeat_interval'); + $dow = array('monday','tuesday','wednesday','thursday','friday','saturday','sunday'); + foreach ($dow as $w) { + $v = 'event-calendar-repeating-'.$w.'-value'; + $event->$v = get_input($v); + } + } + } + $event->fees = get_input('fees'); + $event->contact = get_input('contact'); + $event->organiser = get_input('organiser'); + $event->tags = string_to_tag_array(get_input('tags')); + $event->long_description = get_input('long_description'); + $event->schedule_type = $schedule_type; + $event->send_reminder = get_input('send_reminder'); + $event->reminder_number = get_input('reminder_number'); + $event->reminder_interval = get_input('reminder_interval'); + $event->web_conference = get_input('web_conference'); + $event->real_end_time = event_calendar_get_end_time($event); + foreach ($required_fields as $fn) { + if (!trim($event->$fn)) { + return FALSE; + break; + } + } + if ($event->save()) { + if (!$event_guid && $event->web_conference) { + if (!event_calendar_create_bbb_conf($event)) { + register_error(elgg_echo('event_calendar:conference_create_error')); + } + } + if ($group_guid && (elgg_get_plugin_setting('autogroup', 'event_calendar') == 'yes')) { + event_calendar_add_personal_events_from_group($event->guid,$group_guid); + } + if (elgg_get_plugin_setting('add_users', 'event_calendar') == 'yes') { + if (function_exists('autocomplete_member_to_user')) { + $addusers = get_input('adduser',array()); + foreach($addusers as $adduser) { + if ($adduser) { + $user = autocomplete_member_to_user($adduser); + $user_id = $user->guid; + event_calendar_add_personal_event($event->guid,$user_id); + if (elgg_get_plugin_setting('add_users_notify', 'event_calendar') == 'yes') { + notify_user($user_id, $CONFIG->site->guid, elgg_echo('event_calendar:add_users_notify:subject'), + sprintf( + elgg_echo('event_calendar:add_users_notify:body'), + $user->name, + $event->title, + $event->getURL() + ) + ); + } + } + } + } + } + } + return $event; +} + +function event_calendar_get_events_between($start_date,$end_date,$is_count=FALSE,$limit=10,$offset=0,$container_guid=0,$region='-') { + $polls_supported = elgg_is_active_plugin('event_poll'); + if ($is_count) { + $count = event_calendar_get_entities_from_metadata_between2('start_date','end_date', + $start_date, $end_date, "object", "event_calendar", 0, $container_guid, $limit,$offset,"",0,false,true,$region); + return $count; + } else { + $events = event_calendar_get_entities_from_metadata_between2('start_date','end_date', + $start_date, $end_date, "object", "event_calendar", 0, $container_guid, $limit,$offset,"",0,false,false,$region); + $repeating_events = event_calendar_get_repeating_events_between($start_date,$end_date,$container_guid,$region); + $all_events = event_calendar_merge_repeating_events($events, $repeating_events); + if ($polls_supported) { + elgg_load_library('elgg:event_poll'); + $all_events = event_poll_merge_poll_events($all_events,$start_date,$end_date); + } + + return $all_events; + } +} + +function event_calendar_merge_repeating_events($events, $repeating_events) { + $non_repeating_events = array(); + foreach($events as $e) { + if ($e->repeats != 'yes') { + $non_repeating_events[] = array('event' => $e,'data' => array(array('start_time' => $e->start_date, 'end_time' => $e->real_end_time))); + } + } + + return array_merge($non_repeating_events, $repeating_events); +} + +function event_calendar_get_repeating_events_between($start_date,$end_date,$container_guid,$region) { + // game plan: get all repeating events with start date <= $end_date and then generate all possible events + // sanity check + if ($start_date <= $end_date) { + $options = array( + 'type' => 'object', + 'subtype' => 'event_calendar', + 'limit' => 0, + 'metadata_name_value_pairs' => array( + array( + 'name' => 'start_date', + 'value' => $end_date, + 'operand' => '<=' + ), + array( + 'name' => 'repeats', + 'value' => 'yes' + ), + ) + ); + if ($container_guid) { + if (is_array($container_guid)) { + $options['container_guids'] = $container_guid; + } else { + $options['container_guid'] = $container_guid; + } + } + + if ($region && $region != '-') { + $options['metadata_name_value_pairs'][] = array( + 'name' => 'region', + 'value' => $region + ); + } + + $events = elgg_get_entities_from_metadata($options); + } + return event_calendar_get_repeating_event_structure($events, $start_date, $end_date); +} + + +function event_calendar_get_repeating_event_structure($events, $start_date, $end_date) { + $dow = array('monday','tuesday','wednesday','thursday','friday','saturday','sunday'); + $repeating_events = array(); + if ($events) { + foreach($events as $e) { + $incs = array(); + $repeat_data = array(); + $day_num = date('N',$e->start_date)-1; + for($d=0;$d<7;$d++) { + $fn = 'event-calendar-repeating-'.$dow[$d].'-value'; + if ($e->$fn) { + $increment = $d - $day_num; + $incs[] = $increment; + } + } + if ($incs) { + sort($incs); + + $repeat_interval = $e->repeat_interval; + $event_start_time = $e->start_date; + $event_end_time = $e->real_end_time; + $week = 0; + if ($event_start_time <= $event_end_time) { + $more_to_do = TRUE; + $cur_start_time = $event_start_time; + $cur_end_time = $event_end_time; + // keep generating events until after $end_date + // repeat_times is a sanity check to prevent infinite loops in case of bad data + $repeat_times = 0; + do { + foreach($incs as $inc) { + //$seconds = $inc*60*60*24; + if ($inc >=0) { + $tinc = "+ " . $inc; + } else { + $tinc = $inc; + } + $this_start_time = strtotime($tinc . " day", $cur_start_time); + $this_end_time = strtotime($tinc . " day", $cur_end_time); + if ($this_start_time > $end_date) { + $more_to_do = FALSE; + break; + } + if ($this_start_time >= $event_start_time) { + $repeat_data[] = array ( + 'start_time' => $this_start_time, + 'end_time' => $this_end_time, + ); + } + } + // repeat_interval weeks later + $week += $repeat_interval; + $cur_start_time = strtotime("+" . $week . " week", $event_start_time); + $cur_end_time = strtotime("+" . $week ." week", $event_end_time); + $repeat_times += 1; + } while ($repeat_times < 1000 && $more_to_do); + } + } + $repeating_events[] = array('event'=>$e,'data'=>$repeat_data); + } + } + return $repeating_events; +} + +function event_calendar_get_open_events_between($start_date,$end_date, +$is_count,$limit=10,$offset=0,$container_guid=0,$region='-', $meta_max = 'spots', $annotation_name = 'personal_event') { + if ($is_count) { + $count = event_calendar_get_entities_from_metadata_between2('start_date','end_date', + $start_date, $end_date, "object", "event_calendar", 0, $container_guid, $limit,$offset,"",0,false,true,$region,$meta_max,$annotation_name); + return $count; + } else { + $events = event_calendar_get_entities_from_metadata_between2('start_date','end_date', + $start_date, $end_date, "object", "event_calendar", 0, $container_guid, $limit,$offset,"",0,false,false,$region,$meta_max,$annotation_name); + //return event_calendar_vsort($events,'start_date'); + $repeating_events = event_calendar_get_open_repeating_events_between($start_date,$end_date,$container_guid,$region); + $all_events = event_calendar_merge_repeating_events($events, $repeating_events); + return $all_events; + } +} + +function event_calendar_get_open_repeating_events_between($start_date,$end_date,$container_guid,$region) { + $db_prefix = elgg_get_config('dbprefix'); + $meta_max = 'spots'; + $annotation_name = 'personal_event'; + $joins = array(); + $wheres = array(); + $meta_max_n = get_metastring_id($meta_max); + $ann_n = get_metastring_id($annotation_name); + if (!$meta_max_n || !$ann_n) { + if ($count) { + return 0; + } else { + return false; + } + } + + $joins[] = "LEFT JOIN {$dbprefix}metadata m4 ON (e.guid = m4.entity_guid AND m4.name_id=$meta_max_n) "; + $joins[] = "LEFT JOIN {$dbprefix}metastrings ms4 ON (m4.value_id = ms4.id) "; + $wheres[] = "((ms4.string is null) OR (ms4.string = \"\") OR (CONVERT(ms4.string,SIGNED) > (SELECT count(id) FROM {$dbprefix}annotations ann WHERE ann.entity_guid = e.guid AND name_id = $ann_n GROUP BY entity_guid)))"; + + // sanity check + if ($start_date <= $end_date) { + $options = array( + 'type' => 'object', + 'subtype' => 'event_calendar', + 'limit' => 0, + 'metadata_name_value_pairs' => array( + array( + 'name' => 'start_date', + 'value' => $end_date, + 'operand' => '<=' + ), + array( + 'name' => 'repeats', + 'value' => 'yes' + ), + ), + 'joins' => $joins, + 'wheres' => $wheres, + + ); + if ($container_guid) { + if (is_array($container_guid)) { + $options['container_guids'] = $container_guid; + } else { + $options['container_guid'] = $container_guid; + } + } + + if ($region && $region != '-') { + $options['metadata_name_value_pairs'][] = array( + 'name' => 'region', + 'value' => $region + ); + } + + $events = elgg_get_entities_from_metadata($options); + } + return event_calendar_get_repeating_event_structure($events, $start_date, $end_date); +} + +function event_calendar_get_events_for_user_between($start_date,$end_date,$is_count,$limit=10,$offset=0,$user_guid,$container_guid=0,$region='-') { + if ($is_count) { + // old way + $count = event_calendar_get_entities_from_metadata_between('start_date','end_date', + $start_date, $end_date, "object", "event_calendar", $user_guid, $container_guid, $limit,$offset,"",0,true,true,$region); + + return $count; + } else { + $events = event_calendar_get_entities_from_metadata_between('start_date','end_date', + $start_date, $end_date, "object", "event_calendar", $user_guid, $container_guid, $limit,$offset,"",0,true,false,$region); + //return event_calendar_vsort($events,'start_date'); + return $events; + } +} + +function event_calendar_get_events_for_user_between2($start_date,$end_date,$is_count,$limit=10,$offset=0,$user_guid,$container_guid=0,$region='-') { + $options_new_way = array( + 'type' => 'object', + 'subtype' => 'event_calendar', + 'relationship' => 'personal_event', + 'relationship_guid' => $user_guid, + 'metadata_name_value_pairs' => array( array( 'name' => 'start_date', + 'value' => $start_date, + 'operand' => '>='), + array( 'name' => 'real_end_time', + 'value' => $end_date, + 'operand' => '<=') + ), + ); + + if ($container_guid) { + $options_new_way['container_guid'] = $container_guid; + } + if ($region && $region != '-') { + $options_new_way['metadata_name_value_pairs'][] = array('name'=>'region','value'=>sanitize_string($region)); + } + if ($is_count) { + // old way + $count_old_way = event_calendar_get_entities_from_metadata_between('start_date','real_end_time', + $start_date, $end_date, "object", "event_calendar", $user_guid, $container_guid, $limit,$offset,"",0,true,true,$region); + // new way + $options_new_way['count'] = TRUE; + $count_new_way = elgg_get_entities_from_relationship($options_new_way); + return $count_old_way+$count_new_way; + } else { + $events_old_way = event_calendar_get_entities_from_metadata_between('start_date','real_end_time', + $start_date, $end_date, "object", "event_calendar", $user_guid, $container_guid, $limit,$offset,"",0,true,false,$region); + $options_new_way['limit'] = $limit; + $options_new_way['offset'] = $offset; + $options_new_way['order_by_metadata'] = array(array('name'=>'start_date','direction'=>'ASC','as'=>'integer')); + //print_r($options_new_way); + $events_new_way = elgg_get_entities_from_relationship($options_new_way); + //return event_calendar_vsort($events,'start_date'); + $repeating_events = event_calendar_get_repeating_events_for_user_between($user_guid,$start_date,$end_date,$container_guid,$region); + $all_events = event_calendar_merge_repeating_events(array_merge($events_old_way,$events_new_way), $repeating_events); + return $all_events; + } +} + +function event_calendar_get_repeating_events_for_user_between($user_guid,$start_date,$end_date,$container_guid,$region) { + $options = array( + 'type' => 'object', + 'subtype' => 'event_calendar', + 'relationship' => 'personal_event', + 'relationship_guid' => $user_guid, + 'metadata_name_value_pairs' => array( + array( + 'name' => 'start_date', + 'value' => $end_date, + 'operand' => '<=' + ), + array( + 'name' => 'repeats', + 'value' => 'yes' + ), + ) + ); + + if ($container_guid) { + if (is_array($container_guid)) { + $options['container_guids'] = $container_guid; + } else { + $options['container_guid'] = $container_guid; + } + } + + if ($region && $region != '-') { + $options['metadata_name_value_pairs'][] = array( + 'name' => 'region', + 'value' => $region + ); + } + + $events = elgg_get_entities_from_relationship($options); + return event_calendar_get_repeating_event_structure($events, $start_date, $end_date); +} + +function event_calendar_get_repeating_events_for_friends_between($user_guid,$friend_list,$start_date,$end_date,$container_guid=0,$region='-') { + + $db_prefix = elgg_get_config('dbprefix'); + $options = array( + 'type' => 'object', + 'subtype' => 'event_calendar', + 'metadata_name_value_pairs' => array( + array( 'name' => 'start_date', + 'value' => $end_date, + 'operand' => '<=' + ), + array( 'name' => 'repeats', + 'value' => 'yes' + ) + ), + 'joins' => array("JOIN {$db_prefix}entity_relationships r ON (r.guid_two = e.guid)"), + 'wheres' => array("r.relationship = 'personal_event'","r.guid_one IN ($friend_list)"), + ); + + if ($container_guid) { + if (is_array($container_guid)) { + $options['container_guids'] = $container_guid; + } else { + $options['container_guid'] = $container_guid; + } + } + if ($region && $region != '-') { + $options['metadata_name_value_pairs'][] = array('name'=>'region','value'=>sanitize_string($region)); + } + + $events = elgg_get_entities_from_relationship($options); + return event_calendar_get_repeating_event_structure($events, $start_date, $end_date); +} + +function event_calendar_get_events_for_friends_between($start_date,$end_date,$is_count,$limit=10,$offset=0,$user_guid,$container_guid=0,$region='-') { + if ($user_guid) { + $friends = get_user_friends($user_guid,"",5000); + if ($friends) { + $friend_guids = array(); + foreach($friends as $friend) { + $friend_guids[] = $friend->getGUID(); + } + $friend_list = implode(",",$friend_guids); + // elgg_get_entities_from_relationship does not take multiple relationship guids, so need some custom joins and wheres + $db_prefix = elgg_get_config('dbprefix'); + $options_new_way = array( + 'type' => 'object', + 'subtype' => 'event_calendar', + 'metadata_name_value_pairs' => array(array( 'name' => 'start_date', + 'value' => $start_date, + 'operand' => '>='), + array( 'name' => 'real_end_time', + 'value' => $end_date, + 'operand' => '<=') + ), + 'joins' => array("JOIN {$db_prefix}entity_relationships r ON (r.guid_two = e.guid)"), + 'wheres' => array("r.relationship = 'personal_event'","r.guid_one IN ($friend_list)"), + ); + + if ($container_guid) { + $options_new_way['container_guid'] = $container_guid; + } + if ($region && $region != '-') { + $options_new_way['metadata_name_value_pairs'][] = array('name'=>'region','value'=>sanitize_string($region)); + } + if ($is_count) { + $count_old_way = event_calendar_get_entities_from_metadata_between('start_date','end_date', + $start_date, $end_date, "object", "event_calendar", $friend_guids, $container_guid, $limit,$offset,"",0,true,true,$region); + $options_new_way['count'] = TRUE; + $count_new_way = elgg_get_entities_from_metadata($options_new_way); + return $count_old_way + $count_new_way; + } else { + $events_old_way = event_calendar_get_entities_from_metadata_between('start_date','end_date', + $start_date, $end_date, "object", "event_calendar", $friend_guids, $container_guid, $limit,$offset,"",0,true,false,$region); + //return event_calendar_vsort($events,'start_date'); + $options_new_way['limit'] = $limit; + $options_new_way['offset'] = $offset; + $options_new_way['order_by_metadata'] = array(array('name'=>'start_date','direction'=>'ASC','as'=>'integer')); + //print_r($options_new_way); + $events_new_way = elgg_get_entities_from_metadata($options_new_way); + $repeating_events = event_calendar_get_repeating_events_for_friends_between($user_guid,$friend_list,$start_date,$end_date,$container_guid,$region); + $all_events = event_calendar_merge_repeating_events(array_merge($events_old_way,$events_new_way), $repeating_events); + return $all_events; + } + } + } + return array(); +} + +function event_calendar_vsort($original,$field, $descending = false) { + if (!$original) { + return $original; + } + $sortArr = array(); + + foreach ( $original as $key => $item ) { + $sortArr[ $key ] = $item->$field; + } + + if ( $descending ) { + arsort( $sortArr ); + } else { + asort( $sortArr ); + } + + $resultArr = array(); + foreach ( $sortArr as $key => $value ) { + $resultArr[ $key ] = $original[ $key ]; + } + + return $resultArr; +} + +// TODO - replace with Elgg API if possible + +/** + * Return a list of entities based on the given search criteria. + * In this case, returns entities with the given metadata between two values inclusive + * + * @param mixed $meta_start_name + * @param mixed $meta_end_name + * @param mixed $meta_start_value - start of metadata range, must be numerical value + * @param mixed $meta_end_value - end of metadata range, must be numerical value + * @param string $entity_type The type of entity to look for, eg 'site' or 'object' + * @param string $entity_subtype The subtype of the entity. + * @param mixed $owner_guid Either one integer user guid or an array of user guids + * @param int $container_guid If supplied, the result is restricted to events associated with a specific container + * @param int $limit + * @param int $offset + * @param string $order_by Optional ordering. + * @param int $site_guid The site to get entities for. Leave as 0 (default) for the current site; -1 for all sites. + * @param boolean $filter Filter by events in personal calendar if true + * @param true|false $count If set to true, returns the total number of entities rather than a list. (Default: false) + * + * @return int|array A list of entities, or a count if $count is set to true + */ +function event_calendar_get_entities_from_metadata_between($meta_start_name, $meta_end_name, $meta_start_value, $meta_end_value, $entity_type = "", $entity_subtype = "", $owner_guid = 0, $container_guid = 0, $limit = 10, $offset = 0, $order_by = "", $site_guid = 0, $filter = false, $count = false, $region='-') +{ + global $CONFIG; + + // This should not be possible, but a sanity check just in case + if (!is_numeric($meta_start_value) || !is_numeric($meta_end_value)) { + return FALSE; + } + + $meta_start_n = get_metastring_id($meta_start_name); + $meta_end_n = get_metastring_id($meta_end_name); + if ($region && $region != '-') { + $region_n = get_metastring_id('region'); + $region_value_n = get_metastring_id($region); + if (!$region_n || !$region_value_n) { + if ($count) { + return 0; + } else { + return FALSE; + } + } + } + + $entity_type = sanitise_string($entity_type); + $entity_subtype = get_subtype_id($entity_type, $entity_subtype); + $limit = (int)$limit; + $offset = (int)$offset; + //if ($order_by == "") $order_by = "e.time_created desc"; + if ($order_by == "") $order_by = "v.string asc"; + $order_by = sanitise_string($order_by); + $site_guid = (int) $site_guid; + if ((is_array($owner_guid) && (count($owner_guid)))) { + foreach($owner_guid as $key => $guid) { + $owner_guid[$key] = (int) $guid; + } + } else { + $owner_guid = (int) $owner_guid; + } + + if ((is_array($container_guid) && (count($container_guid)))) { + foreach($container_guid as $key => $guid) { + $container_guid[$key] = (int) $guid; + } + } else { + $container_guid = (int) $container_guid; + } + if ($site_guid == 0) + $site_guid = $CONFIG->site_guid; + + //$access = get_access_list(); + + $where = array(); + + if ($entity_type!="") + $where[] = "e.type='$entity_type'"; + if ($entity_subtype) + $where[] = "e.subtype=$entity_subtype"; + $where[] = "m.name_id='$meta_start_n'"; + $where[] = "m2.name_id='$meta_end_n'"; + $where[] = "((v.string >= $meta_start_value AND v.string <= $meta_end_value) OR ( v2.string >= $meta_start_value AND v2.string <= $meta_end_value) OR (v.string <= $meta_start_value AND v2.string >= $meta_start_value) OR ( v2.string <= $meta_end_value AND v2.string >= $meta_end_value))"; + if ($region && $region != '-') { + $where[] = "m3.name_id='$region_n'"; + $where[] = "m3.value_id='$region_value_n'"; + } + if ($site_guid > 0) + $where[] = "e.site_guid = {$site_guid}"; + if ($filter) { + if (is_array($owner_guid)) { + $where[] = "ms2.string in (".implode(",",$owner_guid).")"; + } else if ($owner_guid > 0) { + $where[] = "ms2.string = {$owner_guid}"; + } + + $where[] = "ms.string = 'personal_event'"; + } else { + if (is_array($owner_guid)) { + $where[] = "e.owner_guid in (".implode(",",$owner_guid).")"; + } else if ($owner_guid > 0) { + $where[] = "e.owner_guid = {$owner_guid}"; + } + } + + if (is_array($container_guid)) { + $where[] = "e.container_guid in (".implode(",",$container_guid).")"; + } else if ($container_guid > 0) + $where[] = "e.container_guid = {$container_guid}"; + + if (!$count) { + $query = "SELECT distinct e.* "; + } else { + $query = "SELECT count(distinct e.guid) as total "; + } + + $query .= "from {$CONFIG->dbprefix}entities e JOIN {$CONFIG->dbprefix}metadata m on e.guid = m.entity_guid JOIN {$CONFIG->dbprefix}metadata m2 on e.guid = m2.entity_guid "; + if ($filter) { + $query .= "JOIN {$CONFIG->dbprefix}annotations a ON (a.entity_guid = e.guid) "; + $query .= "JOIN {$CONFIG->dbprefix}metastrings ms ON (a.name_id = ms.id) "; + $query .= "JOIN {$CONFIG->dbprefix}metastrings ms2 ON (a.value_id = ms2.id) "; + } + if ($region && $region != '-') { + $query .= "JOIN {$CONFIG->dbprefix}metadata m3 ON (e.guid = m3.entity_guid) "; + } + $query .= "JOIN {$CONFIG->dbprefix}metastrings v on v.id = m.value_id JOIN {$CONFIG->dbprefix}metastrings v2 on v2.id = m2.value_id where"; + foreach ($where as $w) + $query .= " $w and "; + $query .= get_access_sql_suffix("e"); // Add access controls + $query .= ' and ' . get_access_sql_suffix("m"); // Add access controls + $query .= ' and ' . get_access_sql_suffix("m2"); // Add access controls + + if (!$count) { + $query .= " order by $order_by"; + if ($limit) { + $query .= " limit $offset, $limit"; // Add order and limit + } + $entities = get_data($query, "entity_row_to_elggstar"); + if (elgg_get_plugin_setting('add_to_group_calendar', 'event_calendar') == 'yes') { + if (get_entity($container_guid) instanceOf ElggGroup) { + $entities = event_calendar_get_entities_from_metadata_between_related($meta_start_name, $meta_end_name, + $meta_start_value, $meta_end_value, $entity_type, + $entity_subtype, $owner_guid, $container_guid, + 0, 0, "", 0, + false, false, '-',$entities); + } + } + return $entities; + } else { + if ($row = get_data_row($query)) + return $row->total; + } + return false; +} + +// adds any related events (has the display_on_group relation) +// that meet the appropriate criteria + +function event_calendar_get_entities_from_metadata_between_related($meta_start_name, $meta_end_name, +$meta_start_value, $meta_end_value, $entity_type = "", +$entity_subtype = "", $owner_guid = 0, $container_guid = 0, +$limit = 10, $offset = 0, $order_by = "", $site_guid = 0, +$filter = false, $count = false, $region='-',$main_events) { + + $main_list = array(); + if ($main_events) { + foreach ($main_events as $event) { + $main_list[$event->guid] = $event; + } + } + $related_list = array(); + $related_events = elgg_get_entities_from_relationship(array( + 'relationship' => 'display_on_group', + 'relationship_guid' => $container_guid, + 'inverse_relationship' => TRUE, + )); + if ($related_events) { + foreach ($related_events as $event) { + $related_list[$event->guid] = $event; + } + } + // get all the events (across all containers) that meet the criteria + $all_events = event_calendar_get_entities_from_metadata_between($meta_start_name, $meta_end_name, + $meta_start_value, $meta_end_value, $entity_type, $entity_subtype, $owner_guid, + 0, $limit, $offset, $order_by, $site_guid, $filter, $count, $region); + + if ($all_events) { + foreach($all_events as $event) { + if (array_key_exists($event->guid,$related_list) + && !array_key_exists($event->guid,$main_list)) { + // add to main events + $main_events[] = $event; + } + } + } + return event_calendar_vsort($main_events,$meta_start_name); +} + +// TODO: try to replace this with new Elgg 1.7 API +/** + * Return a list of entities based on the given search criteria. + * In this case, returns entities with the given metadata between two values inclusive + * + * @param mixed $meta_start_name + * @param mixed $meta_end_name + * @param mixed $meta_start_value - start of metadata range, must be numerical value + * @param mixed $meta_end_value - end of metadata range, must be numerical value + * @param string $entity_type The type of entity to look for, eg 'site' or 'object' + * @param string $entity_subtype The subtype of the entity. + * @param mixed $owner_guid Either one integer user guid or an array of user guids + * @param int $container_guid If supplied, the result is restricted to events associated with a specific container + * @param int $limit + * @param int $offset + * @param string $order_by Optional ordering. + * @param int $site_guid The site to get entities for. Leave as 0 (default) for the current site; -1 for all sites. + * @param boolean $filter Filter by events in personal calendar if true + * @param true|false $count If set to true, returns the total number of entities rather than a list. (Default: false) + * @param string $meta_max metadata name containing maximum annotation count + * @param string $annotation_name annotation name to count + * + * @return int|array A list of entities, or a count if $count is set to true + * + * TODO: see if the new API is robust enough to avoid this custom query + */ +function event_calendar_get_entities_from_metadata_between2 +($meta_start_name, $meta_end_name, $meta_start_value, $meta_end_value, +$entity_type = "", $entity_subtype = "", $owner_guid = 0, $container_guid = 0, +$limit = 10, $offset = 0, $order_by = "", $site_guid = 0, $filter = false, +$count = false, $region='-', $meta_max = '', $annotation_name = '') +{ + global $CONFIG; + + // This should not be possible, but a sanity check just in case + if (!is_numeric($meta_start_value) || !is_numeric($meta_end_value)) { + return FALSE; + } + + $meta_start_n = get_metastring_id($meta_start_name); + $meta_end_n = get_metastring_id($meta_end_name); + if ($region && $region != '-') { + $region_n = get_metastring_id('region'); + $region_value_n = get_metastring_id($region); + if (!$region_n || !$region_value_n) { + if ($count) { + return 0; + } else { + return false; + } + } + } + + $entity_type = sanitise_string($entity_type); + $entity_subtype = get_subtype_id($entity_type, $entity_subtype); + $limit = (int)$limit; + $offset = (int)$offset; + //if ($order_by == "") $order_by = "e.time_created desc"; + if ($order_by == "") $order_by = "v.string asc"; + $order_by = sanitise_string($order_by); + $site_guid = (int) $site_guid; + if ((is_array($owner_guid) && (count($owner_guid)))) { + foreach($owner_guid as $key => $guid) { + $owner_guid[$key] = (int) $guid; + } + } else { + $owner_guid = (int) $owner_guid; + } + + if ((is_array($container_guid) && (count($container_guid)))) { + foreach($container_guid as $key => $guid) { + $container_guid[$key] = (int) $guid; + } + } else { + $container_guid = (int) $container_guid; + } + if ($site_guid == 0) + $site_guid = $CONFIG->site_guid; + + //$access = get_access_list(); + + $where = array(); + + if ($entity_type!="") + $where[] = "e.type='$entity_type'"; + if ($entity_subtype) + $where[] = "e.subtype=$entity_subtype"; + $where[] = "m.name_id='$meta_start_n'"; + $where[] = "m2.name_id='$meta_end_n'"; + $where[] = "((v.string >= $meta_start_value AND v.string <= $meta_end_value) OR ( v2.string >= $meta_start_value AND v2.string <= $meta_end_value) OR (v.string <= $meta_start_value AND v2.string >= $meta_start_value) OR ( v2.string <= $meta_end_value AND v2.string >= $meta_end_value))"; + if ($region && $region != '-') { + $where[] = "m3.name_id='$region_n'"; + $where[] = "m3.value_id='$region_value_n'"; + } + if ($site_guid > 0) + $where[] = "e.site_guid = {$site_guid}"; + if ($filter) { + if (is_array($owner_guid)) { + $where[] = "ms2.string in (".implode(",",$owner_guid).")"; + } else if ($owner_guid > 0) { + $where[] = "ms2.string = {$owner_guid}"; + } + + $where[] = "ms.string = 'personal_event'"; + } else { + if (is_array($owner_guid)) { + $where[] = "e.owner_guid in (".implode(",",$owner_guid).")"; + } else if ($owner_guid > 0) { + $where[] = "e.owner_guid = {$owner_guid}"; + } + } + + if (is_array($container_guid)) { + $where[] = "e.container_guid in (".implode(",",$container_guid).")"; + } else if ($container_guid > 0) + $where[] = "e.container_guid = {$container_guid}"; + + if (!$count) { + $query = "SELECT distinct e.* "; + } else { + $query = "SELECT count(distinct e.guid) as total "; + } + + $query .= "FROM {$CONFIG->dbprefix}entities e JOIN {$CONFIG->dbprefix}metadata m on e.guid = m.entity_guid JOIN {$CONFIG->dbprefix}metadata m2 on e.guid = m2.entity_guid "; + if ($filter) { + $query .= "JOIN {$CONFIG->dbprefix}annotations a ON (a.entity_guid = e.guid) "; + $query .= "JOIN {$CONFIG->dbprefix}metastrings ms ON (a.name_id = ms.id) "; + $query .= "JOIN {$CONFIG->dbprefix}metastrings ms2 ON (a.value_id = ms2.id) "; + } + if ($region && $region != '-') { + $query .= "JOIN {$CONFIG->dbprefix}metadata m3 ON (e.guid = m3.entity_guid) "; + } + if ($meta_max && $annotation_name) { + // This groups events for which the meta max name is defined + // perhaps this should be a left join and accept null values? + // so it would return groups with no spots defined as well + $meta_max_n = get_metastring_id($meta_max); + $ann_n = get_metastring_id($annotation_name); + if (!$meta_max_n || !$ann_n) { + if ($count) { + return 0; + } else { + return false; + } + } + + $query .= " LEFT JOIN {$CONFIG->dbprefix}metadata m4 ON (e.guid = m4.entity_guid AND m4.name_id=$meta_max_n) "; + $query .= " LEFT JOIN {$CONFIG->dbprefix}metastrings ms4 ON (m4.value_id = ms4.id) "; + $where[] = "((ms4.string is null) OR (ms4.string = \"\") OR (CONVERT(ms4.string,SIGNED) > (SELECT count(id) FROM {$CONFIG->dbprefix}annotations ann WHERE ann.entity_guid = e.guid AND name_id = $ann_n GROUP BY entity_guid)))"; + } + $query .= "JOIN {$CONFIG->dbprefix}metastrings v on v.id = m.value_id JOIN {$CONFIG->dbprefix}metastrings v2 on v2.id = m2.value_id where"; + foreach ($where as $w) + $query .= " $w AND "; + $query .= get_access_sql_suffix("e"); // Add access controls + $query .= ' AND ' . get_access_sql_suffix("m"); // Add access controls + $query .= ' AND ' . get_access_sql_suffix("m2"); // Add access controls + + if (!$count) { + $query .= " order by $order_by"; + if ($limit) { + $query .= " limit $offset, $limit"; // Add order and limit + } + $entities = get_data($query, "entity_row_to_elggstar"); + if (elgg_get_plugin_setting('add_to_group_calendar', 'event_calendar') == 'yes') { + if (get_entity($container_guid) instanceOf ElggGroup) { + $entities = event_calendar_get_entities_from_metadata_between_related($meta_start_name, $meta_end_name, + $meta_start_value, $meta_end_value, $entity_type, + $entity_subtype, $owner_guid, $container_guid, + 0, 0, "", 0, + false, false, '-',$entities); + } + } + return $entities; + } else { + if ($row = get_data_row($query)) + return $row->total; + } + return false; +} + +function event_calendar_has_personal_event($event_guid,$user_guid) { + // check legacy implementation and new one + if (check_entity_relationship($user_guid,'personal_event',$event_guid)) { + return TRUE; + } else { + // use old method for now + $options = array('guid'=>$event_guid,'annotation_name' => 'personal_event', 'annotation_value' => $user_guid,'count'=>TRUE); + //$annotations = get_annotations($event_guid, "object", "event_calendar", "personal_event", (int) $user_guid, $user_guid); + if (elgg_get_annotations($options)) { + return TRUE; + } else { + return FALSE; + } + } +} + +function event_calendar_add_personal_event($event_guid,$user_guid) { + if ($event_guid && $user_guid) { + if (!event_calendar_has_personal_event($event_guid,$user_guid) + && !event_calendar_has_collision($event_guid,$user_guid)) { + if (!event_calendar_is_full($event_guid)) { + add_entity_relationship($user_guid,'personal_event',$event_guid); + return TRUE; + } + } + } + return FALSE; +} + +function event_calendar_add_personal_events_from_group($event_guid,$group_guid) { + $members = get_group_members($group_guid, 100000); + foreach($members as $member) { + $member_id = $member->getGUID(); + event_calendar_add_personal_event($event_guid,$member_id); + } +} + +function event_calendar_remove_personal_event($event_guid,$user_guid) { + remove_entity_relationship($user_guid,'personal_event',$event_guid); + // also use old method for now + $annotations = get_annotations($event_guid, "object", "event_calendar", "personal_event", (int) $user_guid, $user_guid); + if ($annotations) { + foreach ($annotations as $annotation) { + $annotation->delete(); + } + } +} + +function event_calendar_get_personal_events_for_user($user_guid,$limit) { + $events_old_way = elgg_get_entities_from_annotations(array( + 'type' => 'object', + 'subtype' => 'event_calendar', + 'annotation_names' => 'personal_event', + 'annotation_value' => $user_guid, + 'limit' => 0, + )); + + $events_new_way = elgg_get_entities_from_relationship(array( + 'type' => 'object', + 'subtype' => 'event_calendar', + 'relationship' => 'personal_event', + 'relationship_guid' => $user_guid, + 'limit' => 0, + )); + + $events = array_merge($events_old_way,$events_new_way); + + $final_events = array(); + if ($events) { + $now = time(); + $one_day = 60*60*24; + // don't show events that have been over for more than a day + foreach($events as $event) { + if (($event->start_date > $now-$one_day) || ($event->end_date && ($event->end_date > $now-$one_day))) { + $final_events[] = $event; + } + } + } + $sorted = event_calendar_vsort($final_events,'start_date'); + return array_slice($sorted,0,$limit); +} + +// the old way used annotations, and the new Elgg 1.8 way uses relationships +// for now this version attempts to bridge the gap by using both methods for older sites + +function event_calendar_get_users_for_event($event_guid,$limit,$offset=0,$is_count=FALSE) { + $options = array( + 'type' => 'user', + 'relationship' => 'personal_event', + 'relationship_guid' => $event_guid, + 'inverse_relationship' => TRUE, + 'limit' => 0, + ); + if ($is_count) { + //$count_old_way = count_annotations($event_guid, "object", "event_calendar", "personal_event"); + $count_old_way = elgg_get_annotations(array( + 'guid'=>$event_guid, + 'type'=>"object", + 'subtype'=>"event_calendar", + 'annotation_name' => "personal_event", + 'count'=>TRUE) + ); + $options ['count'] = TRUE; + $count_new_way = elgg_get_entities_from_relationship($options); + return $count_old_way + $count_new_way; + } else { + $users_old_way = array(); + //$annotations = get_annotations($event_id, "object", "event_calendar", "personal_event", "", 0, $limit, $offset); + $annotations = elgg_get_annotations(array( + 'guid'=>$event_guid, + 'type'=>"object", + 'subtype'=>"event_calendar", + 'annotation_name' => "personal_event", + 'limit' => $limit, + 'offset' => $offset) + ); + if ($annotations) { + foreach($annotations as $annotation) { + if (($user = get_entity($annotation->value)) && ($user instanceOf ElggUser)) { + $users_old_way[] = $user; + } + } + } + $users_new_way = elgg_get_entities_from_relationship($options); + return array_merge($users_old_way,$users_new_way); + } +} + +function event_calendar_security_fields() { + $ts = time(); + $token = generate_action_token($ts); + return "__elgg_token=$token&__elgg_ts=$ts"; +} + +function event_calendar_get_events_for_group($group_guid, $limit = 0) { + $options = array( + 'type' => 'object', + 'subtype' => 'event_calendar', + 'container_guid' => $group_guid, + 'limit' => $limit, + ); + return elgg_get_entities($options); +} + +function event_calendar_convert_time($time) { + $event_calendar_time_format = elgg_get_plugin_setting('timeformat','event_calendar'); + if ($event_calendar_time_format == '12') { + $hour = floor($time/60); + $minute = sprintf("%02d",$time-60*$hour); + if ($hour < 12) { + return "$hour:$minute am"; + } else { + $hour -= 12; + return "$hour:$minute pm"; + } + } else { + $hour = floor($time/60); + $minute = sprintf("%02d",$time-60*$hour); + return "$hour:$minute"; + } +} + +function event_calendar_format_time($date,$time1,$time2='') { + if (is_numeric($time1)) { + $t = event_calendar_convert_time($time1); + if (is_numeric($time2)) { + $t .= " - ".event_calendar_convert_time($time2); + } + return "$t, $date"; + } else { + return $date; + } +} + +function event_calender_get_gmt_from_server_time($server_time) { + $gmtime = $server_time - (int)substr(date('O'),0,3)*60*60; +} + +function event_calendar_activated_for_group($group) { + $group_calendar = elgg_get_plugin_setting('group_calendar', 'event_calendar'); + $group_default = elgg_get_plugin_setting('group_default', 'event_calendar'); + if ($group && ($group_calendar != 'no')) { + if ( ($group->event_calendar_enable == 'yes') || ((!$group->event_calendar_enable && (!$group_default || $group_default == 'yes')))) { + return true; + } + } + return false; +} + +function event_calendar_get_region($event) { + $event_calendar_region_list_handles = elgg_get_plugin_setting('region_list_handles', 'event_calendar'); + $region = trim($event->region); + if ($event_calendar_region_list_handles == 'yes') { + $region = elgg_echo('event_calendar:region:'.$region); + } + return htmlspecialchars($region); +} + +function event_calendar_get_type($event) { + $event_calendar_type_list_handles = elgg_get_plugin_setting('type_list_handles', 'event_calendar'); + $type = trim($event->event_type); + if ($type) { + if ($event_calendar_type_list_handles == 'yes') { + $type = elgg_echo('event_calendar:type:'.$type); + } + return htmlspecialchars($type); + } else { + return $type; + } +} + +function event_calendar_get_formatted_full_items($event) { + $time_bit = event_calendar_get_formatted_time($event); + $event_calendar_region_display = elgg_get_plugin_setting('region_display', 'event_calendar'); + $event_calendar_type_display = elgg_get_plugin_setting('type_display', 'event_calendar'); + $event_items = array(); + if ($time_bit) { + $item = new stdClass(); + $item->title = elgg_echo('event_calendar:when_label'); + $item->value = $time_bit; + $event_items[] = $item; + } + $item = new stdClass(); + $item->title = elgg_echo('event_calendar:venue_label'); + $item->value = htmlspecialchars($event->venue); + $event_items[] = $item; + if ($event_calendar_region_display == 'yes') { + $item = new stdClass(); + $item->title = elgg_echo('event_calendar:region_label'); + $item->value = event_calendar_get_region($event); + $event_items[] = $item; + } + if ($event_calendar_type_display == 'yes') { + $event_type = event_calendar_get_type($event); + if ($event_type) { + $item = new stdClass(); + $item->title = elgg_echo('event_calendar:type_label'); + $item->value = event_calendar_get_type($event); + $event_items[] = $item; + } + } + $item = new stdClass(); + $item->title = elgg_echo('event_calendar:fees_label'); + $item->value = htmlspecialchars($event->fees); + $event_items[] = $item; + $item = new stdClass(); + $item->title = elgg_echo('event_calendar:organiser_label'); + $item->value = htmlspecialchars($event->organiser); + $event_items[] = $item; + $item = new stdClass(); + $item->title = elgg_echo('event_calendar:contact_label'); + $item->value = htmlspecialchars($event->contact); + $event_items[] = $item; + + return $event_items; +} + +function event_calendar_get_formatted_time($event) { + if (!$event->start_date) { + return ''; + } + $date_format = 'j M Y'; + $event_calendar_times = elgg_get_plugin_setting('times', 'event_calendar') != 'no'; + + $start_date = date($date_format,$event->start_date); + if ($event->end_date) { + $end_date = date($date_format,$event->end_date); + } + if ((!$event->end_date) || ($end_date == $start_date)) { + if (!$event->all_day && $event_calendar_times) { + $start_date = event_calendar_format_time($start_date,$event->start_time,$event->end_time); + } + $time_bit = $start_date; + } else { + if (!$event->all_day && $event_calendar_times) { + $start_date = event_calendar_format_time($start_date,$event->start_time); + $end_date = event_calendar_format_time($end_date,$event->end_time); + } + $time_bit = "$start_date - $end_date"; + } + + if ($event->repeats == 'yes') { + $dow = array('monday','tuesday','wednesday','thursday','friday','saturday','sunday'); + $r = array(); + foreach ($dow as $w) { + $fn = 'event-calendar-repeating-'.$w.'-value'; + if ($event->$fn) { + $r[] = elgg_echo('event_calendar:dow:full:'.$w); + } + } + $week_bit = implode(", ",$r); + if ($event->repeat_interval > 1) { + $week_bit .= ' '.elgg_echo('event_calendar:repeated_event:week_interval',array($event->repeat_interval)); + } else { + $week_bit .= ' '.elgg_echo('event_calendar:repeated_event:week_single'); + } + $time_bit = elgg_echo('event_calendar:repeated_event:format',array($time_bit, $week_bit)); + } + + return $time_bit; +} + +function event_calendar_get_formatted_date($ts) { + // TODO: make the date format configurable + return date('j/n/Y',$ts); +} + +function event_calendar_is_full($event_id) { + $event_calendar_spots_display = elgg_get_plugin_setting('spots_display', 'event_calendar'); + if ($event_calendar_spots_display == 'yes') { + $count = event_calendar_get_users_for_event($event_id,0,0,TRUE); + $event = get_entity($event_id); + if ($event) { + $spots = $event->spots; + if (is_numeric($spots)) { + if ($count >= $spots) { + return TRUE; + } + } + } + } + return FALSE; +} + +function event_calendar_has_collision($event_id, $user_id) { + $no_collisions = elgg_get_plugin_setting('no_collisions', 'event_calendar'); + if ($no_collisions == 'yes') { + $event = get_entity($event_id); + if ($event) { + $start_time = $event->start_date; + $end_time = event_calendar_get_end_time($event); + // look to see if the user already has events within this period + $count = event_calendar_get_events_for_user_between2($start_time,$end_time,TRUE,10,0,$user_id); + if ($count > 0) { + return TRUE; + } else { + return FALSE; + } + } + } + + return FALSE; +} + +// this complicated bit of code determines the event end time +function event_calendar_get_end_time($event) { + $default_length = elgg_get_plugin_setting('collision_length', 'event_calendar'); + $start_time = $event->start_date; + $end_time = $event->end_time; + $end_date = $event->end_date; + if($end_date) { + if ($end_time) { + $end_time = $end_date+$end_time*60; + } else if ($start_time == $end_date) { + if (is_numeric($default_length)) { + $end_time = $end_date + $default_length; + } else { + // default to an hour length + $end_time = $start_time + 3600; + } + } else { + $end_time = $end_date; + } + } else { + if ($end_time) { + if ($event->start_time) { + $end_time = $start_time + ($end_time*60 - $event->start_time*60); + } else { + $end_time = $start_time + $end_time*60; + } + } else { + if (is_numeric($default_length)) { + $end_time = $start_time + $default_length; + } else { + // default to an hour length + $end_time = $start_time + 3600; + } + } + } + + return $end_time; +} + +// a version to allow for some customised options +function event_calendar_view_entity_list($entities, $count, $offset, $limit, $fullview = true, $viewtypetoggle = true, $pagination = true) { + $count = (int) $count; + $limit = (int) $limit; + + // do not require views to explicitly pass in the offset + if (!$offset = (int) $offset) { + $offset = sanitise_int(get_input('offset', 0)); + } + + $context = elgg_get_context(); + + $html = elgg_view('event_calendar/entities/entity_list',array( + 'entities' => $entities, + 'count' => $count, + 'offset' => $offset, + 'limit' => $limit, + 'baseurl' => $_SERVER['REQUEST_URI'], + 'fullview' => $fullview, + 'context' => $context, + 'viewtypetoggle' => $viewtypetoggle, + 'viewtype' => get_input('search_viewtype','list'), + 'pagination' => $pagination + )); + + return $html; +} + +// returns open, closed or private for the given event and user +function event_calendar_personal_can_manage($event,$user_id) { + $status = 'private'; + $event_calendar_personal_manage = elgg_get_plugin_setting('personal_manage', 'event_calendar'); + if (!$event_calendar_personal_manage + || $event_calendar_personal_manage == 'open' + || $event_calendar_personal_manage == 'yes' + || (($event_calendar_personal_manage == 'by_event' && (!$event->personal_manage || ($event->personal_manage == 'open'))))) { + $status = 'open'; + } else { + // in this case only admins or event owners can manage events on their personal calendars + if(elgg_is_admin_logged_in()) { + $status = 'open'; + } else if ($event && ($event->owner_guid == $user_id)) { + $status = 'open'; + } else if (($event_calendar_personal_manage == 'closed') + || ($event_calendar_personal_manage == 'no') + || (($event_calendar_personal_manage == 'by_event') && ($event->personal_manage == 'closed'))) { + $status = 'closed'; + } + } + + return $status; +} + +function event_calendar_send_event_request($event,$user_guid) { + $result = FALSE; + if(add_entity_relationship($user_guid, 'event_calendar_request', $event->guid)) { + $subject = elgg_echo('event_calendar:request_subject'); + $name = get_entity($user_guid)->name; + $title = $event->title; + $url = $event->getUrl(); + $link = elgg_get_site_url().'event_calendar/review_requests/'.$event->guid; + $message = sprintf(elgg_echo('event_calendar:request_message'),$name,$title,$url,$link); + notify_user($event->owner_guid,elgg_get_site_entity()->guid,$subject,$message); + $result = TRUE; + } + return $result; +} + +// pages + +function event_calendar_get_page_content_list($page_type,$container_guid,$start_date,$display_mode,$filter,$region='-') { + elgg_load_js('elgg.event_calendar'); + global $autofeed; + $autofeed = true; + if ($page_type == 'group') { + if (!event_calendar_activated_for_group($container_guid)) { + forward(); + } + elgg_push_breadcrumb(elgg_echo('event_calendar:group_breadcrumb')); + elgg_push_context('groups'); + elgg_set_page_owner_guid($container_guid); + $user_guid = elgg_get_logged_in_user_guid(); + if(event_calendar_can_add($container_guid)) { + elgg_register_menu_item('title', array( + 'name' => 'add', + 'href' => "event_calendar/add/".$container_guid, + 'text' => elgg_echo('event_calendar:add'), + 'class' => 'elgg-button elgg-button-action event-calendar-button-add', + )); + } + } else { + elgg_push_breadcrumb(elgg_echo('item:object:event_calendar')); + $user_guid = elgg_get_logged_in_user_guid(); + if(event_calendar_can_add($container_guid)) { + elgg_register_menu_item('title', array( + 'name' => 'add', + 'href' => "event_calendar/add", + 'text' => elgg_echo('event_calendar:add'), + 'class' => 'elgg-button elgg-button-action event-calendar-button-add', + )); + } + } + + $params = event_calendar_generate_listing_params($page_type,$container_guid,$start_date,$display_mode,$filter,$region); + + $url = current_page_url(); + if (substr_count($url, '?')) { + $url .= "&view=ical"; + } else { + $url .= "?view=ical"; + } + + $url = elgg_format_url($url); + $menu_options = array( + 'name' => 'ical', + 'id' => 'event-calendar-ical-link', + 'text' => elgg_view_icon('calendar'), + 'href' => $url, + 'title' => elgg_echo('feed:ical'), + 'priority' => 800, + 'rel' => 'popup', + ); + $menu_item = ElggMenuItem::factory($menu_options); + elgg_register_menu_item('extras', $menu_item); + + $body = elgg_view_layout("content", $params); + $body .= elgg_view_module('popup', elgg_echo('feed:ical'), elgg_echo('event_calendar:ical_popup_message') . elgg_view('output/url', array( + 'href' => $url, + 'text' => elgg_echo('export'), + 'class' => 'elgg-button elgg-button-action', + )), array( + 'id' => 'event-calendar-ical', + 'class' => 'event-calendar-ical hidden', + )); + + return elgg_view_page($title, $body); +} + +function event_calendar_get_page_content_edit($page_type,$guid,$start_date='') { + elgg_load_js('elgg.event_calendar'); + $vars = array(); + $vars['id'] = 'event-calendar-edit'; + // just in case a feature adds an image upload + $vars['enctype'] = 'multipart/form-data'; + + $body_vars = array(); + + if ($page_type == 'edit') { + $title = elgg_echo('event_calendar:manage_event_title'); + $event = get_entity((int)$guid); + if (elgg_instanceof($event, 'object', 'event_calendar') && $event->canEdit()) { + $body_vars['event'] = $event; + $body_vars['form_data'] = event_calendar_prepare_edit_form_vars($event,$page_type); + + $event_container = get_entity($event->container_guid); + if (elgg_instanceof($event_container, 'group')) { + elgg_push_breadcrumb(elgg_echo('event_calendar:group_breadcrumb'), 'event_calendar/group/'.$event->container_guid); + $body_vars['group_guid'] = $event_container->guid; + } else { + elgg_push_breadcrumb(elgg_echo('event_calendar:show_events_title'),'event_calendar/list'); + $body_vars['group_guid'] = 0; + } + elgg_push_breadcrumb($event->title,$event->getURL()); + elgg_push_breadcrumb(elgg_echo('event_calendar:manage_event_title')); + + $content = elgg_view_form('event_calendar/edit', $vars,$body_vars); + } else { + $content = elgg_echo('event_calendar:error_event_edit'); + } + } else { + $title = elgg_echo('event_calendar:add_event_title'); + + if ($guid) { + // add to group + $group = get_entity($guid); + if (elgg_instanceof($group, 'group')) { + $body_vars['group_guid'] = $guid; + elgg_push_breadcrumb(elgg_echo('event_calendar:group_breadcrumb'), 'event_calendar/group/'.$guid); + elgg_push_breadcrumb(elgg_echo('event_calendar:add_event_title')); + $body_vars['form_data'] = event_calendar_prepare_edit_form_vars(NULL,$page_type,$start_date); + $content = elgg_view_form('event_calendar/edit', $vars, $body_vars); + } else { + $content = elgg_echo('event_calendar:no_group'); + } + } else { + $body_vars['group_guid'] = 0; + elgg_push_breadcrumb(elgg_echo('event_calendar:show_events_title'),'event_calendar/list'); + + elgg_push_breadcrumb(elgg_echo('event_calendar:add_event_title')); + $body_vars['form_data'] = event_calendar_prepare_edit_form_vars(NULL,$page_type,$start_date); + + $content = elgg_view_form('event_calendar/edit', $vars, $body_vars); + } + } + + $params = array('title' => $title, 'content' => $content,'filter' => ''); + + $body = elgg_view_layout("content", $params); + + return elgg_view_page($title,$body); +} + +/** + * Pull together variables for the edit form + * + * @param ElggObject $event + * @return array + */ +function event_calendar_prepare_edit_form_vars($event = NULL, $page_type = '', $start_date = '') { + + // input names => defaults + $now = time(); + $iso_date = date('Y-m-d',$now); + $now_midnight = strtotime($iso_date); + if ($start_date) { + $start_date = strtotime($start_date); + } else { + $start_date = $now+60*60; + } + $start_time = floor(($now-$now_midnight)/60) + 60; + $start_time = floor($start_time/5)*5; + $values = array( + 'title' => NULL, + 'description' => NULL, + 'venue' => NULL, + 'start_date' => $start_date, + 'end_date' => $start_date+60*60, + 'start_time' => $start_time, + 'end_time' => $start_time + 60, + 'spots' => NULL, + 'region' => '-', + 'event_type' => '-', + 'fees' => NULL, + 'contact' => NULL, + 'organiser' => NULL, + 'tags' => NULL, + 'send_reminder' => NULL, + 'reminder_number' => 1, + 'reminder_interval' => 60, + 'repeats' => NULL, + 'repeat_interval' => 1, + 'event-calendar-repeating-monday-value' => 0, + 'event-calendar-repeating-tuesday-value' => 0, + 'event-calendar-repeating-wednesday-value' => 0, + 'event-calendar-repeating-thursday-value' => 0, + 'event-calendar-repeating-friday-value' => 0, + 'event-calendar-repeating-saturday-value' => 0, + 'event-calendar-repeating-sunday-value' => 0, + 'personal_manage' => 'open', + 'web_conference' => NULL, + 'long_description' => NULL, + 'access_id' => ACCESS_DEFAULT, + 'group_guid' => NULL, + ); + + if ($page_type == 'schedule') { + $values['schedule_type'] = 'poll'; + } else { + $values['schedule_type'] = 'all_day'; + } + + if ($event) { + foreach (array_keys($values) as $field) { + if (isset($event->$field)) { + $values[$field] = $event->$field; + } + } + } + + if (elgg_is_sticky_form('event_calendar')) { + $sticky_values = elgg_get_sticky_values('event_calendar'); + foreach ($sticky_values as $key => $value) { + $values[$key] = $value; + } + } + + elgg_clear_sticky_form('event_calendar'); + + return $values; +} + +function event_calendar_generate_listing_params($page_type,$container_guid,$original_start_date,$display_mode,$filter,$region='-') { + $event_calendar_listing_format = elgg_get_plugin_setting('listing_format', 'event_calendar'); + $event_calendar_spots_display = trim(elgg_get_plugin_setting('spots_display', 'event_calendar')); + $event_calendar_first_date = trim(elgg_get_plugin_setting('first_date', 'event_calendar')); + $event_calendar_last_date = trim(elgg_get_plugin_setting('last_date', 'event_calendar')); + + if (!$original_start_date) { + $original_start_date = date('Y-m-d'); + } + if ( $event_calendar_first_date && ($original_start_date < $event_calendar_first_date) ) { + $original_start_date = $event_calendar_first_date; + } + if ( $event_calendar_last_date && ($original_start_date > $event_calendar_last_date) ) { + $original_start_date = $event_calendar_first_date; + } + + if ($event_calendar_listing_format == 'paged') { + $start_ts = strtotime($original_start_date); + $start_date = $original_start_date; + if ($event_calendar_last_date) { + $end_ts = strtotime($event_calendar_last_date); + } else { + // set to a large number + $end_ts = 2000000000; + } + $mode = 'paged'; + } else { + + // the default interval is one month + $day = 60*60*24; + $week = 7*$day; + $month = 31*$day; + + $mode = trim($display_mode); + if (!$mode) { + $mode = 'month'; + } + + if ($mode == "day") { + $start_date = $original_start_date; + $end_date = $start_date; + $start_ts = strtotime($start_date); + $end_ts = strtotime($end_date)+$day-1; + } else if ($mode == "week") { + // need to adjust start_date to be the beginning of the week + $start_ts = strtotime($original_start_date); + $start_ts -= date("w",$start_ts)*$day; + $end_ts = $start_ts + 6*$day; + + $start_date = date('Y-m-d',$start_ts); + $end_date = date('Y-m-d',$end_ts); + } else { + $start_ts = strtotime($original_start_date); + $month = date('m',$start_ts); + $year = date('Y',$start_ts); + $start_date = $year.'-'.$month.'-1'; + $end_date = $year.'-'.$month.'-'.getLastDayOfMonth($month,$year); + } + + if ($event_calendar_first_date && ($start_date < $event_calendar_first_date)) { + $start_date = $event_calendar_first_date; + } + + if ($event_calendar_last_date && ($end_date > $event_calendar_last_date)) { + $end_date = $event_calendar_last_date; + } + + $start_ts = strtotime($start_date); + + if ($mode == "day") { + $end_ts = strtotime($end_date)+$day-1; + $subtitle = elgg_echo('event_calendar:day_label').': '.date('j F Y',strtotime($start_date)); + } else if ($mode == "week") { + // KJ - fix for end date bug + //$end_ts = $start_ts + 6*$day; + $end_ts = $start_ts + 7*$day; + $subtitle = elgg_echo('event_calendar:week_label').': '.date('j F',$start_ts) . ' - '.date('j F Y',$end_ts); + } else { + // KJ - fix for end date bug + //$end_ts = strtotime($end_date); + $end_ts = strtotime($end_date)+24*60*60-1; + $subtitle = date('F Y',$start_ts); + } + } + + $current_user_guid = elgg_get_logged_in_user_guid(); + + $access_status = elgg_get_ignore_access(); + + if ($page_type == 'owner') { + $container = get_entity($container_guid); + if (elgg_instanceof($container, 'user')) { + $auth_token = get_input('auth_token'); + if ($auth_token) { + $secret_key = event_calendar_get_secret_key(); + if ($secret_key && ($auth_token === sha1($container->username . $secret_key))) { + elgg_set_ignore_access(TRUE); + } + } + if ($container->canEdit()) { + $user_guid = $container_guid; + $group_guid = 0; + } else { + register_error('event_calendar:owner:permissions_error'); + forward(); + exit; + } + } else { + register_error('event_calendar:owner:permissions_error'); + forward(); + exit; + } + } else { + $user_guid = $current_user_guid; + $group_guid = $container_guid; + } + + $offset = get_input('offset'); + $limit = get_input('limit',15); + + if ($event_calendar_spots_display == 'yes') { + if (!$filter) { + $filter = 'open'; + } + } else { + if (!$filter) { + $filter = 'all'; + } + } + + if ($filter == 'all') { + $count = event_calendar_get_events_between($start_ts,$end_ts,true,$limit,$offset,$container_guid,$region); + $events = event_calendar_get_events_between($start_ts,$end_ts,false,$limit,$offset,$container_guid,$region); + } else if ($filter == 'open') { + $count = event_calendar_get_open_events_between($start_ts,$end_ts,true,$limit,$offset,$container_guid,$region); + $events = event_calendar_get_open_events_between($start_ts,$end_ts,false,$limit,$offset,$container_guid,$region); + } else if ($filter == 'friends') { + $count = event_calendar_get_events_for_friends_between($start_ts,$end_ts,true,$limit,$offset,$user_guid,$container_guid,$region); + $events = event_calendar_get_events_for_friends_between($start_ts,$end_ts,false,$limit,$offset,$user_guid,$container_guid,$region); + } else if ($filter == 'mine') { + $count = event_calendar_get_events_for_user_between2($start_ts,$end_ts,true,$limit,$offset,$user_guid,$container_guid,$region); + $events = event_calendar_get_events_for_user_between2($start_ts,$end_ts,false,$limit,$offset,$user_guid,$container_guid,$region); + } + + $vars = array( + 'original_start_date' => $original_start_date, + 'start_date' => $start_date, + 'end_date' => $end_date, + 'first_date' => $event_calendar_first_date, + 'last_date' => $event_calendar_last_date, + 'mode' => $mode, + 'events' => $events, + 'count' => $count, + 'offset' => $offset, + 'limit' => $limit, + 'group_guid' => $group_guid, + 'filter' => $filter, + 'region' => $region, + 'listing_format' => $event_calendar_listing_format, + ); + + $content = elgg_view('event_calendar/show_events', $vars); + if ($page_type == 'group') { + $filter_override = ''; + } else { + $filter_override = elgg_view('event_calendar/filter_menu',$vars); + } + + if ($event_calendar_listing_format == 'paged') { + $title = elgg_echo('event_calendar:upcoming_events_title'); + } else if ($event_calendar_listing_format == 'full') { + $title = elgg_echo('event_calendar:show_events_title'); + } else if ($page_type == 'group') { + $title = elgg_echo('event_calendar:group'). ' ('.$subtitle.')'; + } else { + $title = elgg_echo('event_calendar:listing_title:'.$filter). ' ('.$subtitle.')'; + } + + $params = array('title' => $title, 'content' => $content, 'filter_override'=>$filter_override); + elgg_set_ignore_access($access_status); + return $params; +} + +function event_calendar_get_page_content_view($event_guid,$light_box = FALSE) { + // add personal calendar button and links + elgg_push_context('event_calendar:view'); + $event = get_entity($event_guid); + + if (!elgg_instanceof($event, 'object', 'event_calendar')) { + $content = elgg_echo('event_calendar:error_nosuchevent'); + $title = elgg_echo('event_calendar:generic_error_title'); + } else { + $title = htmlspecialchars($event->title); + $event_container = get_entity($event->container_guid); + if (elgg_instanceof($event_container, 'group')) { + if ($event_container->canEdit()) { + event_calendar_handle_menu($event_guid); + } + elgg_push_breadcrumb(elgg_echo('event_calendar:group_breadcrumb'), 'event_calendar/group/'.$event->container_guid); + } else { + if ($event->canEdit()) { + event_calendar_handle_menu($event_guid); + } + elgg_push_breadcrumb(elgg_echo('event_calendar:show_events_title'),'event_calendar/list'); + } + + elgg_push_breadcrumb($event->title); + $content = elgg_view_entity($event, array('full_view' => true,'light_box'=>$light_box)); + //check to see if comment are on - TODO - add this feature to all events + if ($event->comments_on != 'Off') { + $content .= elgg_view_comments($event); + } + } + + if ($light_box) { + return '<div class="event-calendar-lightbox">'.elgg_view_title($title).$content.'</div>'; + } else { + $params = array('title' => $title, 'content' => $content,'filter' => ''); + + $body = elgg_view_layout("content", $params); + + return elgg_view_page($title,$body); + } +} + +function event_calendar_get_page_content_display_users($event_guid) { + elgg_load_js('elgg.event_calendar'); + $event = get_entity($event_guid); + + if (!elgg_instanceof($event, 'object', 'event_calendar')) { + $content = elgg_echo('event_calendar:error_nosuchevent'); + $title = elgg_echo('event_calendar:generic_error_title'); + } else { + event_calendar_handle_menu($event_guid); + $title = elgg_echo('event_calendar:users_for_event_title',array(htmlspecialchars($event->title))); + $event_container = get_entity($event->container_guid); + if (elgg_instanceof($event_container, 'group')) { + elgg_push_context('groups'); + elgg_set_page_owner_guid($event->container_guid); + elgg_push_breadcrumb(elgg_echo('event_calendar:group_breadcrumb'), 'event_calendar/group/'.$event->container_guid); + } else { + elgg_push_breadcrumb(elgg_echo('event_calendar:show_events_title'),'event_calendar/list'); + } + elgg_push_breadcrumb($event->title,$event->getURL()); + elgg_push_breadcrumb(elgg_echo('event_calendar:users_for_event_breadcrumb')); + $limit = 12; + $offset = get_input('offset', 0); + $users = event_calendar_get_users_for_event($event_guid,$limit,$offset,false); + $options = array( + 'full_view' => FALSE, + 'list_type_toggle' => FALSE, + 'limit'=>$limit, + 'event_calendar_event'=>$event, + ); + elgg_extend_view('user/default','event_calendar/calendar_toggle'); + $content = elgg_view_entity_list($users,$options); + } + $params = array('title' => $title, 'content' => $content,'filter' => ''); + + $body = elgg_view_layout("content", $params); + + return elgg_view_page($title,$body); +} + +// display a list of all the members of the container of $event_guid and allowing +// adding or removing them + +function event_calendar_get_page_content_manage_users($event_guid) { + // TODO: make this an optional feature, toggled off + elgg_load_js('elgg.event_calendar'); + $event = get_entity($event_guid); + $limit = 10; + $offset = get_input('offset', 0); + + $event_calendar_add_users = elgg_get_plugin_setting('add_users', 'event_calendar'); + if ($event_calendar_add_users != 'yes') { + register_error(elgg_echo('event_calendar:feature_not_activated')); + forward(); + exit; + } + + if (!elgg_instanceof($event, 'object', 'event_calendar')) { + $content = elgg_echo('event_calendar:error_nosuchevent'); + $title = elgg_echo('event_calendar:generic_error_title'); + } else { + event_calendar_handle_menu($event_guid); + $title = elgg_echo('event_calendar:manage_users:title',array($event->title)); + $event_container = get_entity($event->container_guid); + if ($event_container->canEdit()) { + if (elgg_instanceof($event_container, 'group')) { + elgg_push_context('groups'); + elgg_set_page_owner_guid($event->container_guid); + elgg_push_breadcrumb(elgg_echo('event_calendar:group_breadcrumb'), 'event_calendar/group/'.$event->container_guid); + elgg_register_menu_item('title', array( + 'name' => 'remove_from_group_members', + 'href' => elgg_add_action_tokens_to_url('action/event_calendar/remove_from_group_members?event_guid='.$event_guid), + 'text' => elgg_echo('event_calendar:remove_from_group_members:button'), + 'class' => 'elgg-button elgg-button-action', + )); + elgg_register_menu_item('title', array( + 'name' => 'add_to_group_members', + 'href' => elgg_add_action_tokens_to_url('action/event_calendar/add_to_group_members?event_guid='.$event_guid), + 'text' => elgg_echo('event_calendar:add_to_group_members:button'), + 'class' => 'elgg-button elgg-button-action', + )); + $users = $event_container->getMembers($limit,$offset); + $count = $event_container->getMembers($limit,$offset,TRUE); + elgg_extend_view('user/default','event_calendar/calendar_toggle'); + $options = array( + 'full_view' => FALSE, + 'list_type_toggle' => FALSE, + 'limit'=>$limit, + 'event_calendar_event'=>$event, + 'pagination' => TRUE, + 'count'=>$count, + ); + $content .= elgg_view_entity_list($users,$options,$offset,$limit); + } else { + elgg_push_breadcrumb(elgg_echo('event_calendar:show_events_title'),'event_calendar/list'); + $content = '<p>'.elgg_echo('event_calendar:manage_users:description').'</p>'; + $content .= elgg_view_form('event_calendar/manage_subscribers',array(),array('event'=>$event)); + } + elgg_push_breadcrumb($event->title,$event->getURL()); + elgg_push_breadcrumb(elgg_echo('event_calendar:manage_users:breadcrumb')); + + } else { + $content = elgg_echo('event_calendar:manage_users:unauthorized'); + } + } + $params = array('title' => $title, 'content' => $content,'filter' => ''); + + $body = elgg_view_layout("content", $params); + + return elgg_view_page($title,$body); +} + +function event_calendar_get_page_content_review_requests($event_guid) { + $event = get_entity($event_guid); + + if (!elgg_instanceof($event, 'object', 'event_calendar')) { + $content = elgg_echo('event_calendar:error_nosuchevent'); + $title = elgg_echo('event_calendar:generic_error_title'); + } else { + event_calendar_handle_menu($event_guid); + $title = elgg_echo('event_calendar:review_requests_title',array(htmlspecialchars($event->title))); + $event_container = get_entity($event->container_guid); + if (elgg_instanceof($event_container, 'group')) { + elgg_push_context('groups'); + elgg_set_page_owner_guid($event->container_guid); + elgg_push_breadcrumb(elgg_echo('event_calendar:group_breadcrumb'), 'event_calendar/group/'.$event->container_guid); + } else { + elgg_push_breadcrumb(elgg_echo('event_calendar:show_events_title'),'event_calendar/list'); + } + elgg_push_breadcrumb($event->title,$event->getURL()); + elgg_push_breadcrumb(elgg_echo('event_calendar:review_requests_menu_title')); + + if ($event->canEdit()) { + $requests = elgg_get_entities_from_relationship( + array( + 'relationship' => 'event_calendar_request', + 'relationship_guid' => $event_guid, + 'inverse_relationship' => TRUE, + 'limit' => 0) + ); + if ($requests) { + $content = elgg_view('event_calendar/review_requests',array('requests' => $requests, 'entity' => $event)); + } else { + $content = elgg_echo('event_calendar:review_requests_request_none'); + } + } else { + $content = elgg_echo('event_calendar:review_requests_error'); + } + } + $params = array('title' => $title, 'content' => $content,'filter' => ''); + + $body = elgg_view_layout("content", $params); + + return elgg_view_page($title,$body); +} + +function event_calendar_handle_menu($event_guid) { + $event = get_entity($event_guid); + $event_calendar_personal_manage = elgg_get_plugin_setting('personal_manage', 'event_calendar'); + if ((($event_calendar_personal_manage == 'by_event') && ($event->personal_manage == 'closed')) + || (($event_calendar_personal_manage == 'closed') || ($event_calendar_personal_manage == 'no'))) { + $url = "event_calendar/review_requests/$event_guid"; + $item = new ElggMenuItem('event-calendar-0review_requests', elgg_echo('event_calendar:review_requests_menu_title'), $url); + $item->setSection('event_calendar'); + elgg_register_menu_item('page', $item); + //elgg_register_menu_item(elgg_echo('event_calendar:review_requests_title'), $CONFIG->wwwroot . "pg/event_calendar/review_requests/".$event_id, '0eventcalendaradmin'); + } + $event_calendar_add_users = elgg_get_plugin_setting('add_users', 'event_calendar'); + if ($event_calendar_add_users == 'yes') { + $url = "event_calendar/manage_users/$event_guid"; + $item = new ElggMenuItem('event-calendar-1manage_users', elgg_echo('event_calendar:manage_users:breadcrumb'), $url); + $item->setSection('event_calendar'); + elgg_register_menu_item('page', $item); + } +} +function event_calendar_get_secret_key() { + $key_file_name = elgg_get_plugin_setting('ical_auth_file_name','event_calendar'); + if ($key_file_name && file_exists($key_file_name)) { + $key = (require($key_file_name)); + + return $key['tokenSecretKey']; + } else { + return FALSE; + } +} + +function getLastDayOfMonth($month,$year) { + return idate('d', mktime(0, 0, 0, ($month + 1), 0, $year)); +} + +function event_calendar_modify_full_calendar($event_guid,$day_delta,$minute_delta,$start_time,$resend,$minutes,$iso_date) { + $event = get_entity($event_guid); + if (elgg_instanceof($event,'object','event_calendar') && $event->canEdit()) { + if ($event->is_event_poll) { + if (elgg_is_active_plugin('event_poll')) { + elgg_load_library('elgg:event_poll'); + return event_poll_change($event_guid,$day_delta,$minute_delta,$start_time,$resend,$minutes,$iso_date); + } else { + return FALSE; + } + } else { + $event->start_date = strtotime("$day_delta days",$event->start_date)+60*$minute_delta; + if ($event->end_date) { + $event->end_date = strtotime("$day_delta days",$event->end_date); + } + $times = elgg_get_plugin_setting('times','event_calendar'); + //$inc = 24*60*60*$day_delta+60*$minute_delta; + + //$event->real_end_time += $inc; + $event->real_end_time = strtotime("$day_delta days",$event->real_end_time)+60*$minute_delta; + if ($times != 'no') { + $event->start_time += $minute_delta; + if ($event->end_time) { + $event->end_time += $minute_delta; + } + } + $dow = array('monday','tuesday','wednesday','thursday','friday','saturday','sunday'); + $week_repeats = array(); + $weekday_delta = (($day_delta % 7) + 7) % 7; // Imagine delta is -12: ((-12 % 7) + 7 % 7) = +2 (thursdays are saturdays) + foreach ($dow as $i => $w) { + $v = 'event-calendar-repeating-'.$w.'-value'; + $new_day = $dow[($i+$weekday_delta)%7]; + $week_repeats[$new_day] = $event->$v; + } + foreach ($week_repeats as $w => $value) { + $v = 'event-calendar-repeating-'.$w.'-value'; + $event->$v = $value; + } + return TRUE; + } + } + return FALSE; +} + +function event_calendar_get_page_content_fullcalendar_events($start_date,$end_date,$filter='all',$container_guid=0,$region='-') { + //print "$start_date - $end_date"; + $start_ts = strtotime($start_date); + $end_ts = strtotime($end_date); + if ($filter == 'all') { + $events = event_calendar_get_events_between($start_ts,$end_ts,false,0,0,$container_guid,$region); + } else if ($filter == 'open') { + $events = event_calendar_get_open_events_between($start_ts,$end_ts,false,0,0,$container_guid,$region); + } else if ($filter == 'friends') { + $user_guid = elgg_get_logged_in_user_guid(); + $events = event_calendar_get_events_for_friends_between($start_ts,$end_ts,false,0,0,$user_guid,$container_guid,$region); + } else if ($filter == 'mine') { + $user_guid = elgg_get_logged_in_user_guid(); + $events = event_calendar_get_events_for_user_between2($start_ts,$end_ts,false,0,0,$user_guid,$container_guid,$region); + } + $event_array = array(); + $times_supported = elgg_get_plugin_setting('times','event_calendar') != 'no'; + $polls_supported = elgg_is_active_plugin('event_poll'); + foreach($events as $e) { + $event = $e['event']; + $event_data = $e['data']; + $c = count($event_data); + foreach($event_data as $ed) { + $event_item = array( + 'guid' => $event->guid, + 'title' => $event->title, + 'start' => date('c',$ed['start_time']), + 'end' => date('c',$ed['end_time']), + ); + if (!$times_supported || ($event->schedule_type == 'all_day')) { + $event_item['allDay'] = TRUE; + } else { + $event_item['allDay'] = FALSE; + } + + if ($polls_supported && isset($e['is_event_poll']) && $e['is_event_poll']) { + $event_item['className'] = 'event-poll-class'; + $event_item['title'] .= ' '.elgg_echo('event_calendar:poll_suffix'); + $event_item['is_event_poll'] = TRUE; + $event_item['url'] = elgg_get_site_url().'event_poll/vote/'.$event->guid; + $event_item['minutes'] = $ed['minutes']; + $event_item['iso_date'] = $ed['iso_date']; + } else { + $event_item['id'] = $event->guid; + $event_item['is_event_poll'] = FALSE; + $event_item['url'] = elgg_get_site_url().'event_calendar/view/'.$event->guid; + } + + $event_array[] = $event_item; + } + } + + $json_events_string = json_encode($event_array); + return $json_events_string; +} + +// right now this does not return repeated events in sorted order, so repeated events only really work properly for the full calendar +// TODO: find another solution for displaying repeated events + +function event_calendar_flatten_event_structure($events) { + $flattened = array(); + $guids = array(); + foreach($events as $e) { + $this_event = $e['event']; + $guid = $this_event->guid; + if (!in_array($guid,$guids)) { + $guids[] = $guid; + $flattened[] = $this_event; + } + } + return $flattened; +} + +function event_calendar_queue_reminders() { + // game plan - get all events up to 60 days ahead + // with no reminder sent + // compute reminder period + // if <= current time, set reminder_queued flag and queue the + // notification message using the message_queue plugin + if (elgg_plugin_exists('message_queue')) { + $now = time(); + // oops - this does not work for repeated events + // need extra stuff for that + /*$options = array( + 'type' => 'object', + 'subtype' => 'event_calendar', + 'metadata_name_value_pairs' => array( + array('name' => 'reminder_queued', 'value' => 'no'), + array('name' => 'send_reminder', 'value' => 1), + array('name' => 'start_date', 'value' => $now + 60*24*60*60, 'operand' => '>='), + ), + 'limit' => 0, + ); + $events = elgg_get_entities_from_metadata($options); + */ + $event_list = event_calendar_get_events_between($now,$now + 60*24*60*60,FALSE,0); + + foreach($event_list as $es) { + $e = $es['event']; + if ($e->send_reminder) { + $reminder_period = 60*$e->reminder_interval*$e->reminder_number; + if ($e->repeats) { + // repeated events require more complex handing + foreach($es['data'] as $d) { + // if event falls in the reminder period + if ($d->start_time - $reminder_period >= $now) { + // and the reminder has not already been queued + if (!event_calendar_repeat_reminder_logged($e,$d->start_time)) { + // set the reminder queued flag + event_calendar_repeat_reminder_log($e,$d->start_time); + // queue the reminder for sending + event_calendar_queue_reminder($e); + } + break; + } + } + } else { + // if this is just a normal non-repeated event, then we just need to set a flag and queue the reminder + if (($e->reminder_queued != 'yes') && ($e->start_date - $now <= $reminder_period)) { + $e->reminder_queued = 'yes'; + event_calendar_queue_reminder($e); + } + } + } + } + } +} + +function event_calendar_repeat_reminder_log($e,$start) { + // this simple log just uses annotations on the event + // TODO - remove log entries for past events + create_annotation($e->guid, 'repeat_reminder_log_item', $start, '',0,ACCESS_PUBLIC); +} + +function event_calendar_repeat_reminder_logged($e,$start) { + $options = array( + 'guid' => $e->guid, + 'annotation_name' => 'repeat_reminder_log_item', + 'annotation_value' => $start, + 'limit' => 1 + ); + + if (elgg_get_annotations($options)) { + return TRUE; + } else { + return FALSE; + } +} + +function event_calendar_queue_reminder($e) { + elgg_load_library('elgg:message_queue'); + $subject = elgg_echo('event_calendar:reminder:subject',array($e->title)); + $time_string = event_calendar_get_formatted_time($e); + $body = elgg_echo('event_calendar:reminder:body',array($e->title,$time_string,$e->getURL())); + $m = message_queue_create_message($subject,$body); + if ($m) { + $users = event_calendar_get_users_for_event($e->guid,0); + foreach($users as $u) { + message_queue_add($m->guid,$u->guid); + } + message_queue_set_for_sending($m->guid); + } +} + +/*function event_calendar_create_bbb_conf($event) { + $bbb_security_salt = elgg_get_plugin_setting('bbb_security_salt','event_calendar'); + $bbb_server_url = rtrim(elgg_get_plugin_setting('bbb_server_url','event_calendar'), '/') . '/'; + if ($bbb_security_salt) { + $day_in_minutes = 60*24; + $now = time(); + // fix duration bug + # $duration = (int)(($event->real_end_time-$event->start_date)/60)+$day_in_minutes; + $duration = (int)(($event->real_end_time-$now)/60)+$day_in_minutes; + $title = urlencode($event->title); + $params = "name=$title&meetingID={$event->guid}&duration=$duration"; + $checksum = sha1('create'.$params.$bbb_security_salt); + $params .= "&checksum=$checksum"; + + // create curl resource + $ch = curl_init(); + + // set url + curl_setopt($ch, CURLOPT_URL, $bbb_server_url.'api/create?'.$params); + + //return the transfer as a string + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + + // $output contains the output string + $output = curl_exec($ch); + + // close curl resource to free up system resources + curl_close($ch); + + #error_log("BBB create request:"); + #error_log($bbb_server_url.'api/create?'.$params); + + #error_log("BBB create response:"); + #error_log($output); + + $xml = new SimpleXMLElement($output); + if ($xml->returncode == 'SUCCESS') { + $event->bbb_attendee_password = (string) $xml->attendeePW; + $event->bbb_moderator_password = (string) $xml->moderatorPW; + } else { + register_error(elgg_echo('event_calendar:bbb_create_error',array($xml->message))); + } + } else { + register_error(elgg_echo('event_calendar:bbb_settings_error')); + } +}*/ + +// utility function for BBB api calls +function event_calendar_bbb_api($api_function,$params=NULL) { + + $bbb_security_salt = elgg_get_plugin_setting('bbb_security_salt','event_calendar'); + $bbb_server_url = rtrim(elgg_get_plugin_setting('bbb_server_url','event_calendar'), '/') . '/'; + if ($bbb_security_salt) { + if (isset($params) && is_array($params) && count($params) > 0) { + $query = array(); + foreach($params as $k => $v) { + $query[] = $k.'='.rawurlencode($v); + } + $qs = implode('&',$query); + } else { + $qs = ''; + } + $checksum = sha1($api_function.$qs.$bbb_security_salt); + if ($qs) { + $qs .= "&checksum=$checksum"; + } + + // create curl resource + $ch = curl_init(); + + // set url + curl_setopt($ch, CURLOPT_URL, $bbb_server_url.'api/'.$api_function.'?'.$qs); + + //return the transfer as a string + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + + // $output contains the output string + $output = curl_exec($ch); + + // close curl resource to free up system resources + curl_close($ch); + + error_log("BBB api call: ".$api_function); + error_log(print_r($params,TRUE)); + error_log("BBB response: \n".$output); + return $output; + } else { + return FALSE; + } +} + +function event_calendar_create_bbb_conf($event) { + $day_in_minutes = 60*24; + $now = time(); + // fix duration bug + # $duration = (int)(($event->real_end_time-$event->start_date)/60)+$day_in_minutes; + $duration = (int)(($event->real_end_time-$now)/60)+$day_in_minutes; + if ($duration > 0) { + $title = urlencode($event->title); + $output = event_calendar_bbb_api('create',array('meetingID'=>$event->guid,'name'=>$title,'duration'=>$duration)); + if ($output) { + $xml = new SimpleXMLElement($output); + if ($xml->returncode == 'SUCCESS') { + $event->bbb_attendee_password = (string) $xml->attendeePW; + $event->bbb_moderator_password = (string) $xml->moderatorPW; + return TRUE; + } else { + return FALSE; + } + } else { + return FALSE; + } + } else { + return FALSE; + } +} + +// checks to see if a BBB conference is actually running +function event_calendar_is_conference_running($event) { + $output = event_calendar_bbb_api('isMeetingRunning',array('meetingID'=>$event->guid)); + if (!$output) { + return FALSE; + } else { + $xml = new SimpleXMLElement($output); + if ($xml->returncode == 'SUCCESS' && $xml->running == 'true') { + return TRUE; + } else { + return FALSE; + } + } +} + +// checks to see if a BBB conference exists +function event_calendar_conference_exists($event) { + $output = event_calendar_bbb_api('getMeetingInfo',array('meetingID'=>$event->guid,'password'=>$event->bbb_moderator_password)); + if (!$output) { + return FALSE; + } else { + $xml = new SimpleXMLElement($output); + if ($xml->returncode == 'SUCCESS' && $xml->meetingID == $event->guid) { + return TRUE; + } else { + return FALSE; + } + } +} + +// forwards to the join link +// this function assumes that the conference is running +function event_calendar_join_conference($event) { + forward(event_calendar_get_join_bbb_url($event)); +} + +function event_calendar_get_join_bbb_url($event) { + $bbb_security_salt = elgg_get_plugin_setting('bbb_security_salt','event_calendar'); + $bbb_server_url = rtrim(elgg_get_plugin_setting('bbb_server_url','event_calendar'), '/') . '/'; + $user = elgg_get_logged_in_user_entity(); + $full_name = urlencode($user->name); + if ($event->canEdit()) { + $password = urlencode($event->bbb_moderator_password); + } else { + $password = urlencode($event->bbb_attendee_password); + } + $params = "fullName=$full_name&meetingID={$event->guid}&userID={$user->username}&password=$password"; + $checksum = sha1('join'.$params.$bbb_security_salt); + $params .= "&checksum=$checksum"; + $url = $bbb_server_url.'api/join?'.$params; + return $url; +} + +// returns TRUE if the given user can add an event to the given calendar +// if group_guid is 0, this is assumed to be the site calendar +function event_calendar_can_add($group_guid=0,$user_guid=0) { + if (!$user_guid) { + if (elgg_is_logged_in()) { + $user_guid = elgg_get_logged_in_user_guid(); + } else { + return FALSE; + } + } + if ($group_guid) { + if (!event_calendar_activated_for_group($group_guid)) { + return FALSE; + } + $group = get_entity($group_guid); + if (elgg_instanceof($group,'group')) { + $group_calendar = elgg_get_plugin_setting('group_calendar', 'event_calendar'); + if (!$group_calendar || $group_calendar == 'members') { + return $group->canWriteToContainer($user_guid); + } else if ($group_calendar == 'admin') { + if ($group->canEdit($user_guid)) { + return TRUE; + } else { + return FALSE; + } + } + } else { + return FALSE; + } + } else { + $site_calendar = elgg_get_plugin_setting('site_calendar', 'event_calendar'); + if (!$site_calendar || $site_calendar == 'admin') { + // only admins can post directly to the site-wide calendar + return elgg_is_admin_user($user_guid); + } else if ($site_calendar == 'loggedin') { + // any logged-in user can post to the site calendar + return TRUE; + } + } + + return FALSE; +} |