Please make sure IN_MYBB is defined."); } /** * Event handling class, provides common structure to handle event data. * */ class EventDataHandler extends DataHandler { /** * The language file used in the data handler. * * @var string */ public $language_file = 'datahandler_event'; /** * The prefix for the language variables used in the data handler. * * @var string */ public $language_prefix = 'eventdata'; /** * Array of data inserted in to an event. * * @var array */ public $event_insert_data = array(); /** * Array of data used to update an event. * * @var array */ public $event_update_data = array(); /** * Event ID currently being manipulated by the datahandlers. * * @var int */ public $eid = 0; /** * Values to be returned after inserting/updating an event. * * @var array */ public $return_values = array(); /** * Verifies if an event name is valid or not and attempts to fix it * * @return boolean True if valid, false if invalid. */ function verify_name() { $name = &$this->data['name']; $name = trim($name); if(!$name) { $this->set_error("missing_name"); return false; } return true; } /** * Verifies if an event description is valid or not and attempts to fix it * * @return boolean True if valid, false if invalid. */ function verify_description() { $description = &$this->data['description']; $description = trim($description); if(!$description) { $this->set_error("missing_description"); return false; } return true; } /** * Verifies if an event date is valid or not and attempts to fix it * * @return boolean True if valid, false if invalid. */ function verify_date() { $event = &$this->data; // All types of events require a start date if(!$event['start_date']['day'] || !$event['start_date']['month'] || !$event['start_date']['year']) { $this->set_error("invalid_start_date"); return false; } $event['start_date']['day'] = (int)$event['start_date']['day']; $event['start_date']['month'] = (int)$event['start_date']['month']; $event['start_date']['year'] = (int)$event['start_date']['year']; if($event['start_date']['day'] > date("t", mktime(0, 0, 0, $event['start_date']['month'], 1, $event['start_date']['year']))) { $this->set_error("invalid_start_date"); return false; } // Calendar events can only be within the next 5 years if($event['start_date']['year'] > date("Y") + 5) { $this->set_error("invalid_start_year"); return false; } //Check to see if the month is within 1 and 12 if($event['start_date']['month'] > 12 || $event['start_date']['month'] < 1) { $this->set_error("invalid_start_month"); return false; } // For ranged events, we check the end date & times too if($event['type'] == "ranged") { if(!$event['end_date']['day'] || !$event['end_date']['month'] || !$event['end_date']['year']) { $this->set_error("invalid_end_date"); return false; } $event['end_date']['day'] = (int)$event['end_date']['day']; $event['end_date']['month'] = (int)$event['end_date']['month']; $event['end_date']['year'] = (int)$event['end_date']['year']; if($event['end_date']['day'] > date("t", mktime(0, 0, 0, $event['end_date']['month'], 1, $event['end_date']['year']))) { $this->set_error("invalid_end_date"); return false; } // Calendar events can only be within the next 5 years if($event['end_date']['year'] > date("Y") + 5) { $this->set_error("invalid_end_year"); return false; } //Check to see if the month is within 1 and 12 if($event['end_date']['month'] > 12 || $event['end_date']['month'] < 1) { $this->set_error("invalid_end_month"); return false; } // Validate time input if($event['start_date']['time'] || $event['end_date']['time']) { if(($event['start_date']['time'] && !$event['end_date']['time']) || ($event['end_date']['time'] && !$event['start_date']['time'])) { $this->set_error("cant_specify_one_time"); return false; } // Begin start time validation $start_time = $this->verify_time($event['start_date']['time']); if(!is_array($start_time)) { $this->set_error("start_time_invalid"); return false; } // End time validation $end_time = $this->verify_time($event['end_date']['time']); if(!is_array($end_time)) { $this->set_error("end_time_invalid"); return false; } $event['usingtime'] = 1; } else { $start_time = array("hour" => 0, "min" => 0); $end_time = array("hour" => 23, "min" => 59); $event['usingtime'] = 0; } } if(array_key_exists('timezone', $event)) { $event['timezone'] = (float)$event['timezone']; if($event['timezone'] > 12 || $event['timezone'] < -12) { $this->set_error("invalid_timezone"); return false; } $start_time['hour'] -= $event['timezone']; $end_time['hour'] -= $event['timezone']; } if(!isset($start_time)) { $start_time = array("hour" => 0, "min" => 0); } $start_timestamp = gmmktime($start_time['hour'], $start_time['min'], 0, $event['start_date']['month'], $event['start_date']['day'], $event['start_date']['year']); if($event['type'] == "ranged") { $end_timestamp = gmmktime($end_time['hour'], $end_time['min'], 0, $event['end_date']['month'], $event['end_date']['day'], $event['end_date']['year']); if($end_timestamp <= $start_timestamp) { $this->set_error("end_in_past"); return false; } } if(!isset($end_timestamp)) { $end_timestamp = 0; } // Save our time stamps for saving $event['starttime'] = $start_timestamp; $event['endtime'] = $end_timestamp; return true; } /** * @param string $time * * @return array|bool */ function verify_time($time) { preg_match('#^(0?[1-9]|1[012])\s?([:\.]?)\s?([0-5][0-9])?(\s?[ap]m)|([01][0-9]|2[0-3])\s?([:\.])\s?([0-5][0-9])$#i', $time, $matches); if(count($matches) == 0) { return false; } // 24h time if(count($matches) == 8) { $hour = $matches[5]; $min = $matches[7]; } // 12 hour time else { $hour = $matches[1]; $min = (int)$matches[3]; $matches[4] = trim($matches[4]); if(my_strtolower($matches[4]) == "pm" && $hour != 12) { $hour += 12; } else if(my_strtolower($matches[4]) == "am" && $hour == 12) { $hour = 0; } } return array("hour" => $hour, "min" => $min); } /** * @return bool */ function verify_repeats() { $event = &$this->data; if(!is_array($event['repeats']) || !$event['repeats']['repeats']) { return true; } if(!$event['endtime']) { $this->set_error("only_ranged_events_repeat"); return false; } switch($event['repeats']['repeats']) { case 1: $event['repeats']['days'] = (int)$event['repeats']['days']; if($event['repeats']['days'] <= 0) { $this->set_error("invalid_repeat_day_interval"); return false; } case 2: break; case 3: $event['repeats']['weeks'] = (int)$event['repeats']['weeks']; if($event['repeats']['weeks'] <= 0) { $this->set_error("invalid_repeat_week_interval"); return false; } if(is_array($event['repeats']['days']) && count($event['repeats']['days']) == 0) { $this->set_error("invalid_repeat_weekly_days"); return false; } asort($event['repeats']['days']); break; case 4: if($event['repeats']['day']) { $event['repeats']['day'] = (int)$event['repeats']['day']; if($event['repeats']['day'] <= 0 || $event['repeats']['day'] > 31) { $this->set_error("invalid_repeat_day_interval"); return false; } } else { if($event['repeats']['occurance'] != "last") { $event['repeats']['occurance'] = (int)$event['repeats']['occurance']; } $event['repeats']['weekday'] = (int)$event['repeats']['weekday']; } $event['repeats']['months'] = (int)$event['repeats']['months']; if($event['repeats']['months'] <= 0 || $event['repeats']['months'] > 12) { $this->set_error("invalid_repeat_month_interval"); return false; } break; case 5: if($event['repeats']['day']) { $event['repeats']['day'] = (int)$event['repeats']['day']; if($event['repeats']['day'] <= 0 || $event['repeats']['day'] > 31) { $this->set_error("invalid_repeat_day_interval"); return false; } } else { if($event['repeats']['occurance'] != "last") { $event['repeats']['occurance'] = (int)$event['repeats']['occurance']; } $event['repeats']['weekday'] = (int)$event['repeats']['weekday']; } $event['repeats']['month'] = (int)$event['repeats']['month']; if($event['repeats']['month'] <= 0 || $event['repeats']['month'] > 12) { $this->set_error("invalid_repeat_month_interval"); return false; } $event['repeats']['years'] = (int)$event['repeats']['years']; if($event['repeats']['years'] <= 0 || $event['repeats']['years'] > 4) { $this->set_error("invalid_repeat_year_interval"); return false; } break; default: $event['repeats'] = array(); } require_once MYBB_ROOT."inc/functions_calendar.php"; $event['starttime_user'] = $event['starttime']; $event['endtime_user'] = $event['endtime']; $next_occurance = fetch_next_occurance($event, array('start' => $event['starttime'], 'end' => $event['endtime']), $event['starttime'], true); if($next_occurance > $event['endtime']) { $this->set_error("event_wont_occur"); return false; } return true; } /** * Validate an event. * * @return bool */ function validate_event() { global $plugins; $event = &$this->data; if($this->method == "insert" || array_key_exists('name', $event)) { $this->verify_name(); } if($this->method == "insert" || array_key_exists('description', $event)) { $this->verify_description(); } if($this->method == "insert" || array_key_exists('start_date', $event) || array_key_exists('end_date', $event)) { $this->verify_date(); } if(($this->method == "insert" && $event['endtime']) || array_key_exists('repeats', $event)) { $this->verify_repeats(); } $plugins->run_hooks("datahandler_event_validate", $this); // We are done validating, return. $this->set_validated(true); if(count($this->get_errors()) > 0) { return false; } else { return true; } } /** * Insert an event into the database. * * @return array Array of new event details, eid and private. */ function insert_event() { global $db, $mybb, $plugins; // Yes, validating is required. if(!$this->get_validated()) { die("The event needs to be validated before inserting it into the DB."); } if(count($this->get_errors()) > 0) { die("The event is not valid."); } $event = &$this->data; $query = $db->simple_select("calendars", "*", "cid='".(int)$event['cid']."'"); $calendar_moderation = $db->fetch_field($query, "moderation"); if($calendar_moderation == 1 && (int)$event['private'] != 1) { $visible = 0; if($event['uid'] == $mybb->user['uid']) { $calendar_permissions = get_calendar_permissions($event['cid']); if($calendar_permissions['canbypasseventmod'] == 1) { $visible = 1; } } } else { $visible = 1; } // Prepare an array for insertion into the database. $this->event_insert_data = array( 'cid' => (int)$event['cid'], 'uid' => (int)$event['uid'], 'name' => $db->escape_string($event['name']), 'description' => $db->escape_string($event['description']), 'visible' => $visible, 'private' => (int)$event['private'], 'dateline' => TIME_NOW, 'starttime' => (int)$event['starttime'], 'endtime' => (int)$event['endtime'] ); if(isset($event['timezone'])) { $this->event_insert_data['timezone'] = $db->escape_string((float)$event['timezone']); } if(isset($event['ignoretimezone'])) { $this->event_insert_data['ignoretimezone'] = (int)$event['ignoretimezone']; } if(isset($event['usingtime'])) { $this->event_insert_data['usingtime'] = (int)$event['usingtime']; } if(isset($event['repeats'])) { $this->event_insert_data['repeats'] = $db->escape_string(my_serialize($event['repeats'])); } else { $this->event_insert_data['repeats'] = ''; } $plugins->run_hooks("datahandler_event_insert", $this); $this->eid = $db->insert_query("events", $this->event_insert_data); // Return the event's eid and whether or not it is private. $this->return_values = array( 'eid' => $this->eid, 'private' => $event['private'], 'visible' => $visible ); $plugins->run_hooks("datahandler_event_insert_end", $this); return $this->return_values; } /** * Updates an event that is already in the database. * * @return array */ function update_event() { global $db, $plugins; // Yes, validating is required. if(!$this->get_validated()) { die("The event needs to be validated before inserting it into the DB."); } if(count($this->get_errors()) > 0) { die("The event is not valid."); } $event = &$this->data; $this->eid = $event['eid']; if(isset($event['cid'])) { $this->event_update_data['cid'] = $db->escape_string($event['cid']); } if(isset($event['name'])) { $this->event_update_data['name'] = $db->escape_string($event['name']); } if(isset($event['description'])) { $this->event_update_data['description'] = $db->escape_string($event['description']); } if(isset($event['starttime'])) { $this->event_update_data['starttime'] = (int)$event['starttime']; $this->event_update_data['usingtime'] = (int)$event['usingtime']; } if(isset($event['endtime'])) { $this->event_update_data['endtime'] = (int)$event['endtime']; $this->event_update_data['usingtime'] = (int)$event['usingtime']; } else { $this->event_update_data['endtime'] = 0; $this->event_update_data['usingtime'] = 0; } if(isset($event['repeats'])) { if(!empty($event['repeats'])) { $event['repeats'] = my_serialize($event['repeats']); } $this->event_update_data['repeats'] = $db->escape_string($event['repeats']); } if(isset($event['timezone'])) { $this->event_update_data['timezone'] = $db->escape_string((float)$event['timezone']); } if(isset($event['ignoretimezone'])) { $this->event_update_data['ignoretimezone'] = (int)$event['ignoretimezone']; } if(isset($event['private'])) { $this->event_update_data['private'] = (int)$event['private']; } if(isset($event['visible'])) { $this->event_update_data['visible'] = $db->escape_string($event['visible']); } if(isset($event['uid'])) { $this->event_update_data['uid'] = (int)$event['uid']; } $plugins->run_hooks("datahandler_event_update", $this); $db->update_query("events", $this->event_update_data, "eid='".(int)$event['eid']."'"); // Return the event's eid and whether or not it is private. $this->return_values = array( 'eid' => $event['eid'], 'private' => $event['private'] ); $plugins->run_hooks("datahandler_event_update_end", $this); return $this->return_values; } }