eventbrite-for-the-events-c.../includes/class-eb4tec-organizer-sync.php
Laurence Horrocks-Barlow f3bc795d9a 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.
2026-05-17 08:48:04 +01:00

129 lines
3.7 KiB
PHP

<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
final class EB4TEC_Organizer_Sync {
public function __construct( private readonly EB4TEC_API_Client $api ) {}
public function pull_organizer( string $eb_organizer_id ): int|WP_Error {
if ( empty( $eb_organizer_id ) ) {
return 0;
}
$result = $this->api->get_organizer( $eb_organizer_id );
if ( is_wp_error( $result ) ) {
return $result;
}
$existing_id = $this->find_tec_organizer( $eb_organizer_id );
$name = sanitize_text_field( $result['name'] ?? '' );
$post_args = [
'post_title' => $name ?: __( 'Untitled Organizer', 'eb4tec' ),
'post_content' => wp_kses_post( $result['description']['html'] ?? '' ),
'post_type' => 'tribe_organizer',
'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;
}
update_post_meta( $post_id, '_eb4tec_organizer_id', sanitize_text_field( $eb_organizer_id ) );
if ( ! empty( $result['website'] ) ) {
update_post_meta( $post_id, '_OrganizerWebsite', esc_url_raw( $result['website'] ) );
}
if ( ! empty( $result['twitter'] ) ) {
update_post_meta( $post_id, '_OrganizerTwitter', sanitize_text_field( $result['twitter'] ) );
}
// Sideload logo if not already set.
if ( ! has_post_thumbnail( $post_id ) && ! empty( $result['logo']['url'] ) ) {
$this->sideload_image( $result['logo']['url'], $post_id, $name );
}
return $post_id;
}
public function push_organizer( 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_organizer_id = get_post_meta( $post_id, '_eb4tec_organizer_id', true );
$post = get_post( $post_id );
if ( ! $post ) {
return new WP_Error( 'eb4tec_no_post', __( 'Organizer post not found.', 'eb4tec' ) );
}
$website = (string) get_post_meta( $post_id, '_OrganizerWebsite', true );
$twitter = (string) get_post_meta( $post_id, '_OrganizerTwitter', true );
$body = [
'organizer' => [
'name' => $post->post_title,
'website' => $website,
'twitter' => $twitter,
],
];
if ( $eb_organizer_id ) {
$result = $this->api->update_organizer( $eb_organizer_id, $body );
} else {
$result = $this->api->create_organizer( $org_id, $body );
}
if ( is_wp_error( $result ) ) {
return $result;
}
$new_id = $result['id'] ?? '';
if ( $new_id ) {
update_post_meta( $post_id, '_eb4tec_organizer_id', sanitize_text_field( $new_id ) );
}
return $new_id ?: new WP_Error( 'eb4tec_no_organizer_id', __( 'Eventbrite did not return an organizer ID.', 'eb4tec' ) );
}
public function find_tec_organizer( string $eb_organizer_id ): int {
$query = new WP_Query( [
'post_type' => 'tribe_organizer',
'post_status' => 'publish',
'posts_per_page' => 1,
'fields' => 'ids',
'meta_query' => [ [
'key' => '_eb4tec_organizer_id',
'value' => $eb_organizer_id,
] ],
] );
return $query->posts[0] ?? 0;
}
private function sideload_image( string $url, int $post_id, string $title ): void {
if ( ! function_exists( 'media_sideload_image' ) ) {
require_once ABSPATH . 'wp-admin/includes/media.php';
require_once ABSPATH . 'wp-admin/includes/file.php';
require_once ABSPATH . 'wp-admin/includes/image.php';
}
$attachment_id = media_sideload_image( $url, $post_id, $title, 'id' );
if ( ! is_wp_error( $attachment_id ) ) {
set_post_thumbnail( $post_id, $attachment_id );
}
}
}