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.
129 lines
3.7 KiB
PHP
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 );
|
|
}
|
|
}
|
|
}
|