PK ! ɥ event.class.phpnu [ $timetable_events_settings['slug'], ); $parent_defaults = parent::GetDefaults(); $defaults += $parent_defaults; return $defaults; } public static function GetDefaultFetchArgs() { $timetable_events_settings = timetable_events_settings(); $defaults = array( 'post_type' => $timetable_events_settings['slug'], ); $parent_defaults = parent::GetDefaultFetchArgs(); $defaults += $parent_defaults; return $defaults; } protected static function GetDefaultCreateArgs() { $timetable_events_settings = timetable_events_settings(); $defaults = array( 'post_type' => $timetable_events_settings['slug'], ); $parent_defaults = parent::GetDefaultCreateArgs(); $defaults += $parent_defaults; return $defaults; } }PK ! ]( ]( event-hour.class.phpnu [ event) && $this->event_id>0) { $this->event = TT_Event::FetchOneById($this->event_id); } return $this->event; } public function setEvent($event) { $this->event = $event; } public function GetWeekday() { if(is_null($this->weekday) && $this->weekday_id>0) { $this->weekday = TT_Weekday::FetchOneById($this->weekday_id); } return $this->weekday; } public function SetWeekday($weekday) { $this->weekday = $weekday; } public function __construct($data = array()) { $this->SetDefaults(); $this->Set($data); } public function Set($data = array()) { if(isset($data['event_hours_id'])) $this->event_hours_id = $data['event_hours_id']; if(isset($data['event_id'])) $this->event_id = $data['event_id']; if(isset($data['weekday_id'])) $this->weekday_id = $data['weekday_id']; if(isset($data['start'])) $this->start = $data['start']; if(isset($data['end'])) $this->end = $data['end']; if(isset($data['tooltip'])) $this->tooltip = $data['tooltip']; if(isset($data['before_hour_text'])) $this->before_hour_text = $data['before_hour_text']; if(isset($data['after_hour_text'])) $this->after_hour_text = $data['after_hour_text']; if(isset($data['category'])) $this->category = $data['category']; if(isset($data['available_places'])) $this->available_places = $data['available_places']; if(isset($data['slots_per_user'])) $this->slots_per_user = $data['slots_per_user']; if(isset($data['event_title'])) $this->event_title = $data['event_title']; if(isset($data['event_name'])) $this->event_name = $data['event_name']; if(isset($data['weekday_title'])) $this->weekday_title = $data['weekday_title']; if(isset($data['weekday_name'])) $this->weekday_name = $data['weekday_name']; } protected function SetDefaults() { $defaults = static::GetDefaults(); $this->event_hours_id = $defaults['event_hours_id']; $this->event_id = $defaults['event_id']; $this->weekday_id = $defaults['weekday_id']; $this->start = $defaults['start']; $this->end = $defaults['end']; $this->tooltip = $defaults['tooltip']; $this->before_hour_text = $defaults['before_hour_text']; $this->after_hour_text = $defaults['after_hour_text']; $this->category = $defaults['category']; $this->available_places = $defaults['available_places']; $this->slots_per_user = $defaults['slots_per_user']; $this->event_title = $defaults['event_title']; $this->event_name = $defaults['event_name']; $this->weekday_title = $defaults['weekday_title']; $this->weekday_name = $defaults['weekday_name']; } protected static function GetDefaults() { return array( 'event_hours_id' => 0, 'event_id' => 0, 'weekday_id' => 0, 'start' => '', 'end' => '', 'tooltip' => '', 'before_hour_text' => '', 'after_hour_text' => '', 'category' => '', 'available_places' => 0, 'slots_per_user' => 1, 'event_title' => '', 'event_name' => '', 'weekday_title' => '', 'weekday_name' => '', ); } public static function Fetch($args = array()) { $defaults = static::GetDefaultFetchArgs(); $args = shortcode_atts($defaults, $args); global $wpdb; $query = ''; $queryArgs = array(); $query .= 'SELECT event_hour.event_hours_id, event_hour.event_id, event_hour.weekday_id, TIME_FORMAT(event_hour.start, "%H:%i") AS start, TIME_FORMAT(event_hour.end, "%H:%i") AS end, event_hour.tooltip, event_hour.before_hour_text, event_hour.after_hour_text, event_hour.category, event_hour.available_places, event_hour.slots_per_user, event.post_title AS event_title, event.post_name as event_name, weekday.post_title AS weekday_title, weekday.post_name as weekday_name FROM ' . $wpdb->prefix . 'event_hours AS event_hour LEFT JOIN ' . $wpdb->posts . ' AS event ON(event_hour.event_id=event.ID) LEFT JOIN ' . $wpdb->posts . ' AS weekday ON(event_hour.weekday_id=weekday.ID) WHERE 1 = 1'; if($args['event_hour_id']) { $query .= ' AND event_hour.event_hours_id IN ('; $temp = array(); foreach($args['event_hour_id'] as $val) { $temp[] = '%d'; $queryArgs[] = (int)$val; } $query .= implode(',', $temp); $query .= ')'; } if($args['event']) { $query .= ' AND event.post_name IN ('; $temp = array(); foreach($args['event'] as $val) { $temp[] = '%s'; $queryArgs[] = $val; } $query .= implode(',', $temp); $query .= ')'; } if($args['weekday']) { $query .= ' AND weekday.post_name IN ('; $temp = array(); foreach($args['weekday'] as $val) { if($val=='') continue; $temp[] = '%s'; $queryArgs[] = $val; } $query .= implode(',', $temp); $query .= ')'; } $query = $wpdb->prepare($query, $queryArgs); $result = $wpdb->get_results($query, 'ARRAY_A'); if(!$result) return null; $eventHours = array(); foreach($result as $key=>$val) $eventHours[] = new static($val); return $eventHours; } public static function FetchById($id) { $eventHours = static::Fetch(array('event_hour_id' => array($id))); if(count($eventHours)==1) return $eventHours[0]; else return null; } public static function GetDefaultFetchArgs() { $defaults = array( 'event_hour_id' => array(), 'event' => array(), 'weekday' => array(), ); return $defaults; } public static function Insert(TT_Event_Hour $eventHour) { global $wpdb; $query = ''; $queryFieldsClause = array(); $queryValuesClause = array(); $queryArgs = array(); if($eventHour->event_id>0) { $queryFieldsClause[] = "event_id"; $queryValuesClause[] = "%s"; $queryArgs[] = $eventHour->event_id; } if($eventHour->weekday_id>0) { $queryFieldsClause[] = "weekday_id"; $queryValuesClause[] = "%s"; $queryArgs[] = $eventHour->weekday_id; } if($eventHour->start!='') { $queryFieldsClause[] = "start"; $queryValuesClause[] = "%s"; $queryArgs[] = $eventHour->start; } if($eventHour->end!='') { $queryFieldsClause[] = "end"; $queryValuesClause[] = "%s"; $queryArgs[] = $eventHour->end; } if($eventHour->tooltip!='') { $queryFieldsClause[] = "tooltip"; $queryValuesClause[] = "%s"; $queryArgs[] = $eventHour->tooltip; } if($eventHour->before_hour_text!='') { $queryFieldsClause[] = "before_hour_text"; $queryValuesClause[] = "%s"; $queryArgs[] = $eventHour->before_hour_text; } if($eventHour->after_hour_text!='') { $queryFieldsClause[] = "after_hour_text"; $queryValuesClause[] = "%s"; $queryArgs[] = $eventHour->after_hour_text; } if($eventHour->category!='') { $queryFieldsClause[] = "category"; $queryValuesClause[] = "%s"; $queryArgs[] = $eventHour->category; } if($eventHour->available_places>=0) { $queryFieldsClause[] = "available_places"; $queryValuesClause[] = "%s"; $queryArgs[] = $eventHour->available_places; } if($eventHour->slots_per_user>=0) { $queryFieldsClause[] = "slots_per_user"; $queryValuesClause[] = "%s"; $queryArgs[] = $eventHour->slots_per_user; } $queryFieldsClause = implode(", ", $queryFieldsClause); $queryValuesClause = implode(", ", $queryValuesClause); $query .= "INSERT INTO `" . $wpdb->prefix . "event_hours` (" . $queryFieldsClause . ") VALUES(" . $queryValuesClause . ")"; $query = $wpdb->prepare($query, $queryArgs); $result = $wpdb->query($query); if($result) return $wpdb->insert_id; else false; } public static function Update(TT_Event_Hour $eventHour) { global $wpdb; $query = ''; $querySetClause = array(); $queryArgs = array(); if($eventHour->event_id>0) { $querySetClause[] = "event_id = %s"; $queryArgs[] = $eventHour->event_id; } if($eventHour->weekday_id>0) { $querySetClause[] = "weekday_id = %s"; $queryArgs[] = $eventHour->weekday_id; } if($eventHour->start!='') { $querySetClause[] = "start = %s"; $queryArgs[] = $eventHour->start; } if($eventHour->end!='') { $querySetClause[] = "end = %s"; $queryArgs[] = $eventHour->end; } if($eventHour->tooltip!='') { $querySetClause[] = "tooltip = %s"; $queryArgs[] = $eventHour->tooltip; } if($eventHour->before_hour_text!='') { $querySetClause[] = "before_hour_text = %s"; $queryArgs[] = $eventHour->before_hour_text; } if($eventHour->after_hour_text!='') { $querySetClause[] = "after_hour_text = %s"; $queryArgs[] = $eventHour->after_hour_text; } if($eventHour->category!='') { $querySetClause[] = "category = %s"; $queryArgs[] = $eventHour->category; } if($eventHour->available_places>=0) { $querySetClause[] = "available_places = %s"; $queryArgs[] = $eventHour->available_places; } if($eventHour->slots_per_user>=0) { $querySetClause[] = "slots_per_user = %s"; $queryArgs[] = $eventHour->slots_per_user; } $querySetClause = implode(", ", $querySetClause); $query .= "UPDATE `" . $wpdb->prefix . "event_hours` SET " . $querySetClause . " WHERE event_hours_id = %s"; $queryArgs[] = $eventHour->event_hours_id; $query = $wpdb->prepare($query, $queryArgs); $result = $wpdb->query($query); return $result; } public static function Exists($Id) { global $wpdb; $query = ''; $queryArgs = array(); $query .= "SELECT event_hours_id FROM `" . $wpdb->prefix . "event_hours` WHERE event_hours_id=%s "; $queryArgs[] = $Id; $query = $wpdb->prepare($query, $queryArgs); $result = $wpdb->get_var($query); return $result; } } PK ! N}U3 U3 google-calendar.class.phpnu [ token && $this->token_expiration && $this->token_expiration>time())) $this->token = $this->GenerateToken(); return $this->token; } public function GetCalendarEventId($event_id) { if(isset($this->events_mapping[$this->id]) && isset($this->events_mapping[$this->id][$event_id])) { return $this->events_mapping[$this->id][$event_id]; } else return null; } function SetDefaultOptions() { $this->options = array( 'id' => '', 'service_account_encoded' => '', 'token' => '', 'token_expiration' => 0, 'events_data' => '', 'events_mapping' => '', ); update_option('tt_google_calendar', $this->options); } function LoadOptions() { $this->options = get_option('tt_google_calendar'); if($this->options===false) $this->SetDefaultOptions(); $this->id = $this->options['id']; $this->service_account_encoded = $this->options['service_account_encoded']; $this->service_account = json_decode($this->service_account_encoded); $this->token = $this->options['token']; $this->token_expiration = $this->options['token_expiration']; $this->events_data = $this->options['events_data']; $this->events_mapping = $this->options['events_mapping']; } public function SaveOptions() { $this->options = array( 'id' => $this->id, 'service_account_encoded' => $this->service_account_encoded, 'token' => $this->token, 'token_expiration' => $this->token_expiration, 'events_data' => $this->events_data, 'events_mapping' => $this->events_mapping, ); update_option('tt_google_calendar', $this->options); } public function __construct() { $this->LoadOptions(); $this->current_day = date('N'); $this->timezone = new DateTimeZone($this->GetWPTimezone()); } function ExportEvents($eventsHours, $weekdays) { if(!($this->id!='' && !is_null($this->service_account))) return false; if(!$eventsHours) return false; foreach($eventsHours as $eventHour) { $calendarEventDetails = $this->prepareCalendarEvent($eventHour, $weekdays); if($calendarEventId = $this->GetCalendarEventId($eventHour->event_hours_id)) { $result = $this->UpdateCalendarEvent($calendarEventId, $calendarEventDetails); } else { $result = $this->InsertCalendarEvent($calendarEventDetails); if($result!=false) { $this->AddCalendarEvent($eventHour->event_hours_id, $result->id); } } } return true; } public function ImportEvents($calendar_event, $weekdays) { if(!($this->id!='' && $this->service_account!='')) return false; $calendarEvents = $this->events_data; if(!($calendarEvents && $calendarEvents->items)) return false; foreach($calendarEvents->items as $item) { if(!in_array($item->summary, $calendar_event)) continue; $event = TT_Event::FetchOne(array( 'title' => $item->summary, )); if(is_null($event)) { $event = new TT_Event(); $event->post_title = $item->summary; $result = TT_Event::Insert($event); if($result>0) { $event = TT_Event::FetchOneById($result); } else continue; } $eventHourDetails = $this->prepareEventHourDetails($event, $item, $weekdays); $eventHourId = array_search($item->id, $this->events_mapping[$this->id]); if($eventHourId && TT_Event_Hour::Exists($eventHourId)) { $eventHour = TT_Event_Hour::FetchById($eventHourId); $eventHour->Set($eventHourDetails); $result = TT_Event_Hour::Update($eventHour); } else { $eventHour = new TT_Event_Hour($eventHourDetails); $result = TT_Event_Hour::Insert($eventHour); if($result) { $this->AddCalendarEvent($result, $item->id); } } } return true; } function getEvent($calendarEventId) { $token = $this->getToken(); if(!$token) return false; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://www.googleapis.com/calendar/v3/calendars/' . $this->id . '/events/' . $calendarEventId . '?access_token=' . $token); curl_setopt($ch, CURLOPT_HTTPGET, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); $responseDecoded = json_decode($response); curl_close($ch); if(is_object($responseDecoded) && property_exists($responseDecoded, 'kind') && $responseDecoded->kind=='calendar#event' ) return $responseDecoded; else return false; } function ListEvents() { $token = $this->getToken(); if(!$token) return false; $ch=curl_init(); curl_setopt($ch, CURLOPT_URL,'https://www.googleapis.com/calendar/v3/calendars/' . $this->id . '/events?access_token=' . $token); curl_setopt($ch, CURLOPT_HTTPGET, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); $responseDecoded = json_decode($response); curl_close($ch); if(is_object($responseDecoded) && property_exists($responseDecoded,'kind') && $responseDecoded->kind=='calendar#events' ) return $responseDecoded; else return false; } function UniqueCalendarEvents() { $events = $this->events_data; if(!($events && $events->items)) return false; $uniqueCalendarEvents = array(); foreach($events->items as $item) { if(!in_array($item->summary, $uniqueCalendarEvents)) $uniqueCalendarEvents[] = $item->summary; } return $uniqueCalendarEvents; } function LoadEventsData() { $this->events_data = $this->ListEvents(); $this->SaveOptions(); } function InsertCalendarEvent($eventDetails) { $token = $this->getToken(); if(!$token) return false; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://www.googleapis.com/calendar/v3/calendars/' . $this->id . '/events?access_token=' . $token); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($eventDetails)); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); $responseDecoded = json_decode($response); if((is_object($responseDecoded)) && (property_exists($responseDecoded, 'kind')) && ($responseDecoded->kind=='calendar#event')) { return $responseDecoded; } return false; } function UpdateCalendarEvent($calendarEventId, $eventDetails) { $token = $this->getToken(); if(!$token) return false; $eventDetailsJson = json_encode($eventDetails); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,'https://www.googleapis.com/calendar/v3/calendars/' . $this->id . '/events/' . $calendarEventId . '?access_token=' . $token); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT'); curl_setopt($ch, CURLOPT_POSTFIELDS, $eventDetailsJson); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Content-Length: ' . strlen($eventDetailsJson))); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); $responseDecoded = json_decode($response); if(is_object($responseDecoded) && property_exists($responseDecoded,'kind') && $responseDecoded->kind=='calendar#event' ) return true; else return false; } function GenerateToken() { if(!property_exists($this->service_account, 'client_email')) return false; $header = '{"alg":"RS256","typ":"JWT"}'; $headerEncoded = $this->base64URLEncode($header); $assertionTime = time(); $expirationTime = $assertionTime+3600; $claimSet = '{ "iss":"' . $this->service_account->client_email . '", "scope":"https://www.googleapis.com/auth/calendar", "aud":"https://www.googleapis.com/oauth2/v4/token", "exp":' . $expirationTime . ', "iat":' . $assertionTime . ' }'; $claimSetEncoded = $this->base64URLEncode($claimSet); $signature = ''; openssl_sign($headerEncoded . '.' . $claimSetEncoded, $signature, $this->service_account->private_key, 'SHA256'); $signatureEncoded = $this->base64URLEncode($signature); $assertion = $headerEncoded . '.' . $claimSetEncoded . '.' . $signatureEncoded; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://www.googleapis.com/oauth2/v4/token'); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded')); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_POSTFIELDS, 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=' . $assertion); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); curl_close($ch); $responseDecoded = json_decode($response); if(is_object($responseDecoded) && property_exists($responseDecoded,'access_token') ) { $this->token = $responseDecoded->access_token; $this->token_expiration = $expirationTime; $this->SaveOptions(); return $this->token; } return false; } protected function base64URLEncode($data) { return rtrim(strtr(base64_encode($data), '+/', '-_'), '='); } protected function prepareEventHourDetails(TT_Event $event, $calendarEvent, $weekdays) { if(property_exists($calendarEvent->start, 'timeZone')) $startTimeZone = new DateTimeZone($calendarEvent->end->timeZone); else $startTimeZone = new DateTimeZone('+0000'); if(property_exists($calendarEvent->end, 'timeZone')) $endTimeZone = new DateTimeZone($calendarEvent->end->timeZone); else $endTimeZone = new DateTimeZone('+0000'); $startDate = new DateTime($calendarEvent->start->dateTime, $startTimeZone); $endDate = new DateTime($calendarEvent->end->dateTime, $endTimeZone); $dayNum = $startDate->format('N')-1; $weekday = TT_Weekday::FetchOne(array( 'name' => $weekdays[$dayNum], )); if(is_null($weekday)) return false; $beforeHourText = (property_exists($calendarEvent, 'description') ? $calendarEvent->description : ''); $eventHourDetails = array( 'event_id' => $event->ID, 'weekday_id' => $weekday->ID, 'start' => $startDate->format('H:i'), 'end' => $endDate->format('H:i'), 'before_hour_text' => $beforeHourText, ); return $eventHourDetails; } protected function prepareCalendarEvent(TT_Event_Hour $eventHour, $weekdays) { $dayNum = array_search(urldecode($eventHour->weekday_name), $weekdays)+1; $offset = $dayNum-$this->current_day; $time = strtotime(($offset!=0 ? $offset . ' days' : 'now')); $startTimeStr = date('Y-m-d', $time) . ' ' . $eventHour->start; $endTimeStr = date('Y-m-d', $time) . ' ' . $eventHour->end; $startDate = new DateTime($startTimeStr, $this->timezone); $endDate = new DateTime($endTimeStr, $this->timezone); $calendarEventDetails = array ( 'summary' => $eventHour->event_title, 'description' => $eventHour->before_hour_text, 'start' => array ( 'dateTime' => $startDate->format(DateTime::RFC3339), 'timeZone' => $this->timezone->getName(), ), 'end' => array ( 'dateTime' => $endDate->format(DateTime::RFC3339), 'timeZone' => $this->timezone->getName(), ), 'recurrence' => array ( 'RRULE:FREQ=WEEKLY;', ), ); return $calendarEventDetails; } protected function AddCalendarEvent($eventHourId, $calendarEventId) { if(!isset($this->events_mapping[$this->id])) { if(!is_array($this->events_mapping)) $this->events_mapping = array(); $this->events_mapping[$this->id] = array(); } foreach($this->events_mapping[$this->id] as $key=>$val) { if($val==$calendarEventId) unset($this->events_mapping[$this->id][$key]); } $this->events_mapping[$this->id][$eventHourId] = $calendarEventId; $this->SaveOptions(); } function GetWPTimezone() { $timezone_string = get_option('timezone_string'); if(!$timezone_string) { $gmt_offset = get_option('gmt_offset'); $timezone_string = timezone_name_from_abbr('', $gmt_offset*3600, false); if($timezone_string===false) $timezone_string = timezone_name_from_abbr('', 0, false); } return $timezone_string; } } PK ! {I weekday.class.phpnu [ 'timetable_weekdays', ); $parent_defaults = parent::GetDefaultFetchArgs(); $defaults += $parent_defaults; return $defaults; } protected static function GetDefaultCreateArgs() { $defaults = array( 'post_type' => 'timetable_weekdays', ); $parent_defaults = parent::GetDefaultCreateArgs(); $defaults += $parent_defaults; return $defaults; } }PK ! (#L L bookings-list.class.phpnu [ __('Booking', 'timetable'), 'plural' => __('Bookings', 'timetable'), 'ajax' => false, )); if(isset($_REQUEST['deleted']) && $_REQUEST['deleted']) { add_action('admin_notices', array($this, 'booking_deleted_notice')); } } /** * Retrieve bookings data from the database * * @param int $per_page * @param int $page_number * * @return mixed */ public static function get_bookings($per_page=5, $page_number=1) { $args = array( 'per_page' => $per_page, 'page_number' => $page_number, ); if(isset($_REQUEST['order'])) $args['order'] = $_REQUEST['order']; if(isset($_REQUEST['orderby'])) $args['orderby'] = $_REQUEST['orderby']; $bookings = TT_DB::getBookings($args); return $bookings; } /** * Delete a booking record. * * @param int $id booking ID */ public static function delete_booking($id) { TT_DB::deleteBooking($id); } public function booking_deleted_notice() { $output = ''; $output .= '
' . __('Booking deleted.', 'timetable') . '