"event_id",
self::FLD_START_DATE => "start_date",
self::FLD_END_DATE => "end_date",
self::FLD_TEXT => "text",
self::FLD_RECURRING_TYPE => "rec_type",
self::FLD_PARENT_ID => "event_pid",
self::FLD_LENGTH => "event_length"
);
private $_connect_configs;
private $_fields_values = array();
public $config = array(
"debug" => true
);
protected function getIdFieldName()
{
return $this->getFieldsNames(self::FLD_ID);
}
protected function getStartDateFieldName()
{
return $this->getFieldsNames(self::FLD_START_DATE);
}
protected function getEndDateFieldName()
{
return $this->getFieldsNames(self::FLD_END_DATE);
}
protected function getTextFieldName()
{
return $this->getFieldsNames(self::FLD_TEXT);
}
protected function getRecurringTypeFieldName()
{
return $this->getFieldsNames(self::FLD_RECURRING_TYPE);
}
protected function getParentIdFieldName()
{
return $this->getFieldsNames(self::FLD_PARENT_ID);
}
protected function getLengthFieldName()
{
return $this->getFieldsNames(self::FLD_LENGTH);
}
protected function getConnectConfigs()
{
return $this->_connect_configs;
}
protected function setConnectConfigs($connectConfigs)
{
$this->_connect_configs = $connectConfigs;
return $this;
}
protected function getFieldsNames($field = NULL)
{
if(is_null($field))
return $this->_fields_names;
if(!isset($this->_fields_names[$field]))
throw new Exception("Field {$field} not found.");
return $this->_fields_names[$field];
}
public function setFieldsNames($fieldsDataArray)
{
if(!is_array($fieldsDataArray))
throw new Exception("Fields data must be array.");
foreach($fieldsDataArray as $fieldKey => $fieldValue) {
//If field name is numeric, then made same field key and field value.
if(is_numeric($fieldKey))
$fieldKey = $fieldValue;
$this->_fields_names[$fieldKey] = $fieldValue;
}
return $this;
}
protected function setFieldsValues($dataArray)
{
foreach($dataArray as $fieldKey => $fieldValue)
$this->_fields_values[$this->_fields_names[$fieldKey]] = $fieldValue;
return $this;
}
protected function getFieldsValues($field = NULL)
{
if(is_null($field))
return $this->_fields_values;
if(isset($this->_fields_values[$this->_fields_names[$field]]))
return $this->_fields_values[$this->_fields_names[$field]];
return NULL;
}
}
interface IHelper
{
public function getData($startDate, $endDate);
public function saveData($dataArray);
public function deleteById($id);
}
class Helper extends DHelper implements IHelper
{
public function __construct($connectConfigs = NULL)
{
$this->setConnectConfigs($connectConfigs);
parent::__construct($connectConfigs);
}
public static function getInstance($connectConfigs = NULL)
{
return new self($connectConfigs);
}
/**
* Get recurring events data exceptions. And prepare data to format: []
* @param $startDate
* @param $endDate
* @return array
*/
private function _getRecurringEventsExceptionsByInterval($startDate, $endDate)
{
$getEventsSql = "
SELECT
*
FROM
".$this->getTableName()."
WHERE
".$this->getStartDateFieldName()." <= '{$endDate}'
AND ".$this->getEndDateFieldName()." >= '{$startDate}'
AND (
".$this->getRecurringTypeFieldName()." = '".RecurringType::IS_RECURRING_EXCEPTION."'
OR ".$this->getRecurringTypeFieldName()." = '".RecurringType::IS_RECURRING_BREAK."'
OR ".$this->getRecurringTypeFieldName()." IS NULL
)
AND ".$this->getLengthFieldName()." > '0'
";
$query = $this->getPDO()->prepare($getEventsSql);
$query->execute();
$events = array();
while($eventData = $query->fetch(PDO::FETCH_ASSOC))
{
$eventParentId = $eventData[$this->getParentIdFieldName()];
if(!isset($events[$eventParentId]))
$events[$eventParentId] = array();
$eventLength = $eventData[$this->getLengthFieldName()];
$events[$eventParentId][$eventLength] = $eventData;
}
return $events;
}
/**
* Get simple events by interval.
* @param $startDate
* @param $endDate
* @return array
*/
private function _getSimpleEventsByInterval($startDate, $endDate) {
$getEventsSql = "
SELECT
*
FROM
".$this->getTablename()."
WHERE
".$this->getStartDateFieldName()." <= '{$endDate}'
AND ".$this->getEndDateFieldName()." >= '{$startDate}'
AND (
".$this->getRecurringTypeFieldName()." = '".RecurringType::IS_RECURRING_EXCEPTION."'
OR ".$this->getRecurringTypeFieldName()." = '".RecurringType::IS_RECURRING_BREAK."'
OR ".$this->getRecurringTypeFieldName()." IS NULL
)
AND ".$this->getLengthFieldName()." = '0'
";
$query = $this->getPDO()->prepare($getEventsSql);
$query->execute();
return $query->fetchAll();
}
/**
* Get recurring events data by interval.
* @param $startDate
* @param $endDate
* @return array
*/
private function _getRecurringEventsByInterval($startDate, $endDate)
{
$getEventsSql = "
SELECT
*
FROM
".$this->getTablename()."
WHERE
".$this->getStartDateFieldName()." >= '{$startDate}'
AND ".$this->getEndDateFieldName()." <= '{$endDate}'
AND (
".$this->getRecurringTypeFieldName()." != '".RecurringType::IS_RECURRING_EXCEPTION."'
AND ".$this->getRecurringTypeFieldName()." != '".RecurringType::IS_RECURRING_BREAK."'
AND ".$this->getRecurringTypeFieldName()." IS NOT NULL
)
AND ".$this->getLengthFieldName()." != '0'
";
$query = $this->getPDO()->prepare($getEventsSql);
$query->execute();
return $query->fetchAll();
}
/**
* Exclude event extra data.
* @param $eventDataArray
* @return array
*/
private function _filterEventDataToResponse($eventDataArray)
{
$filteredEventData = array();
foreach($eventDataArray as $dataKey => $dataValue) {
switch($dataKey) {
case $this->getIdFieldName():
case $this->getRecurringTypeFieldName():
case $this->getParentIdFieldName():
case $this->getLengthFieldName():
continue;
break;
default:
$filteredEventData[$dataKey] = $dataValue;
break;
}
}
return $filteredEventData;
}
/**
* Exclude recurring exceptions from dates and prepare events data.
* @param $recurringDatesStamps
* @param $recurringEventData
* @param array $recurringEventExceptionsData
* @return array
*/
private function _prepareRecurringDataWithoutExceptions($recurringDatesStamps, $recurringEventData, $recurringEventExceptionsData = array())
{
$recurringData = array();
$parentRecurringExceptions = array();
if(isset($recurringEventExceptionsData[$recurringEventData[$this->getIdFieldName()]]))
$parentRecurringExceptions = $recurringEventExceptionsData[$recurringEventData[$this->getIdFieldName()]];
for($i = 0; $i < count($recurringDatesStamps); $i++) {
$preparedEventData = $recurringEventData;
$eventStartDateStamp = $recurringDatesStamps[$i];
$preparedEventData[$this->getStartDateFieldName()] = date(SchedulerHelperDate::FORMAT_DEFAULT, $eventStartDateStamp);
$eventEndDateStamp = $eventStartDateStamp + $recurringEventData[$this->getLengthFieldName()];
$preparedEventData[$this->getEndDateFieldName()] = date(SchedulerHelperDate::FORMAT_DEFAULT, $eventEndDateStamp);
if(isset($parentRecurringExceptions[$eventStartDateStamp])) {
$eventExceptionData = $parentRecurringExceptions[$eventStartDateStamp];
if($eventExceptionData[$this->getRecurringTypeFieldName()] != RecurringType::IS_RECURRING_BREAK)
$preparedEventData = $eventExceptionData;
else
continue;
}
$preparedEventData = $this->_filterEventDataToResponse($preparedEventData);
array_push($recurringData, $preparedEventData);
}
return $recurringData;
}
/**
* Get recurring events data by interval.
* @param $startDate
* @param $endDate
* @return array
*/
public function getData($startDate, $endDate)
{
$eventsData = array();
$recurringEventsExceptions = $this->_getRecurringEventsExceptionsByInterval($startDate, $endDate);
$recurringEvents = $this->_getRecurringEventsByInterval($startDate, $endDate);
$intervalStartDateStamp = SchedulerHelperDate::getDateTimestamp($startDate);
$intervalEndDateStamp = SchedulerHelperDate::getDateTimestamp($endDate);
for($i = 0; $i < count($recurringEvents); $i++) {
$eventData = $recurringEvents[$i];
//Parse recurring data format.
$recurringTypeData = $eventData[$this->getRecurringTypeFieldName()];
$recurringStartDateStamp = SchedulerHelperDate::getDateTimestamp($eventData[$this->getStartDateFieldName()]);
$recurringEndDateStamp = SchedulerHelperDate::getDateTimestamp($eventData[$this->getEndDateFieldName()]);
$recurringTypeObj = new RecurringType($recurringTypeData, $recurringStartDateStamp, $recurringEndDateStamp);
//Get recurring dates by parsed format.
$recurringDatesStamps = $recurringTypeObj->getRecurringDates($intervalStartDateStamp, $intervalEndDateStamp);
//Exclude recurring exceptions by dates and prepare events data.
$recurringEventData = $this->_prepareRecurringDataWithoutExceptions($recurringDatesStamps, $eventData, $recurringEventsExceptions);
$eventsData = array_merge($eventsData, $recurringEventData);
}
//Add simple events.
$simpleEvents = $this->_getSimpleEventsByInterval($startDate, $endDate);
$eventsData = array_merge($eventsData, $simpleEvents);
//Leave events that belongs to interval.
$resultData = array();
for($i = 0; $i < count($eventsData); $i++) {
$eventData = $eventsData[$i];
$recurringStartDateStamp = SchedulerHelperDate::getDateTimestamp($eventData[$this->getStartDateFieldName()]);
$recurringEndDateStamp = SchedulerHelperDate::getDateTimestamp($eventData[$this->getEndDateFieldName()]);
if(
(($intervalStartDateStamp <= $recurringStartDateStamp) && ($recurringStartDateStamp <= $intervalEndDateStamp))
|| (($intervalStartDateStamp <= $recurringEndDateStamp) && ($recurringEndDateStamp <= $intervalEndDateStamp))
) {
array_push($resultData, $eventData);
}
}
return $resultData;
}
/**
* Save recurring events data.
* @param $dataArray
* @throws Exception
*/
public function saveData($dataArray)
{
//If exist recurring type field and this array, then parse this to string.
if((isset($dataArray[self::FLD_RECURRING_TYPE])) && is_array($dataArray[self::FLD_RECURRING_TYPE]))
$dataArray[self::FLD_RECURRING_TYPE] = RecurringType::parseRecurringDataArrayToString($dataArray[self::FLD_RECURRING_TYPE]);
$PDO = $this->getPDO();
$PDO->beginTransaction();
try {
self::getInstance($this->getConnectConfigs())
->setFieldsNames($this->getFieldsNames())
->setFieldsValues($dataArray)
->save();
$PDO->commit();
}
catch(Exception $error) {
$PDO->rollBack();
throw new Exception("Data not saved.");
}
}
/**
* Delete data event by id.
* @param $id
* @throws Exception
*/
public function deleteById($id)
{
$PDO = $this->getPDO();
$PDO->beginTransaction();
try {
self::getInstance($this->getConnectConfigs())
->setFieldsNames($this->getFieldsNames())
->setFieldsValues(array(self::FLD_ID => $id))
->delete();
$PDO->commit();
}
catch(Exception $error) {
$PDO->rollBack();
throw new Exception("Data not deleted.");
}
}
/**
* Get max recurring end date for recurring type.
* @param $recurringType
* @param $startDateStr
* @param $eventLength
* @return int
*/
public function getRecurringEndDateStr($recurringType, $startDateStr, $eventLength) {
$endDateStamp = RecurringType::getRecurringEndDate($recurringType, SchedulerHelperDate::getDateTimestamp($startDateStr), $eventLength);
return date(SchedulerHelperDate::FORMAT_DEFAULT, $endDateStamp);
}
}