<?php
/**
* MyBB 1.6
* Copyright 2010 MyBB Group, All Rights Reserved
*
* Website: http://mybb.com
* License: http://mybb.com/about/license
*
* $Id: event.php 5828 2012-05-08 16:06:16Z Tomm $
*/
// Disallow direct access to this file for security reasons
if(!defined("IN_MYBB"))
{
die("Direct initialization of this file is not allowed.<br /><br />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.
*/
public $eid = 0;
/**
* 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;
}
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;
}
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'] = floatval($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'];
}
$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;
}
}
// Save our time stamps for saving
$event['starttime'] = $start_timestamp;
$event['endtime'] = $end_timestamp;
return true;
}
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 = intval($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);
}
function verify_repeats()
{
global $mybb;
$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'] = intval($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'] = intval($event['repeats']['weeks']);
if($event['repeats']['weeks'] <= 0)
{
$this->set_error("invalid_repeat_week_interval");
return false;
}
if(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'] = intval($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'] = intval($event['repeats']['occurance']);
}
$event['repeats']['weekday'] = intval($event['repeats']['weekday']);
}
$event['repeats']['months'] = intval($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'] = intval($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'] = intval($event['repeats']['occurance']);
}
$event['repeats']['weekday'] = intval($event['repeats']['weekday']);
}
$event['repeats']['month'] = intval($event['repeats']['month']);
if($event['repeats']['month'] <= 0 || $event['repeats']['month'] > 12)
{
$this->set_error("invalid_repeat_month_interval");
return false;
}
$event['repeats']['years'] = intval($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.
*
* @param array The event data array.
*/
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.
*
* @param array The array of event data.
* @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='".intval($event['cid'])."'");
$calendar_moderation = $db->fetch_field($query, "moderation");
if($calendar_moderation == 1 && intval($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' => intval($event['cid']),
'uid' => intval($event['uid']),
'name' => $db->escape_string($event['name']),
'description' => $db->escape_string($event['description']),
'visible' => $visible,
'private' => intval($event['private']),
'dateline' => TIME_NOW,
'starttime' => intval($event['starttime']),
'endtime' => intval($event['endtime']),
'timezone' => $db->escape_string(floatval($event['timezone'])),
'ignoretimezone' => intval($event['ignoretimezone']),
'usingtime' => intval($event['usingtime']),
'repeats' => $db->escape_string(serialize($event['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.
return array(
'eid' => $this->eid,
'private' => $event['private'],
'visible' => $visible
);
}
/**
* Updates an event that is already in the database.
*
* @param array The event data 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'] = intval($event['starttime']);
$this->event_update_data['usingtime'] = intval($event['usingtime']);
}
if(isset($event['endtime']))
{
$this->event_update_data['endtime'] = intval($event['endtime']);
$this->event_update_data['usingtime'] = intval($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'] = 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(floatval($event['timezone']));
}
if(isset($event['ignoretimezone']))
{
$this->event_update_data['ignoretimezone'] = intval($event['ignoretimezone']);
}
if(isset($event['private']))
{
$this->event_update_data['private'] = intval($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'] = intval($event['uid']);
}
$plugins->run_hooks("datahandler_event_update", $this);
$db->update_query("events", $this->event_update_data, "eid='".intval($event['eid'])."'");
// Return the event's eid and whether or not it is private.
return array(
'eid' => $event['eid'],
'private' => $event['private']
);
}
}
?>