diff options
author | Egor <elazarovich@xbsoftware.com> | 2015-03-06 11:58:17 +0300 |
---|---|---|
committer | Egor <elazarovich@xbsoftware.com> | 2015-03-06 11:58:17 +0300 |
commit | c84f7d0038fa9bc1c6569bc7e4d73da17fb414fd (patch) | |
tree | d9ac8a6ee2f0b457e388dfe3579770dcc02cf5e5 | |
download | scheduler-helper-php-c84f7d0038fa9bc1c6569bc7e4d73da17fb414fd.zip scheduler-helper-php-c84f7d0038fa9bc1c6569bc7e4d73da17fb414fd.tar.gz scheduler-helper-php-c84f7d0038fa9bc1c6569bc7e4d73da17fb414fd.tar.bz2 |
Added.
-rw-r--r-- | RecurringType.php | 383 | ||||
-rw-r--r-- | SchedulerDate.php | 99 | ||||
-rw-r--r-- | SchedulerHelper.php | 391 | ||||
-rw-r--r-- | SchedulerHelperConnector.php | 105 |
4 files changed, 978 insertions, 0 deletions
diff --git a/RecurringType.php b/RecurringType.php new file mode 100644 index 0000000..b5ff1de --- /dev/null +++ b/RecurringType.php @@ -0,0 +1,383 @@ +<?php +namespace Scheduler; +use Exception; + +class RecurringType { + + //RECURRING DATA FIELDS + const FLD_REC_TYPE = "type"; + const FLD_REC_TYPE_STEP = "count"; + const FLD_WEEK_DAY = "day"; + const FLD_WEEK_NUMBER = "count2"; + const FLD_WEEK_DAYS_LIST = "days"; + const FLD_REPEAT = "repeat"; + + //RECURRING TYPES + const REC_TYPE_DAY = "day"; + const REC_TYPE_WEEK = "week"; + const REC_TYPE_MONTH = "month"; + const REC_TYPE_YEAR = "year"; + + //RECURRING VALUES + const IS_RECURRING_EXCEPTION = ""; + const IS_RECURRING_BREAK = "none"; + + private $_fields_values = array(); + private $_recurring_start_date_stamp; + private $_recurring_end_date_stamp; + + public function __construct($recurringType, $recurringStartDateStamp, $recurringEndDateStamp) + { + if(is_array($recurringType)) + $recurringType = self::parseRecurringDataArrayToString($recurringType); + + $this->_fields_values = self::_parseRecurringDataString($recurringType); + $this->_recurring_start_date_stamp = $recurringStartDateStamp; + $this->_recurring_end_date_stamp = $recurringEndDateStamp; + } + + public static function getInstance($recurringTypeString, $recurringStartDateStamp, $recurringEndDateStamp) { + return new self($recurringTypeString, $recurringStartDateStamp, $recurringEndDateStamp); + } + + /** + * Get field value. + * @param $fieldName + * @return mixed + * @throws Exception + */ + private function _getFieldValue($fieldName) + { + if(!isset($this->_fields_values[$fieldName])) + throw new Exception("Field '{$fieldName}' not found."); + + return $this->_fields_values[$fieldName]; + } + + /** + * Parse recurring data from array to string. + * @param $dataArray + * @return string + * @throws Exception + */ + static function parseRecurringDataArrayToString($dataArray) + { + $dataFields = array( + self::FLD_REC_TYPE => "each", + self::FLD_REC_TYPE_STEP => "step", +// self::FLD_WEEK_DAY => "day_of_week",//ToDo: delete. + self::FLD_WEEK_NUMBER => "week_number", + self::FLD_WEEK_DAYS_LIST => "days_of_week", + self::FLD_REPEAT => "repeat" + ); + + $recurringTypes = array(self::REC_TYPE_DAY, self::REC_TYPE_WEEK, self::REC_TYPE_MONTH, self::REC_TYPE_YEAR); + $daysOfWeek = array("sunday" => 0, "monday" => 1, "tuesday" => 2, "wednesday" => 3, "thursday" => 4, "friday" => 5, "saturday" => 6); + $dataFieldsValues = array(); + + foreach($dataArray as $field => $value) { + switch($field) { + case $dataFields[self::FLD_REC_TYPE_STEP]: + case $dataFields[self::FLD_REPEAT]: + $value = str_replace(" ", "", $value); + $dataFieldsValues[$field] = $value; + break; + + case $dataFields[self::FLD_REC_TYPE]: + $value = str_replace(" ", "", $value); + if(!in_array($value, $recurringTypes)) + throw new Exception("Field '{$field}' will contains value of ".join(", ", $recurringTypes)); + + $dataFieldsValues[$field] = $value; + break; + + + case $dataFields[self::FLD_WEEK_NUMBER]: + $value = str_replace(" ", "", $value); + if(count(explode(",", $dataArray[$dataFields[self::FLD_WEEK_DAYS_LIST]])) > 1) + throw new Exception("If field {$field} not null, then field ".$dataFields[self::FLD_WEEK_DAYS_LIST]." will contains only one value of ".join(", ", array_keys($daysOfWeek))); + + if(!in_array($value, $daysOfWeek)) + throw new Exception("Field {$field} will contains value of ".join(",", array_keys($daysOfWeek))); + + $dataFieldsValues[$field] = $value; + break; + + case $dataFields[self::FLD_WEEK_DAYS_LIST]: + $weekDaysToRecurring = explode(",", $value); + $days = array(); + foreach($weekDaysToRecurring as $day) { + $day = str_replace(" ", "", $day); + if(!in_array($day, $daysOfWeek)) + throw new Exception("Field {$field} will contains data like 'monday,tuesday,wednesday'."); + + array_push($days, $daysOfWeek[$day]); + } + + $dataFieldsValues[$field] = join("," ,$days); + break; + + default: + $dataFieldsValues[$field] = ""; + break; + } + } + + //Check required data and fill gaps of data. + $requiredFields = array( + self::FLD_REC_TYPE, + self::FLD_REC_TYPE_STEP + ); + + foreach($dataFields as $fieldKey => $fieldName) { + if(isset($dataFieldsValues[$fieldName])) + continue; + + if(in_array($fieldKey, $requiredFields)) + throw new Exception("Field '{$fieldName}' is required"); + + $dataFieldsValues[$fieldName] = ""; + } + + $recurringFormat = "%s_%s_%s_%s_%s#%s"; + return sprintf( + $recurringFormat, + $dataFieldsValues[$dataFields[self::FLD_REC_TYPE]], + $dataFieldsValues[$dataFields[self::FLD_REC_TYPE_STEP]], + (!empty($dataFieldsValues[$dataFields[self::FLD_WEEK_NUMBER]])) ? $dataFieldsValues[$dataFields[self::FLD_WEEK_DAYS_LIST]] : "", + $dataFieldsValues[$dataFields[self::FLD_WEEK_NUMBER]], + (empty($dataFieldsValues[$dataFields[self::FLD_WEEK_NUMBER]])) ? $dataFieldsValues[$dataFields[self::FLD_WEEK_DAYS_LIST]] : "", + $dataFieldsValues[$dataFields[self::FLD_REPEAT]] + ); + } + + /** + * Parse recurring data from string. + * @param $dataStr + * @return array + */ + static private function _parseRecurringDataString($dataStr) + { + $formatPartsReg = "/(_|#)/"; + $formatDaysListPartReg = "/,/"; + $parsedData = array(); + + list( + $parsedData[self::FLD_REC_TYPE], + $parsedData[self::FLD_REC_TYPE_STEP], + $parsedData[self::FLD_WEEK_DAY], + $parsedData[self::FLD_WEEK_NUMBER], + $parsedData[self::FLD_WEEK_DAYS_LIST], + $parsedData[self::FLD_REPEAT] + ) = preg_split($formatPartsReg, $dataStr); + + $parsedData[self::FLD_WEEK_DAYS_LIST] = ($parsedData[self::FLD_WEEK_DAYS_LIST]) ? + preg_split($formatDaysListPartReg, $parsedData[self::FLD_WEEK_DAYS_LIST]) : array(); + + return $parsedData; + } + + public function getRecurringTypeValue() + { + return $this->_getFieldValue(self::FLD_REC_TYPE); + } + + public function getRecurringTypeStepValue() + { + return $this->_getFieldValue(self::FLD_REC_TYPE_STEP); + } + + public function getWeekNumberValue() + { + return $this->_getFieldValue(self::FLD_WEEK_NUMBER); + } + + public function getWeekDayValue() + { + return $this->_getFieldValue(self::FLD_WEEK_DAY); + } + + public function getWeekDaysListValue() + { + return $this->_getFieldValue(self::FLD_WEEK_DAYS_LIST); + } + + public function getRepeatValue() + { + return $this->_getFieldValue(self::FLD_REPEAT); + } + + /** + * Correcting interval by recurring start($this->_recurring_start_date_stamp) + * and end($this->_recurring_end_date_stamp) dates. + * @param $intervalStartDateStamp + * @param $intervalEndDateStamp + * @return array + */ + private function _getCorrectedRecurringInterval($intervalStartDateStamp, $intervalEndDateStamp) + { + $recurringStartDateStamp = $this->_recurring_start_date_stamp; + $recurringEndDateStamp = $this->_recurring_end_date_stamp; + + $recurringInterval = array( + "start_date_stamp" => $intervalStartDateStamp, + "end_date_stamp" => $intervalEndDateStamp + ); + + //Return recurring interval without correcting if it not belongs to assigned interval. + if(($intervalStartDateStamp >= $recurringEndDateStamp) || ($intervalEndDateStamp <= $recurringStartDateStamp)) + return $recurringInterval; + + //Correct start date interval if it smaller then recurring start date. + if($intervalStartDateStamp < $recurringStartDateStamp) + $intervalStartDateStamp = $recurringStartDateStamp; + + //Correct end date interval if it smaller then recurring end date. + if($intervalEndDateStamp > $recurringEndDateStamp) + $intervalEndDateStamp = $recurringEndDateStamp; + + $differenceStartDates = SchedulerDate::differenceBetweenDates($intervalStartDateStamp, $recurringStartDateStamp); + $differenceEndDates = SchedulerDate::differenceBetweenDates($intervalEndDateStamp, $recurringEndDateStamp); + $dateUnits = SchedulerDate::$DATE_UNITS; + + //Add years. + $recurringInterval["start_date_stamp"] = SchedulerDate::addYears($recurringStartDateStamp, $differenceStartDates[$dateUnits["year"]]); + $recurringInterval["end_date_stamp"] = SchedulerDate::addYears($recurringEndDateStamp, -$differenceEndDates[$dateUnits["year"]]); + + //If recurring type is "year" then exit, else add months. + if($this->getRecurringTypeValue() == self::REC_TYPE_YEAR) + return $recurringInterval; + + //Add months. + $recurringInterval["start_date_stamp"] = SchedulerDate::addMonths($recurringInterval["start_date_stamp"], $differenceStartDates[$dateUnits["month"]]); + $recurringInterval["end_date_stamp"] = SchedulerDate::addMonths($recurringInterval["end_date_stamp"], -$differenceEndDates[$dateUnits["month"]]); + return $recurringInterval; + } + + /** + * Get step to recurring day from current day of week in date. + * @param $dateStamp + * @param $recurringWeekDay + * @return int + */ + private function _getRecurringDayStep($dateStamp, $recurringWeekDay) + { + $weekDay = SchedulerDate::getDayOfWeek($dateStamp); + $dayStep = $recurringWeekDay - $weekDay; + $dayStep = ($dayStep < 0) ? (SchedulerDate::DAYS_IN_WEEK - (-$dayStep)) : $dayStep; + return $dayStep; + } + + /** + * Get recurring days for date. + * @param $dateStamp + * @return array + */ + private function _getRecurringDays($dateStamp) + { + $recurringDays = array(); + + //If recurring type has list of days, then get those days. + $recurringWeekDays = $this->getWeekDaysListValue(); + if($recurringWeekDays) { + for($i = 0; $i < count($recurringWeekDays); $i++) { + $dayStep = $this->_getRecurringDayStep($dateStamp, $recurringWeekDays[$i]); + array_push($recurringDays, SchedulerDate::addDays($dateStamp, $dayStep)); + } + } + //Else if recurring type has day of week and step for it, then get this day. + elseif($this->getWeekDayValue() && $this->getWeekNumberValue()) { + $dayStep = $this->_getRecurringDayStep($dateStamp, $this->getWeekDayValue()); + $dayStep += (SchedulerDate::DAYS_IN_WEEK * ($this->getWeekNumberValue() - 1)); + array_push($recurringDays, SchedulerDate::addDays($dateStamp, $dayStep)); + } + //Else return recurring date without change. + else + array_push($recurringDays, $dateStamp); + + return $recurringDays; + } + + /** + * Get recurring dates by interval or $intervalStartDateStamp and $countDates. + * @param $intervalStartDateStamp + * @param $intervalEndDateStamp + * @param null $countDates + * @return array|bool + */ + public function getRecurringDates($intervalStartDateStamp, $intervalEndDateStamp, $countDates = NULL) + { + if(!($this->getRecurringTypeStepValue() && $this->getRecurringTypeValue())) + return false; + + //Correct interval by recurring interval. + $correctedInterval = $this->_getCorrectedRecurringInterval($intervalStartDateStamp, $intervalEndDateStamp); + $intervalStartDateStamp = $correctedInterval["start_date_stamp"]; + $intervalEndDateStamp = $correctedInterval["end_date_stamp"]; + $currentRecurringStartDateStamp = $intervalStartDateStamp; + $recurringDates = array(); + + //Generate dates wile next recurring date belongs to interval. + $countRecurringCycles = 0; + while( + (!is_null($countDates) && ($countRecurringCycles <= $countDates)) + || ( + ($intervalStartDateStamp <= $currentRecurringStartDateStamp) + && ($currentRecurringStartDateStamp <= $intervalEndDateStamp) + ) + ) { + $countRecurringCycles++; + $recurringDays = $this->_getRecurringDays($currentRecurringStartDateStamp); + $recurringDates = array_merge($recurringDates, $recurringDays); + + $recurringTypeStep = $this->getRecurringTypeStepValue(); + switch($this->getRecurringTypeValue()) { + case self::REC_TYPE_DAY: + $currentRecurringStartDateStamp = SchedulerDate::addDays($currentRecurringStartDateStamp, $recurringTypeStep); + break; + + case self::REC_TYPE_WEEK: + $currentRecurringStartDateStamp = SchedulerDate::addWeeks($currentRecurringStartDateStamp, $recurringTypeStep); + break; + + case self::REC_TYPE_MONTH: + $currentRecurringStartDateStamp = SchedulerDate::addMonths($currentRecurringStartDateStamp, $recurringTypeStep); + break; + + case self::REC_TYPE_YEAR: + $currentRecurringStartDateStamp = SchedulerDate::addYears($currentRecurringStartDateStamp, $recurringTypeStep); + break; + } + } + + return (!is_null($countDates)) + ? array_splice($recurringDates, (count($recurringDates) - $countDates)) + : $recurringDates; + } + + /** + * @param $recurringType + * @param $startDateStamp + * @param $eventLength + * @return int|NULL + */ + public static function getRecurringEndDate($recurringType, $startDateStamp, $eventLength) + { + $recurringTypeObj = self::getInstance($recurringType, $startDateStamp, NULL); + + $repeatValue = $recurringTypeObj->getRepeatValue(); + if(empty($repeatValue)) + return ($startDateStamp + $eventLength); + + $recurringStartDatesStamps = $recurringTypeObj->getRecurringDates($startDateStamp, NULL, $repeatValue); + + $maxEndDateStamp = NULL; + foreach($recurringStartDatesStamps as $startDateStamp) { + $endDateStamp = $startDateStamp + $eventLength; + $maxEndDateStamp = ($endDateStamp > $maxEndDateStamp) ? $endDateStamp : $maxEndDateStamp; + } + + return $maxEndDateStamp; + } + +}
\ No newline at end of file diff --git a/SchedulerDate.php b/SchedulerDate.php new file mode 100644 index 0000000..52d342f --- /dev/null +++ b/SchedulerDate.php @@ -0,0 +1,99 @@ +<?php + +namespace Scheduler; +use DateTime; + +interface ISchedulerDate +{ + static public function getDateTimestamp($date); +} + +class SchedulerDate implements ISchedulerDate +{ + const SECONDS_IN_DAY = 86400; + const DAYS_IN_WEEK = 7; + const MONTHS_IN_YEAR = 12; + + const FORMAT_DEFAULT = "Y-m-d H:i:s"; + + static $DATE_UNITS = array( + "hour" => "H", + "minute" => "i", + "second" => "s", + "month" => "m", + "day" => "d", + "year" => "Y" + ); + + static public function differenceBetweenDates($firstDateStamp, $secondDateStamp) { + $firstDate = new DateTime(date(self::FORMAT_DEFAULT, $firstDateStamp)); + $secondDate = new DateTime(date(self::FORMAT_DEFAULT, $secondDateStamp)); + $dateUnits = self::$DATE_UNITS; + $differenceArray = array(); + + foreach($dateUnits as $dateUnit) + $differenceArray[$dateUnit] = $firstDate->diff($secondDate, true)->format("%".$dateUnit); + + return $differenceArray; + } + + static public function getDateTimestamp($date) + { + $parsedDate = date_parse($date); + return mktime( + $parsedDate["hour"], + $parsedDate["minute"], + $parsedDate["second"], + $parsedDate["month"], + $parsedDate["day"], + $parsedDate["year"] + ); + } + + static public function getDayOfWeek($timestamp) { + $weekDay = getdate($timestamp)["wday"]; + return $weekDay; + } + + static public function addDate($timestamp, $unit, $count) { + $dateUnits = self::$DATE_UNITS; + $units = array( + $dateUnits["hour"], + $dateUnits["minute"], + $dateUnits["second"], + $dateUnits["month"], + $dateUnits["day"], + $dateUnits["year"] + ); + $args = array(); + + for($i = 0; $i < count($units); $i++){ + $time_part = $units[$i]; + $param = date($time_part, $timestamp); + if($unit == $time_part) + $param += $count; + + array_push($args, $param); + + } + + return call_user_func_array("mktime", $args); + } + + static public function addDays($timestamp, $count) { + return self::addDate($timestamp, self::$DATE_UNITS["day"], $count); + } + + static public function addWeeks($timestamp, $count) { + return self::addDate($timestamp, self::$DATE_UNITS["day"], ($count * self::DAYS_IN_WEEK)); + } + + static public function addMonths($timestamp, $count) { + return self::addDate($timestamp, self::$DATE_UNITS["month"], $count); + } + + static public function addYears($timestamp, $count) { + return self::addDate($timestamp, self::$DATE_UNITS["year"], $count); + } + +}
\ No newline at end of file diff --git a/SchedulerHelper.php b/SchedulerHelper.php new file mode 100644 index 0000000..2387dbe --- /dev/null +++ b/SchedulerHelper.php @@ -0,0 +1,391 @@ +<?php + +namespace Scheduler; +require_once "SchedulerDate.php"; +require_once "SchedulerHelperConnector.php"; +require_once "RecurringType.php"; + +use PDO, Exception; + +abstract class DHelper extends Connector +{ + const FLD_ID = "id"; + const FLD_START_DATE = "start_date"; + const FLD_END_DATE = "end_date"; + const FLD_TEXT = "text"; + const FLD_RECURRING_TYPE = "recurring_type"; + const FLD_PARENT_ID = "parent_id"; + const FLD_LENGTH = "length"; + + private $_fields_names = array( + self::FLD_ID => "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: [] + * @return array + */ + private function _getRecurringEventsExceptions() + { + $getEventsSql = " + SELECT + * + FROM + ".$this->getTableName()." + WHERE + ".$this->getRecurringTypeFieldName()." = '".RecurringType::IS_RECURRING_BREAK."' + OR ( + ".$this->getRecurringTypeFieldName()." = '".RecurringType::IS_RECURRING_EXCEPTION."' + 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 recurring events data by interval. + * @param $startDate + * @param $endDate + * @return array + */ + private function _getRecurringEventsByInterval($startDate, $endDate) + { + $getEventsSql = " + SELECT + * + FROM + ".$this->getTablename()." + WHERE + ".$this->getStartDateFieldName()." <= '{$endDate}' + AND ".$this->getEndDateFieldName()." >= '{$startDate}' + AND ( + ".$this->getParentIdFieldName()." = '0' + OR ( + ".$this->getParentIdFieldName()." != '0' + AND ".$this->getLengthFieldName()." < '".SchedulerDate::getDateTimestamp($startDate)."' + ) + )"; + + $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(SchedulerDate::FORMAT_DEFAULT, $eventStartDateStamp); + + $eventEndDateStamp = $eventStartDateStamp + $recurringEventData[$this->getLengthFieldName()]; + $preparedEventData[$this->getEndDateFieldName()] = date(SchedulerDate::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) + { + $recurringData = array(); + $recurringEventsExceptions = $this->_getRecurringEventsExceptions(); + $recurringEvents = $this->_getRecurringEventsByInterval($startDate, $endDate); + + $intervalStartDateStamp = SchedulerDate::getDateTimestamp($startDate); + $intervalEndDateStamp = SchedulerDate::getDateTimestamp($endDate); + + for($i = 0; $i < count($recurringEvents); $i++) { + $eventData = $recurringEvents[$i]; + + //Parse recurring data format. + $recurringTypeData = $eventData[$this->getRecurringTypeFieldName()]; + $recurringStartDateStamp = SchedulerDate::getDateTimestamp($eventData[$this->getStartDateFieldName()]); + $recurringEndDateStamp = SchedulerDate::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); + $recurringData = array_merge($recurringData, $recurringEventData); + } + + //Leave events that belongs to interval. + $resultData = array(); + for($i = 0; $i < count($recurringData); $i++) { + $recurringEvent = $recurringData[$i]; + $recurringStartDateStamp = SchedulerDate::getDateTimestamp($recurringEvent[$this->getStartDateFieldName()]); + $recurringEndDateStamp = SchedulerDate::getDateTimestamp($recurringEvent[$this->getEndDateFieldName()]); + + if( + (($intervalStartDateStamp <= $recurringStartDateStamp) && ($recurringStartDateStamp <= $intervalEndDateStamp)) + || (($intervalStartDateStamp <= $recurringEndDateStamp) && ($recurringEndDateStamp <= $intervalEndDateStamp)) + ) { + array_push($resultData, $recurringEvent); + } + + } + + 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, SchedulerDate::getDateTimestamp($startDateStr), $eventLength); + return date(SchedulerDate::FORMAT_DEFAULT, $endDateStamp); + } +}
\ No newline at end of file diff --git a/SchedulerHelperConnector.php b/SchedulerHelperConnector.php new file mode 100644 index 0000000..88e8203 --- /dev/null +++ b/SchedulerHelperConnector.php @@ -0,0 +1,105 @@ +<?php + +namespace Scheduler; +use PDO, Exception; + +class Connector +{ + private $_dbsm, $_host, $_db_name, $_user, $_password, $_table_name; + private $_PDO; + + protected function __construct($configs = array()) + { + $this->_dbsm = isset($configs["dbsm"]) ? $configs["dbsm"] : "mysql"; + $this->_host = isset($configs["host"]) ? $configs["host"] : "localhost"; + $this->_db_name = $configs["db_name"]; + $this->_user = $configs["user"]; + $this->_password = $configs["password"]; + $this->_table_name = $configs["table_name"]; + } + + protected function getTableName() + { + return $this->_table_name; + } + + private function getConfigStringPDO() + { + return "{$this->_dbsm}:host={$this->_host};dbname={$this->_db_name}"; + } + + public function getPDO() + { + $PDO_options = array( + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC + ); + + $this->_PDO = ($this->_PDO) ? $this->_PDO : new PDO($this->getConfigStringPDO(), $this->_user, $this->_password, $PDO_options); + return $this->_PDO; + } + + protected function save() + { + if(!is_null($this->getFieldsValues(Helper::FLD_ID))) + $this->update(); + else + $this->insert(); + } + + protected function update() + { + if(is_null($this->getFieldsValues(Helper::FLD_ID))) + throw new Exception("For updating data needs value of field Helper::FLD_ID"); + + $fieldsValues = $this->getFieldsValues(); + $sqlSetPart = []; + foreach($fieldsValues as $field => $value) + array_push($sqlSetPart, "{$field}='{$value}'"); + + $sql = " + UPDATE + {$this->_table_name} + SET + ".join("," ,$sqlSetPart)." + WHERE + ".$this->getIdFieldName()." = ".$this->getFieldsValues(Helper::FLD_ID)." + "; + + if($this->config["debug"]) + echo("Update operation sql: ".$sql."<BR>"); + + $this->getPDO()->prepare($sql)->execute(); + } + + protected function insert() + { + $fieldsValues = $this->getFieldsValues(); + $sqlFields = join(",", array_keys($fieldsValues)); + $sqlValues = "'".join("','", array_values($fieldsValues))."'"; + $sql = "INSERT INTO {$this->_table_name} ({$sqlFields}) values ({$sqlValues})"; + + if($this->config["debug"]) + echo("Insert operation sql: ".$sql."<BR>"); + + $this->getPDO()->prepare($sql)->execute(); + } + + protected function delete() + { + $dataId = $this->getFieldsValues(Helper::FLD_ID); + if(is_null($dataId)) + throw new Exception("For deleting needs value of FLD_ID"); + + $sql = " + DELETE FROM + ".$this->_table_name." + WHERE + ".$this->getIdFieldName()." = '{$dataId}'"; + + if($this->config["debug"]) + echo("Delete operation sql: ".$sql."<BR>"); + + $this->getPDO()->prepare($sql)->execute(); + } +}
\ No newline at end of file |