<?php
namespace TEC\Tickets\Commerce;
use TEC\Tickets\Commerce;
use TEC\Tickets\Commerce\Communications\Email;
use TEC\Tickets\Commerce\Status\Status_Handler;
use \Tribe__Tickets__Ticket_Object as Ticket_Object;
use Tribe__Utils__Array as Arr;
use Tribe__Date_Utils;
use WP_Post;
/**
* Class Attendee
*
* @since 5.1.9
*
* @package TEC\Tickets\Commerce
*/
class Attendee {
/**
* Tickets Commerce Attendee Post Type slug.
*
* @since 5.1.9
*
* @var string
*/
const POSTTYPE = 'tec_tc_attendee';
/**
* Which meta holds the Relation ship between an attendee and which user it's registered to.
*
* @since 5.1.9
*
* @var string
*/
public static $user_relation_meta_key = '_tribe_tickets_attendee_user_id';
/**
* Which meta holds the Relation ship between an attendee and which event it's registered to.
*
* @since 5.1.9
*
* @var string
*/
public static $event_relation_meta_key = '_tec_tickets_commerce_event';
/**
* Which meta holds the Relation ship between an attendee and which ticket it was created from.
*
* @since 5.1.9
*
* @var string
*/
public static $ticket_relation_meta_key = '_tec_tickets_commerce_ticket';
/**
* Which meta holds the Relation ship between an attendee and which order it belongs to.
*
* @since 5.1.9
*
* @var string
*/
public static $order_relation_meta_key = '_tec_tickets_commerce_order';
/**
* Which meta holds the purchaser name for an attendee.
*
* @since 5.1.9
*
* @var string
*/
public static $purchaser_name_meta_key = '_tec_tickets_commerce_purchaser_name';
/**
* Which meta holds the purchaser email for an attendee.
*
* @since 5.1.9
*
* @var string
*/
public static $purchaser_email_meta_key = '_tec_tickets_commerce_purchaser_email';
/**
* Which meta holds the security code for an attendee.
*
* @since 5.1.9
*
* @var string
*/
public static $security_code_meta_key = '_tec_tickets_commerce_security_code';
/**
* Which meta holds the status value for an attendee.
*
* @since 5.1.9
*
* @var string
*/
public static $status_meta_key = '_tec_tickets_commerce_status';
/**
* Which meta holds the optout value for an attendee.
*
* @since 5.1.9
*
* @var string
*/
public static $optout_meta_key = '_tec_tickets_commerce_optout';
/**
* Which meta holds the checked in status for an attendee.
*
* @since 5.1.9
*
* @var string
*/
public static $checked_in_meta_key = '_tec_tickets_commerce_checked_in';
/**
* Which meta holds the checked in status for an attendee.
*
* @since 5.1.9
*
* @var string
*/
public static $deleted_ticket_meta_key = '_tribe_deleted_product_name';
/**
* Indicates if a ticket for this attendee was sent out via email.
*
* @since 5.1.9
*
* @var string
*/
public static $ticket_sent_meta_key = '_tec_tickets_commerce_attendee_ticket_sent';
/**
* Meta key holding an indication if this attendee was subscribed.
*
* @since 5.1.9
*
* @var string
*/
public static $subscribed_meta_key = '_tribe_tickets_subscribed';
/**
* Meta key holding the first name for the attendee. (not purchaser)
*
* @since 5.1.9
*
* @var string
*/
public static $full_name_meta_key = '_tec_tickets_commerce_full_name';
/**
* Meta key holding the email for the attendee. (not purchaser)
*
* @since 5.1.9
*
* @var string
*/
public static $email_meta_key = '_tec_tickets_commerce_email';
/**
* Meta key holding price paid for this attendee.
*
* @since 5.1.10
*
* @var string
*/
public static $price_paid_meta_key = '_tec_tickets_commerce_price_paid';
/**
* Meta key holding currency which the price was paid in.
*
* @since 5.1.10
*
* @var string
*/
public static $currency_meta_key = '_tec_tickets_commerce_currency';
/**
* Meta key holding the attendee's unique id
*
* @since 5.2.0
*
* @var string
*/
public static $unique_id_meta_key = '_unique_id';
/**
* Register this Class post type into WP.
*
* @since 5.1.9
*/
public function register_post_type() {
$post_type_args = [
'label' => __( 'Attendees', 'event-tickets' ),
'public' => false,
'show_ui' => false,
'show_in_menu' => false,
'query_var' => false,
'rewrite' => false,
'capability_type' => 'post',
'has_archive' => false,
'hierarchical' => false,
];
/**
* Filter the arguments that craft the attendee post type.
*
* @see register_post_type
*
* @since 5.1.9
*
* @param array $post_type_args Post type arguments, passed to register_post_type()
*/
$post_type_args = apply_filters( 'tec_tickets_commerce_attendee_post_type_args', $post_type_args );
register_post_type( static::POSTTYPE, $post_type_args );
}
/**
* Archives an attendee. In WordPress this means the attendee post will have `trash` status, but it won't be
* deleted.
*
* @since 5.2.1
*
* @param int $attendee_id The Attendee ID.
*/
public function archive( $attendee_id ) {
/**
* Allows filtering the Attendee ID for archival.
*
* @since 5.2.1
*
* @param int $attendee_id The Attendee ID.
*/
$attendee_id = apply_filters( 'tec_tickets_commerce_attendee_to_archive', $attendee_id );
/**
* Allows actions to run right before archiving an attendee.
*
* @since 5.2.1
*
* @param int $attendee_id The Attendee ID.
*/
do_action( 'tec_tickets_commerce_attendee_before_archive', $attendee_id );
$result = wp_trash_post( $attendee_id );
/**
* Allows actions to run right after archiving an attendee.
*
* @since 5.2.1
*
* @param int $attendee_id The Attendee ID.
* @param WP_Post|false|null $result Attendee post data on success, false or null on failure.
*/
do_action( 'tec_tickets_commerce_attendee_after_archive', $attendee_id, $result );
/**
* Allows filtering of the return from the `wp_trash_post`.
*
* @since 5.2.1
*
* @param WP_Post|false|null $result Attendee post data on success, false or null on failure.
* @param int $attendee_id The Attendee ID.
*/
return apply_filters( 'tec_tickets_commerce_attendee_archived', $result, $attendee_id );
}
/**
* Permanently deletes an attendee.
*
* @since 5.2.1
*
* @since 5.5.10 Avoid force delete of WP_Post objects and integrate stock management.
*
* @param int $attendee_id The Attendee ID.
* @param boolean $force Force the deletion.
*/
public function delete( $attendee_id, $force = true ) {
/**
* Allows filtering the Attendee ID for deletion.
*
* @since 5.2.1
*
* @param int $attendee_id The Attendee ID
* @param boolean $force Force the deletion.
*/
$attendee_id = (int) apply_filters( 'tec_tickets_commerce_attendee_to_delete', $attendee_id, $force );
// Bail if we don't have a valid ID.
if ( ! $attendee_id ) {
return false;
}
$event_id = (int) get_post_meta( $attendee_id, static::$event_relation_meta_key, true );
/**
* Allows actions to run right before deleting an attendee.
*
* @since 5.2.1
*
* @param int $attendee_id The Attendee ID.
* @param boolean $force Force the deletion.
*/
do_action( 'tec_tickets_commerce_attendee_before_delete', $attendee_id, $force );
$result = wp_delete_post( $attendee_id );
/**
* Allows actions to run right after deleting an attendee.
*
* @since 5.2.1
*
* @param int $attendee_id The Attendee ID.
* @param WP_Post|false|null $result Attendee post data on success, false or null on failure.
* @param boolean $force Force the deletion.
*/
do_action( 'tec_tickets_commerce_attendee_after_delete', $attendee_id, $result, $force );
/**
* Allows filtering of the return from the `wp_delete_post`.
*
* @since 5.2.1
*
* @param WP_Post|false|null $result Attendee post data on success, false or null on failure.
* @param int $attendee_id The Attendee ID.
* @param boolean $force Force the deletion.
*/
return apply_filters( 'tec_tickets_commerce_attendee_deleted', $result, $attendee_id, $force );
}
/**
* Creates an individual attendee given an Order and Ticket.
*
* @since 5.1.10
*
* @param \WP_Post $order Which order generated this attendee.
* @param Ticket_Object $ticket Which ticket generated this Attendee.
* @param array $args Set of extra arguments used to populate the data for the attendee.
*
* @return \WP_Error|\WP_Post
*/
public function create( \WP_Post $order, $ticket, array $args = [] ) {
$create_args = [
'order_id' => $order->ID,
'ticket_id' => $ticket->ID,
'event_id' => $ticket->get_event_id(),
'security_code' => Arr::get( $args, 'security_code' ),
'opt_out' => Arr::get( $args, 'opt_out' ),
'price_paid' => Arr::get( $args, 'price_paid' ),
'currency' => Arr::get( $args, 'currency' ),
];
if ( ! empty( $order->purchaser['user_id'] ) ) {
$create_args['user_id'] = $order->purchaser['user_id'];
}
if ( ! empty( $args['email'] ) ) {
$create_args['email'] = $args['email'];
}
if (
empty( $args['email'] )
&& ! empty( $order->purchaser['email'] )
) {
$create_args['email'] = $order->purchaser['email'];
}
if ( ! empty( $args['full_name'] ) ) {
$create_args['full_name'] = $args['full_name'];
$create_args['title'] = $args['full_name'];
}
if (
empty( $args['full_name'] )
&& ! empty( $order->purchaser['full_name'] )
) {
$create_args['full_name'] = $order->purchaser['full_name'];
$create_args['title'] = $order->purchaser['full_name'];
}
$fields = Arr::get( $args, 'fields', [] );
if ( ! empty( $fields ) ) {
$create_args['fields'] = $fields;
}
/**
* Allow the filtering of the create arguments for attendee.
*
* @since 5.1.10
*
* @param array $create_args Which arguments we are going to use to create the attendee.
* @param \WP_Post $order Which order generated this attendee.
* @param Ticket_Object $ticket Which ticket generated this Attendee.
* @param array $args Set of extra arguments used to populate the data for the attendee.
*/
$create_args = apply_filters( 'tec_tickets_commerce_attendee_create_args', $create_args, $order, $ticket, $args );
/**
* Allow the actions before creating the attendee.
*
* @since 5.1.10
*
* @param array $create_args Which arguments we are going to use to create the attendee.
* @param \WP_Post $order Which order generated this attendee.
* @param Ticket_Object $ticket Which ticket generated this Attendee.
* @param array $args Set of extra arguments used to populate the data for the attendee.
*/
do_action( 'tec_tickets_commerce_attendee_before_create', $create_args, $order, $ticket, $args );
$attendee = tec_tc_attendees()->set_args( $create_args )->create();
/**
* Allow the actions after creating the attendee.
*
* @since 5.1.10
*
* @param \WP_Post $attendee Post object for the attendee.
* @param \WP_Post $order Which order generated this attendee.
* @param Ticket_Object $ticket Which ticket generated this Attendee.
* @param array $args Set of extra arguments used to populate the data for the attendee.
*/
do_action( 'tec_tickets_commerce_attendee_after_create', $attendee, $order, $ticket, $args );
/**
* Allow the filtering of the attendee WP_Post after creating attendee.
*
* @since 5.1.10
*
* @param \WP_Post $attendee Post object for the attendee.
* @param \WP_Post $order Which order generated this attendee.
* @param Ticket_Object $ticket Which ticket generated this Attendee.
* @param array $args Set of extra arguments used to populate the data for the attendee.
*/
return apply_filters( 'tec_tickets_commerce_attendee_create', $attendee, $order, $ticket, $args );
}
/**
* Updates or creates an individual attendee given an Order and Ticket.
*
* @since 5.18.1
*
* @param \WP_Post $order Which order generated this attendee.
* @param Ticket_Object $ticket Which ticket generated this Attendee.
* @param array $args Set of extra arguments used to populate the data for the attendee.
* @param ?int $existing The ID of the existing attendee.
*
* @return \WP_Error|\WP_Post
*/
public function upsert( \WP_Post $order, $ticket, array $args = [], ?int $existing = null ) {
if ( ! $existing ) {
return $this->create( $order, $ticket, $args );
}
$update_args = [
'order_id' => $order->ID,
'ticket_id' => $ticket->ID,
'event_id' => $ticket->get_event_id(),
'security_code' => Arr::get( $args, 'security_code' ),
'opt_out' => Arr::get( $args, 'opt_out' ),
'price_paid' => Arr::get( $args, 'price_paid' ),
'currency' => Arr::get( $args, 'currency' ),
];
if ( ! empty( $order->purchaser['user_id'] ) ) {
$update_args['user_id'] = $order->purchaser['user_id'];
}
if ( ! empty( $args['email'] ) ) {
$update_args['email'] = $args['email'];
}
if (
empty( $args['email'] )
&& ! empty( $order->purchaser['email'] )
) {
$update_args['email'] = $order->purchaser['email'];
}
if ( ! empty( $args['full_name'] ) ) {
$update_args['full_name'] = $args['full_name'];
$update_args['title'] = $args['full_name'];
}
if (
empty( $args['full_name'] )
&& ! empty( $order->purchaser['full_name'] )
) {
$update_args['full_name'] = $order->purchaser['full_name'];
$update_args['title'] = $order->purchaser['full_name'];
}
$fields = Arr::get( $args, 'fields', [] );
if ( ! empty( $fields ) ) {
$update_args['fields'] = $fields;
}
// No need to update the security code.
unset( $update_args['security_code'] );
/**
* Allow the filtering of the update arguments for attendee.
*
* @since 5.18.1
*
* @param array $update_args Which arguments we are going to use to update the attendee.
* @param \WP_Post $order Which order generated this attendee.
* @param Ticket_Object $ticket Which ticket generated this Attendee.
* @param array $args Set of extra arguments used to populate the data for the attendee.
*/
$update_args = apply_filters( 'tec_tickets_commerce_attendee_update_args', $update_args, $order, $ticket, $args );
/**
* Allow the actions before updating the attendee.
*
* @since 5.18.1
*
* @param array $update_args Which arguments we are going to use to update the attendee.
* @param \WP_Post $order Which order generated this attendee.
* @param Ticket_Object $ticket Which ticket generated this Attendee.
* @param array $args Set of extra arguments used to populate the data for the attendee.
*/
do_action( 'tec_tickets_commerce_attendee_before_update', $update_args, $order, $ticket, $args );
$updated = tec_tc_attendees()->where( 'id', $existing )->set_args( $update_args )->save();
if ( empty( $updated[ $existing ] ) ) {
return $this->create( $order, $ticket, $args );
}
$attendee = tec_tc_attendees()->where( 'id', $existing )->first();
/**
* Allow the actions after updating the attendee.
*
* @since 5.18.1
*
* @param \WP_Post $attendee Post object for the attendee.
* @param \WP_Post $order Which order generated this attendee.
* @param Ticket_Object $ticket Which ticket generated this Attendee.
* @param array $args Set of extra arguments used to populate the data for the attendee.
*/
do_action( 'tec_tickets_commerce_attendee_after_update', $attendee, $order, $ticket, $args );
/**
* Allow the filtering of the attendee WP_Post after updating attendee.
*
* @since 5.18.1
*
* @param \WP_Post $attendee Post object for the attendee.
* @param \WP_Post $order Which order generated this attendee.
* @param Ticket_Object $ticket Which ticket generated this Attendee.
* @param array $args Set of extra arguments used to populate the data for the attendee.
*/
return apply_filters( 'tec_tickets_commerce_attendee_update', $attendee, $order, $ticket, $args );
}
/**
* If the post that was moved to the trash was a Tickets Commerce attendee post type, redirect to
* the Attendees Report rather than the Tickets Commerce attendees post list (because that's kind of
* confusing)
*
* @todo @backend this should probably be moved to the Archive Attendees flag action and handled from there.
*
* @since 5.1.9
*
* @param int $post_id WP_Post ID.
*/
public function maybe_redirect_to_attendees_report( $post_id ) {
if ( ! tribe_context()->is_editing_post( $post_id ) ) {
// If the context of the trashing is not an edit request to trash this post (i.e. it's programmatic), bail.
return;
}
$post = get_post( $post_id );
if ( static::POSTTYPE !== $post->post_type ) {
return;
}
// Do not redirect if this status change is being handled by a Flag Action.
if ( did_action( 'tec_tickets_commerce_order_status_flag_archive_attendees' ) ) {
return;
}
$args = [
'post_type' => 'tribe_events',
'page' => \Tribe__Tickets__Tickets_Handler::$attendees_slug,
'event_id' => get_post_meta( $post_id, static::$event_relation_meta_key, true ),
];
$url = add_query_arg( $args, admin_url( 'edit.php' ) );
$url = esc_url_raw( $url );
wp_redirect( $url );
tribe_exit();
}
/**
* Update the Ticket Commerce values for this user.
*
* Note that, within this method, $order_id refers to the attendee or ticket ID
* (it does not refer to an "order" in the sense of a transaction that may include
* multiple tickets, as is the case in some other methods for instance).
*
* @todo Adjust to the Ticket Commerce data.
*
* @since 5.1.9
*
* @param array $attendee_data Information that we are trying to save.
* @param int $attendee_id The attendee ID.
* @param int $post_id The event/post ID.
*/
public function update_attendee_data( $attendee_data, $attendee_id, $post_id ) {
// Bail if the user is not logged in.
if ( ! is_user_logged_in() ) {
return;
}
$user_id = get_current_user_id();
$ticket_attendees = tribe( Module::class )->get_attendees_by_user_id( $user_id, $post_id );
$ticket_attendee_ids = wp_list_pluck( $ticket_attendees, 'attendee_id' );
// This makes sure we don't save attendees for attendees that are not from this current user and event.
if ( ! in_array( $attendee_id, $ticket_attendee_ids, true ) ) {
return;
}
$attendee_data_to_save = [];
// Only update full name if set.
if ( ! empty( $attendee_data['full_name'] ) ) {
$attendee_data_to_save['full_name'] = sanitize_text_field( $attendee_data['full_name'] );
}
// Only update email if set.
if ( ! empty( $attendee_data['email'] ) ) {
$attendee_data['email'] = sanitize_email( $attendee_data['email'] );
// Only update email if valid.
if ( is_email( $attendee_data['email'] ) ) {
$attendee_data_to_save['email'] = $attendee_data['email'];
}
}
// Only update optout if set.
if ( isset( $attendee_data['optout'] ) ) {
$attendee_data_to_save['optout'] = (int) tribe_is_truthy( $attendee_data['optout'] );
}
// Only update if there's data to set.
if ( empty( $attendee_data_to_save ) ) {
return;
}
tribe( Module::class )->update_attendee( $attendee_id, $attendee_data_to_save );
}
/**
* Triggers the sending of ticket emails after Tickets Commerce information is updated.
*
* This is useful if a user initially suggests they will not be attending
* an event (in which case we do not send tickets out) but where they
* incrementally amend the status of one or more of those tickets to
* attending, at which point we should send tickets out for any of those
* newly attending persons.
*
* @since 5.1.9
*
* @param int $event_id the event id.
*/
public function maybe_send_tickets_after_status_change( $event_id ) {
$transaction_ids = [];
foreach ( tribe( Module::class )->get_event_attendees( $event_id ) as $attendee ) {
$transaction = get_post_meta( $attendee['attendee_id'], static::$order_relation_meta_key, true );
if ( ! empty( $transaction ) ) {
$transaction_ids[ $transaction ] = $transaction;
}
}
foreach ( $transaction_ids as $transaction ) {
// This method takes care of intelligently sending out emails only when
// required, for attendees that have not yet received their tickets
tribe( Email::class )->send_tickets_email( $transaction, $event_id );
}
}
/**
* Add our class to the list of classes for the attendee registration form
*
* @since 5.2.0
*
* @param array $classes existing array of classes.
*
* @return array $classes with our class added
*/
public function registration_form_class( $classes ) {
$classes[ static::POSTTYPE ] = \TEC\Tickets\Commerce::ABBR;
return $classes;
}
/**
* Filter the provider object to return this class if tickets are for this provider.
*
* @since 5.1.9
*
* @param object $provider_obj
* @param string $provider
*
* @return object
*/
public function registration_cart_provider( $provider_obj, $provider ) {
$options = [
\TEC\Tickets\Commerce::ABBR,
static::POSTTYPE,
\TEC\Tickets\Commerce::PROVIDER,
static::class,
];
if ( in_array( $provider, $options, true ) ) {
return tribe( Module::class );
}
return $provider_obj;
}
/**
* Whether a specific attendee is valid toward inventory decrease or not.
*
* By default only attendees generated as part of a Completed order will count toward
* an inventory decrease but, if the option to reserve stock for Pending Orders is activated,
* then those attendees generated as part of a Pending Order will, for a limited time after the
* order creation, cause the inventory to be decreased.
*
* @todo TribeCommerceLegacy: Move this method a Flag action.
* @todo For some forsaken reason the calculation of inventory is happening on the fly instead of when orders
* are modified we need to address that for performance reasons.
*
* @since 5.1.9
*
* @param array $attendee array of attendee information.
*
* @return bool
*/
public function decreases_inventory( $attendee ) {
$attendee = tec_tc_get_attendee( $attendee['ID'] );
$order = tec_tc_get_order( $attendee->post_parent );
$statuses = array_unique(
[
tribe( Status_Handler::class )->get_inventory_decrease_status()->get_wp_slug(),
tribe( Commerce\Status\Completed::class )->get_wp_slug(),
]
);
return in_array( $order->post_status, $statuses, true );
}
/**
* Hydrate attendee object with ticket data
*
* @todo We should not be using this particular piece of the code until it's using `tec_tc_get_attendee`.
*
* @since 5.2.0
*
* @param \WP_Post $attendee the attendee object.
*
* @return \WP_Post
*/
public function get_attendee( \WP_Post $attendee ) {
if ( static::POSTTYPE !== $attendee->post_type ) {
$attendee->is_legacy_attendee = true;
$legacy_provider = tribe_tickets_get_ticket_provider( $attendee->ID );
$attendee_data = (array) $legacy_provider->get_attendee( $attendee );
foreach ( $attendee_data as $key => $value ) {
$attendee->{$key} = $value;
}
} else {
$attendee = $this->load_attendee_data( $attendee );
}
return $attendee;
}
/**
* Get attendees by ticket ID.
*
* @since 5.14.0
* @since 5.25.0 Added check to return empty array if Tickets Commerce is disabled.
*
* @param int $ticket_id Ticket ID.
* @param string $orm_provider ORM provider string.
*
* @return array List of attendees.
*/
public function get_attendees_by_ticket_id( $ticket_id, $orm_provider ) {
// Check if Tickets Commerce is enabled.
if ( ! tec_tickets_commerce_is_enabled() ) {
return [];
}
// Check cache.
$cache = tribe_cache();
$attendees_by_ticket_id = $cache->get( 'tec_tickets_attendees_by_ticket_id' );
if ( ! is_array( $attendees_by_ticket_id ) ) {
$attendees_by_ticket_id = [];
}
if ( ! isset( $attendees_by_ticket_id[ $ticket_id ] ) ) {
/** @var Tribe__Tickets__Attendee_Repository $repository */
$repository = tec_tc_attendees( $orm_provider );
$attendees = $repository->by( 'ticket_id', $ticket_id )->all();
// Store in cache.
$attendees_by_ticket_id[ $ticket_id ] = $attendees;
$cache->set( 'tec_tickets_attendees_by_ticket_id', $attendees_by_ticket_id );
}
return tribe( Module::class )->get_attendees_from_module( $attendees_by_ticket_id[ $ticket_id ] );
}
/**
* Loads event, ticket, order and other data into an attendee object
*
* @todo We should not be using this particular piece of the code until it's using `tec_tc_get_attendee`.
*
* @since 5.2.0
*
* @param \WP_Post $attendee the attendee object.
*
* @return \WP_Post
*/
public function load_attendee_data( \WP_Post $attendee ) {
$attendee->attendee_id = $attendee->ID;
$attendee->attendee_meta = null;
$attendee->check_in = $this->get_check_in_status( $attendee );
$attendee->event_id = $this->get_event_id( $attendee );
$attendee->holder_email = $this->get_holder_email( $attendee );
$attendee->holder_name = $this->get_holder_name( $attendee );
$attendee->is_legacy_attendee = false;
$attendee->is_purchaser = true;
$attendee->is_subscribed = null;
$attendee->optout = null;
$attendee->order_id = 0;
$attendee->product = $this->get_product( $attendee );
$attendee->product_id = $this->get_product_id( $attendee );
$attendee->provider = Commerce::ABBR;
$attendee->provider_slug = Commerce::ABBR;
$attendee->purchase_time = get_post_time( Tribe__Date_Utils::DBDATETIMEFORMAT, false, $attendee->order_id );
$attendee->qr_ticket_id = null;
$attendee->security = $this->get_security_code( $attendee );
$attendee->security_code = $this->get_security_code( $attendee );
$attendee->ticket = $this->get_product_title( $attendee );
$attendee->ticket_id = $this->get_unique_id( $attendee );
$attendee->ticket_name = $this->get_product_title( $attendee );
$attendee->ticket_sent = null;
$attendee->user_id = null;
$order = $this->get_order( $attendee );
if ( $order ) {
$attendee->order_id = $order->ID;
$attendee->order_status = $order->post_status;
$attendee->order_status_label = tribe( Tickets_View::class )->get_rsvp_options( $attendee->order_status );
$attendee->purchaser_name = get_post_meta( $order->ID, Order::$purchaser_full_name_meta_key, true );
$attendee->purchaser_email = get_post_meta( $order->ID, Order::$purchaser_email_meta_key, true );
}
if ( empty( $attendee->ticket_id ) ) {
$attendee->ticket_id = $attendee->ID;
}
return $attendee;
}
/**
* Returns the product object related to an attendee
*
* @since 5.2.0
*
* @param \WP_Post $attendee the attendee object.
*
* @return \WP_Post|\stdClass
*/
public function get_product( \WP_Post $attendee ) {
$product = get_post_meta( $attendee->ID, Module::ATTENDEE_PRODUCT_KEY, true );
if ( $product ) {
return get_post( $product );
}
return (object) [];
}
/**
* Returns the product id related to an attendee
*
* @since 5.2.0
*
* @param \WP_Post $attendee the attendee object.
*
* @return string
*/
public function get_product_id( \WP_Post $attendee ) {
if ( empty( $attendee->product->ID ) ) {
return '';
}
return (string) $attendee->product->ID;
}
/**
* Returns the product title related to an attendee
*
* @since 5.2.0
*
* @param \WP_Post $attendee the attendee object.
*
* @return string
*/
public function get_product_title( \WP_Post $attendee ) {
$ticket = get_post( $attendee->ticket_id );
return ! empty( $ticket->post_title ) ?
esc_html( $this->post_title ) :
get_post_meta( $attendee->ID, static::$deleted_ticket_meta_key, true );
}
/**
* Returns the event id related to an attendee
*
* @since 5.2.0
*
* @param \WP_Post $attendee the attendee object.
*
* @return string
*/
public function get_event_id( \WP_Post $attendee ) {
return get_post_meta( $attendee->ID, static::$event_relation_meta_key, true );
}
/**
* Returns the ticket unique id related to an attendee
*
* @since 5.2.0
*
* @param \WP_Post $attendee the attendee object.
*
* @return string
*/
public function get_unique_id( \WP_Post $attendee ) {
$id = ! empty( $attendee->attendee_id ) ? $attendee->attendee_id : $attendee->ID;
return get_post_meta( $id, static::$unique_id_meta_key, true );
}
/**
* Returns the ticket id related to an attendee
*
* @since 5.2.0
*
* @param \WP_Post $attendee the attendee object.
*
* @return string
*/
public function get_ticket_id( \WP_Post $attendee ) {
if ( $attendee->is_legacy_attendee ) {
return $attendee->product_id;
}
return get_post_meta( $attendee->ID, static::$ticket_relation_meta_key, true );
}
/**
* Returns the security code for an attendee
*
* @since 5.2.0
*
* @param \WP_Post $attendee the attendee object.
*
* @return string
*/
public function get_security_code( \WP_Post $attendee ) {
if ( $attendee->is_legacy_attendee ) {
return $attendee->security_code;
}
return get_post_meta( $attendee->ID, static::$security_code_meta_key, true );
}
/**
* Returns the check in status of an attendee
*
* @since 5.2.0
*
* @param \WP_Post $attendee the attendee object.
*
* @return string
*/
public function get_check_in_status( \WP_Post $attendee ) {
if ( $attendee->is_legacy_attendee ) {
return $attendee->check_in;
}
return get_post_meta( $attendee->ID, static::$checked_in_meta_key, true );
}
/**
* Returns the status label used in the Status column
*
* @since 5.2.0
*
* @param \WP_Post $attendee the attendee object.
*
* @return string
*/
public function get_status_label( \WP_Post $attendee ) {
if ( $attendee->is_legacy_attendee ) {
return $attendee->order_status_label;
}
$checked_in = $this->get_check_in_status( $attendee );
if ( empty( $checked_in ) ) {
return '';
}
return tribe( Tickets_View::class )->get_rsvp_options( '1' === $checked_in ? 'yes' : 'no' );
}
/**
* Returns the order object related to an attendee
*
* @since 5.2.0
*
* @param \WP_Post $attendee the attendee object.
*
* @return array|WP_Post|null The Order post object or array, `null` if not found.
*/
public function get_order( \WP_Post $attendee ) {
return tec_tc_get_order(
get_post_meta( $attendee->ID, static::$order_relation_meta_key, true )
);
}
/**
* Returns the purchaser name if available
*
* @since 5.2.0
*
* @param \WP_Post $attendee the attendee object.
*
* @return string
*/
public function get_holder_name( \WP_Post $attendee ) {
$name = get_post_meta( $attendee->ID, static::$purchaser_name_meta_key, true );
if ( $name ) {
return esc_html( $name );
}
return esc_html__( 'Name not available', 'event-tickets' );
}
/**
* Returns the purchaser email if available
*
* @since 5.2.0
*
* @param \WP_Post $attendee the attendee object.
*
* @return string
*/
public function get_holder_email( \WP_Post $attendee ) {
$email = get_post_meta( $attendee->ID, static::$purchaser_email_meta_key, true );
if ( $email ) {
return esc_html( $email );
}
return esc_html__( 'Email not available', 'event-tickets' );
}
/**
* Check if the attendee is of valid type.
*
* @since 5.2.0
*
* @param int|\WP_Post $attendee The attendee object to check.
*
* @return bool
*/
public static function is_valid( $attendee ) {
$attendee = get_post( $attendee );
if ( ! $attendee ) {
return false;
}
return static::POSTTYPE === $attendee->post_type;
}
}
|