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:
commit
f3bc795d9a
15 changed files with 3132 additions and 0 deletions
129
includes/class-eb4tec-organizer-sync.php
Normal file
129
includes/class-eb4tec-organizer-sync.php
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
<?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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue