| Current File : /home/digitaw/www/wp-content/plugins/event-tickets/src/Tribe/Data_API.php |
<?php
/**
* Class to connect ticketing information requests with ticket provider
*
* Class Tribe__Tickets__Data_API
*/
class Tribe__Tickets__Data_API {
protected $ticket_types = [];
protected $ticket_class = [];
/**
* Class constructor
*/
public function __construct() {
$this->setup_data();
}
/**
* Setup activate ticket classes and field for data api
*/
protected function setup_data() {
/** @var Tribe__Tickets__Status__Manager $status_mgr */
$status_mgr = tribe( 'tickets.status' );
foreach ( Tribe__Tickets__Tickets::modules() as $module_class => $module_instance ) {
$provider = call_user_func( array( $module_class, 'get_instance' ) );
/**
* The usage of plain `$module_class::ATTENDEE_EVENT_KEY` will throw a `T_PAAMAYIM_NEKUDOTAYIM`
* when using PHP 5.2, which is a fatal.
*
* So we have to construct the constant name using a string and use the `constant` function.
*/
$types['order'] = constant( "$module_class::ORDER_OBJECT" );
$types['product'] = $provider->ticket_object;
$types['ticket'] = constant( "$module_class::ATTENDEE_OBJECT" );
if ( 'Tribe__Tickets__RSVP' === $module_class ) {
$types['ticket'] = $provider->ticket_object;
}
$types['attendee'] = constant( "$module_class::ATTENDEE_OBJECT" );
$this->ticket_class[ $module_class ] = [];
foreach ( $types as $key => $value ) {
$this->ticket_types[ $key ][] = $value;
$this->ticket_class[ $module_class ][ $key ] = $value;
}
$this->ticket_class[ $module_class ]['tribe_for_event'] = $provider->get_event_key();
$this->ticket_class[ $module_class ]['event_id_key'] = constant( "$module_class::ATTENDEE_EVENT_KEY" );
$this->ticket_class[ $module_class ]['order_id_key'] = constant( "$module_class::ATTENDEE_ORDER_KEY" );
$this->ticket_class[ $module_class ]['slug'] = $status_mgr->get_provider_slug( $module_class );
}
$this->ticket_types['events'][] = class_exists( 'Tribe__Events__Main' ) ? Tribe__Events__Main::POSTTYPE : '';
}
/**
* Detect what is available in the custom post type by the id passed to it
*
* @param null $post id or post object.
*
* @return array|bool An array of available information about the object and the tribe_tickets_tickets class to use
*/
public function detect_by_id( $post = null ) {
// only the rsvp order key is non numeric.
if ( is_object( $post ) && ! empty( $post->ID ) ) {
$cpt = get_post_type( $post->ID );
$post = (int) $post->ID;
} elseif ( ! is_numeric( $post ) ) {
$post = esc_attr( $post );
$cpt = $this->check_rsvp_order_key_exists( $post );
} else {
$post = absint( $post );
$cpt = get_post_type( $post );
}
// If no custom post type.
if ( ! $cpt ) {
return false;
}
$cpt_arr = [];
$cpt_arr['post_type'] = $cpt;
foreach ( $this->ticket_types as $type => $cpts ) {
if ( in_array( $cpt, $cpts ) ) {
$cpt_arr[] = $type;
}
}
foreach ( $this->ticket_class as $classes => $cpts ) {
if ( in_array( $cpt, $cpts ) ) {
$cpt_arr['class'] = $classes;
}
}
return $cpt_arr;
}
/**
* Return Array of Event IDs when passed an Order, Ticket, or Attendee ID
*
* @param int|WP_Post $post_id The Post ID of the event.
*
* @return array
*/
public function get_event_ids( $post_id ) {
$services = $this->detect_by_id( $post_id );
if ( ! is_array( $services ) ) {
$services = array();
}
// if this id is not an order id or a ticket id return
$is_ticket_related = array_intersect( array( 'order', 'ticket', 'attendee', 'product' ), $services );
if ( ! $is_ticket_related ) {
return array();
}
// if no post type or module class return
if ( empty( $services['post_type'] ) || empty( $services['class'] ) ) {
return array();
}
$module_class = ! empty( $services['class'] ) ? $services['class'] : '';
/**
* if we have a rsvp order with a unique rsvp order key
* change $post_id to the first rsvp post's id
*/
if ( ! is_numeric( $post_id ) && 'Tribe__Tickets__RSVP' === $module_class ) {
$post_id = $this->get_rsvp_post_id_from_order_key( $post_id );
}
$event_id_key = $this->ticket_class[ $module_class ]['event_id_key'];
$event_ids = array();
$is_product = array_intersect( array( 'product' ), $services );
if ( $is_product ) {
$tribe_for_event = $this->ticket_class[ $module_class ]['tribe_for_event'];
$event_ids[] = (int) get_post_meta( $post_id, $tribe_for_event, true );
return $event_ids;
}
// if rsvp or a ticket id get the connected id field
$is_ticket_attendee = array_intersect( array( 'ticket', 'attendee' ), $services );
if ( 'Tribe__Tickets__RSVP' === $module_class || $is_ticket_attendee ) {
$event_ids[] = (int) get_post_meta( $post_id, $event_id_key, true );
return $event_ids;
}
$ticket_cpt = $this->ticket_class[ $module_class ]['ticket'];
$order_id_key = $this->ticket_class[ $module_class ]['order_id_key'];
if ( ! $order_id_key ) {
return array();
}
$order_tickets = get_posts( array(
'post_type' => $ticket_cpt,
'meta_key' => $order_id_key,
'meta_value' => $post_id,
'posts_per_page' => -1,
) );
foreach ( $order_tickets as $ticket ) {
$event_id = get_post_meta( $ticket->ID, $event_id_key, true );
if ( ! in_array( $event_id, $event_ids ) ) {
$event_ids[] = (int) $event_id;
}
}
return $event_ids;
}
/**
* Return Ticket Provider by Order, Product, Attendee, or Ticket ID.
*
* @since 4.5
* @since 4.12.3 Use new helper method to account for possibly inactive ticket provider.
*
* @param int|string $post_id
*
* @return Tribe__Tickets__Tickets|false Ticket provider instance or False if provider is not active.
*/
public function get_ticket_provider( $post_id ) {
$services = $this->detect_by_id( $post_id );
if ( empty( $services['class'] ) ) {
return false;
}
return Tribe__Tickets__Tickets::get_ticket_provider_instance( $services['class'] );
}
/**
* Get the Providers for a Post
*
* @since 4.11.0
*
* @param int $post_id the id of the post
*
* @return array an array of providers
*/
public function get_providers_for_post( $post_id ) {
$providers = [];
$modules = $this->ticket_class;
foreach ( $modules as $class => $module ) {
$obj = call_user_func( [ $class, 'get_instance' ] );
$provider_tickets = $obj->get_tickets( $post_id );
if ( ! empty( $provider_tickets ) ) {
$providers[ $module['slug'] ] = $class;
}
}
return $providers;
}
/**
* Get attendee(s) by id
*
* @param int|WP_Post $post_id The Post ID of the event.
* @param null $context The context of the current screen.
*
* @return mixed
*/
public function get_attendees_by_id( $post_id, $context = null ) {
return $this->get_attendees( $post_id, $context );
}
/**
* Return if attendee(s) have meta fields with data
*
* @param $post_id
* @param null $context
*
* @return bool
*/
public function attendees_has_meta_data( $post_id, $context = null ) {
$attendees = $this->get_attendees( $post_id, $context );
if ( ! is_array( $attendees ) ) {
return false;
}
return $this->attendees_meta_check( false, $attendees );
}
/**
* Return if tickets have meta fields
*
* @param $post_id
* @param null $context
*
* @return bool
*/
public function ticket_has_meta_fields( $post_id, $context = null ) {
$services = $this->detect_by_id( $post_id );
if ( ! is_array( $services ) ) {
$services = array();
}
$has_meta_fields = false;
$products = [];
// if no class then look for tickets by event/post id
if ( ! isset( $services['class'] ) ) {
$products = $this->get_product_ids_from_tickets( Tribe__Tickets__Tickets::get_all_event_tickets( $post_id ) );
}
$has_products = ! empty( $products );
// if no product ids and id is not ticket related return false
$is_ticket_related = array_intersect( array( 'order', 'ticket', 'attendee', 'product' ), $services );
if ( ! $has_products && ! $is_ticket_related ) {
return false;
}
// if the id is a product add the id to the array
$is_product = array_intersect( array( 'product' ), $services );
if ( ! $has_products && $is_product ) {
$has_products = true;
$products[] = absint( $post_id );
}
//elseif handle order id ticket&attendee
$is_order_ticket_attendee = array_intersect( array( 'order', 'ticket', 'attendee' ), $services );
if ( ! $has_products && $is_order_ticket_attendee ) {
$products = $this->get_product_ids_from_attendees( $this->get_attendees( $post_id, $context, $services ) );
}
if ( ! empty( $products ) ) {
$has_meta_fields = $this->check_for_meta_fields_by_product_id( $products );
}
return $has_meta_fields;
}
/**
* Return an array of product ids from an array of ticket objects
*
* @param array $tickets an array of ticket objects
*
* @return array
*/
protected function get_product_ids_from_tickets( $tickets ) {
$product_ids = array();
foreach ( $tickets as $ticket ) {
if ( isset( $ticket->ID ) && ! in_array( $ticket->ID, $product_ids ) ) {
$product_ids[] = $ticket->ID;
}
}
return $product_ids;
}
/**
* Return an array of product ids from an array of attendee(s)
*
* @param array $attendees an array of attendee(s)
*
* @return array
*/
protected function get_product_ids_from_attendees( $attendees ) {
$product_ids = array();
foreach ( $attendees as $attendee ) {
if ( isset( $attendee['product_id'] ) && ! in_array( $attendee['product_id'], $product_ids ) ) {
$product_ids[] = $attendee['product_id'];
}
}
return $product_ids;
}
/**
* Determine whether the ticket IDs have meta fields.
*
* @param array $ticket_ids The ticket IDs.
*
* @return bool Whether the ticket IDs have meta.
*/
protected function check_for_meta_fields_by_product_id( $ticket_ids ) {
/**
* Allow filtering whether the ticket IDs have meta fields.
*
* @since 5.0.3
*
* @param bool $tickets_have_meta_fields Whether the ticket IDs have meta fields.
* @param array $ticket_ids The ticket IDs.
*/
return apply_filters( 'tribe_tickets_data_ticket_ids_have_meta_fields', false, $ticket_ids );
}
/**
* Get attendee(s) from any id.
*
* @since 4.5
* @since 4.12.3 Use new helper method to account for possibly inactive ticket provider.
*
* @param int|WP_Post $post_id The Post ID of the event.
* @param null $context The context of the current screen.
*
* @return mixed
*/
protected function get_attendees( $post_id, $context, $services = false ) {
if ( ! $services ) {
$services = $this->detect_by_id( $post_id );
}
/**
* if a post id is passed with rsvp order context
* get the order key to return all attendees by the key
*/
if ( 'rsvp_order' === $context && is_numeric( $post_id ) ) {
$post_id = $this->get_rsvp_order_key( $post_id );
}
// if no provider class, use the passed id to return attendee(s)
if ( ! isset( $services['class'] ) && is_numeric( $post_id ) ) {
return Tribe__Tickets__Tickets::get_event_attendees( $post_id );
} elseif ( ! isset( $services['class'] ) && ! is_numeric( $post_id ) ) {
return [];
}
if ( ! empty( $services['class'] ) ) {
$provider = Tribe__Tickets__Tickets::get_ticket_provider_instance( $services['class'] );
}
if ( empty( $provider ) ) {
return [];
}
return $provider->get_attendees_by_id( $post_id, $services['post_type'] );
}
/**
* Check if attendee(s) have meta data
*
* @param bool $has_meta Whether the attendee has meta data.
* @param array $attendees The attendees.
*
* @return bool
*/
protected function attendees_meta_check( $has_meta, $attendees ) {
foreach ( $attendees as $attendee ) {
if ( isset( $attendee['attendee_meta'] ) && ! empty( $attendee['attendee_meta'] ) ) {
$has_meta = true;
}
}
return $has_meta;
}
/**
* Check if a order key passed exists and return attendee object name
*
* @param string $order_key The order key.
*
* @return string
*/
protected function check_rsvp_order_key_exists( $order_key ) {
$attendees_query = $this->query_by_rsvp_order_key( $order_key, 1 );
if ( ! $attendees_query->have_posts() ) {
return '';
}
return Tribe__Tickets__RSVP::ATTENDEE_OBJECT;
}
/**
* Get the rsvp order key from a post id
*
* @param int $post_id The Post ID of the event.
*
* @return mixed
*/
protected function get_rsvp_order_key( $post_id ) {
$order_key = get_post_meta( $post_id, Tribe__Tickets__RSVP::get_instance()->order_key, true );
if ( ! $order_key ) {
return $post_id;
}
return $order_key;
}
/**
* Get a post id when passing a rsvp order key
* Since all rsvp orders will be from one post,
* we only need to return the first match
*
* @param string $order_key The order key.
*
* @return false|int|string
*/
protected function get_rsvp_post_id_from_order_key( $order_key ) {
$attendees_query = $this->query_by_rsvp_order_key( $order_key, 1 );
if ( ! $attendees_query->have_posts() ) {
return '';
}
$post_id = '';
while ( $attendees_query->have_posts() ) {
$attendees_query->the_post();
$post_id = get_the_ID();
}
wp_reset_postdata();
return $post_id;
}
/**
* Query RSVP Orders by the Order Key
*
* @param string $order_key The order key.
* @param string $post_per_page
*
* @return WP_Query
*/
protected function query_by_rsvp_order_key( $order_key, $post_per_page = '-1' ) {
$attendees_query = new WP_Query( array(
'posts_per_page' => $post_per_page,
'post_type' => Tribe__Tickets__RSVP::ATTENDEE_OBJECT,
'meta_key' => Tribe__Tickets__RSVP::get_instance()->order_key,
'meta_value' => esc_attr( $order_key ),
'orderby' => 'ID',
'order' => 'ASC',
) );
return $attendees_query;
}
}