Initial release of Eventbrite for The Events Calendar (v1.0.0)

Bidirectional sync between Eventbrite and The Events Calendar, with
WooCommerce ticket purchasing that bypasses Eventbrite's processing
fees by registering buyers as free attendees via API. Includes venue/
organizer sync, QR code ticket generation, attendee management with
CSV export, scheduled sync via WP-Cron, and real-time Eventbrite
webhooks.
This commit is contained in:
Laurence Horrocks-Barlow 2026-05-17 08:48:04 +01:00
commit f3bc795d9a
15 changed files with 3132 additions and 0 deletions

View file

@ -0,0 +1,125 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
final class EB4TEC_Venue_Sync {
public function __construct( private readonly EB4TEC_API_Client $api ) {}
public function pull_venue( string $eb_venue_id ): int|WP_Error {
if ( empty( $eb_venue_id ) ) {
return 0;
}
$result = $this->api->get_venue( $eb_venue_id );
if ( is_wp_error( $result ) ) {
return $result;
}
$existing_id = $this->find_tec_venue( $eb_venue_id );
$name = sanitize_text_field( $result['name'] ?? '' );
$address = $result['address'] ?? [];
$post_args = [
'post_title' => $name ?: __( 'Untitled Venue', 'eb4tec' ),
'post_type' => 'tribe_venue',
'post_status' => 'publish',
];
if ( $existing_id ) {
$post_args['ID'] = $existing_id;
$post_id = wp_update_post( $post_args, true );
} else {
$post_id = wp_insert_post( $post_args, true );
}
if ( is_wp_error( $post_id ) ) {
return $post_id;
}
$this->save_venue_meta( $post_id, $eb_venue_id, $address, $result );
return $post_id;
}
public function push_venue( int $post_id ): string|WP_Error {
$org_id = (string) get_option( 'eb4tec_org_id', '' );
if ( empty( $org_id ) ) {
return new WP_Error( 'eb4tec_no_org', __( 'Eventbrite organization ID not configured.', 'eb4tec' ) );
}
$eb_venue_id = get_post_meta( $post_id, '_eb4tec_venue_id', true );
$post = get_post( $post_id );
if ( ! $post ) {
return new WP_Error( 'eb4tec_no_post', __( 'Venue post not found.', 'eb4tec' ) );
}
$body = [
'venue' => [
'name' => $post->post_title,
'address' => [
'address_1' => (string) get_post_meta( $post_id, '_VenueAddress', true ),
'city' => (string) get_post_meta( $post_id, '_VenueCity', true ),
'region' => (string) get_post_meta( $post_id, '_VenueStateProvince', true ),
'postal_code' => (string) get_post_meta( $post_id, '_VenueZip', true ),
'country' => (string) get_post_meta( $post_id, '_VenueCountry', true ),
],
],
];
if ( $eb_venue_id ) {
$result = $this->api->update_venue( $eb_venue_id, $body );
} else {
$result = $this->api->create_venue( $org_id, $body );
}
if ( is_wp_error( $result ) ) {
return $result;
}
$new_id = $result['id'] ?? '';
if ( $new_id ) {
update_post_meta( $post_id, '_eb4tec_venue_id', sanitize_text_field( $new_id ) );
}
return $new_id ?: new WP_Error( 'eb4tec_no_venue_id', __( 'Eventbrite did not return a venue ID.', 'eb4tec' ) );
}
public function find_tec_venue( string $eb_venue_id ): int {
$query = new WP_Query( [
'post_type' => 'tribe_venue',
'post_status' => 'publish',
'posts_per_page' => 1,
'fields' => 'ids',
'meta_query' => [ [
'key' => '_eb4tec_venue_id',
'value' => $eb_venue_id,
] ],
] );
return $query->posts[0] ?? 0;
}
private function save_venue_meta( int $post_id, string $eb_venue_id, array $address, array $result ): void {
update_post_meta( $post_id, '_eb4tec_venue_id', sanitize_text_field( $eb_venue_id ) );
update_post_meta( $post_id, '_eb4tec_venue_last_synced', time() );
update_post_meta( $post_id, '_VenueAddress', sanitize_text_field( $address['address_1'] ?? '' ) );
update_post_meta( $post_id, '_VenueCity', sanitize_text_field( $address['city'] ?? '' ) );
update_post_meta( $post_id, '_VenueStateProvince', sanitize_text_field( $address['region'] ?? '' ) );
update_post_meta( $post_id, '_VenueZip', sanitize_text_field( $address['postal_code'] ?? '' ) );
update_post_meta( $post_id, '_VenueCountry', sanitize_text_field( $address['country'] ?? '' ) );
$lat = $address['latitude'] ?? '';
$lng = $address['longitude'] ?? '';
if ( $lat ) {
update_post_meta( $post_id, '_VenueGeoLat', sanitize_text_field( $lat ) );
}
if ( $lng ) {
update_post_meta( $post_id, '_VenueGeoLng', sanitize_text_field( $lng ) );
}
}
}