Last active
February 27, 2026 07:31
-
-
Save chikaibeneme/18ff1f47f06005dcda003461e48e92fc to your computer and use it in GitHub Desktop.
resync events.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| function tecdev_fallback_sync_event_custom_tables( $event_id, &$reason = '' ) { | |
| global $wpdb; | |
| $event_id = absint( $event_id ); | |
| if ( ! $event_id ) { | |
| $reason = 'Fallback: invalid event ID.'; | |
| return false; | |
| } | |
| $start_date = (string) get_post_meta( $event_id, '_EventStartDate', true ); | |
| $end_date = (string) get_post_meta( $event_id, '_EventEndDate', true ); | |
| $start_utc = (string) get_post_meta( $event_id, '_EventStartDateUTC', true ); | |
| $end_utc = (string) get_post_meta( $event_id, '_EventEndDateUTC', true ); | |
| $timezone = (string) get_post_meta( $event_id, '_EventTimezone', true ); | |
| $duration = (int) get_post_meta( $event_id, '_EventDuration', true ); | |
| if ( '' === $start_date || '' === $end_date || '' === $start_utc || '' === $end_utc ) { | |
| $reason = 'Fallback: required event date meta is missing.'; | |
| return false; | |
| } | |
| if ( '' === $timezone ) { | |
| $timezone = 'UTC'; | |
| } | |
| if ( 0 === strpos( $timezone, 'UTC+' ) || 0 === strpos( $timezone, 'UTC-' ) ) { | |
| if ( 'UTC+0' === $timezone || 'UTC-0' === $timezone ) { | |
| $timezone = 'UTC'; | |
| } | |
| } | |
| if ( $duration <= 0 ) { | |
| $start_ts = strtotime( $start_utc ); | |
| $end_ts = strtotime( $end_utc ); | |
| if ( $start_ts && $end_ts && $end_ts > $start_ts ) { | |
| $duration = (int) ( $end_ts - $start_ts ); | |
| } else { | |
| $duration = 7200; | |
| } | |
| } | |
| $events_table = $wpdb->prefix . 'tec_events'; | |
| $occurrences_table = $wpdb->prefix . 'tec_occurrences'; | |
| $events_table_exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $events_table ) ); | |
| $occ_table_exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $occurrences_table ) ); | |
| if ( $events_table !== $events_table_exists || $occurrences_table !== $occ_table_exists ) { | |
| $reason = sprintf( 'Fallback: required tables not found for prefix %s.', $wpdb->prefix ); | |
| return false; | |
| } | |
| $event_hash = md5( implode( '|', [ $event_id, $start_date, $end_date, $timezone, $start_utc, $end_utc, $duration ] ) ); | |
| $existing_event_id = (int) $wpdb->get_var( | |
| $wpdb->prepare( "SELECT event_id FROM {$events_table} WHERE post_id = %d LIMIT 1", $event_id ) | |
| ); | |
| $event_row = [ | |
| 'post_id' => $event_id, | |
| 'start_date' => $start_date, | |
| 'end_date' => $end_date, | |
| 'timezone' => $timezone, | |
| 'start_date_utc' => $start_utc, | |
| 'end_date_utc' => $end_utc, | |
| 'duration' => $duration, | |
| 'hash' => $event_hash, | |
| ]; | |
| if ( $existing_event_id > 0 ) { | |
| $updated = $wpdb->update( $events_table, $event_row, [ 'event_id' => $existing_event_id ] ); | |
| if ( false === $updated ) { | |
| $reason = 'Fallback: failed to update wp_tec_events row. DB: ' . $wpdb->last_error; | |
| return false; | |
| } | |
| $event_table_id = $existing_event_id; | |
| } else { | |
| $inserted = $wpdb->insert( $events_table, $event_row ); | |
| if ( false === $inserted ) { | |
| $reason = 'Fallback: failed to insert wp_tec_events row. DB: ' . $wpdb->last_error; | |
| return false; | |
| } | |
| $event_table_id = (int) $wpdb->insert_id; | |
| } | |
| $wpdb->delete( $occurrences_table, [ 'post_id' => $event_id ], [ '%d' ] ); | |
| $occurrence_hash = md5( implode( '|', [ $event_table_id, $event_id, $start_utc, $end_utc ] ) ); | |
| $occurrence_row = [ | |
| 'event_id' => $event_table_id, | |
| 'post_id' => $event_id, | |
| 'start_date' => $start_date, | |
| 'start_date_utc' => $start_utc, | |
| 'end_date' => $end_date, | |
| 'end_date_utc' => $end_utc, | |
| 'duration' => $duration, | |
| 'hash' => $occurrence_hash, | |
| ]; | |
| $occurrence_inserted = $wpdb->insert( $occurrences_table, $occurrence_row ); | |
| if ( false === $occurrence_inserted ) { | |
| $reason = 'Fallback: failed to insert wp_tec_occurrences row. DB: ' . $wpdb->last_error; | |
| return false; | |
| } | |
| $reason = 'Fallback SQL sync applied.'; | |
| return true; | |
| } | |
| function tecdev_sync_event_custom_tables( $event_id, &$reason = '' ) { | |
| $event_id = absint( $event_id ); | |
| if ( ! $event_id ) { | |
| $reason = 'Invalid event ID.'; | |
| return false; | |
| } | |
| $post = get_post( $event_id ); | |
| if ( ! ( $post instanceof WP_Post ) ) { | |
| $reason = 'Post not found.'; | |
| return false; | |
| } | |
| if ( 'tribe_events' !== $post->post_type ) { | |
| $reason = sprintf( 'Post type is %s, expected tribe_events.', $post->post_type ); | |
| return false; | |
| } | |
| $start = get_post_meta( $event_id, '_EventStartDate', true ); | |
| $end = get_post_meta( $event_id, '_EventEndDate', true ); | |
| if ( empty( $start ) || empty( $end ) ) { | |
| $reason = 'Missing _EventStartDate/_EventEndDate meta values.'; | |
| return false; | |
| } | |
| if ( ! class_exists( '\\TEC\\Events\\Custom_Tables\\V1\\Updates\\Events' ) || ! function_exists( 'tribe' ) ) { | |
| $reason = 'TEC updater class or tribe() helper is unavailable.'; | |
| if ( tecdev_fallback_sync_event_custom_tables( $event_id, $fallback_reason ) ) { | |
| $reason .= ' ' . $fallback_reason; | |
| return true; | |
| } | |
| if ( ! empty( $fallback_reason ) ) { | |
| $reason .= ' ' . $fallback_reason; | |
| } | |
| return false; | |
| } | |
| try { | |
| $updater = tribe( '\\TEC\\Events\\Custom_Tables\\V1\\Updates\\Events' ); | |
| if ( ! is_object( $updater ) ) { | |
| $updater = new \TEC\Events\Custom_Tables\V1\Updates\Events(); | |
| } | |
| if ( ! is_object( $updater ) || ! method_exists( $updater, 'update' ) ) { | |
| $reason = 'Could not initialize TEC updater service.'; | |
| return false; | |
| } | |
| $updated = (bool) $updater->update( $event_id ); | |
| if ( method_exists( $updater, 'rebuild_known_range' ) ) { | |
| $updater->rebuild_known_range(); | |
| } | |
| if ( ! $updated ) { | |
| $reason = 'TEC updater returned false (event data could not be upserted).'; | |
| if ( tecdev_fallback_sync_event_custom_tables( $event_id, $fallback_reason ) ) { | |
| $reason = $reason . ' ' . $fallback_reason; | |
| return true; | |
| } | |
| if ( ! empty( $fallback_reason ) ) { | |
| $reason = $reason . ' ' . $fallback_reason; | |
| } | |
| } | |
| return $updated; | |
| } catch ( Throwable $throwable ) { | |
| $reason = $throwable->getMessage(); | |
| if ( tecdev_fallback_sync_event_custom_tables( $event_id, $fallback_reason ) ) { | |
| $reason .= ' ' . $fallback_reason; | |
| return true; | |
| } | |
| if ( ! empty( $fallback_reason ) ) { | |
| $reason .= ' ' . $fallback_reason; | |
| } | |
| return false; | |
| } | |
| } | |
| add_action( 'save_post_tribe_events', function ( $post_id, $post, $update ) { | |
| if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) { | |
| return; | |
| } | |
| tecdev_sync_event_custom_tables( $post_id ); | |
| }, 100, 3 ); | |
| add_action( 'admin_init', function () { | |
| if ( ! is_admin() || ! current_user_can( 'manage_options' ) ) { | |
| return; | |
| } | |
| if ( empty( $_GET['tecdev_resync_events'] ) ) { | |
| return; | |
| } | |
| $raw_ids = sanitize_text_field( wp_unslash( $_GET['tecdev_resync_events'] ) ); | |
| $ids = array_filter( array_map( 'absint', array_map( 'trim', explode( ',', $raw_ids ) ) ) ); | |
| if ( empty( $ids ) ) { | |
| return; | |
| } | |
| $synced = 0; | |
| $failed = []; | |
| foreach ( $ids as $id ) { | |
| $reason = ''; | |
| if ( tecdev_sync_event_custom_tables( $id, $reason ) ) { | |
| $synced++; | |
| } else { | |
| $failed[ (int) $id ] = $reason ?: 'Unknown failure.'; | |
| } | |
| } | |
| if ( ! empty( $failed ) ) { | |
| set_transient( 'tecdev_resync_report_' . get_current_user_id(), $failed, 10 * MINUTE_IN_SECONDS ); | |
| } | |
| wp_safe_redirect( | |
| add_query_arg( | |
| [ | |
| 'post_type' => 'tribe_events', | |
| 'tecdev_resync_done' => (int) $synced, | |
| 'tecdev_resync_fail' => count( $failed ), | |
| ], | |
| admin_url( 'edit.php' ) | |
| ) | |
| ); | |
| exit; | |
| } ); | |
| add_action( 'admin_notices', function () { | |
| if ( ! is_admin() || ! current_user_can( 'manage_options' ) ) { | |
| return; | |
| } | |
| if ( ! isset( $_GET['post_type'] ) || 'tribe_events' !== sanitize_key( wp_unslash( $_GET['post_type'] ) ) ) { | |
| return; | |
| } | |
| if ( ! isset( $_GET['tecdev_resync_done'] ) ) { | |
| return; | |
| } | |
| $done = absint( $_GET['tecdev_resync_done'] ); | |
| $fails = isset( $_GET['tecdev_resync_fail'] ) ? absint( $_GET['tecdev_resync_fail'] ) : 0; | |
| echo '<div class="notice notice-info"><p>'; | |
| echo esc_html( sprintf( 'TEC resync complete. Synced: %d. Failed: %d.', $done, $fails ) ); | |
| echo '</p></div>'; | |
| $failed = get_transient( 'tecdev_resync_report_' . get_current_user_id() ); | |
| if ( ! empty( $failed ) && is_array( $failed ) ) { | |
| echo '<div class="notice notice-warning"><p><strong>TEC resync failures:</strong></p><ul style="margin-left:1.25em; list-style:disc;">'; | |
| foreach ( $failed as $id => $reason ) { | |
| echo '<li>' . esc_html( sprintf( 'Event %d: %s', (int) $id, (string) $reason ) ) . '</li>'; | |
| } | |
| echo '</ul></div>'; | |
| delete_transient( 'tecdev_resync_report_' . get_current_user_id() ); | |
| } | |
| } ); | |
| add_action( 'init', function () { | |
| add_rewrite_rule( '^event/([^/]+)/([0-9]{4}-[0-9]{2}-[0-9]{2})/([0-9]+)/?$', 'index.php?tribe_events=$matches[1]&eventDate=$matches[2]&eventSequence=$matches[3]', 'top' ); | |
| add_rewrite_rule( '^event/([^/]+)/([0-9]{4}-[0-9]{2}-[0-9]{2})/?$', 'index.php?tribe_events=$matches[1]&eventDate=$matches[2]', 'top' ); | |
| add_rewrite_rule( '^event/([^/]+)/?$', 'index.php?tribe_events=$matches[1]', 'top' ); | |
| }, 20 ); | |
| add_action( 'admin_init', function () { | |
| $rewrite_version = '2'; | |
| if ( get_option( 'tecdev_single_event_rewrite_version' ) === $rewrite_version ) { | |
| return; | |
| } | |
| add_rewrite_rule( '^event/([^/]+)/([0-9]{4}-[0-9]{2}-[0-9]{2})/([0-9]+)/?$', 'index.php?tribe_events=$matches[1]&eventDate=$matches[2]&eventSequence=$matches[3]', 'top' ); | |
| add_rewrite_rule( '^event/([^/]+)/([0-9]{4}-[0-9]{2}-[0-9]{2})/?$', 'index.php?tribe_events=$matches[1]&eventDate=$matches[2]', 'top' ); | |
| add_rewrite_rule( '^event/([^/]+)/?$', 'index.php?tribe_events=$matches[1]', 'top' ); | |
| flush_rewrite_rules( false ); | |
| update_option( 'tecdev_single_event_rewrite_version', $rewrite_version, false ); | |
| } ); | |
| add_action( 'template_redirect', function () { | |
| if ( ! is_404() ) { | |
| return; | |
| } | |
| $request_uri = isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : ''; | |
| $path = (string) wp_parse_url( $request_uri, PHP_URL_PATH ); | |
| $path = trim( $path, '/' ); | |
| if ( ! preg_match( '#^event/([^/]+)/([0-9]{4}-[0-9]{2}-[0-9]{2})(?:/([0-9]+))?$#', $path, $matches ) ) { | |
| return; | |
| } | |
| $slug = sanitize_title( $matches[1] ); | |
| $date_ymd = sanitize_text_field( $matches[2] ); | |
| if ( empty( $slug ) || empty( $date_ymd ) ) { | |
| return; | |
| } | |
| $parent = get_page_by_path( $slug, OBJECT, 'tribe_events' ); | |
| if ( ! ( $parent instanceof WP_Post ) ) { | |
| return; | |
| } | |
| $occurrence_query = new WP_Query( | |
| [ | |
| 'post_type' => 'tribe_events', | |
| 'post_status' => [ 'publish', 'private' ], | |
| 'post_parent' => (int) $parent->ID, | |
| 'posts_per_page' => 1, | |
| 'fields' => 'ids', | |
| 'meta_query' => [ | |
| [ | |
| 'key' => '_EventStartDate', | |
| 'value' => $date_ymd, | |
| 'compare' => 'LIKE', | |
| ], | |
| ], | |
| ] | |
| ); | |
| if ( ! empty( $occurrence_query->posts ) ) { | |
| $target = get_permalink( (int) $occurrence_query->posts[0] ); | |
| if ( ! empty( $target ) ) { | |
| wp_safe_redirect( $target, 302 ); | |
| exit; | |
| } | |
| } | |
| $parent_url = get_permalink( $parent->ID ); | |
| if ( ! empty( $parent_url ) ) { | |
| wp_safe_redirect( $parent_url, 302 ); | |
| exit; | |
| } | |
| }, 1 ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment