token = (string) get_option( 'eb4tec_api_token', '' ); } // --------------------------------------------------------------------------- // Credentials / user // --------------------------------------------------------------------------- public function get_user_me(): array|WP_Error { return $this->get( 'users/me/', cacheable: false ); } // --------------------------------------------------------------------------- // Events // --------------------------------------------------------------------------- public function get_organization_events( string $org_id, int $page = 1 ): array|WP_Error { return $this->get( "organizations/{$org_id}/events/", [ 'status' => 'draft,live,started,ended,completed', 'expand' => 'venue,organizer,ticket_classes', 'page' => $page, 'page_size' => 50, 'order_by' => 'start_asc', ] ); } public function get_event( string $eb_event_id ): array|WP_Error { return $this->get( "events/{$eb_event_id}/", [ 'expand' => 'venue,organizer,ticket_classes' ] ); } public function create_event( array $data ): array|WP_Error { $org_id = (string) get_option( 'eb4tec_org_id', '' ); return $this->post( "organizations/{$org_id}/events/", $data ); } public function update_event( string $eb_event_id, array $data ): array|WP_Error { return $this->post( "events/{$eb_event_id}/", $data ); } public function publish_event( string $eb_event_id ): array|WP_Error { return $this->post( "events/{$eb_event_id}/publish/", [] ); } public function unpublish_event( string $eb_event_id ): array|WP_Error { return $this->post( "events/{$eb_event_id}/unpublish/", [] ); } // --------------------------------------------------------------------------- // Ticket classes // --------------------------------------------------------------------------- public function get_ticket_classes( string $eb_event_id ): array|WP_Error { return $this->get( "events/{$eb_event_id}/ticket_classes/" ); } public function create_ticket_class( string $eb_event_id, array $data ): array|WP_Error { return $this->post( "events/{$eb_event_id}/ticket_classes/", $data ); } public function update_ticket_class( string $eb_event_id, string $class_id, array $data ): array|WP_Error { return $this->post( "events/{$eb_event_id}/ticket_classes/{$class_id}/", $data ); } // --------------------------------------------------------------------------- // Attendees // --------------------------------------------------------------------------- public function create_attendee( string $eb_event_id, array $data ): array|WP_Error { return $this->post( "events/{$eb_event_id}/attendees/", $data ); } public function get_attendees( string $eb_event_id, int $page = 1 ): array|WP_Error { return $this->get( "events/{$eb_event_id}/attendees/", [ 'page' => $page, 'page_size' => 50, 'expand' => 'ticket_class', ], cacheable: false ); } // --------------------------------------------------------------------------- // Venues // --------------------------------------------------------------------------- public function get_venue( string $venue_id ): array|WP_Error { return $this->get( "venues/{$venue_id}/" ); } public function create_venue( string $org_id, array $data ): array|WP_Error { return $this->post( "organizations/{$org_id}/venues/", $data ); } public function update_venue( string $venue_id, array $data ): array|WP_Error { return $this->post( "venues/{$venue_id}/", $data ); } // --------------------------------------------------------------------------- // Organizers // --------------------------------------------------------------------------- public function get_organizer( string $organizer_id ): array|WP_Error { return $this->get( "organizers/{$organizer_id}/" ); } public function create_organizer( string $org_id, array $data ): array|WP_Error { return $this->post( "organizations/{$org_id}/organizers/", $data ); } public function update_organizer( string $organizer_id, array $data ): array|WP_Error { return $this->post( "organizers/{$organizer_id}/", $data ); } // --------------------------------------------------------------------------- // Webhooks // --------------------------------------------------------------------------- public function create_webhook( array $data ): array|WP_Error { $org_id = (string) get_option( 'eb4tec_org_id', '' ); return $this->post( "organizations/{$org_id}/webhooks/", $data ); } public function list_webhooks(): array|WP_Error { $org_id = (string) get_option( 'eb4tec_org_id', '' ); return $this->get( "organizations/{$org_id}/webhooks/", cacheable: false ); } public function delete_webhook( string $webhook_id ): array|WP_Error { return $this->delete_request( "webhooks/{$webhook_id}/" ); } // --------------------------------------------------------------------------- // Cache helpers // --------------------------------------------------------------------------- public function bust_cache( string $endpoint ): void { delete_transient( $this->cache_key( $endpoint, [] ) ); } // --------------------------------------------------------------------------- // HTTP internals // --------------------------------------------------------------------------- private function get( string $endpoint, array $query = [], bool $cacheable = true ): array|WP_Error { if ( $cacheable ) { $key = $this->cache_key( $endpoint, $query ); $cached = get_transient( $key ); if ( false !== $cached ) { return $cached; } } $url = self::BASE_URL . $endpoint; $result = $this->request( 'GET', $url, [ 'body' => $query ] ); if ( ! is_wp_error( $result ) && $cacheable ) { set_transient( $key, $result, self::CACHE_TTL ); } return $result; } private function post( string $endpoint, array $body ): array|WP_Error { $url = self::BASE_URL . $endpoint; return $this->request( 'POST', $url, [ 'body' => wp_json_encode( $body ), 'content-type' => 'application/json', ] ); } private function delete_request( string $endpoint ): array|WP_Error { $url = self::BASE_URL . $endpoint; return $this->request( 'DELETE', $url, [] ); } private function request( string $method, string $url, array $args ): array|WP_Error { if ( empty( $this->token ) ) { return new WP_Error( 'eb4tec_no_token', __( 'Eventbrite API token is not configured.', 'eb4tec' ) ); } $defaults = [ 'method' => $method, 'timeout' => 15, 'headers' => [ 'Authorization' => 'Bearer ' . $this->token, 'Content-Type' => 'application/json', 'Accept' => 'application/json', ], ]; $args = array_merge( $defaults, $args ); $response = wp_remote_request( $url, $args ); if ( is_wp_error( $response ) ) { return $response; } $status = wp_remote_retrieve_response_code( $response ); $body = wp_remote_retrieve_body( $response ); // Track rate limit. $remaining = wp_remote_retrieve_header( $response, 'x-ratelimit-remaining' ); if ( '' !== $remaining ) { $this->rate_limit_remaining = (int) $remaining; if ( $this->rate_limit_remaining <= 10 ) { set_transient( 'eb4tec_rate_limit_warning', true, 60 ); } } $decoded = json_decode( $body, true ); if ( $status < 200 || $status >= 300 ) { $message = $decoded['error_description'] ?? $decoded['error'] ?? __( 'Unknown Eventbrite API error.', 'eb4tec' ); return new WP_Error( 'eb4tec_api_error', $message, [ 'status' => $status, 'response' => $decoded ] ); } return $decoded ?? []; } private function cache_key( string $endpoint, array $query ): string { return 'eb4tec_' . md5( $endpoint . serialize( $query ) ); } public function get_rate_limit_remaining(): int { return $this->rate_limit_remaining; } }