From 848fd89063c62a1ce2e0f2a49cf93163b47c7740 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arttu=20Erkkil=C3=A4?= Date: Tue, 10 Oct 2023 10:33:46 +0300 Subject: [PATCH 1/4] TMS-974: Add recurring events. --- CHANGELOG.MD | 2 + models/page-events-calendar.php | 18 ++++++-- models/page-events-search.php | 74 +++++++++++++++++++++++++++++---- 3 files changed, 81 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.MD b/CHANGELOG.MD index 17621bab..eefda4bd 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +- TMS-974: Add recurring events to lists as single item. + ## [1.49.0] - 2023-09-15 - TMS-962: Add Lunch Menus plugin caps to roles. diff --git a/models/page-events-calendar.php b/models/page-events-calendar.php index 1844210d..2b6efa16 100644 --- a/models/page-events-calendar.php +++ b/models/page-events-calendar.php @@ -100,8 +100,6 @@ protected function get_events() : array { 'targets' => get_field( 'target' ), 'tags' => get_field( 'tag' ), 'sort' => 'startDate', - 'size' => get_option( 'posts_per_page' ), - 'skip' => $skip, 'show_images' => get_field( 'show_images' ), ]; @@ -135,8 +133,20 @@ protected function get_events() : array { } } - if ( ! empty( $response['meta'] ) ) { - $this->set_pagination_data( $response['meta']->total ); + if ( ! empty ( $response ) ) { + $response = $this->create_recurring_events( $response ); + } + + if ( ! empty( $response['events'] ) ) { + + // Sort events. + usort( $response['events'], function( $a, $b ) { + return $a['start_date_raw'] <=> $b['start_date_raw']; + } ); + + $this->set_pagination_data( count( $response['events'] ) ); + + $response['events'] = array_slice( $response['events'], $skip, get_option( 'posts_per_page' ) ); } return $response; diff --git a/models/page-events-search.php b/models/page-events-search.php index 64069019..8291d403 100644 --- a/models/page-events-search.php +++ b/models/page-events-search.php @@ -140,6 +140,7 @@ protected function get_events() : array { $paged = get_query_var( 'paged', 1 ); $skip = 0; + $count = 0; if ( $paged > 1 ) { $skip = ( $paged - 1 ) * get_option( 'posts_per_page' ); @@ -152,8 +153,6 @@ protected function get_events() : array { 'end' => $end_date, 'sort' => 'startDate', 'category_id' => get_field( 'category' ) ?? [], - 'size' => get_option( 'posts_per_page' ), - 'skip' => $skip, ]; $formatter = new EventzFormatter(); @@ -176,12 +175,22 @@ protected function get_events() : array { } } - if ( ! empty( $response['meta'] ) ) { - $this->set_pagination_data( $response['meta']->total ); + if ( ! empty( $response['events'] ) ) { + + // Sort and paginate events. + usort( $response['events'], function( $a, $b ) { + return $a['start_date_raw'] <=> $b['start_date_raw']; + } ); + + $this->set_pagination_data( count( $response['events'] ) ); + + $count = count( $response['events'] ); + + $response['events'] = array_slice( $response['events'], $skip, get_option( 'posts_per_page' ) ); } return [ - 'summary' => $this->get_results_text( $response['meta']->total ?? 0 ), + 'summary' => $this->get_results_text( $count ), 'posts' => $response['events'], ]; } @@ -227,12 +236,12 @@ protected function get_results_text( $event_count ) : ?string { protected function do_get_events( array $params ) : array { $event_data = $this->do_api_call( $params ); - if ( ! empty( $event_data['meta'] ) ) { - $this->set_pagination_data( $event_data['meta']->total ); - } - if ( ! empty( $event_data['events'] ) ) { + + $event_data = $this->create_recurring_events( $event_data ); + $event_data['events'] = ( new EventzFormatter() )->format_events( $event_data['events'] ); + $event_data['events'] = array_map( function ( $item ) { $item['short_description'] = wp_trim_words( $item['short_description'], 30 ); $item['location_icon'] = $item['is_virtual_event'] @@ -294,4 +303,51 @@ protected function set_pagination_data( int $event_count ) : void { $this->pagination->items = $event_count; $this->pagination->max_page = (int) ceil( $event_count / $per_page ); } + + /** + * Create recurring events as single item. + * + * @param array $events Events. + * + * @return void + */ + protected function create_recurring_events( $events ) { + + $recurring_events = []; + foreach( $events['events'] as $event ) { + if ( count( $event['dates'] ) > 1 ) { + foreach( $event['dates'] as $date ) { + $clone = $event; + // Split the string into date and time range + list($datePart, $timeRange) = explode(' ', $date['date'], 2); + + // Parse the date + $newDate = DateTime::createFromFormat('d.m.Y', $datePart); + + // Split the time range into start and end times + list($startTime, $endTime) = explode(' - ', $timeRange); + + // Parse the start and end times + $startDateTime = DateTime::createFromFormat('H.i', $startTime); + $startDateTime->setDate( $newDate->format('Y'), $newDate->format('m'), $newDate->format('d') ); + $endDateTime = DateTime::createFromFormat('H.i', $endTime); + $endDateTime->setDate( $newDate->format('Y'), $newDate->format('m'), $newDate->format('d') ); + + $clone['date'] = $newDate->format('d.m.Y'); + $clone['start_date_raw'] = $startDateTime; + $clone['end_date_raw'] = $endDateTime; + $clone['url'] = $event['url'].'&date='.urlencode( $date['date'] ); + + $recurring_events[] = $clone; + } + } else { + $recurring_events[] = $event; + } + } + + $events['events'] = $recurring_events; + + return $events; + + } } From 5efc7c3d97661d0286d5edfcd77d91a66689133a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20V=C3=A4nttinen?= Date: Fri, 10 Nov 2023 09:28:39 +0200 Subject: [PATCH 2/4] TMS-974: Recurring event functionalities --- lib/Eventz.php | 41 +++++++++++++++++-- lib/Traits/Sharing.php | 8 +++- models/page-event.php | 4 +- models/page-events-calendar.php | 4 -- models/page-events-search.php | 27 +++++++----- partials/page-events-calendar.dust | 6 +-- .../single-dynamic-event-info.dust | 8 ++-- 7 files changed, 69 insertions(+), 29 deletions(-) diff --git a/lib/Eventz.php b/lib/Eventz.php index 00cd53dc..e2962caa 100644 --- a/lib/Eventz.php +++ b/lib/Eventz.php @@ -103,17 +103,17 @@ public static function normalize_event( $event ) : array { 'date_title' => __( 'Dates', 'tms-theme-base' ), 'date' => static::get_event_date( $event ), 'dates' => static::get_event_dates( $event ), - 'recurring' => ! empty( $event->event->dates ), + 'recurring' => count( $event->event->dates ) > 1, 'time_title' => __( 'Time', 'tms-theme-base' ), 'time' => static::get_event_time( $event ), // Include raw dates for possible sorting. - 'start_date_raw' => static::get_as_datetime( $event->event->start ), - 'end_date_raw' => static::get_as_datetime( $event->event->end ), + 'start_date_raw' => static::get_as_datetime( $event->event->start ), + 'end_date_raw' => static::get_as_datetime( $event->event->end ), 'location_title' => __( 'Location', 'tms-theme-base' ), 'location' => static::get_event_location( $event ), 'price_title' => __( 'Price', 'tms-theme-base' ), 'price' => static::get_event_price_info( $event, $lang_key ), - 'provider_title' => __( 'Organizer', 'tms-theme-base' ), + 'provider_title' => __( 'Organizer', 'tms-theme-base' ), 'area_title' => __( 'Area', 'tms-theme-base' ), 'areas' => static::get_area_info( $event ), 'target_title' => __( 'Target', 'tms-theme-base' ), @@ -172,6 +172,24 @@ public static function get_event_date( $event ) { $end_time = static::get_as_datetime( $event->event->end ); $date_format = get_option( 'date_format' ); + // If date-parameter exists in url + if ( ! empty( $_GET['date'] ) ) { + list( $start_date, $end_date ) = explode( ' - ', $_GET['date'] ); + + $start_datetime = static::get_as_datetime( $start_date ); + $end_datetime = ! is_null($end_date) ? static::get_as_datetime( $end_date ) : ''; + + if ( $start_datetime && $end_datetime && $start_datetime->diff( $end_datetime )->days >= 1 ) { + return sprintf( + '%s - %s', + $start_datetime->format( $date_format ), + $end_datetime->format( $date_format ) + ); + } + + return $start_datetime->format( $date_format ); + } + if ( $start_time && $end_time && $start_time->diff( $end_time )->days >= 1 ) { return sprintf( '%s - %s', @@ -195,6 +213,21 @@ public static function get_event_time( $event ) { return null; } + // If time-parameter exists in url + if ( ! empty( $_GET['time'] ) ) { + list( $start_time, $end_time) = explode( ' - ', urldecode($_GET['time'] ) ); + + if ( $start_time && $end_time ) { + return sprintf( + '%s - %s', + $start_time, + $end_time + ); + } + + return $start_time; + } + $start_time = static::get_as_datetime( $event->event->start ); $end_time = static::get_as_datetime( $event->event->end ); $time_format = 'H.i'; diff --git a/lib/Traits/Sharing.php b/lib/Traits/Sharing.php index 4b6f8bf3..c069ef6e 100644 --- a/lib/Traits/Sharing.php +++ b/lib/Traits/Sharing.php @@ -64,6 +64,8 @@ protected function get_share_links() : ?array { $selected_channels = array_filter( $selected_channels, fn( $item ) => isset( $channels[ $item ] ) ); $current_post = get_queried_object(); $event_query_var = get_query_var( 'event-id' ); + $event_date = $_GET['date']; + $event_time = $_GET['time']; $overwrite_url = ''; if ( ! $current_post instanceof \WP_Post ) { @@ -72,8 +74,12 @@ protected function get_share_links() : ?array { // If the url has event-id url parameter set, use the whole url as share link // instead of getting the permalink of the post. + // Add also date & time-parameters if they exist in event url. if ( ! empty( $event_query_var ) ) { - $overwrite_url = get_permalink( $current_post->ID ) . '?event-id=' . $event_query_var; + $overwrite_url = get_permalink( $current_post->ID ) + . '?event-id=' . $event_query_var + . ( ! empty( $event_date ) ? '&date=' . $event_date : '' ) + . ( ! empty( $event_time ) ? '&time=' . urlencode( $event_time ) : '' ); } return array_map( function ( $selected_channel ) use ( $channels, $current_post, $overwrite_url ) { diff --git a/models/page-event.php b/models/page-event.php index 1b7e63e9..7062bedb 100644 --- a/models/page-event.php +++ b/models/page-event.php @@ -172,9 +172,9 @@ protected function seo_image_generator() { */ protected function alter_desc( $description ) { $event = $this->get_event(); - $event = Eventz::normalize_event( $event ); if ( $event ) { + $event = Eventz::normalize_event( $event ); $description = $event['short_description']; } @@ -297,7 +297,7 @@ protected function set_event() : void { * @return object|null */ protected function get_event() { - return $this->event; + return $this->event ?? null; } /** diff --git a/models/page-events-calendar.php b/models/page-events-calendar.php index 2b6efa16..3059d180 100644 --- a/models/page-events-calendar.php +++ b/models/page-events-calendar.php @@ -133,10 +133,6 @@ protected function get_events() : array { } } - if ( ! empty ( $response ) ) { - $response = $this->create_recurring_events( $response ); - } - if ( ! empty( $response['events'] ) ) { // Sort events. diff --git a/models/page-events-search.php b/models/page-events-search.php index 8291d403..c5121560 100644 --- a/models/page-events-search.php +++ b/models/page-events-search.php @@ -314,29 +314,34 @@ protected function set_pagination_data( int $event_count ) : void { protected function create_recurring_events( $events ) { $recurring_events = []; - foreach( $events['events'] as $event ) { + foreach ( $events['events'] as $event ) { if ( count( $event['dates'] ) > 1 ) { - foreach( $event['dates'] as $date ) { + foreach ( $event['dates'] as $date ) { $clone = $event; // Split the string into date and time range - list($datePart, $timeRange) = explode(' ', $date['date'], 2); + list( $datePart, $timeRange ) = explode( ' ', $date['date'], 2 ); // Parse the date - $newDate = DateTime::createFromFormat('d.m.Y', $datePart); + $newDate = DateTime::createFromFormat( 'd.m.Y', $datePart ); // Split the time range into start and end times - list($startTime, $endTime) = explode(' - ', $timeRange); + list( $startTime, $endTime ) = explode( ' - ', $timeRange ); // Parse the start and end times - $startDateTime = DateTime::createFromFormat('H.i', $startTime); - $startDateTime->setDate( $newDate->format('Y'), $newDate->format('m'), $newDate->format('d') ); - $endDateTime = DateTime::createFromFormat('H.i', $endTime); - $endDateTime->setDate( $newDate->format('Y'), $newDate->format('m'), $newDate->format('d') ); + $startDateTime = DateTime::createFromFormat( 'H.i', $startTime ); + $startDateTime->setDate( $newDate->format( 'Y' ), $newDate->format( 'm' ), $newDate->format( 'd' ) ); + $endDateTime = DateTime::createFromFormat( 'H.i', $endTime ); + $endDateTime->setDate( $newDate->format( 'Y' ), $newDate->format( 'm' ), $newDate->format( 'd' ) ); - $clone['date'] = $newDate->format('d.m.Y'); + $clone['date'] = $newDate->format( 'd.m.Y' ); $clone['start_date_raw'] = $startDateTime; $clone['end_date_raw'] = $endDateTime; - $clone['url'] = $event['url'].'&date='.urlencode( $date['date'] ); + $clone['url'] = $event['url'] . '&date=' . urlencode( $datePart ) . '&time=' . urlencode( $timeRange ); + $clone['time'] = sprintf( + '%s - %s', + $startDateTime->format( 'H.i' ), + $endDateTime->format( 'H.i' ) + ); $recurring_events[] = $clone; } diff --git a/partials/page-events-calendar.dust b/partials/page-events-calendar.dust index ffb8d3a6..b785e13d 100644 --- a/partials/page-events-calendar.dust +++ b/partials/page-events-calendar.dust @@ -12,7 +12,7 @@ {?description}
- {description|s} + {description|kses}
{/description} @@ -25,7 +25,7 @@ - {title|s} + {title|html} @@ -58,7 +58,7 @@ {^events}
- {no_results|s} + {no_results|kses}
{/events} diff --git a/partials/views/single-dynamic-event/single-dynamic-event-info.dust b/partials/views/single-dynamic-event/single-dynamic-event-info.dust index 96e3f2f8..9b07dd1b 100644 --- a/partials/views/single-dynamic-event/single-dynamic-event-info.dust +++ b/partials/views/single-dynamic-event/single-dynamic-event-info.dust @@ -5,10 +5,10 @@
{#event.normalized.dates} -
- {date|attr} -
- {/event.normalized.dates} +
+ {date|attr} +
+ {/event.normalized.dates}
{/event.normalized.date} From 659aff9536cf0a10eca998adb20fa4f0375db2e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20V=C3=A4nttinen?= Date: Mon, 13 Nov 2023 10:29:58 +0200 Subject: [PATCH 3/4] TMS-974: Rework recurring events creation --- lib/Eventz.php | 2 +- models/page-events-search.php | 54 ++++++++++++++++++++++++----------- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/lib/Eventz.php b/lib/Eventz.php index e2962caa..1052ca38 100644 --- a/lib/Eventz.php +++ b/lib/Eventz.php @@ -103,7 +103,7 @@ public static function normalize_event( $event ) : array { 'date_title' => __( 'Dates', 'tms-theme-base' ), 'date' => static::get_event_date( $event ), 'dates' => static::get_event_dates( $event ), - 'recurring' => count( $event->event->dates ) > 1, + 'recurring' => isset( $event->event->dates ) ? count( $event->event->dates ) > 1 : null, 'time_title' => __( 'Time', 'tms-theme-base' ), 'time' => static::get_event_time( $event ), // Include raw dates for possible sorting. diff --git a/models/page-events-search.php b/models/page-events-search.php index c5121560..fc5a177f 100644 --- a/models/page-events-search.php +++ b/models/page-events-search.php @@ -318,30 +318,50 @@ protected function create_recurring_events( $events ) { if ( count( $event['dates'] ) > 1 ) { foreach ( $event['dates'] as $date ) { $clone = $event; - // Split the string into date and time range - list( $datePart, $timeRange ) = explode( ' ', $date['date'], 2 ); - // Parse the date - $newDate = DateTime::createFromFormat( 'd.m.Y', $datePart ); + // Split the dates and times into parts + list( $startPart, $endPart ) = explode( ' - ', $date['date'], 2 ); + list( $startDate, $startTime ) = explode( ' ', $startPart, 2 ); - // Split the time range into start and end times - list( $startTime, $endTime ) = explode( ' - ', $timeRange ); + // Check if endPart includes date & time + if ( strpos($endPart, ' ') ) { + list( $endDate, $endTime ) = explode( ' ', $endPart, 2 ); + } + else { + $endTime = $endPart; + } + + // Parse the dates + $newStartDate = DateTime::createFromFormat( 'd.m.Y', $startDate ); + $newEndDate = $endDate ? DateTime::createFromFormat( 'd.m.Y', $endDate ) : null; // Parse the start and end times $startDateTime = DateTime::createFromFormat( 'H.i', $startTime ); - $startDateTime->setDate( $newDate->format( 'Y' ), $newDate->format( 'm' ), $newDate->format( 'd' ) ); - $endDateTime = DateTime::createFromFormat( 'H.i', $endTime ); - $endDateTime->setDate( $newDate->format( 'Y' ), $newDate->format( 'm' ), $newDate->format( 'd' ) ); - - $clone['date'] = $newDate->format( 'd.m.Y' ); + $startDateTime->setDate( $newStartDate->format( 'Y' ), $newStartDate->format( 'm' ), $newStartDate->format( 'd' ) ); + if ( $newEndDate ) { + $endDateTime = DateTime::createFromFormat( 'H.i', $endTime ); + $endDateTime->setDate( $newEndDate->format( 'Y' ), $newEndDate->format( 'm' ), $newEndDate->format( 'd' ) ); + } + + // Create time & date-ranges + if ( $endTime ) { + $timeRange = $startTime . ' - ' . $endTime; + } + else { + $timeRange = $startTime; + } + + if ( $newEndDate ) { + $dateRange = $newStartDate->format( 'd.m.Y' ) . ' - ' . $newEndDate->format( 'd.m.Y' ); + } + else { + $dateRange = $newStartDate->format( 'd.m.Y' ); + } + + $clone['date'] = $dateRange; $clone['start_date_raw'] = $startDateTime; $clone['end_date_raw'] = $endDateTime; - $clone['url'] = $event['url'] . '&date=' . urlencode( $datePart ) . '&time=' . urlencode( $timeRange ); - $clone['time'] = sprintf( - '%s - %s', - $startDateTime->format( 'H.i' ), - $endDateTime->format( 'H.i' ) - ); + $clone['url'] = $event['url'] . '&date=' . urlencode( $dateRange ) . '&time=' . urlencode( $timeRange ); $recurring_events[] = $clone; } From 7b58bb79e9b921249b65fc6a9ef69e00f700a0de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20V=C3=A4nttinen?= Date: Mon, 20 Nov 2023 15:08:24 +0200 Subject: [PATCH 4/4] TMS-974: Update changelog --- CHANGELOG.MD | 2 ++ style.css | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.MD b/CHANGELOG.MD index eefda4bd..9d569160 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +## [1.50.0] - 2023-11-21 + - TMS-974: Add recurring events to lists as single item. ## [1.49.0] - 2023-09-15 diff --git a/style.css b/style.css index 2ffc4d9c..6152480b 100644 --- a/style.css +++ b/style.css @@ -2,7 +2,7 @@ * Theme Name: TMS Theme Base * Description: Tampere Multisite Base Theme * Domain Path: /lang - * Version: 1.48.0 + * Version: 1.50.0 * Author: Geniem * Author URI: https://geniem.fi * Text Domain: tms-theme-base