*/ class MEC_render extends MEC_base { public $db; public $main; public $file; public $settings; public $post_atts; /** * Constructor method * @author Webnus */ public function __construct() { // Add image size for list and carousel add_image_size('thumblist', '300', '300', true); add_image_size('thumbrelated', '500', '500', true); add_image_size('meccarouselthumb', '474', '324', true); add_image_size('gridsquare', '391', '260', true); add_image_size('tileview', '300', '400', true); // Import MEC skin class MEC::import('app.libraries.skins'); // MEC main library $this->main = $this->getMain(); // MEC file library $this->file = $this->getFile(); // MEC DB library $this->db = $this->getDB(); // MEC Settings $this->settings = $this->main->get_settings(); } /** * Do the shortcode and return its output * @author Webnus * @param array $atts * @return string */ public function shortcode($atts) { $calendar_id = isset($atts['id']) ? (int) $atts['id'] : 0; $atts['id'] = $calendar_id; global $MEC_Shortcode_id; $MEC_Shortcode_id = $calendar_id; $atts = apply_filters('mec_calendar_atts', $this->parse($calendar_id, $atts)); $skin = $atts['skin'] ?? $this->get_default_layout(); return $this->skin($skin, $atts); } /** * Do the shortcode and return its json output * @author Webnus * @param array $atts * @return string */ public function shortcode_json($atts) { $calendar_id = $atts['id'] ?? 0; $atts = apply_filters('mec_calendar_atts', $this->parse($calendar_id, $atts)); $skin = $atts['skin'] ?? $this->get_default_layout(); $json = $this->skin($skin, $atts); $path = MEC::import('app.skins.'.$skin, true, true); $skin_path = apply_filters('mec_skin_path', $skin); if($skin_path != $skin and $this->file->exists($skin_path)) $path = $skin_path; if(!$this->file->exists($path)) { return esc_html__('Skin controller does not exist.', 'modern-events-calendar-lite'); } include_once $path; $skin_class_name = 'MEC_skin_'.$skin; // Create Skin Object Class $SKO = new $skin_class_name(); // Initialize the skin $SKO->initialize($atts); $atts['content_html'] = $SKO->output(); if( 'full_calendar' == $skin ) { $default_atts = $SKO->prepare_skin_options( $skin, $atts ); $default_view = $default_atts['default_view'] ?? 'list'; $skin_class_name = 'MEC_skin_'.$default_view; // Create Skin Object Class $default_SKO = new $skin_class_name(); // Initialize the skin $default_SKO->initialize($default_atts); // Fetch the events $atts['content_json'] = $default_SKO->fetch(); }else{ // Fetch the events $atts['content_json'] = $SKO->fetch(); } return $atts; } /** * Do the widget and return its output * @author Webnus * @param int $calendar_id * @param array $atts * @return string */ public function widget($calendar_id, $atts = array()) { $atts = apply_filters('mec_calendar_atts', $this->parse($calendar_id, $atts)); $skin = $atts['skin'] ?? $this->get_default_layout(); return $this->skin($skin, $atts); } /** * Do the yearly_view skin and returns its output * @author Webnus * @param array $atts * @return string */ public function vyear($atts = array()) { $atts = apply_filters('mec_vyear_atts', $atts); $skin = 'yearly_view'; return $this->skin($skin, $atts); } /** * Do the monthly_view skin and returns its output * @author Webnus * @param array $atts * @return string */ public function vmonth($atts = array()) { $atts = apply_filters('mec_vmonth_atts', $atts); $skin = 'monthly_view'; return $this->skin($skin, $atts); } /** * Do the full_calendar skin and returns its output * @author Webnus * @param array $atts * @return string */ public function vfull($atts = array()) { $atts = apply_filters('mec_vfull_atts', $atts); $skin = 'full_calendar'; return $this->skin($skin, $atts); } /** * Do the default_full_calendar skin and returns its output (archive page) * @author Webnus * @param array $atts * @return string */ public function vdefaultfull($atts = array()) { $atts = apply_filters('mec_vdefaultfull_atts', $atts); $skin = 'default_full_calendar'; return $this->skin($skin, $atts); } /** * Do the weekly_view skin and returns its output * @author Webnus * @param array $atts * @return string */ public function vweek($atts = array()) { $atts = apply_filters('mec_vweek_atts', $atts); $skin = 'weekly_view'; return $this->skin($skin, $atts); } /** * Do the timetable skin and returns its output * @author Webnus * @param array $atts * @return string */ public function vtimetable($atts = array()) { $atts = apply_filters('mec_vtimetable_atts', $atts); $skin = 'timetable'; return $this->skin($skin, $atts); } /** * Do the Masonry skin and returns its output * @author Webnus * @param array $atts * @return string */ public function vmasonry($atts = array()) { $atts = apply_filters('mec_vmasonry_atts', $atts); $skin = 'masonry'; return $this->skin($skin, $atts); } /** * Do the daily_view skin and returns its output * @author Webnus * @param array $atts * @return string */ public function vday($atts = array()) { $atts = apply_filters('mec_vday_atts', $atts); $skin = 'daily_view'; return $this->skin($skin, $atts); } /** * Do the map skin and returns its output * @author Webnus * @param array $atts * @return string */ public function vmap($atts = array()) { $atts = apply_filters('mec_vmap_atts', $atts); $skin = 'map'; return $this->skin($skin, $atts); } /** * Do the list skin and returns its output * @author Webnus * @param array $atts * @return string */ public function vlist($atts = array()) { $atts = apply_filters('mec_vlist_atts', $atts); $skin = 'list'; return $this->skin($skin, $atts); } /** * Do the tile skin and returns its output * @author Webnus * @param array $atts * @return string */ public function vtile($atts = array()) { $atts = apply_filters('mec_vtile_atts', $atts); $skin = 'tile'; return $this->skin($skin, $atts); } /** * Do the custom skin and returns its output * @author Webnus * @param array $atts * @param string $type * @param boolean $category * @return string */ public function vcustom($atts, $type = 'archive', $category = false) { $k = 'custom_'.$type; $shortcode = (isset($this->settings[$k]) && !empty($this->settings[$k])) ? stripslashes($this->settings[$k]) : ''; // Add Category if($category and is_tax('mec_category') and get_queried_object_id()) $shortcode = str_replace(']', ' category="'.get_queried_object_id().'"]', $shortcode); if(trim($shortcode)) return do_shortcode($shortcode); return ''; } /** * Do the grid skin and returns its output * @author Webnus * @param array $atts * @return string */ public function vgrid($atts = array()) { $atts = apply_filters('mec_vgrid_atts', $atts); $skin = 'grid'; return $this->skin($skin, $atts); } /** * Do the agenda skin and returns its output * @author Webnus * @param array $atts * @return string */ public function vagenda($atts = array()) { $atts = apply_filters('mec_vagenda_atts', $atts); $skin = 'agenda'; return $this->skin($skin, $atts); } /** * Do the agenda skin and returns its output * @author Webnus * @param array $atts * @return string */ public function vgeneral_calendar($atts = array()) { $atts = array('is_categoy_page' => is_tax( 'mec_category' )); $atts = apply_filters('mec_vgeneral_calendar_atts', $atts); $skin = 'general_calendar'; return $this->skin($skin, $atts); } public function get_skins() { return [ 'monthly_view', 'full_calendar', 'yearly_view', 'weekly_view', 'daily_view', 'timetable', 'masonry', 'list', 'grid', 'agenda', 'map', 'general_calendar', 'custom' ]; } /** * Do the default archive skin and returns its output * @author Webnus * @param array $atts * @return string */ public function vdefault($atts = array()) { $skins = $this->get_skins(); foreach($skins as $skin) { $skin_style = (isset($this->settings[$skin . '_archive_skin']) and trim($this->settings[$skin . '_archive_skin']) != '') ? $this->settings[$skin . '_archive_skin'] : null; if(!empty($skin_style)) { $atts['sk-options'][ $skin ]['style'] = $skin_style; } } $monthly_skin = (isset($this->settings['monthly_view_archive_skin']) and trim($this->settings['monthly_view_archive_skin']) != '') ? $this->settings['monthly_view_archive_skin'] : 'clean'; $list_skin = (isset($this->settings['list_archive_skin']) and trim($this->settings['list_archive_skin']) != '') ? $this->settings['list_archive_skin'] : 'standard'; $grid_skin = (isset($this->settings['grid_archive_skin']) and trim($this->settings['grid_archive_skin']) != '') ? $this->settings['grid_archive_skin'] : 'classic'; $timetable_skin = (isset($this->settings['timetable_archive_skin']) and trim($this->settings['timetable_archive_skin']) != '') ? $this->settings['timetable_archive_skin'] : 'modern'; if(!isset($this->settings['default_skin_archive']) or (isset($this->settings['default_skin_archive']) and trim($this->settings['default_skin_archive']) == '')) { return $this->vdefaultfull($atts); } if($this->settings['default_skin_archive'] == 'monthly_view') $content = $this->vmonth(array_merge($atts, array('sk-options'=>array('monthly_view'=>array('style'=>$monthly_skin))))); elseif($this->settings['default_skin_archive'] == 'full_calendar') $content = $this->vdefaultfull($atts); elseif($this->settings['default_skin_archive'] == 'yearly_view') $content = $this->vyear($atts); elseif($this->settings['default_skin_archive'] == 'weekly_view') $content = $this->vweek($atts); elseif($this->settings['default_skin_archive'] == 'daily_view') $content = $this->vday($atts); elseif($this->settings['default_skin_archive'] == 'timetable') $content = $this->vtimetable(array_merge($atts, array('sk-options'=>array('timetable'=>array('style'=>$timetable_skin))))); elseif($this->settings['default_skin_archive'] == 'masonry') $content = $this->vmasonry($atts); elseif($this->settings['default_skin_archive'] == 'list') $content = $this->vlist(array_merge($atts, array('sk-options'=>array('list'=>array('style'=>$list_skin))))); elseif($this->settings['default_skin_archive'] == 'grid') $content = $this->vgrid(array_merge($atts, array('sk-options'=>array('grid'=>array('style'=>$grid_skin))))); elseif($this->settings['default_skin_archive'] == 'agenda') $content = $this->vagenda($atts); elseif($this->settings['default_skin_archive'] == 'map') $content = $this->vmap($atts); elseif($this->settings['default_skin_archive'] == 'general_calendar') $content = $this->vgeneral_calendar($atts); elseif($this->settings['default_skin_archive'] == 'custom') $content = $this->vcustom($atts); else $content = apply_filters('mec_default_skin_content', ''); return $content; } /** * Do the single skin and returns its output * @author Webnus * @param array $atts * @return string */ public function vsingle($atts) { // Force to array if(!is_array($atts)) $atts = []; // Get event ID $event_id = $atts['id'] ?? 0; $defaults = array('maximum_dates'=>$this->settings['booking_maximum_dates'] ?? 6); $atts = apply_filters('mec_vsingle_atts', $this->parse($event_id, wp_parse_args($atts, $defaults))); $skin = 'single'; return $this->skin($skin, $atts); } /** * Do the category archive skin and returns its output * @author Webnus * @param array $atts * @return string */ public function vcategory($atts = array()) { // Skin $skin = (isset($this->settings['default_skin_category']) and trim($this->settings['default_skin_category']) != '') ? $this->settings['default_skin_category'] : 'list'; $skins = $this->get_skins(); foreach($skins as $sk) { $skin_style = (isset($this->settings[$sk . '_archive_skin']) and trim($this->settings[$sk . '_archive_skin']) != '') ? $this->settings[$sk . '_archive_skin'] : null; if(!empty($skin_style)) { $atts['sk-options'][ $sk ]['style'] = $skin_style; } } // Show Only Expired Events if(isset($this->settings['category_events_method']) and $this->settings['category_events_method'] == 2) $atts['show_only_past_events'] = 1; $monthly_skin = (isset($this->settings['monthly_view_category_skin']) and trim($this->settings['monthly_view_category_skin']) != '') ? $this->settings['monthly_view_category_skin'] : 'classic'; $list_skin = (isset($this->settings['list_category_skin']) and trim($this->settings['list_category_skin']) != '') ? $this->settings['list_category_skin'] : 'standard'; $grid_skin = (isset($this->settings['grid_category_skin']) and trim($this->settings['grid_category_skin']) != '') ? $this->settings['grid_category_skin'] : 'classic'; $timetable_skin = (isset($this->settings['timetable_category_skin']) and trim($this->settings['timetable_category_skin']) != '') ? $this->settings['timetable_category_skin'] : 'modern'; if($skin == 'full_calendar') $content = $this->vfull($atts); elseif($skin == 'yearly_view') $content = $this->vyear($atts); elseif($skin == 'masonry') $content = $this->vmasonry($atts); elseif($skin == 'timetable') $content = $this->vtimetable(array_merge($atts, array('sk-options'=>array('timetable'=>array('style'=>$timetable_skin))))); elseif($skin == 'monthly_view') $content = $this->vmonth(array_merge($atts, array('sk-options'=>array('monthly_view'=>array('style'=>$monthly_skin))))); elseif($skin == 'weekly_view') $content = $this->vweek($atts); elseif($skin == 'daily_view') $content = $this->vday($atts); elseif($skin == 'list') $content = $this->vlist(array_merge($atts, array('sk-options'=>array('list'=>array('style'=>$list_skin))))); elseif($skin == 'grid') $content = $this->vgrid(array_merge($atts, array('sk-options'=>array('grid'=>array('style'=>$grid_skin))))); elseif($skin == 'agenda') $content = $this->vagenda($atts); elseif($skin == 'map') $content = $this->vmap($atts); elseif($skin == 'general_calendar') $content = $this->vgeneral_calendar($atts); elseif($skin == 'custom') $content = $this->vcustom($atts,'archive_category', true); else $content = apply_filters('mec_default_skin_content', ''); return $content; } /** * Merge args * @author Webnus * @param int $post_id * @param array $atts * @return array */ public function parse($post_id, $atts = array()) { if($this->post_atts) return wp_parse_args($atts, $this->post_atts); $post_atts = []; if($post_id) $post_atts = $this->main->get_post_meta($post_id); return wp_parse_args($atts, $post_atts); } /** * Run the skin and returns its output * @author Webnus * @param string $skin * @param array $atts * @return string */ public function skin($skin, $atts = array()) { // Pro is Required for Some Skins if(!$this->main->getPRO() and in_array($skin, array('agenda', 'yearly_view', 'timetable', 'masonry', 'map', 'available_spot'))) { return ''; } $path = MEC::import('app.skins.'.$skin, true, true); $skin_path = apply_filters('mec_skin_path', $skin); if($skin_path != $skin and $this->file->exists($skin_path)) $path = $skin_path; if(!$this->file->exists($path)) { return esc_html__('Skin controller does not exist.', 'modern-events-calendar-lite'); } include_once $path; $skin_class_name = 'MEC_skin_'.$skin; // Create Skin Object Class $SKO = new $skin_class_name(); // Initialize the skin $SKO->initialize($atts); // Search Events If Not Found In Current Month $c = 0; $break = false; do { if($c > 12 || $skin !== 'monthly_view') $break = true; if($c && !$break) { if(intval($SKO->month) == 12) { $SKO->year = intval($SKO->year)+1; $SKO->month = '01'; } else $SKO->month = sprintf("%02d", intval($SKO->month)+1); $SKO->start_date = date('Y-m-d', strtotime($SKO->year.'-'.$SKO->month.'-01')); $day = current_time('d'); $SKO->active_day = $SKO->year.'-'.$SKO->month.'-'.$day; } // Fetch the events $events = $SKO->fetch(); if($break) break; // Auto Rotation is Disabled if(!isset($atts['auto_month_rotation']) || !$atts['auto_month_rotation']) break; $c++; } while(!count($events)); // Return the output return $SKO->output(); } /** * Returns default skin * @author Webnus * @return string */ public function get_default_layout() { return apply_filters('mec_default_layout', 'list'); } /** * Renders and returns all event data * @param int $post_id * @param string $content * @return \stdClass * @throws Exception * @author Webnus */ public function data($post_id, $content = NULL) { $cached = wp_cache_get($post_id, 'mec-events-data'); if($cached) return $cached; $data = new stdClass(); // Post Data $data->ID = $post_id; $data->title = get_the_title($post_id); $data->content = is_null($content) ? $this->main->get_post_content($post_id) : $content; // All Post Data $post = get_post($post_id); $data->post = $post; // All Meta Data $meta = $this->main->get_post_meta($post_id, true); if(isset($meta['mec_notifications'])) unset($meta['mec_notifications']); if(isset($meta['mec_fees']) and is_array($meta['mec_fees']) and isset($meta['mec_fees'][':i:'])) unset($meta['mec_fees'][':i:']); $data->meta = $meta; // All MEC Data $data->mec = $this->main->get_mec_events_data($post_id); $allday = $data->meta['mec_allday'] ?? 0; $hide_time = $data->meta['mec_hide_time'] ?? 0; $hide_end_time = $this->main->hide_end_time_status($post_id); $start_timestamp = ((isset($meta['mec_start_day_seconds']) and isset($meta['mec_start_date'])) ? (strtotime($meta['mec_start_date'])+$meta['mec_start_day_seconds']) : (isset($meta['mec_start_date']) ? strtotime($meta['mec_start_date']) : 0)); $end_timestamp = ((isset($meta['mec_end_day_seconds']) and isset($meta['mec_end_date'])) ? (strtotime($meta['mec_end_date'])+$meta['mec_end_day_seconds']) : (isset($meta['mec_end_date']) ? strtotime($meta['mec_end_date']) : 0)); $start_time = $this->main->get_time($start_timestamp); $end_time = $this->main->get_time($end_timestamp); if($hide_time) { $data->time = array( 'start'=>'', 'end'=>'', 'start_raw'=>$start_time, 'end_raw'=>$end_time, 'start_timestamp'=>$start_timestamp, 'end_timestamp'=>$end_timestamp, ); } elseif($allday) { $data->time = array( 'start'=>$this->main->m('all_day', esc_html__('All Day' , 'modern-events-calendar-lite')), 'end'=>'', 'start_raw'=>$start_time, 'end_raw'=>$end_time, 'start_timestamp'=>$start_timestamp, 'end_timestamp'=>$end_timestamp, ); } else { $data->time = array( 'start'=>$start_time, 'end'=>($hide_end_time ? '' : $end_time), 'start_raw'=>$start_time, 'end_raw'=>$end_time, 'start_timestamp'=>$start_timestamp, 'end_timestamp'=>$end_timestamp, ); } // Hourly Schedules $meta_hourly_schedules = $meta['mec_hourly_schedules'] ?? []; $first_key = key($meta_hourly_schedules); $hourly_schedules = []; if(count($meta_hourly_schedules) and !isset($meta_hourly_schedules[$first_key]['schedules'])) { $hourly_schedules[] = array( 'title' => esc_html__('Day 1', 'modern-events-calendar-lite'), 'schedules'=>$meta_hourly_schedules ); } else $hourly_schedules = $meta_hourly_schedules; $data->hourly_schedules = $hourly_schedules; $tickets = (isset($meta['mec_tickets']) and is_array($meta['mec_tickets'])) ? $meta['mec_tickets'] : []; if(isset($tickets[':i:'])) unset($tickets[':i:']); $new_tickets = []; foreach($tickets as $ticket_id => $ticket) { if(!is_numeric($ticket_id)) continue; $ticket['id'] = $ticket_id; $new_tickets[$ticket_id] = $ticket; } $data->tickets = $new_tickets; $data->color = $meta['mec_color'] ?? ''; $data->permalink = ((isset($meta['mec_read_more']) and filter_var($meta['mec_read_more'], FILTER_VALIDATE_URL)) ? $meta['mec_read_more'] : get_post_permalink($post_id)); // Thumbnails $thumbnail = get_the_post_thumbnail($post, 'thumbnail', array('data-mec-postid'=>$post_id)); $thumblist = get_the_post_thumbnail($post, 'thumblist' , array('data-mec-postid'=>$post_id)); $gridsquare = get_the_post_thumbnail($post, 'gridsquare' , array('data-mec-postid'=>$post_id)); $meccarouselthumb = get_the_post_thumbnail($post, 'meccarouselthumb' , array('data-mec-postid'=>$post_id)); $medium = get_the_post_thumbnail($post, 'medium', array('data-mec-postid'=>$post_id)); $large = get_the_post_thumbnail($post, 'large', array('data-mec-postid'=>$post_id)); $full = get_the_post_thumbnail($post, 'full', array('data-mec-postid'=>$post_id)); $tileview = get_the_post_thumbnail($post, 'tileview', array('data-mec-postid'=>$post_id)); if(trim($thumbnail) == '' and trim($medium) != '') $thumbnail = preg_replace("/height=\"[0-9]*\"/", 'height="150"', preg_replace("/width=\"[0-9]*\"/", 'width="150"', $medium)); elseif(trim($thumbnail) == '' and trim($large) != '') $thumbnail = preg_replace("/height=\"[0-9]*\"/", 'height="150"', preg_replace("/width=\"[0-9]*\"/", 'width="150"', $large)); $dataThumbnails = apply_filters('mec-render-data-thumbnails', [ 'thumbnail'=>$thumbnail, 'thumblist'=>$thumblist, 'gridsquare'=>$gridsquare, 'meccarouselthumb'=>$meccarouselthumb, 'medium'=>$medium, 'large'=>$large, 'full'=>$full, 'tileview'=>$tileview ], $post_id); $data->thumbnails = $dataThumbnails; // Featured image URLs $dataFeaturedImage = apply_filters('mec-render-data-featured-image', array( 'thumbnail'=>esc_url($this->main->get_post_thumbnail_url($post_id, 'thumbnail')), 'thumblist'=>esc_url($this->main->get_post_thumbnail_url($post_id, 'thumblist' )), 'gridsquare'=>esc_url($this->main->get_post_thumbnail_url($post_id, 'gridsquare' )), 'meccarouselthumb'=>esc_url($this->main->get_post_thumbnail_url($post_id, 'meccarouselthumb')), 'medium'=>esc_url($this->main->get_post_thumbnail_url($post_id, 'medium')), 'large'=>esc_url($this->main->get_post_thumbnail_url($post_id, 'large')), 'full'=>esc_url($this->main->get_post_thumbnail_url($post_id, 'full')), 'tileview'=>esc_url($this->main->get_post_thumbnail_url($post_id, 'tileview')) ), $post_id); $data->featured_image = $dataFeaturedImage; $taxonomies = array('mec_label', 'mec_location', 'mec_category', apply_filters('mec_taxonomy_tag', '')); if(!isset($this->settings['organizers_status']) || $this->settings['organizers_status']) $taxonomies[] = 'mec_organizer'; if($this->getPRO() and isset($this->settings['sponsors_status']) and $this->settings['sponsors_status']) $taxonomies[] = 'mec_sponsor'; $terms = wp_get_post_terms($post_id, $taxonomies, array('fields'=>'all')); foreach($terms as $term) { // First Validation if(!isset($term->taxonomy)) continue; if($term->taxonomy == 'mec_label') $data->labels[$term->term_id] = array('id'=>$term->term_id, 'name'=>$term->name, 'color'=>get_metadata('term', $term->term_id, 'color', true), 'style'=>get_metadata('term', $term->term_id, 'style', true)); elseif($term->taxonomy == 'mec_organizer') $data->organizers[$term->term_id] = array('id'=>$term->term_id, 'name'=>$term->name, 'tel'=>get_metadata('term', $term->term_id, 'tel', true), 'email'=>get_metadata('term', $term->term_id, 'email', true), 'url'=>get_metadata('term', $term->term_id, 'url', true), 'page_label'=>get_metadata('term', $term->term_id, 'page_label', true), 'thumbnail'=>get_metadata('term', $term->term_id, 'thumbnail', true)); elseif($term->taxonomy == 'mec_location') { $locations = array('id'=>$term->term_id, 'name'=>$term->name, 'address'=>get_metadata('term', $term->term_id, 'address', true), 'opening_hour'=>get_metadata('term', $term->term_id, 'opening_hour', true), 'latitude'=>get_metadata('term', $term->term_id, 'latitude', true), 'longitude'=>get_metadata('term', $term->term_id, 'longitude', true), 'url'=>get_metadata('term', $term->term_id, 'url', true), 'tel'=>get_metadata('term', $term->term_id, 'tel', true), 'thumbnail'=>get_metadata('term', $term->term_id, 'thumbnail', true)); $data->locations[$term->term_id] = apply_filters('mec_map_load_location_terms', $locations, $term); } elseif($term->taxonomy == 'mec_category') { $data->categories[$term->term_id] = array( 'id'=>$term->term_id, 'name'=>$term->name, 'icon'=>get_metadata('term', $term->term_id, 'mec_cat_icon', true), 'color'=>get_metadata('term', $term->term_id, 'mec_cat_color', true), ); } elseif($term->taxonomy == apply_filters('mec_taxonomy_tag', '')) $data->tags[$term->term_id] = array('id'=>$term->term_id, 'name'=>$term->name); elseif($term->taxonomy == 'mec_sponsor') { $data->sponsors[$term->term_id] = array( 'id'=>$term->term_id, 'name'=>$term->name, 'link'=>get_metadata('term', $term->term_id, 'link', true), 'logo'=>get_metadata('term', $term->term_id, 'logo', true) ); } } // Speakers if(isset($this->settings['speakers_status']) and $this->settings['speakers_status']) { $terms = wp_get_post_terms($post_id, 'mec_speaker', [ 'fields' => 'all', 'orderby' => 'meta_value_num', 'meta_key' => 'mec_index' ]); foreach($terms as $term) { $speaker_type = get_metadata('term', $term->term_id, 'type', true); $data->speakers[$term->term_id] = array( 'id'=>$term->term_id, 'name'=>$term->name, 'type'=>$speaker_type ?: 'person', 'job_title'=>get_metadata('term', $term->term_id, 'job_title', true), 'tel'=>get_metadata('term', $term->term_id, 'tel', true), 'email'=>get_metadata('term', $term->term_id, 'email', true), 'facebook'=>get_metadata('term', $term->term_id, 'facebook', true), 'twitter'=>get_metadata('term', $term->term_id, 'twitter', true), 'gplus'=>get_metadata('term', $term->term_id, 'gplus', true), 'thumbnail'=>get_metadata('term', $term->term_id, 'thumbnail', true) ); } } // Event Fields $fields = $this->main->get_event_fields(); if(!is_array($fields)) $fields = []; $fields_data = (isset($data->meta['mec_fields']) and is_array($data->meta['mec_fields'])) ? $data->meta['mec_fields'] : get_post_meta($post_id, 'mec_fields', true); if(!is_array($fields_data)) $fields_data = []; foreach($fields as $f => $field) { if(!is_numeric($f)) continue; if(!isset($field['label'])) continue; $field_value = isset($fields_data[$f]) ? (is_array($fields_data[$f]) ? implode(', ', $fields_data[$f]) : $fields_data[$f]) : ''; $data->fields[] = array( 'id' => $f, 'type' => ($field['type'] ?? NULL), 'label' => esc_html__(stripslashes($field['label']), 'modern-events-calendar-lite'), 'value' => stripslashes($field_value), ); } // Timezone Object $data->TZO = $this->main->get_TZO($post_id); // Add mec event past index to array. $end_date = (isset($data->meta['mec_date']['end']) and isset($data->meta['mec_date']['end']['date'])) ? $data->meta['mec_date']['end']['date'] : current_time('Y-m-d H:i:s'); $e_time = ''; $e_time .= sprintf("%02d", ($data->meta['mec_date']['end']['hour'] ?? '6')).':'; $e_time .= sprintf("%02d", ($data->meta['mec_date']['end']['minutes'] ?? '0')); $e_time .= isset($data->meta['mec_date']['end']['ampm']) ? trim($data->meta['mec_date']['end']['ampm']) : 'PM'; $end_time = date('D M j Y G:i:s', strtotime($end_date.' '.$e_time)); $d1 = new DateTime(current_time("D M j Y G:i:s")); $d2 = new DateTime($end_time); if($d2 < $d1) $data->meta['event_past'] = true; else $data->meta['event_past'] = false; // Apply Filters $data = apply_filters('mec_render_event_data', $data, $post_id); // Set to cache wp_cache_set($post_id, $data, 'mec-events-data', 43200); //Edited Occurrences $settings = $this->main->get_settings(); $edit_per_occurrences=[]; if(isset($settings['per_occurrences_status']) and $settings['per_occurrences_status']) { $occ = new MEC_feature_occurrences(); $occurrences = $occ->get_all_occurrences($post_id); foreach ($occurrences as $occurrence) { $date_start=date('Y-m-d', $occurrence['occurrence']); $params=json_decode($occurrence['params'], true); $params['location'] = (isset($params['location_id']) ? $this->main->get_location_data($params['location_id']) : array()); $params['organizer'] = (isset($params['organizer_id']) ? $this->main->get_organizer_data($params['organizer_id']) : array()); $edit_per_occurrences[$date_start]=$params; } } $data->edited_occurrences=$edit_per_occurrences; return $data; } /** * @param $event * @param MEC_skins $skin * @param int $serie * @return mixed */ public function after_render($event, $skin, $serie = 1) { // If event is custom days and current date is available if(isset($event->data) and isset($event->data->meta) and isset($event->data->meta['mec_repeat_type']) and $event->data->meta['mec_repeat_type'] === 'custom_days' and isset($event->data->mec) and isset($event->data->mec->days) and isset($event->date) and is_array($event->date) and isset($event->date['start']) and isset($event->date['start']['date'])) { // Time is already available if(isset($event->date['start']['hour'])) { $hide_time = $event->data->meta['mec_hide_time'] ?? 0; $hide_end_time = $this->main->hide_end_time_status($event->ID); $s_hour = $event->date['start']['hour']; if(strtoupper($event->date['start']['ampm']) == 'AM' and $s_hour == '0') $s_hour = 12; $e_hour = $event->date['end']['hour']; if(strtoupper($event->date['end']['ampm']) == 'AM' and $e_hour == '0') $e_hour = 12; $start_time = $event->date['start']['date'].' '.sprintf("%02d", $s_hour).':'.sprintf("%02d", $event->date['start']['minutes']).' '.$event->date['start']['ampm']; $end_time = $event->date['end']['date'].' '.sprintf("%02d", $e_hour).':'.sprintf("%02d", $event->date['end']['minutes']).' '.$event->date['end']['ampm']; $start_timestamp = strtotime($start_time); $end_timestamp = strtotime($end_time); $st = $this->main->get_time($start_timestamp); $et = $this->main->get_time($end_timestamp); $allday = $event->data->meta['mec_allday'] ?? 0; if($allday) { $st = $this->main->m('all_day', esc_html__('All Day' , 'modern-events-calendar-lite')); $et = ''; } $event->data->time = array( 'start'=>($hide_time ? '' : $st), 'end'=>(($hide_time or $hide_end_time) ? '' : $et), 'start_raw'=>$st, 'end_raw'=>$et, 'start_timestamp'=>$start_timestamp, 'end_timestamp'=>$end_timestamp, ); } // Detect the time when not available else { $multiple_day_show_method = \MEC\Settings\Settings::getInstance()->get_settings('multiple_day_show_method'); $days_str = $event->data->mec->days; if(trim($days_str)) { $original_start_date = $event->data->meta['mec_start_date']; $p_start_date = $event->date['start']['date']; $allday = $event->data->meta['mec_allday'] ?? 0; // Do not change the hour if it is the first serie of the event if(!($original_start_date == $p_start_date and $serie == 1)) { if($original_start_date == $p_start_date ) $serie -= 1; $periods = explode(',', $days_str); $datetime_timestamp = strtotime($p_start_date); $p = 0; foreach($periods as $period) { $ex = explode(':', $period); $s_date = $ex[0] ?? false; $e_date = $ex[1] ?? false; if(!$s_date || ($p_start_date!== $s_date && 'all_days' !== $multiple_day_show_method)) continue; $sd_timestamp = strtotime($s_date); if($e_date) { $ed_timestamp = strtotime($e_date); if(!($datetime_timestamp >= $sd_timestamp && $datetime_timestamp <= $ed_timestamp && isset($ex[2]) && isset($ex[3]))) continue; } $p++; if($p !== $serie) continue; $pos = strpos($ex[2], '-'); if($pos !== false) $ex[2] = substr_replace($ex[2], ':', $pos, 1); $pos = strpos($ex[3], '-'); if($pos !== false) $ex[3] = substr_replace($ex[3], ':', $pos, 1); $start_time = $s_date . ' ' . str_replace('-', ' ', $ex[2]); $end_time = $e_date . ' ' . str_replace('-', ' ', $ex[3]); $this->add_time_to_event($event, $start_time, $end_time, $allday); } } // Do not show expired occurrences if(!$skin->args['mec-past-events']) { $periods = explode(',', $days_str); $current_time = current_time('timestamp'); if($event->data->time['start_timestamp'] < $current_time) { foreach($periods as $period) { $ex = explode(':', $period); $s_date = $ex[0] ?? ''; $e_date = $ex[1] ?? ''; if(!$s_date or !$e_date) continue; $s_time = $ex[2] ?? ''; $e_time = $ex[3] ?? ''; $pos = strpos($s_time, '-'); if($pos !== false) $s_time = substr_replace($s_time, ':', $pos, 1); $pos = strpos($e_time, '-'); if($pos !== false) $e_time = substr_replace($e_time, ':', $pos, 1); $start_time = trim($s_date . ' ' . str_replace('-', ' ', $s_time)); $end_time = trim($e_date . ' ' . str_replace('-', ' ', $e_time)); if(strtotime($start_time) < $current_time) continue; $this->add_time_to_event($event, $start_time, $end_time, $allday); } } } } } } // If not custom days elseif(isset($event->data) and isset($event->data->time) and isset($event->data->time['start_raw']) and isset($event->data->time['end_raw']) and isset($event->date) and isset($event->date['start']) and isset($event->date['end'])) { $start_time = $event->date['start']['date'].' '.$event->data->time['start_raw']; $end_time = $event->date['end']['date'].' '.$event->data->time['end_raw']; $start_timestamp = strtotime($start_time); $end_timestamp = strtotime($end_time); if((!$start_timestamp or !$end_timestamp) and isset($event->data->meta['mec_date']) and isset($event->data->meta['mec_date']['start']) and isset($event->data->meta['mec_date']['start']['hour']) and isset($event->data->meta['mec_date']['end']) and isset($event->data->meta['mec_date']['end']['hour'])) { $start_time = $event->date['start']['date'].' '.sprintf("%02d", $event->data->meta['mec_date']['start']['hour']).':'.sprintf("%02d", $event->data->meta['mec_date']['start']['minutes']).' '.$event->data->meta['mec_date']['start']['ampm']; $end_time = $event->date['end']['date'].' '.sprintf("%02d", $event->data->meta['mec_date']['end']['hour']).':'.sprintf("%02d", $event->data->meta['mec_date']['end']['minutes']).' '.$event->data->meta['mec_date']['end']['ampm']; $start_timestamp = strtotime($start_time); $end_timestamp = strtotime($end_time); } if($start_timestamp and $end_timestamp) { $event->data->time['start_timestamp'] = $start_timestamp; $event->data->time['end_timestamp'] = $end_timestamp; } } // Fill Start and End Dates if(!isset($event->date['start']['hour']) or !isset($event->date['end']['hour'])) { $s_hour = $s_minutes = $s_ampm = $e_hour = $e_minutes = $e_ampm = NULL; if(isset($event->data->meta['mec_date']) and isset($event->data->meta['mec_date']['start']) and is_array($event->data->meta['mec_date']['start'])) { $s_hour = sprintf("%02d", $event->data->meta['mec_date']['start']['hour']); $s_minutes = sprintf("%02d", $event->data->meta['mec_date']['start']['minutes']); $s_ampm = strtolower($event->data->meta['mec_date']['start']['ampm']); } if(isset($event->data->meta['mec_date']) and isset($event->data->meta['mec_date']['end']) and is_array($event->data->meta['mec_date']['end'])) { $e_hour = sprintf("%02d", $event->data->meta['mec_date']['end']['hour']); $e_minutes = sprintf("%02d", $event->data->meta['mec_date']['end']['minutes']); $e_ampm = strtolower($event->data->meta['mec_date']['end']['ampm']); } if(isset($event->data->time) and isset($event->data->time['start_timestamp']) and $event->data->time['start_timestamp']) { $s_hour = date('h', $event->data->time['start_timestamp']); $s_minutes = date('i', $event->data->time['start_timestamp']); $s_ampm = date('a', $event->data->time['start_timestamp']); } if(isset($event->data->time) and isset($event->data->time['end_timestamp']) and $event->data->time['end_timestamp']) { $e_hour = date('h', $event->data->time['end_timestamp']); $e_minutes = date('i', $event->data->time['end_timestamp']); $e_ampm = date('a', $event->data->time['end_timestamp']); } $start_time = $event->date['start']['date'].' '.sprintf("%02d", $s_hour).':'.sprintf("%02d", $s_minutes).' '.$s_ampm; $end_time = $event->date['end']['date'].' '.sprintf("%02d", $e_hour).':'.sprintf("%02d", $e_minutes).' '.$e_ampm; if($s_hour and $s_minutes and $s_ampm and strtotime($start_time)) { $d = ((isset($event->date['start']) and is_array($event->date['start'])) ? $event->date['start'] : array()); $event->date['start'] = array_merge($d, array( 'hour' => sprintf("%02d", $s_hour), 'minutes' => sprintf("%02d", $s_minutes), 'ampm' => $s_ampm, 'timestamp' => strtotime($start_time), )); } if($e_hour and $e_minutes and $e_ampm and strtotime($end_time)) { $d = ((isset($event->date['end']) and is_array($event->date['end'])) ? $event->date['end'] : array()); $event->date['end'] = array_merge($d, array( 'hour' => sprintf("%02d", $e_hour), 'minutes' => sprintf("%02d", $e_minutes), 'ampm' => $e_ampm, 'timestamp' => strtotime($end_time), )); } } if($skin->skin != 'single' and !($skin->multiple_days_method == 'first_day' or ($skin->multiple_days_method == 'first_day_listgrid' and in_array($skin->skin, array('list', 'grid', 'slider', 'carousel', 'agenda', 'tile'))))) { // MEC Cache $cache = $this->getCache(); // Cache Key $key = $event->data->ID.'-'.$event->date['end']['date']; // Is Midnight Event $midnight = $this->main->is_midnight_event($event); // Improve Time for Multiple Day Events if($cache->has($key) or ($event->date['start']['date'] !== $event->date['end']['date'] and !$midnight)) { $allday = $event->data->meta['mec_allday'] ?? 0; $hide_time = $event->data->meta['mec_hide_time'] ?? 0; $hide_end_time = $this->main->hide_end_time_status($event->ID); // Get From Cache (Last Day) if($cache->has($key) and $event->date['start']['date'] === $event->date['end']['date']) { list($new_start_time, $new_end_time) = $cache->get($key); // Delete the Cache $cache->delete($key); } // Get From Cache (Between Days) elseif($cache->has($key) and $event->date['start']['date'] !== $event->date['end']['date']) { $new_start_time = $this->main->get_time(0); $new_end_time = $this->main->get_time((24*3600)); $allday = 1; } // First Day else { $new_start_time = $event->data->time['start_raw']; $new_end_time = $skin->skin === 'general_calendar' ? $event->data->time['end_raw'] : $this->main->get_time((24*3600)); $second_start_time = $this->main->get_time(0); $second_end_time = $event->data->time['end_raw']; // Set to Cache $cache->set($key, array($second_start_time, $second_end_time)); } // Flag to Multiple Day $event->data->multipleday = 1; $event->data->time['start_raw'] = $new_start_time; $event->data->time['end_raw'] = $new_end_time; if($hide_time) { $event->data->time['start'] = ''; $event->data->time['end'] = ''; } elseif($allday) { $event->data->time['start'] = $this->main->m('all_day', esc_html__('All Day' , 'modern-events-calendar-lite')); $event->data->time['end'] = ''; } else { $event->data->time['start'] = $new_start_time; $event->data->time['end'] = ($hide_end_time ? '' : $new_end_time); } } } return $event; } public function add_time_to_event(&$event, $start_datetime, $end_datetime, $allday = false) { $hide_time = $event->data->meta['mec_hide_time'] ?? 0; $hide_end_time = $this->main->hide_end_time_status($event->ID); $start_timestamp = strtotime($start_datetime); $end_timestamp = strtotime($end_datetime); $st = $this->main->get_time($start_timestamp); $et = $this->main->get_time($end_timestamp); if($allday) { $st = $this->main->m('all_day', esc_html__('All Day' , 'modern-events-calendar-lite')); $et = ''; } $event->data->time = [ 'start'=>($hide_time ? '' : $st), 'end'=>(($hide_time or $hide_end_time) ? '' : $et), 'start_raw'=>$st, 'end_raw'=>$et, 'start_timestamp'=>$start_timestamp, 'end_timestamp'=>$end_timestamp, ]; } /** * Renders and Returns event dats * @author Webnus * @param int $event_id * @param object $event * @param int $maximum * @param string $today * @return array */ public function dates($event_id, $event = NULL, $maximum = 6, $today = '') { if(!$today) $today = date('Y-m-d'); // Original Start Date $original_start_date = $today; $dates = []; // Get event data if it is NULL if(is_null($event)) { $event = new stdClass(); $event->meta = $this->main->get_post_meta($event_id, true); $event->mec = $this->db->select("SELECT * FROM `#__mec_events` WHERE `post_id`='$event_id'", "loadObject"); } $start_date = $event->meta['mec_date']['start'] ?? []; $end_date = $event->meta['mec_date']['end'] ?? []; $first_occurrence = $event->meta['mec_start_date'] ?? $today; // Return empty array if date is not valid if(!isset($start_date['date']) or !strtotime($start_date['date'])) return $dates; // Return empty array if mec data is not exists on mec_events table if(!isset($event->mec->end)) return $dates; $allday = $event->meta['mec_allday'] ?? 0; $hide_time = $event->meta['mec_hide_time'] ?? 0; $event_period = $this->main->date_diff($start_date['date'], $end_date['date']); $event_period_days = $event_period ? $event_period->days : 0; $finish_date = array('date'=>$event->mec->end, 'hour'=>$event->meta['mec_date']['end']['hour'], 'minutes'=>$event->meta['mec_date']['end']['minutes'], 'ampm'=>$event->meta['mec_date']['end']['ampm']); $exceptional_days = (isset($event->mec->not_in_days) and trim($event->mec->not_in_days)) ? explode(',', trim($event->mec->not_in_days, ', ')) : []; $exceptional_days = $this->main->add_global_exceptional_days($exceptional_days); // Event Passed $past = $this->main->is_past($finish_date['date'], $today); // Event is not passed for custom days if($past and isset($event->meta['mec_repeat_type']) and $event->meta['mec_repeat_type'] == 'custom_days') $past = 0; // Normal event if(isset($event->mec->repeat) and $event->mec->repeat == '0') { $dates[] = $this->add_timestamps(array( 'start'=>$start_date, 'end'=>$end_date, 'allday'=>$allday, 'hide_time'=>$hide_time, 'past'=>$past )); } elseif($past) { $dates[] = $this->add_timestamps(array( 'start'=>$start_date, 'end'=>$end_date, 'allday'=>$allday, 'hide_time'=>$hide_time, 'past'=>$past )); } else { $repeat_type = $event->meta['mec_repeat_type']; if(in_array($repeat_type, array('daily', 'weekly'))) { $repeat_interval = $event->meta['mec_repeat_interval']; $date_interval = $this->main->date_diff($start_date['date'], date('Y-m-d', strtotime($today))); $passed_days = $date_interval ? $date_interval->days : 0; // Check if date interval is negative (It means the event didn't start yet) if($date_interval and $date_interval->invert == 1) $remained_days_to_next_repeat = $passed_days; else $remained_days_to_next_repeat = $repeat_interval - fmod($passed_days, $repeat_interval); $start_date = date('Y-m-d', strtotime('+'.$remained_days_to_next_repeat.' Days', strtotime($today))); if( !$this->main->is_date_after($finish_date['date'], $start_date) && $this->main->is_date_after($first_occurrence, $start_date, true) && !in_array($start_date, $exceptional_days) ) $dates[] = $this->add_timestamps(array( 'start'=>array('date'=>$start_date, 'hour'=>$event->meta['mec_date']['start']['hour'], 'minutes'=>$event->meta['mec_date']['start']['minutes'], 'ampm'=>$event->meta['mec_date']['start']['ampm']), 'end'=>array('date'=>date('Y-m-d', strtotime('+'.$event_period_days.' Days', strtotime($start_date))), 'hour'=>$event->meta['mec_date']['end']['hour'], 'minutes'=>$event->meta['mec_date']['end']['minutes'], 'ampm'=>$event->meta['mec_date']['end']['ampm']), 'allday'=>$allday, 'hide_time'=>$hide_time, 'past'=>0 )); for($i = 2; $i <= $maximum; $i++) { $start_date = date('Y-m-d', strtotime('+'.$repeat_interval.' Days', strtotime($start_date))); // Event Not Started if(!$this->main->is_date_after($first_occurrence, $start_date, true)) continue; // Event finished if($this->main->is_past($finish_date['date'], $start_date)) break; if(!in_array($start_date, $exceptional_days)) $dates[] = $this->add_timestamps(array( 'start'=>array('date'=>$start_date, 'hour'=>$event->meta['mec_date']['start']['hour'], 'minutes'=>$event->meta['mec_date']['start']['minutes'], 'ampm'=>$event->meta['mec_date']['start']['ampm']), 'end'=>array('date'=>date('Y-m-d', strtotime('+'.$event_period_days.' Days', strtotime($start_date))), 'hour'=>$event->meta['mec_date']['end']['hour'], 'minutes'=>$event->meta['mec_date']['end']['minutes'], 'ampm'=>$event->meta['mec_date']['end']['ampm']), 'allday'=>$allday, 'hide_time'=>$hide_time, 'past'=>0 )); } } elseif(in_array($repeat_type, array('weekday', 'weekend', 'certain_weekdays'))) { $date_interval = $this->main->date_diff($start_date['date'], $today); $passed_days = $date_interval ? $date_interval->days : 0; // Check if date interval is negative (It means the event didn't start yet) if($date_interval and $date_interval->invert == 1) $today = date('Y-m-d', strtotime('+'.$passed_days.' Days', strtotime($original_start_date))); $event_days = explode(',', trim($event->mec->weekdays, ', ')); $today_id = date('N', strtotime($today)); $found = 0; $i = 0; while($found < $maximum) { if($this->main->is_past($finish_date['date'], $today)) break; if(!in_array($today_id, $event_days)) { $today = date('Y-m-d', strtotime('+1 Days', strtotime($today))); $today_id = date('N', strtotime($today)); $i++; continue; } $start_date = $today; if(!in_array($start_date, $exceptional_days)) $dates[] = $this->add_timestamps(array( 'start'=>array('date'=>$start_date, 'hour'=>$event->meta['mec_date']['start']['hour'], 'minutes'=>$event->meta['mec_date']['start']['minutes'], 'ampm'=>$event->meta['mec_date']['start']['ampm']), 'end'=>array('date'=>date('Y-m-d', strtotime('+'.$event_period_days.' Days', strtotime($start_date))), 'hour'=>$event->meta['mec_date']['end']['hour'], 'minutes'=>$event->meta['mec_date']['end']['minutes'], 'ampm'=>$event->meta['mec_date']['end']['ampm']), 'allday'=>$allday, 'hide_time'=>$hide_time, 'past'=>0 )); $today = date('Y-m-d', strtotime('+1 Days', strtotime($today))); $today_id = date('N', strtotime($today)); $found++; $i++; } } elseif($repeat_type == 'monthly') { $repeat_interval = ((isset($event->meta) and isset($event->meta['mec_repeat_interval'])) ? max(1, $event->meta['mec_repeat_interval']) : 1); // Start from Event Start Date if(strtotime($start_date['date']) > strtotime($original_start_date)) $original_start_date = $start_date['date']; $event_days = explode(',', trim($event->mec->day, ', ')); $event_start_day = $event_days[0]; $diff = $this->main->date_diff($start_date['date'], $end_date['date']); $event_period_days = $diff->days; $found = 0; $i = 0; while($found < $maximum) { $t = strtotime('+'.$i.' Months', strtotime($original_start_date)); if(!$t) break; $today = date('Y-m-d', $t); if($this->main->is_past($finish_date['date'], $today)) break; $year = date('Y', strtotime($today)); $month = date('m', strtotime($today)); $day = $event_start_day; $hour = isset($event->meta['mec_date']['end']['hour']) ? sprintf('%02d', $event->meta['mec_date']['end']['hour']) : '06'; $minutes = isset($event->meta['mec_date']['end']['minutes']) ? sprintf('%02d', $event->meta['mec_date']['end']['minutes']) : '00'; $ampm = isset($event->meta['mec_date']['end']['ampm']) ? strtoupper($event->meta['mec_date']['end']['ampm']) : 'PM'; // Fix for 31st, 30th, 29th of some months while(!checkdate((int) $month, (int) $day, (int) $year)) $day--; $start_date = $year.'-'.$month.'-'.$day; $end_time = $hour.':'.$minutes.' '.$ampm; // Wrong Date & Time if(!strtotime($start_date.' '.$end_time)) break; if(strtotime($start_date.' '.$end_time) < strtotime($original_start_date)) { $i += $repeat_interval; continue; } if(!in_array($start_date, $exceptional_days)) $dates[] = $this->add_timestamps(array( 'start'=>array('date'=>$start_date, 'hour'=>$event->meta['mec_date']['start']['hour'], 'minutes'=>$event->meta['mec_date']['start']['minutes'], 'ampm'=>$event->meta['mec_date']['start']['ampm']), 'end'=>array('date'=>date('Y-m-d', strtotime('+'.$event_period_days.' Days', strtotime($start_date))), 'hour'=>$event->meta['mec_date']['end']['hour'], 'minutes'=>$event->meta['mec_date']['end']['minutes'], 'ampm'=>$event->meta['mec_date']['end']['ampm']), 'allday'=>$allday, 'hide_time'=>$hide_time, 'past'=>0 )); $found++; $i += $repeat_interval; } } elseif($repeat_type == 'yearly') { // Start from Event Start Date if(strtotime($start_date['date']) > strtotime($original_start_date)) $original_start_date = $start_date['date']; $event_days = explode(',', trim($event->mec->day, ', ')); $event_months = explode(',', trim($event->mec->month, ', ')); $event_start_day = $event_days[0]; $event_period_days = $this->main->date_diff($start_date['date'], $end_date['date'])->days; $event_start_year = date('Y', strtotime($original_start_date)); $event_start_month = date('n', strtotime($original_start_date)); $found = 0; $i = 0; while($found < $maximum) { $today = date('Y-m-d', strtotime($event_start_year.'-'.$event_start_month.'-'.$event_start_day)); if($this->main->is_past($finish_date['date'], $today)) break; $year = date('Y', strtotime($today)); $month = date('m', strtotime($today)); if(!in_array($month, $event_months)) { if($event_start_month == '12') { $event_start_month = 1; $event_start_year += 1; } else $event_start_month += 1; $i++; continue; } $day = $event_start_day; // Fix for 31st, 30th, 29th of some months while(!checkdate($month, $day, $year)) $day--; $event_date = $year.'-'.$month.'-'.$day; if(strtotime($event_date) >= strtotime($original_start_date)) { $start_date = $event_date; if(!in_array($start_date, $exceptional_days)) $dates[] = $this->add_timestamps(array( 'start'=>array('date'=>$start_date, 'hour'=>$event->meta['mec_date']['start']['hour'], 'minutes'=>$event->meta['mec_date']['start']['minutes'], 'ampm'=>$event->meta['mec_date']['start']['ampm']), 'end'=>array('date'=>date('Y-m-d', strtotime('+'.$event_period_days.' Days', strtotime($start_date))), 'hour'=>$event->meta['mec_date']['end']['hour'], 'minutes'=>$event->meta['mec_date']['end']['minutes'], 'ampm'=>$event->meta['mec_date']['end']['ampm']), 'allday'=>$allday, 'hide_time'=>$hide_time, 'past'=>0 )); $found++; } if($event_start_month == '12') { $event_start_month = 1; $event_start_year += 1; } else $event_start_month += 1; $i++; } } elseif($repeat_type == 'custom_days') { $custom_days = explode(',', $event->mec->days); // Add current time if we're checking today's events if($today == current_time('Y-m-d')) $today .= ' '.current_time('H:i:s'); $found = 0; if((strtotime($event->mec->start) + $event->meta['mec_start_day_seconds']) >= strtotime($today) and !in_array($event->mec->start, $exceptional_days)) { $dates[] = $this->add_timestamps(array( 'start'=>array('date'=>$event->mec->start, 'hour'=>$event->meta['mec_date']['start']['hour'], 'minutes'=>$event->meta['mec_date']['start']['minutes'], 'ampm'=>$event->meta['mec_date']['start']['ampm']), 'end'=>array('date'=>$event->mec->end, 'hour'=>$event->meta['mec_date']['end']['hour'], 'minutes'=>$event->meta['mec_date']['end']['minutes'], 'ampm'=>$event->meta['mec_date']['end']['ampm']), 'allday'=>$allday, 'hide_time'=>$hide_time, 'past'=>0 )); $found++; } foreach($custom_days as $custom_day) { // Found maximum dates if($found >= $maximum) break; $cday = explode(':', $custom_day); $c_start = $cday[0]; if(isset($cday[2])) $c_start .= ' '.str_replace('-', ' ', substr_replace($cday[2], ':', strpos($cday[2], '-'), 1)); // Date is past if(strtotime($c_start) < strtotime($today)) continue; $cday_start_hour = $event->meta['mec_date']['start']['hour']; $cday_start_minutes = $event->meta['mec_date']['start']['minutes']; $cday_start_ampm = $event->meta['mec_date']['start']['ampm']; $cday_end_hour = $event->meta['mec_date']['end']['hour']; $cday_end_minutes = $event->meta['mec_date']['end']['minutes']; $cday_end_ampm = $event->meta['mec_date']['end']['ampm']; if(isset($cday[2]) and isset($cday[3])) { $cday_start_ex = explode('-', $cday[2]); $cday_start_hour = $cday_start_ex[0]; $cday_start_minutes = $cday_start_ex[1]; $cday_start_ampm = $cday_start_ex[2]; $cday_end_ex = explode('-', $cday[3]); $cday_end_hour = $cday_end_ex[0]; $cday_end_minutes = $cday_end_ex[1]; $cday_end_ampm = $cday_end_ex[2]; } if(!in_array($cday[0], $exceptional_days)) $dates[] = $this->add_timestamps(array( 'start'=>array('date'=>$cday[0], 'hour'=>$cday_start_hour, 'minutes'=>$cday_start_minutes, 'ampm'=>$cday_start_ampm), 'end'=>array('date'=>$cday[1], 'hour'=>$cday_end_hour, 'minutes'=>$cday_end_minutes, 'ampm'=>$cday_end_ampm), 'allday'=>$allday, 'hide_time'=>$hide_time, 'past'=>0 )); $found++; } // No future date found so the event is passed if(!count($dates)) { $dates[] = $this->add_timestamps(array( 'start'=>$start_date, 'end'=>$finish_date, 'allday'=>$allday, 'hide_time'=>$hide_time, 'past'=>$past )); } } elseif($repeat_type == 'advanced') { // Start from Event Start Date if(strtotime($start_date['date']) > strtotime($today)) $today = $start_date['date']; // Get user specifed days of month for repeat $advanced_days = get_post_meta($event_id, 'mec_advanced_days', true); // Generate dates for event $event_info = array('start' => $start_date, 'end' => $end_date, 'allday' => $allday, 'hide_time' => $hide_time, 'finish_date' => $finish_date['date'], 'exceptional_days' => $exceptional_days, 'mec_repeat_end' => ((isset($event->meta['mec_repeat']) and isset($event->meta['mec_repeat']['end'])) ? $event->meta['mec_repeat']['end'] : ''), 'occurrences' => ((isset($event->meta['mec_repeat']) and isset($event->meta['mec_repeat']['end_at_occurrences'])) ? $event->meta['mec_repeat']['end_at_occurrences'] : '')); $dates = $this->generate_advanced_days($advanced_days, $event_info, $maximum, $today); } } return $dates; } /** * Render advanced dates * @author Webnus * @param array $advanced_days * @param array $event_info * @param int $maximum * @param string $referer_date * @param string $mode * @return array */ public function generate_advanced_days($advanced_days = array(), $event_info = array(), $maximum = 6, $referer_date = NULL, $mode = 'render') { if(!count($advanced_days)) return []; if(!trim($referer_date)) $referer_date = date('Y-m-d', current_time('timestamp', 0)); $levels = array('first', 'second', 'third', 'fourth', 'last'); $year = date('Y', strtotime($event_info['start']['date'])); $dates = []; // Set last month for include current month results $month = date('m', strtotime('first day of last month', strtotime($event_info['start']['date']))); if($month == '12') $year = $year - 1; $maximum = intval($maximum); $i = 0; // Event info $exceptional_days = array_key_exists('exceptional_days', $event_info) ? $event_info['exceptional_days'] : []; $start_date = $event_info['start']; $end_date = $event_info['end']; $allday = array_key_exists('allday', $event_info) ? $event_info['allday'] : 0; $hide_time = array_key_exists('hide_time', $event_info) ? $event_info['hide_time'] : 0; $finish_date = array_key_exists('finish_date', $event_info) ? $event_info['finish_date'] : '0000-00-00'; $event_period = $this->main->date_diff($start_date['date'], $end_date['date']); $event_period_days = $event_period ? $event_period->days : 0; $mec_repeat_end = array_key_exists('mec_repeat_end', $event_info) ? $event_info['mec_repeat_end'] : ''; $occurrences = array_key_exists('occurrences', $event_info) ? $event_info['occurrences'] : 0; // Include default start date to results if(!$this->main->is_past($start_date['date'], $referer_date) and !in_array($start_date['date'], $exceptional_days)) { $dates[] = $this->add_timestamps(array( 'start' => $start_date, 'end' => $end_date, 'allday' => $allday, 'hide_time' => $hide_time, 'past' => 0, )); if($mode == 'render') $i++; } while($i < $maximum) { $start = NULL; foreach($advanced_days as $day) { if($i >= $maximum) break; // Explode $day value for example (Sun.1) to Sun and 1 $d = explode('.', $day); // Set indexes for {$levels} index if number day is Last(Sun.l) then indexes set 4th {$levels} index $index = intval($d[1]) ? (intval($d[1]) - 1) : 4; // Generate date $date = date('Y-m-t', strtotime("{$year}-{$month}-01")); // Generate start date for example "first Sun of next month" $start = date('Y-m-d', strtotime("{$levels[$index]} {$d[0]} of next month", strtotime($date))); $end = date('Y-m-d', strtotime("+{$event_period_days} Days", strtotime($start))); // Occurence equals to the main start date if($start === $start_date['date']) continue; // When ends repeat date set if($mode == 'render' and $this->main->is_past($finish_date, $start)) continue; // Jump to next level if start date is past if($this->main->is_past($start, $referer_date) or in_array($start, $exceptional_days)) continue; // Add dates $dates[] = $this->add_timestamps(array( 'start' => array( 'date' => $start, 'hour' => $start_date['hour'], 'minutes' => $start_date['minutes'], 'ampm' => $start_date['ampm'], ), 'end' => array( 'date' => $end, 'hour' => $end_date['hour'], 'minutes' => $end_date['minutes'], 'ampm' => $end_date['ampm'], ), 'allday' => $allday, 'hide_time' => $hide_time, 'past' => 0, )); $i++; } // When ends repeat date set if($mode == 'render' and $this->main->is_past($finish_date, $start)) break; // Change month and years for next resualts if(intval($month) == 12) { $year = intval($year) + 1; $month = '00'; } $month = sprintf("%02d", intval($month) + 1); } if(($mode == 'render') and (trim($mec_repeat_end) == 'occurrences') and (count($dates) > $occurrences)) { $max = strtotime(reset($dates)['start']['date']); $pos = 0; for($i = 1; $i < count($dates); $i++) { if(strtotime($dates[$i]['start']['date']) > $max) { $max = strtotime($dates[$i]['start']['date']); $pos = $i; } } unset($dates[$pos]); } // Remove Duplicates $uniques = []; $timestamps = []; foreach($dates as $key => $date) { $start_timestamp = $date['start']['timestamp']; $end_timestamp = $date['end']['timestamp']; $timestamp_key = $start_timestamp.'-'.$end_timestamp; if(isset($timestamps[$timestamp_key])) continue; $timestamps[$timestamp_key] = true; $uniques[] = $date; } // Sort usort($uniques, array($this, 'sort_dates')); return $uniques; } public function sort_dates($a, $b) { $a_timestamp = $a['start']['timestamp']; $b_timestamp = $b['end']['timestamp']; if($a_timestamp == $b_timestamp) return 0; return ($a_timestamp > $b_timestamp) ? +1 : -1; } /** * Render markers * @author Webnus * @param array $events * @param string $skin_style * @return array */ public function markers($events, $skin_style = 'classic') { $date_format = (isset($this->settings['google_maps_date_format1']) and trim($this->settings['google_maps_date_format1'])) ? $this->settings['google_maps_date_format1'] : 'M d Y'; $requested_location_id = isset($_REQUEST['sf'], $_REQUEST['sf']['location']) ? $_REQUEST['sf']['location'] : null; $markers = []; foreach($events as $event) { if(!is_object($event)) continue; if(!isset($event->data->locations) or (isset($event->data->locations) and !is_array($event->data->locations))) continue; $locations = []; $main_location_id = get_post_meta($event->ID, 'mec_location_id', true); if(isset($event->date, $event->date['start'], $event->date['start']['timestamp'])) $main_location_id = MEC_feature_occurrences::param($event->ID, $event->date['start']['timestamp'], 'location_id', $main_location_id); $main_location_id = apply_filters('wpml_object_id', $main_location_id, 'mec_location', true); if($main_location_id && $main_location_id > 1) $locations[] = $main_location_id; $additional_location_ids = get_post_meta($event->ID, 'mec_additional_location_ids', true); if(!is_array($additional_location_ids)) $additional_location_ids = []; $locations = array_merge($locations, $additional_location_ids); $locations = array_unique($locations); if($requested_location_id && !is_array($requested_location_id)) { if($main_location_id !== $requested_location_id && !in_array($requested_location_id, $additional_location_ids)) continue; $locations = [$requested_location_id]; } // No Locations if(!count($locations)) continue; foreach($locations as $location_id) { $location_id = (int) $location_id; $latitude = get_term_meta($location_id, 'latitude', true); $longitude = get_term_meta($location_id, 'longitude', true); // No latitude/Longitude if(trim($latitude) == '' or trim($longitude) == '') continue; $location = get_term($location_id); $name = $location->name ?? ''; $latitude = floatval($latitude); $longitude = floatval($longitude); $key = $latitude.','.$longitude; if(!isset($markers[$key])) { $markers[$key] = array( 'latitude'=>$latitude, 'longitude'=>$longitude, 'name'=>$name, 'address'=>get_term_meta($location_id, 'address', true), 'event_ids'=>array($event->data->ID), 'lightbox'=>$this->main->get_marker_lightbox($event, $date_format, $skin_style), ); } else { $markers[$key]['event_ids'][] = $event->data->ID; $markers[$key]['lightbox'] .= $this->main->get_marker_lightbox($event, $date_format, $skin_style); } } } $points = []; foreach($markers as $key=>$marker) { $points[$key] = $marker; $points[$key]['lightbox'] = '
'.(trim($marker['address']) ? esc_html($marker['address']) : esc_html($marker['name'])).'
'.MEC_kses::element($marker['lightbox']).'
'; $points[$key]['count'] = count($marker['event_ids']); $points[$key]['infowindow'] = $this->main->get_marker_infowindow($marker); } return apply_filters('mec_render_markers', $points); } public function add_timestamps($date) { $start = (isset($date['start']) and is_array($date['start'])) ? $date['start'] : []; $end = (isset($date['end']) and is_array($date['end'])) ? $date['end'] : []; if(!count($start) or !count($end)) return $date; $s_hour = $start['hour']; if(strtoupper($start['ampm']) == 'AM' and $s_hour == '0') $s_hour = 12; $e_hour = $end['hour']; if(strtoupper($end['ampm']) == 'AM' and $e_hour == '0') $e_hour = 12; $allday = ($date['allday'] ?? 0); // All Day Event if($allday) { $s_hour = 12; $start['minutes'] = 1; $start['ampm'] = 'AM'; $e_hour = 11; $end['minutes'] = 59; $end['ampm'] = 'PM'; } $start_time = $start['date'].' '.sprintf("%02d", $s_hour).':'.sprintf("%02d", $start['minutes']).' '.$start['ampm']; $end_time = $end['date'].' '.sprintf("%02d", $e_hour).':'.sprintf("%02d", $end['minutes']).' '.$end['ampm']; $start['timestamp'] = strtotime($start_time); $end['timestamp'] = strtotime($end_time); $hide_time = $date['hide_time'] ?? 0; $past = $date['past'] ?? 0; return array( 'start' => $start, 'end' => $end, 'allday' => $allday, 'hide_time' => $hide_time, 'past' => $past, ); } }