status) { return ''; } return '' . esc_html__('Cancelled', '3task-calendar') . ' '; } /** * Settings */ private $settings; /** * Constructor */ public function __construct() { $this->settings = get_option('threecal_settings', array()); } /** * Date format from the plugin settings or WordPress. */ private function date_format() { return threecal_date_format(); } /** * Time format from the plugin settings or WordPress. */ private function time_format() { return threecal_time_format(); } /** * Render full calendar */ public function render_calendar($args = array()) { $defaults = array( 'view' => 'month', 'category_id' => 0, 'location_id' => 0, 'theme' => '', 'show_filters' => true, 'show_legend' => true, 'show_subscribe' => true, 'mobile_list' => true, 'week_starts_on' => null ); $args = wp_parse_args($args, $defaults); ThreeCal_Themes::remember_page_theme($args['theme']); $args['theme'] = ThreeCal_Themes::normalize($args['theme']); $args['view'] = in_array($args['view'], array('month', 'list'), true) ? $args['view'] : 'month'; ThreeCal_Themes::enqueue($args['theme']); // Get week start from settings if not specified if ($args['week_starts_on'] === null) { $args['week_starts_on'] = isset($this->settings['week_starts_on']) ? (int) $this->settings['week_starts_on'] : 1; } // Get current month/year. // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Calendar navigation params, sanitized with absint(). $month = isset( $_GET['cc_month'] ) ? absint( $_GET['cc_month'] ) : (int) current_time( 'n' ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Calendar navigation params, sanitized with absint(). $year = isset( $_GET['cc_year'] ) ? absint( $_GET['cc_year'] ) : (int) current_time( 'Y' ); // Validate month/year if ($month < 1 || $month > 12) { $month = (int) current_time('n'); } if ($year < 2000 || $year > 2100) { $year = (int) current_time('Y'); } // Get categories for filter/legend $categories = ThreeCal_Category::get_all(); // Generate unique ID for this calendar instance $calendar_id = 'threecal-' . wp_rand(1000, 9999); ob_start(); ?>
get_month_name($month)); ?>
1) : ?>
render_month_view( $month, $year, $args ); ?>
ThreeCal_Event::visible_statuses(), 'range_start' => gmdate('Y-m-d 00:00:00', $first_day), 'range_end' => gmdate('Y-m-t 23:59:59', $first_day) ); if (!empty($args['category_id'])) { $event_args['category_id'] = $args['category_id']; } if (!empty($args['location_id'])) { $event_args['location_id'] = $args['location_id']; } $events = ThreeCal_Event::get_all($event_args); $categories = ThreeCal_Event::get_categories_for_events(wp_list_pluck($events, 'id')); $time_format = $this->time_format(); // Group events by every day they cover (multi-day events appear on each day) $events_by_day = array(); foreach ($events as $event) { foreach ($event->get_days_in_month($month, $year) as $day) { $events_by_day[$day][] = array( 'event' => $event, 'color' => ThreeCal_Themes::event_color($event, isset($categories[$event->id]) ? $categories[$event->id] : array()), 'starts_here' => substr($event->start_date, 0, 10) === sprintf('%04d-%02d-%02d', $year, $month, $day), ); } } $today = current_time('Y-m-d'); $total_cells = $first_weekday + $days_in_month; $weeks = (int) ceil($total_cells / 7); $day = 1; ob_start(); ?> $days_in_month) : ?>
get_weekday_name(($i + $week_starts_on) % 7)); ?>
>
$item) : $event = $item['event']; $show_time = !$event->all_day && $item['starts_here']; ?> start_date))); ?> title); ?> 3) : ?>
'list', 'theme' => '', 'show_pagination' => true, 'columns' => 3, 'total' => 0, 'per_page' => 10, 'current_page' => 1, 'page_param' => 'tc_page' ); $args = wp_parse_args($args, $defaults); $args['theme'] = ThreeCal_Themes::normalize($args['theme']); $args['view'] = in_array($args['view'], array('list', 'grid', 'compact', 'poster'), true) ? $args['view'] : 'list'; $args['columns'] = min(6, max(1, (int) $args['columns'])); ThreeCal_Themes::enqueue($args['theme']); if (empty($events)) { return '

' . esc_html__('No events found.', '3task-calendar') . '

'; } $categories = ThreeCal_Event::get_categories_for_events(wp_list_pluck($events, 'id')); ob_start(); ?>
> id ] ) ? $categories[ $event->id ] : array(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output is escaped within the card methods. echo 'poster' === $args['view'] ? $this->render_poster_card( $event, $event_cats ) : $this->render_event_card( $event, $args['view'], $event_cats ); ?>
$args['per_page'] ) : ?>
render_pagination( $args['total'], $args['per_page'], $args['current_page'], $args['page_param'] ); ?>
start_date); $when = date_i18n('D', $start) . ', ' . date_i18n($this->date_format(), $start); if (!$event->all_day) { $when .= ' · ' . date_i18n($this->time_format(), $start); } $postponed = ThreeCal_Post_Dates::postponed_text($event); $cancelled = 'cancelled' === $event->status; $link = $event->url; ob_start(); ?>

title); ?> title); ?>

location_id ? ThreeCal_Location::get($event->location_id) : null; if (null === $categories) { $categories = ThreeCal_Event::get_categories($event->id); } $color = ThreeCal_Themes::event_color($event, $categories); $date_format = $this->date_format(); $time_format = $this->time_format(); $start = strtotime($event->start_date); ob_start(); ?>
featured_image && 'compact' !== $view) : ?>
featured_image, 'medium_large', false, array('loading' => 'lazy')); ?>
name); ?>

url) : ?> title); ?> title); ?>

all_day) { echo ' · ' . esc_html(date_i18n($time_format, $start)); } if ($event->end_date && $event->end_date !== $event->start_date) { $end = strtotime($event->end_date); echo ' – '; if (gmdate('Y-m-d', $start) !== gmdate('Y-m-d', $end)) { echo esc_html(date_i18n($date_format, $end)); if (!$event->all_day) { echo ' · '; } } if (!$event->all_day) { echo esc_html(date_i18n($time_format, $end)); } } if ($event->all_day) { echo ' · ' . esc_html__('All day', '3task-calendar'); } ?> name); ?>city) : ?>, city); ?>

description ) ) : ?>

description ), 24 ) ); ?>

'', 'show_map' => true, 'show_description' => true ); $args = wp_parse_args($args, $defaults); $args['theme'] = ThreeCal_Themes::normalize($args['theme']); ThreeCal_Themes::enqueue($args['theme']); $location = $event->location_id ? ThreeCal_Location::get($event->location_id) : null; $categories = ThreeCal_Event::get_categories($event->id); $color = ThreeCal_Themes::event_color($event, $categories); $date_format = $this->date_format(); $time_format = $this->time_format(); ob_start(); ?>
featured_image) : ?>
name); ?>

title); ?>


start_date))); if ($event->end_date && gmdate('Y-m-d', strtotime($event->start_date)) !== gmdate('Y-m-d', strtotime($event->end_date))) { echo ' – ' . esc_html(date_i18n($date_format, strtotime($event->end_date))); } ?>
all_day) : ?>

start_date))); if ($event->end_date) { echo ' – ' . esc_html(date_i18n($time_format, strtotime($event->end_date))); } ?>
name); ?>
get_full_address()); ?> get_route_url()) : ?>
description)) : ?>
description)); ?>
url) : ?>
'', 'show_date' => true, 'show_time' => true, 'show_location' => true ); $args = wp_parse_args($args, $defaults); $args['theme'] = ThreeCal_Themes::normalize($args['theme']); ThreeCal_Themes::enqueue($args['theme']); $date_format = $this->date_format(); $time_format = $this->time_format(); if (empty($events)) { return '

' . esc_html__('No upcoming events.', '3task-calendar') . '

'; } $categories = ThreeCal_Event::get_categories_for_events(wp_list_pluck($events, 'id')); ob_start(); ?> 0, 'theme' => '', 'show_nav' => true, 'show_today' => true, 'week_starts_on' => null ); $args = wp_parse_args($args, $defaults); $args['theme'] = ThreeCal_Themes::normalize($args['theme']); ThreeCal_Themes::enqueue($args['theme']); // Get week start from settings if not specified if ($args['week_starts_on'] === null) { $args['week_starts_on'] = isset($this->settings['week_starts_on']) ? (int) $this->settings['week_starts_on'] : 1; } // Get current month/year from URL or use current date. // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Calendar navigation params, sanitized with absint(). $month = isset($_GET['cc_mini_month']) ? absint($_GET['cc_mini_month']) : (int) current_time('n'); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Calendar navigation params, sanitized with absint(). $year = isset($_GET['cc_mini_year']) ? absint($_GET['cc_mini_year']) : (int) current_time('Y'); // Validate month/year if ($month < 1 || $month > 12) { $month = (int) current_time('n'); } if ($year < 2000 || $year > 2100) { $year = (int) current_time('Y'); } $week_starts_on = (int) $args['week_starts_on']; $date_format = $this->date_format(); $time_format = $this->time_format(); // Get first day of month $first_day = mktime(0, 0, 0, $month, 1, $year); $days_in_month = (int) gmdate('t', $first_day); $first_weekday = ((int) gmdate('w', $first_day) - $week_starts_on + 7) % 7; $event_args = array( 'status' => ThreeCal_Event::visible_statuses(), 'range_start' => gmdate('Y-m-d 00:00:00', $first_day), 'range_end' => gmdate('Y-m-t 23:59:59', $first_day) ); if (!empty($args['category_id'])) { $event_args['category_id'] = $args['category_id']; } $events = ThreeCal_Event::get_all($event_args); $categories = ThreeCal_Event::get_categories_for_events(wp_list_pluck($events, 'id')); // Group events by every day they cover, with event data for the popup $events_data_by_day = array(); foreach ($events as $event) { $color = ThreeCal_Themes::event_color($event, isset($categories[$event->id]) ? $categories[$event->id] : array()); $event_time = $event->all_day ? __('All day', '3task-calendar') : date_i18n($time_format, strtotime($event->start_date)); foreach ($event->get_days_in_month($month, $year) as $day) { $events_data_by_day[$day][] = array( 'id' => $event->id, 'title' => $event->title, 'time' => $event_time, 'color' => $color, 'url' => $event->url ? esc_url_raw($event->url) : '' ); } } // Calculate navigation URLs $prev_month = $month - 1; $prev_year = $year; if ($prev_month < 1) { $prev_month = 12; $prev_year--; } $next_month = $month + 1; $next_year = $year; if ($next_month > 12) { $next_month = 1; $next_year++; } $current_url = remove_query_arg(array('cc_mini_month', 'cc_mini_year')); $prev_url = add_query_arg(array('cc_mini_month' => $prev_month, 'cc_mini_year' => $prev_year), $current_url); $next_url = add_query_arg(array('cc_mini_month' => $next_month, 'cc_mini_year' => $next_year), $current_url); $today_url = remove_query_arg(array('cc_mini_month', 'cc_mini_year'), $current_url); $calendar_id = 'threecal-mini-' . wp_rand(1000, 9999); $today = current_time('Y-m-d'); // Enqueue mini calendar CSS and JS. wp_enqueue_style( 'threecal-mini' ); wp_enqueue_script( 'threecal-mini' ); ob_start(); ?>
get_month_name($month) . ' ' . $year); ?>
$days_in_month) : ?>
get_weekday_initial(($i + $week_starts_on) % 7)); ?>
tabindex="0" role="button" aria-label="" data-date-formatted="" data-events="" >
'; if ($current_page > 1) { $output .= ''; $output .= '« ' . esc_html__('Previous', '3task-calendar'); $output .= ''; } // First, last and the pages around the current one; gaps become an ellipsis. $gap = false; for ($i = 1; $i <= $total_pages; $i++) { if ($i !== 1 && $i !== $total_pages && abs($i - $current_page) > 1) { if (!$gap) { $output .= ''; $gap = true; } continue; } $gap = false; if ($i === $current_page) { $output .= '' . $i . ''; } else { $output .= '' . $i . ''; } } if ($current_page < $total_pages) { $output .= ''; $output .= esc_html__('Next', '3task-calendar') . ' »'; $output .= ''; } $output .= ''; return $output; } /** * Get month name */ private function get_month_name($month) { $months = array( 1 => __('January', '3task-calendar'), 2 => __('February', '3task-calendar'), 3 => __('March', '3task-calendar'), 4 => __('April', '3task-calendar'), 5 => __('May', '3task-calendar'), 6 => __('June', '3task-calendar'), 7 => __('July', '3task-calendar'), 8 => __('August', '3task-calendar'), 9 => __('September', '3task-calendar'), 10 => __('October', '3task-calendar'), 11 => __('November', '3task-calendar'), 12 => __('December', '3task-calendar') ); return isset($months[$month]) ? $months[$month] : ''; } /** * Get weekday name (short) */ private function get_weekday_name($day) { $days = array( 0 => __('Sun', '3task-calendar'), 1 => __('Mon', '3task-calendar'), 2 => __('Tue', '3task-calendar'), 3 => __('Wed', '3task-calendar'), 4 => __('Thu', '3task-calendar'), 5 => __('Fri', '3task-calendar'), 6 => __('Sat', '3task-calendar') ); return isset($days[$day]) ? $days[$day] : ''; } /** * Get weekday initial (single letter for mini calendar) */ private function get_weekday_initial($day) { $days = array( /* translators: Single letter abbreviation for Sunday */ 0 => _x('S', 'Sunday initial', '3task-calendar'), /* translators: Single letter abbreviation for Monday */ 1 => _x('M', 'Monday initial', '3task-calendar'), /* translators: Single letter abbreviation for Tuesday */ 2 => _x('T', 'Tuesday initial', '3task-calendar'), /* translators: Single letter abbreviation for Wednesday */ 3 => _x('W', 'Wednesday initial', '3task-calendar'), /* translators: Single letter abbreviation for Thursday */ 4 => _x('T', 'Thursday initial', '3task-calendar'), /* translators: Single letter abbreviation for Friday */ 5 => _x('F', 'Friday initial', '3task-calendar'), /* translators: Single letter abbreviation for Saturday */ 6 => _x('S', 'Saturday initial', '3task-calendar') ); return isset($days[$day]) ? $days[$day] : ''; } }