* @package WB */ // WBClass::load(); /** * Calender Events And Lists * * * * @version 0.4.2 * @package WB */ class WBDatasource_Calendar_Event extends WBStdClass { const CALENDAR_ID_DEFAULT = 1; const REPEAT_TYPE_NEVER = 1; const REPEAT_TYPE_DAILY = 2; const REPEAT_TYPE_WEEKLY = 3; const REPEAT_TYPE_FORTNIGHT = 4; const REPEAT_TYPE_MONTHLY_DAY = 5; const REPEAT_TYPE_MONTHLY_DATE = 6; const REPEAT_TYPE_YEARLY = 7; const DELETE_TYPE_CURRENT = 'current'; const DELETE_TYPE_FUTURE = 'future'; const DELETE_TYPE_ALL = 'all'; /** * @var WBDatasource_Table */ private $table; /** * @var WBMandator */ private $mandator; /** * Basic Clause */ private $clause = array(); /** * @var WBUser_Auth */ private $user; /** * Limit of records to select * @var int */ private $limit = 100; /** * Current Event Data * @var array */ private $data = array(); /** * Constructor * * @param array */ public function __construct($parameter = array()) { if (empty($parameter['table'])) { $parameter['table'] = WBClass::create('WBDatasource_Table'); } if (empty($parameter['mandator'])) { $parameter['mandator'] = WBClass::create('WBMandator', $parameter); } $this->table = $parameter['table']; $this->mandator = $parameter['mandator']; // prepare clause $this->clause = array(); $this->clause[0] = array( 'field' => $this->getIdentifier4Calendar(), 'relation' => 'not', 'value' => '-1' ); $this->clause[1] = array( 'field' => 'timestampstart', 'relation' => 'ge', 'value' => '' ); $this->clause[2] = array( 'field' => 'timestampstart', 'relation' => 'lt', 'value' => '' ); $this->clause[3] = array( 'field' => 'enabled', 'relation' => 'eq', 'value' => 1 ); $this->setMinDate(); $this->setMaxDate(); WBClass::load('WBUser', 'WBUser_Auth'); $this->user = WBUser_Auth::getCurrent(); } /** * Get Current Event ID * * @return string event id */ public function getId() { if (empty($this->data['id'])) { return ''; } return $this->data['id']; } /** * Load Event By Id * * @param string event id */ public function loadById($id) { // already loaded? if (!empty($this->data['id']) && $id == $this->data['id']) { return true; } $list = $this->table->get(WBDatasource::TABLE_CALENDAREVENT, $id); if (1 != count($list)) { return false; } $this->data = $list[0]; return true; } /** * Is Current Event Loaded? * * @return bool */ public function isOK() { if (empty($this->data)) { return false; } return true; } /** * Save Event * * Update event data * * @param array */ public function save($data) { if (!$this->isOK()) { return; } $key = array( $this->getIdentifier4Calendar(), $this->table->getIdentifier(WBDatasource::TABLE_USER), $this->table->getIdentifier(WBDatasource::TABLE_URL), 'timestampstart', 'timestampend', 'title', 'brief', 'blurb', 'shopurlid', 'shopurltext', 'requireuser', 'requiregroup', 'enabled' ); $save = array(); foreach ($key as $k) { if (!empty($data[$k])) { $save[$k] = $data[$k]; } } $this->table->save(WBDatasource::TABLE_CALENDAREVENT, $this->data['id'], $save); } /** * Add Event * * * @param array */ public function add($data) { $key = array( $this->getIdentifier4Calendar(), $this->getIdentifier4RepeatType(), $this->table->getIdentifier(WBDatasource::TABLE_USER), $this->table->getIdentifier(WBDatasource::TABLE_URL), 'timestampstart', 'timestampend', 'title', 'brief', 'blurb', 'shopurlid', 'shopurltext', 'requireuser', 'requiregroup', 'enabled' ); $save = array(); foreach ($key as $k) { if (!empty($data[$k])) { $save[$k] = $data[$k]; } } // use default calendar id if (empty($save[$key[0]]) || '-1' == $save[$key[0]]) { $save[$key[0]] = self::CALENDAR_ID_DEFAULT; } $this->mandator->inject2Data($save); $id = $this->table->save(WBDatasource::TABLE_CALENDAREVENT, '__new', $save); $key = $this->getIdentifier(); $save['origin' . $key] = array_pop(explode('-', $id)); $this->data = $save; $this->data['id'] = $id; // save again with origin id $save = array(); $save['origin' . $key] = array_pop(explode('-', $id)); $this->table->save(WBDatasource::TABLE_CALENDAREVENT, $id, $save); if (!$this->isRecurrence()) { return; } $this->addRecurrence($data); } /** * Add Recurrence Records 4 Event * * @array calender information to add */ private function addRecurrence($data) { // find method to use switch ($this->data[$this->getIdentifier4RepeatType()]) { case WBDatasource_Calendar_Event::REPEAT_TYPE_DAILY: $method = 'Daily'; break; case WBDatasource_Calendar_Event::REPEAT_TYPE_WEEKLY: $method = 'Weekly'; break; case WBDatasource_Calendar_Event::REPEAT_TYPE_FORTNIGHT: $method = 'Fortnight'; break; case WBDatasource_Calendar_Event::REPEAT_TYPE_MONTHLY_DATE: $method = 'MonthlyByDate'; break; case WBDatasource_Calendar_Event::REPEAT_TYPE_MONTHLY_DAY: $method = 'MonthlyByDay'; break; case WBDatasource_Calendar_Event::REPEAT_TYPE_YEARLY: $method = 'Yearky'; break; default: case WBDatasource_Calendar_Event::REPEAT_TYPE_NEVER: return; break; } $method = 'getNextDateInterval4' . $method; // prepare if (empty($data['repeatuntil'])) { $data['repeatuntil'] = date('Y-m-d 23:59:59', strtotime('+1year')); } $prototype = $this->data; unset($prototype['id']); $start = new DateTime($this->data['timestampstart']); $end = new DateTime($this->data['timestampend']); $until = new DateTime($data['repeatuntil']); $save = array(); while (true) { $interval = $this->$method($start); $start->add($interval); if ($start > $until) { break; } $prototype['timestampstart'] = $start->format('Y-m-d H:i:s'); if ('1970-01-01' != $end->format('Y-m-d')) { $end->add($interval); } $prototype['timestampend'] = $end->format('Y-m-d H:i:s'); $save[] = $prototype; // save list before it get to long if (9 < count($save)) { $this->table->save(WBDatasource::TABLE_CALENDAREVENT, '__new', $save); $save = array(); } } // save the rest if (!empty($save)) { $this->table->save(WBDatasource::TABLE_CALENDAREVENT, '__new', $save); $save = array(); } } /** * Add Daily Recurrence Records 4 Event * * Add one day * * @param DateTime */ private function getNextDateInterval4Daily($start) { return new DateInterval('P1D'); } /** * Add Weekly Recurrence Records 4 Event * * Add one week * * @param DateTime */ private function getNextDateInterval4Weekly($start) { return new DateInterval('P7D'); } /** * Add Fortnight Recurrence Records 4 Event * * Just add two weeks * * @param DateTime */ private function getNextDateInterval4Fortnight($start) { return new DateInterval('P14D'); } /** * Add Monthly (Same date) Recurrence Records 4 Event * * Add one month - if you start on January 6th, you'll get * February 6th, March 6th and so on * * @param DateTime */ private function getNextDateInterval4MonthlyByDate($start) { return new DateInterval('P1M'); } /** * Add Monthly (Same Day) Recurrence Records 4 Event * * So, if you start with the 3rd Friday in August, you'll get * the 3rd Fri in September, 3rd Friday in October and so on * * @param DateTime */ private function getNextDateInterval4MonthlyByDay($start) { $m = ceil($start->format('d') / 7); for ($i = 3; $i < 6; ++$i) { $di = new DateInterval('P' . $i . 'W'); $s0 = clone $start; $s0->add($di); $n = ceil($s0->format('d') / 7); if ($m == $n) { return $di; break; } } return new DateInterval('P10Y'); } /** * Add Yearly Recurrence Records 4 Event * * @param DateTime */ private function getNextDateInterval4Yearly($data) { return new DateInterval('P1Y'); } /** * Delete Event * * Remove current, future or all events of same origin * * @param string */ public function delete($type = self::DELETE_TYPE_CURRENT) { if (!$this->isOK()) { return; } $oKey = 'origin' . $this->getIdentifier(); $clause = array(); $clause[] = array( 'field' => $oKey, 'value' => $this->data[$oKey] ); $this->mandator->inject2Clause($clause); switch ($type) { case self::DELETE_TYPE_ALL: $this->table->delete(WBDatasource::TABLE_CALENDAREVENT, null, null, $clause); break; case self::DELETE_TYPE_FUTURE: $clause[] = array( 'field' => 'timestampstart', 'relation' => 'ge', 'value' => $this->data['timestampstart'] ); $this->table->delete(WBDatasource::TABLE_CALENDAREVENT, null, null, $clause); break; default: case self::DELETE_TYPE_CURRENT: $this->table->delete(WBDatasource::TABLE_CALENDAREVENT, $this->data['id']); break; } $this->data = array(); } /** * Check Event Repeat Type * * @array calender information to add * If event is recurrence return true, false otherwise * * @return bool */ public function isRecurrence() { if (!$this->isOK()) { return false; } $pRT = $this->getIdentifier4RepeatType(); if (empty($this->data[$pRT])) { return false; } switch ($this->data[$pRT]) { case WBDatasource_Calendar_Event::REPEAT_TYPE_DAILY: case WBDatasource_Calendar_Event::REPEAT_TYPE_WEEKLY: case WBDatasource_Calendar_Event::REPEAT_TYPE_FORTNIGHT: case WBDatasource_Calendar_Event::REPEAT_TYPE_MONTHLY_DATE: case WBDatasource_Calendar_Event::REPEAT_TYPE_MONTHLY_DAY: case WBDatasource_Calendar_Event::REPEAT_TYPE_YEARLY: return true; break; case WBDatasource_Calendar_Event::REPEAT_TYPE_NEVER: default: break; } return false; } /** * Set Calender Id * * Only list specified calenders * Mangle internal clause to select events by calender id * * @param string|array Calender id(s) */ public function setCalendarId($id = '-1') { if ('-1' == $id) { $this->clause[0]['relation'] = 'not'; $this->clause[0]['value'] = '-1'; return; } if (!is_array($id)) { $id = array_map('trim', explode(',', trim($id))); } $this->clause[0]['relation'] = 'in'; $this->clause[0]['value'] = $id; } /** * Set Minimal Date * * Mangle internal clause and set min date * * @see strtotime() * @param string something to get a date */ public function setMinDate($date = '-1 day') { $date = strtotime($date); $this->clause[1]['value'] = date('Y-m-d H:i:s', $date); } /** * Set Maximum Date * * Mangle internal clause and set max date * * @see strtotime() * @param string something to get a date */ public function setMaxDate($date = '+1 month') { $date = strtotime($date); $this->clause[2]['value'] = date('Y-m-d H:i:s', $date); } /** * Set Actual Date * * Mangle internal clause and set min and max date * * @see strtotime() * @param string something to get a date */ public function setDay($date = 'now') { $day = strtotime($date); $this->clause[1]['value'] = date('Y-m-d 00:00:00', $day); // add one 1day = 24 * 60 * 60; $day += 86400; $this->clause[2]['value'] = date('Y-m-d 00:00:00', $day); } /** * * @return array */ public function getList() { $option = array(); $option['limit'] = $this->limit; $option['oderby'] = array(); $option['oderby'][] = array( 'field' => 'timestampstart', 'asc' => 1 ); $clause = $this->clause; $this->mandator->inject2Clause($clause); $this->injectPermissionCheck2Clause($clause); return $this->table->get(WBDatasource::TABLE_CALENDAREVENT, null, null, $clause, $option); } /** * Mangle Clause To Check Permissions * * Each event has configured access rules. * * Require user: * - anybody * - anonymous * - user in any group * - user in specified group * * @param array */ private function injectPermissionCheck2Clause(&$clause) { if (!$this->user->isAuthenticated()) { $clause[] = array( 'field' => 'requireuser', 'relation' => 'in', 'value' => array('anybody', 'anonymous') ); return; } // There are three user conditions: // 1) don't care about user $c0 = array(); $c0[] = array( 'field' => 'requireuser', 'value' => 'anybody' ); // 2) any loged in user $c1 = array(); $c1[] = array( 'field' => 'requireuser', 'value' => 'user' ); $c1[] = array( 'field' => 'requiregroup', 'value' => 0 ); $c0[] = array( 'type' => 'complex', 'bond' => 'and', 'clause' => $c1 ); // 3) user in required group $c2 = array(); $c2[] = array( 'field' => 'requireuser', 'value' => 'user' ); $c2[] = array( 'field' => 'requiregroup', 'relation' => 'in', 'value' => array_keys($this->user->getGroups()) ); $c0[] = array( 'type' => 'complex', 'bond' => 'and', 'clause' => $c2 ); // join sub clauses $clause[] = array( 'type' => 'complex', 'bond' => 'or', 'clause' => $c0 ); } /** * Get Identifier For Calendar Event * * @see WBDatasource_Table::getIdentifier() * @param bool as string * @return string | array */ public function getIdentifier($asString = true) { return $this->table->getIdentifier(WBDatasource::TABLE_CALENDAREVENT, $asString); } /** * Get Identifier For Calendar * * @see WBDatasource_Table::getIdentifier() * @param bool as string * @return string | array */ public function getIdentifier4Calendar($asString = true) { return $this->table->getIdentifier(WBDatasource::TABLE_CALENDAR, $asString); } /** * Get Identifier For Calendar Event Repeat Type * * @see WBDatasource_Table::getIdentifier() * @return string */ public function getIdentifier4RepeatType() { return $this->table->getIdentifier(WBDatasource::TABLE_CALENDAREVENTREPEATTYPE, true); } }