0 ) {
$all_data['post_title'] = get_the_title( $post_id );
$all_data['post_id'] = $post_id;
$metas = get_post_meta( $post_id );
if ( ! empty( $metas ) && sizeof( $metas ) > 0 ) {
foreach ( $metas as $key => $meta ) {
$all_data[ $key ] = self::data_sanitize( $meta[0] );
}
}
$all_data['capacity'] = self::get_total_qty( $post_id, $all_data );
}
return $all_data;
}
public static function get_taxonomy( $name ): array|WP_Error|string {
return get_terms( array( 'taxonomy' => $name, 'hide_empty' => false ) );
}
public static function get_all_term_data( $term_name ): array {
$all_data = [];
$taxonomies = self::get_taxonomy( $term_name );
if ( ! empty( $taxonomies ) && is_array( $taxonomies ) && sizeof( $taxonomies ) > 0 ) {
foreach ( $taxonomies as $taxonomy ) {
$all_data[ $taxonomy->term_id ] = $taxonomy->name;
}
}
return $all_data;
}
public static function get_option( $option, $default = [] ) {
$option_data = get_option( sanitize_key( $option ) );
return ! empty( $option_data ) ? $option_data : $default;
}
public static function get_options( $option, $key, $default = '' ) {
$options = get_option( sanitize_key( $option ) );
if ( isset( $options[ $key ] ) && $options[ $key ] ) {
$default = $options[ $key ];
}
return $default;
}
public static function booking_status() { return ( ABPET_Configuration['booked_status'] ?? null ) ?: 'wc-processing,wc-completed'; }
public static function booking_status_sold() {
$booked = self::booking_status();
$statuses = array_map('trim', explode(',', $booked));
if (in_array('all', $statuses, true)) {
return $booked;
}
$statuses = array_values(array_unique(array_merge($statuses, ['wc-pending', 'wc-on-hold'])));
return implode(',', $statuses);
}
public static function label() { return ( ABPET_Configuration['label'] ?? null ) ?: __( 'Events', 'abp-event-ticket' ); }
public static function slug() { return ( ABPET_Configuration['slug'] ?? null ) ?: 'event-ticket'; }
public static function icon_wp() { return ( ABPET_Configuration['icon'] ?? null ) ?: 'dashicons-tickets-alt'; }
public static function icon() { return ( ABPET_Configuration['brand_icon'] ?? null ) ?: '🏟️'; }
public static function feature_label() { return ( ABPET_Configuration['feature_label'] ?? null ) ?: __( 'Feature', 'abp-event-ticket' ); }
public static function brand_label() { return ( ABPET_Configuration['brand_label'] ?? null ) ?: __( 'Brand', 'abp-event-ticket' ); }
public static function brand_slug() { return ( ABPET_Configuration['brand_slug'] ?? null ) ?: 'brand'; }
public static function brand_value( $id ) { return ( ABPET_Brand[ $id ]['label'] ?? null ) ?: $id; }
public static function category_label() { return ( ABPET_Configuration['category_label'] ?? null ) ?: __( 'Category', 'abp-event-ticket' ); }
public static function category_slug() { return ( ABPET_Configuration['cat_slug'] ?? null ) ?: 'category'; }
public static function category_value( $id ) { return ( ABPET_Category[ $id ]['label'] ?? null ) ?: $id; }
public static function organizer_label() { return ( ABPET_Configuration['organizer_label'] ?? null ) ?: __( 'Organizer', 'abp-event-ticket' ); }
public static function organizer_slug() { return ( ABPET_Configuration['org_slug'] ?? null ) ?: 'organizer'; }
public static function organizer_value( $id ) { return ( ABPET_Organizer[ $id ]['label'] ?? null ) ?: $id; }
public static function location_label() { return ( ABPET_Configuration['location_label'] ?? null ) ?: __( 'Location', 'abp-event-ticket' ); }
public static function location_slug() { return ( ABPET_Configuration['location_slug'] ?? null ) ?: 'location'; }
public static function location_value( $id ) { return ( ABPET_Location[ $id ]['label'] ?? null ) ?: $id; }
public static function speaker_label() { return ( ABPET_Configuration['speaker_label'] ?? null ) ?: __( 'Speaker', 'abp-event-ticket' ); }
public static function speaker_slug() { return ( ABPET_Configuration['speaker_slug'] ?? null ) ?: 'speaker'; }
public static function speaker_value( $id ) { return ( ABPET_Speaker[ $id ]['label'] ?? null ) ?: $id; }
/**
* Icon/label map for the social networks a speaker can link to.
*
* @return array
*/
public static function speaker_social_defs(): array {
return [
'twitter' => [ 'icon' => 'fab fa-twitter', 'label' => 'Twitter/X' ],
'linkedin' => [ 'icon' => 'fab fa-linkedin', 'label' => 'LinkedIn' ],
'facebook' => [ 'icon' => 'fab fa-facebook', 'label' => 'Facebook' ],
'instagram' => [ 'icon' => 'fab fa-instagram', 'label' => 'Instagram' ],
];
}
/**
* Resolve a speaker photo to a URL that is guaranteed to exist.
*
* wp_get_attachment_image_url() returns false when the requested size
* was never generated, which happens on servers with no GD/Imagick, for
* formats WordPress cannot resize, and for images smaller than the size
* threshold. Templates gated on that return value silently dropped the
* photo, so fall back through the other sizes and then the original.
*
* @param int $photo_id Attachment ID.
* @param string $size Preferred image size.
* @return string URL, or an empty string when no file exists.
*/
public static function speaker_photo_url( $photo_id, string $size = 'medium_large' ): string {
$photo_id = absint( $photo_id );
if ( $photo_id <= 0 || ! get_post( $photo_id ) ) {
return '';
}
// Reject attachments whose file is gone or was never written, e.g. an
// upload the server refused. wp_get_attachment_url() still returns a
// URL for those, which would render as a broken image.
$file = get_attached_file( $photo_id );
if ( ! $file || ! file_exists( $file ) ) {
return '';
}
$full = wp_get_attachment_url( $photo_id );
$full = is_string( $full ) ? $full : '';
// WordPress does not resize SVGs and image_downsize() can hand back a
// URL without the filename for them, so always use the original file.
if ( 'image/svg+xml' === get_post_mime_type( $photo_id ) ) {
return $full;
}
foreach ( array_unique( array_filter( [ $size, 'large', 'medium', 'thumbnail', 'full' ] ) ) as $candidate ) {
$url = wp_get_attachment_image_url( $photo_id, $candidate );
if ( is_string( $url ) && '' !== $url ) {
return $url;
}
}
return $full;
}
/**
* Build the speaker photo
tag.
*
* Width/height attributes are only emitted when WordPress actually
* measured the file. Without an image library it reports 1x1, and
* browsers honour those attributes, so the photo renders as a single
* pixel and looks like a missing image.
*
* @param int $photo_id Attachment ID.
* @param string $size Preferred image size.
* @param string $alt Alt text, usually the speaker name.
* @param string $class Optional class attribute.
* @return string Img markup, or an empty string when no file exists.
*/
public static function speaker_photo_img( $photo_id, string $size = 'medium_large', string $alt = '', string $class = '' ): string {
$photo_id = absint( $photo_id );
$url = self::speaker_photo_url( $photo_id, $size );
if ( '' === $url ) {
return '';
}
$meta = wp_get_attachment_metadata( $photo_id );
$width = ! empty( $meta['width'] ) ? (int) $meta['width'] : 0;
$height = ! empty( $meta['height'] ) ? (int) $meta['height'] : 0;
$html = '
1 && $height > 1 ) {
$html .= ' width="' . $width . '" height="' . $height . '"';
}
return $html . ' />';
}
/**
* Build the render-ready speaker list for an event.
*
* Reads the `abpet_speaker` term relations first and falls back to the
* `speaker` post meta, so events saved before the taxonomy relation was
* synced still resolve. Returns an empty array when nothing is linked.
*
* @param int $post_id Event post ID.
* @return array List of normalised speaker items.
*/
public static function speaker_items( $post_id ): array {
$post_id = absint( $post_id );
if ( $post_id <= 0 ) {
return [];
}
$terms = get_the_terms( $post_id, 'abpet_speaker' );
if ( empty( $terms ) || is_wp_error( $terms ) ) {
$raw_ids = self::get_post_info( $post_id, 'speaker' );
$raw_ids = array_filter( array_map( 'absint', explode( ',', (string) $raw_ids ) ) );
if ( empty( $raw_ids ) ) {
return [];
}
$terms = [];
foreach ( $raw_ids as $raw_id ) {
$term = get_term( $raw_id, 'abpet_speaker' );
if ( $term instanceof WP_Term ) {
$terms[] = $term;
}
}
}
$items = [];
foreach ( $terms as $term ) {
$items[] = self::speaker_profile( $term );
}
return $items;
}
/**
* Normalise a single speaker term into a render-ready profile array.
*
* @param WP_Term|int $term Speaker term or term ID.
* @return array Profile array, or an empty array when the term is invalid.
*/
public static function speaker_profile( $term ): array {
if ( is_numeric( $term ) ) {
$term = get_term( absint( $term ), 'abpet_speaker' );
}
if ( ! ( $term instanceof WP_Term ) ) {
return [];
}
$social_defs = self::speaker_social_defs();
$meta = get_term_meta( $term->term_id, '_abpet_speaker_meta', true );
$meta = is_array( $meta ) ? $meta : [];
$photo = isset( $meta['photo'] ) ? absint( $meta['photo'] ) : 0;
$stored = isset( $meta['social'] ) && is_array( $meta['social'] ) ? $meta['social'] : [];
$social = [];
foreach ( $social_defs as $key => $def ) {
$url = isset( $stored[ $key ] ) ? esc_url_raw( $stored[ $key ] ) : '';
if ( ! empty( $url ) ) {
$social[] = [
'key' => $key,
'icon' => $def['icon'],
'label' => $def['label'],
'url' => $url,
];
}
}
$website = isset( $meta['website'] ) ? esc_url_raw( $meta['website'] ) : '';
$designation = isset( $meta['designation'] ) ? sanitize_text_field( $meta['designation'] ) : '';
$company = isset( $meta['company'] ) ? sanitize_text_field( $meta['company'] ) : '';
$term_link = get_term_link( $term );
$profile = [
'id' => (int) $term->term_id,
'name' => $term->name,
'slug' => $term->slug,
'description' => $term->description,
'designation' => $designation,
'company' => $company,
'website' => $website,
'social' => $social,
'photo_id' => $photo,
'photo_url' => self::speaker_photo_url( $photo ),
'link' => is_wp_error( $term_link ) ? '' : $term_link,
];
/**
* Filters the normalised speaker profile.
*
* Add fields stored outside the built-in term meta, or reshape the
* values, without replacing the templates that consume this array.
*
* @param array $profile Profile array.
* @param WP_Term $term Speaker term.
*/
return (array) apply_filters( 'abpet_speaker_profile', $profile, $term );
}
/**
* Build the complete view model for a single speaker page.
*
* Every value the template prints is assembled here and passed through a
* filter before the template sees it, so a site can surface data it
* stores itself (pronouns, session title, a second link, custom term
* meta) by adding to these arrays, with no template override needed.
*
* Filters, each receiving the profile so callbacks can key off it:
* - abpet_speaker_page_data the finished view model
* - abpet_speaker_initials fallback avatar initials
* - abpet_speaker_role designation/company line parts
* - abpet_speaker_facts key/value rows shown in the hero card
* - abpet_speaker_socials social icon links
* - abpet_speaker_photo_img hero photo markup
*
* @param WP_Term|int $term Speaker term or term ID.
* @return array View model, or an empty array when the term is not a speaker.
*/
public static function speaker_page_data( $term ): array {
if ( is_numeric( $term ) ) {
$term = get_term( absint( $term ), 'abpet_speaker' );
}
if ( ! ( $term instanceof WP_Term ) ) {
return [];
}
$profile = self::speaker_profile( $term );
if ( empty( $profile ) ) {
return [];
}
$name = (string) ( $profile['name'] ?? '' );
$bio = (string) ( $profile['description'] ?? '' );
// Up to two letters for the avatar placeholder, taken from the first
// two words so "Dr. Sarah Chen" reads as SC rather than DS.
$plain_name = trim( wp_strip_all_tags( $name ) );
$initials = '';
foreach ( preg_split( '/\s+/', $plain_name ) as $name_part ) {
if ( '' !== $name_part ) {
$initials .= mb_substr( $name_part, 0, 1 );
if ( mb_strlen( $initials ) >= 2 ) {
break;
}
}
}
$initials = (string) apply_filters( 'abpet_speaker_initials', mb_strtoupper( $initials ), $name, $profile );
$role_parts = array_map( 'esc_html', array_filter( [ $profile['designation'] ?? '', $profile['company'] ?? '' ] ) );
/** This filter is documented in the method docblock. */
$role_parts = (array) apply_filters( 'abpet_speaker_role', $role_parts, $profile );
// Only rows the admin actually filled in, so a sparse profile stays
// compact rather than showing a wall of empty labels.
$rows = [
'designation' => [ 'icon' => 'fas fa-user-tie', 'label' => __( 'Designation', 'abp-event-ticket' ) ],
'company' => [ 'icon' => 'fas fa-building', 'label' => __( 'Company', 'abp-event-ticket' ) ],
];
$facts = [];
foreach ( $rows as $key => $row ) {
$value = (string) ( $profile[ $key ] ?? '' );
if ( '' !== $value ) {
$facts[] = [
'icon' => $row['icon'],
'label' => $row['label'],
'value' => $value,
'url' => '',
];
}
}
$website = (string) ( $profile['website'] ?? '' );
if ( '' !== $website ) {
$facts[] = [
'icon' => 'fas fa-globe',
'label' => __( 'Website', 'abp-event-ticket' ),
// Host only: the full URL duplicates the link text underneath it.
'value' => (string) ( wp_parse_url( $website, PHP_URL_HOST ) ?: $website ),
'url' => $website,
];
}
/** This filter is documented in the method docblock. */
$facts = (array) apply_filters( 'abpet_speaker_facts', $facts, $profile );
/** This filter is documented in the method docblock. */
$socials = (array) apply_filters( 'abpet_speaker_socials', (array) ( $profile['social'] ?? [] ), $profile );
$photo_id = (int) ( $profile['photo_id'] ?? 0 );
$photo_img = self::speaker_photo_img( $photo_id, 'medium_large', $name, 'attachment-medium_large size-medium_large' );
/** This filter is documented in the method docblock. */
$photo_img = (string) apply_filters( 'abpet_speaker_photo_img', $photo_img, $profile );
$data = [
'id' => (int) ( $profile['id'] ?? 0 ),
'name' => $name,
'slug' => (string) ( $profile['slug'] ?? '' ),
'link' => (string) ( $profile['link'] ?? '' ),
'photo_id' => $photo_id,
'photo_img' => $photo_img,
'initials' => $initials,
'role_parts' => $role_parts,
'facts' => $facts,
'socials' => $socials,
'bio' => $bio,
'has_bio' => '' !== trim( wp_strip_all_tags( $bio ) ),
'profile' => $profile,
];
/** This filter is documented in the method docblock. */
return (array) apply_filters( 'abpet_speaker_page_data', $data, $profile );
}
public static function ticket_name( $id ) { return ( ABPET_Ticket[ $id ]['label'] ?? null ) ?: __( 'Ticket/Seat', 'abp-event-ticket' ); }
public static function ticket_icon( $id ) { return ( ABPET_Ticket[ $id ]['icon'] ?? null ) ?: ''; }
public static function ticket_color( $id ) { return ( ABPET_Ticket[ $id ]['color'] ?? null ) ?: 'inherit'; }
public static function decor_icon( $id ) { return ( ABPET_Decor[ $id ]['icon'] ?? null ) ?: ''; }
public static function decor_color( $id ) { return ( ABPET_Decor[ $id ]['color'] ?? null ) ?: 'inherit'; }
public static function sp_label( $post_id, $id ) {
if ( ! empty( $post_id ) && $post_id > 0 && ! empty( $id ) ) {
$sp_infos = self::get_post_info( $post_id, 'sp_infos', [] );
if ( ! empty( $sp_infos ) && sizeof( $sp_infos ) > 1 ) {
foreach ( $sp_infos as $sp_info ) {
if ( $sp_info['id'] == $id ) {
return $sp_info['name'] ?? $id;
}
}
}
}
return $id;
}
public static function on_off( $key ): bool {
$value = ( ABPET_On_Off[ $key ] ?? 'on' ) ?: 'on';
return $value !== 'off';
}
public static function event_schedule_url( int $post_id, string $event_date, string $session_time = '' ): string {
$args = [ 'event_date' => $event_date ];
if ( $session_time !== '' ) {
$args['session_time'] = $session_time;
}
return add_query_arg( $args, get_permalink( $post_id ) );
}
public static function event_schedule_items( int $post_id, array $dates, array $time_infos ): array {
$items = [];
foreach ( $dates as $date ) {
$date = gmdate( 'Y-m-d', strtotime( (string) $date ) );
if ( isset( $items[ $date ] ) ) {
continue;
}
$times = ABPET_Function::time( $time_infos, $date );
$items[ $date ] = [
'date' => $date,
'times' => array_values( array_unique( array_filter( array_map( 'sanitize_text_field', (array) $times ) ) ) ),
];
}
return array_values( $items );
}
public static function event_schedule_selection( array $dates, array $time_infos ): array {
$dates = array_values( array_unique( array_map( static function ( $date ): string {
return gmdate( 'Y-m-d', strtotime( (string) $date ) );
}, $dates ) ) );
$start_date = (string) ( $dates[0] ?? '' );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only URL pre-select for display; no state change.
$requested_date = isset( $_GET['event_date'] ) ? sanitize_text_field( wp_unslash( $_GET['event_date'] ) ) : '';
if ( $requested_date && in_array( $requested_date, $dates, true ) ) {
$start_date = $requested_date;
}
$all_times = array_values( array_unique( array_filter( array_map( 'sanitize_text_field', (array) self::time( $time_infos, $start_date ) ) ) ) );
$start_time = (string) ( $all_times[0] ?? '' );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only URL pre-select for display; no state change.
$requested_time = isset( $_GET['session_time'] ) ? sanitize_text_field( wp_unslash( $_GET['session_time'] ) ) : '';
if ( $requested_time && in_array( $requested_time, $all_times, true ) ) {
$start_time = $requested_time;
}
return [ $dates, $start_date, $all_times, $start_time ];
}
public static function array_to_string( $array ) {
$ids = '';
if ( sizeof( $array ) > 0 ) {
foreach ( $array as $data ) {
if ( $data ) {
$ids = $ids ? $ids . ',' . $data : $data;
}
}
}
return $ids;
}
public static function build_url( $value = '', $extra_args = [] ): string {
$default_args = [
'page' => ABPET_Function::slug(),
'tab' => $value,
'_abpet_nonce' => wp_create_nonce( 'abpet_url_action' ),
];
$final_args = array_merge( $default_args, $extra_args );
return add_query_arg( $final_args, admin_url( 'admin.php' ) );
}
public static function get_image_url( $post_id = '', $image_id = '', $size = 'full' ): bool|string {
$image_id = $post_id && $post_id > 0 ? get_post_thumbnail_id( $post_id ) : $image_id;
return wp_get_attachment_image_url( $image_id, $size );
}
public static function get_page_by_slug( $slug ): bool|WP_Post {
if ( $pages = get_pages() ) {
foreach ( $pages as $page ) {
if ( $slug === $page->post_name ) {
return $page;
}
}
}
return false;
}
public static function get_id_by_slug( $page_slug ): ?int {
$page = get_page_by_path( $page_slug );
return $page?->ID;
}
public static function check_wc(): int {
if ( class_exists( 'WooCommerce' ) || is_plugin_active( 'woocommerce/woocommerce.php' ) ) {
return 2;
}
$wc_dir = trailingslashit( WP_PLUGIN_DIR ) . 'woocommerce';
if ( is_dir( $wc_dir ) ) {
return 1;
}
return 0;
}
public static function polylang_query_args(): array {
if ( is_admin() || ! function_exists( 'pll_current_language' ) ) {
return [];
}
$language = pll_current_language( 'slug' );
return $language ? [ 'lang' => sanitize_key( $language ) ] : [];
}
public static function get_user_role( $user_ID ): string {
global $wp_roles;
$user_role_list = '';
$user_data = get_userdata( $user_ID );
$user_role_slug = $user_data->roles;
if ( is_array( $user_role_slug ) && sizeof( $user_role_slug ) > 0 ) {
$user_count = 0;
foreach ( $user_role_slug as $user_role ) {
$user_count ++;
if ( $user_count > 1 ) {
$user_role_list .= ", ";
}
$user_role_list .= translate_user_role( $wp_roles->roles[ $user_role ]['name'] );
}
}
return $user_role_list;
}
//=========== Template Related==================//
public static function details_template_path( $post_id ): string {
$post_id = $post_id ?? get_the_id();
$template_name = sanitize_key( self::get_post_info( $post_id, 'abpet_template', 'default' ) );
$template_name = in_array( $template_name, [ 'default', 'light', 'modern' ], true ) ? $template_name : 'default';
$file_name = 'details_theme/' . $template_name . '.php';
$dir = ABPET_DIR . 'tb_templates/' . $file_name;
if ( ! file_exists( $dir ) ) {
$file_name = 'details_theme/default.php';
}
return self::template_path( $file_name );
}
public static function template_path( $file_name ): string {
$file_path = wp_normalize_path( WP_CONTENT_DIR . DIRECTORY_SEPARATOR . '/tb_templates/' . $file_name );
$default_dir = wp_normalize_path( ABPET_DIR . 'tb_templates/' . $file_name );
return file_exists( $file_path ) ? $file_path : $default_dir;
}
//============== Event Function===============//
public static function checkout_validation( $booking_infos ) {
if ( empty( $booking_infos ) ) {
return false;
}
$booking_info = $booking_infos['booking_infos'] ?? [];
$post_id = $booking_infos['post_id'] ?? '';
// Validate post existence and post type.
if ( empty( $booking_info ) || empty( $post_id ) || get_post_type( $post_id ) !== ABPET_Function::get_cpt() ) {
return false;
}
$post_infos = ABPET_Function::get_all_meta( $post_id );
$sale_continue = $post_infos['sale_continue'] ?? 'on';
if ( 'on' !== $sale_continue ) {
return false;
}
$all_dates = self::date( $post_id );
$display_ticket_type = $post_infos['display_ticket_type'] ?? 'on';
$display_ticket_type = ABPET_Function::on_off( 'ticket_type' ) ? $display_ticket_type : 'off';
foreach ( $booking_info as $cart_item ) {
if ( empty( $cart_item ) ) {
continue;
}
$event_date = ! empty( $cart_item['event_date'] ) ? gmdate( 'Y-m-d', strtotime( $cart_item['event_date'] ) ) : '';
$session_time = ! empty( $cart_item['session_time'] ) ? gmdate( 'H:i:s', strtotime( '1970-01-01 ' . $cart_item['session_time'] ) ) : '';
$seat_type = $cart_item['seat_type'] ?? '';
$time_infos = $post_infos['time_infos'] ?? [];
$all_start_time = ABPET_Function::time( $time_infos, $event_date );
$ticket_infos = $cart_item['info'] ?? [];
// Early return if schedule or date validation fails.
$valid_session = false;
foreach ( $all_start_time as $available_time ) {
if ( gmdate( 'H:i', strtotime( '1970-01-01 ' . $available_time ) ) === gmdate( 'H:i', strtotime( '1970-01-01 ' . $session_time ) ) ) {
$valid_session = true;
break;
}
}
if ( empty( $ticket_infos ) || ! in_array( $event_date, $all_dates, true ) || ! $valid_session ) {
return false;
}
$form_data = [
'post_id' => $post_id,
'event_date' => $event_date,
'session_time' => $session_time,
];
// Specific Seat ('sp') Validation Branch.
if ( 'sp' === $seat_type ) {
$sp_id = $cart_item['sp_id'] ?? '';
if ( empty( $sp_id ) ) {
return false;
}
$form_data['sp_id'] = $sp_id;
$sold_seat = ABPET_Query::get_sold_seat( $form_data );
$all_seat = self::get_sp_seat( $sp_id );
foreach ( $ticket_infos as $ticket_info ) {
$name = $ticket_info['name'] ?? '';
if ( empty( $name ) || ! in_array( $name, $all_seat, true ) || in_array( $name, $sold_seat, true ) ) {
return false;
}
}
continue;
}
// Standard Ticket Validation Branch.
$_ticket_infos = $post_infos['ticket_infos'] ?? [];
if ( empty( $_ticket_infos ) || ! is_array( $_ticket_infos ) ) {
return false;
}
$order_tickets = $cart_item['info'] ?? [];
if ( 'off' === $display_ticket_type ) {
$key = array_key_first( $_ticket_infos );
$requested_qty = 0;
foreach ( $order_tickets as $order_ticket ) {
$requested_qty += intval( $order_ticket['qty'] ?? 0 );
}
$order_tickets = [ $key => [ 'qty' => $requested_qty ] ];
}
if ( empty( $order_tickets ) ) {
return false;
}
$sold_infos = ABPET_Query::get_sold_ticket( $form_data );
foreach ( $order_tickets as $tic_id => $order_ticket ) {
if ( ! isset( $_ticket_infos[ $tic_id ] ) ) {
return false;
}
$_ticket_info = $_ticket_infos[ $tic_id ];
$qty = intval( $order_ticket['qty'] ?? 1 );
$sold = $sold_infos[ $tic_id ] ?? 0;
$reserve = intval( $_ticket_info['reserve'] ?? 0 );
$total_qty = intval( $_ticket_info['qty'] ?? 0 );
$max_qty_raw = $_ticket_info['max_qty'] ?? '';
$available_qty = $total_qty - $sold - $reserve;
$max_qty = ( '' !== $max_qty_raw && intval( $max_qty_raw ) <= $available_qty ) ? intval( $max_qty_raw ) : $available_qty;
$min_qty = intval( $_ticket_info['min_qty'] ?? 1 );
if ( $qty < $min_qty || $qty > $max_qty ) {
return false;
}
}
}
return true;
}
//============= Date function================//
public static function date_all( $post_ids = [], $_date = '' ): array {
$all_dates = [];
$post_ids = ! empty( $post_ids ) ? $post_ids : ABPET_ids;
if ( ! empty( $post_ids ) ) {
foreach ( $post_ids as $post_id ) {
if ( ! empty( $post_id ) && $post_id > 0 ) {
$date_infos = self::get_post_info( $post_id, 'abpet_dates', [] );
$dates = self::date( $post_id, $date_infos, $_date );
$all_dates = array_merge( $all_dates, $dates );
}
}
$all_dates = array_unique( $all_dates );
usort( $all_dates, "ABPET_Function::sort_date" );
}
return $all_dates;
}
public static function date( $post_id, $date_infos = [], $_date = '' ): array {
$all_dates = [];
if ( ! empty( $post_id ) && $post_id > 0 ) {
if ( empty( $date_infos ) ) {
$date_infos = self::get_post_info( $post_id, 'abpet_dates', [] );
}
$date_type = $date_infos['date_type'] ?? 'periodic_date';
$now = current_time( 'Y-m-d' );
if ( $date_type == 'specific_date' ) {
$specific_dates = $date_infos['specific_dates'] ?? [];
if ( is_array( $specific_dates ) && sizeof( $specific_dates ) > 0 ) {
foreach ( $specific_dates as $date_item ) {
if ( ! empty( $date_item ) ) {
$date_item = gmdate( 'Y-m-d', strtotime( $date_item ) );
if ( strtotime( $date_item ) >= strtotime( $now ) ) {
$all_dates[] = $date_item;
}
}
}
}
} else {
$start_date = $date_infos['periodic_start_date'] ?? '';
$start_date = ! empty( $_date ) ? $_date : $start_date;
$start_date = $start_date ?: $now;
$sale_end_date = $date_infos['periodic_end_date'] ?? '';
$sale_end_date = $sale_end_date ? gmdate( 'Y-m-d', strtotime( $sale_end_date ) ) : '';
$active_days = ( ABPET_Date_Config['advance_date_number'] ?? null ) ?: 28;
if ( strtotime( $now ) >= strtotime( $start_date ) ) {
$start_date = $now;
}
$end_date = gmdate( 'Y-m-d', strtotime( $start_date . ' +' . $active_days . ' day' ) );
if ( $sale_end_date && strtotime( $sale_end_date ) < strtotime( $end_date ) ) {
$end_date = $sale_end_date;
}
$all_dates = self::date_list_modify( $start_date, $end_date, $date_infos );
}
$all_dates = sizeof( $all_dates ) > 1 ? array_unique( $all_dates ) : $all_dates;
usort( $all_dates, "ABPET_Function::sort_date" );
$current_date = current( $all_dates );
$now = strtotime( current_time( 'Y-m-d' ) );
if ( $now == strtotime( $current_date ) ) {
$time_infos = self::get_post_info( $post_id, 'time_infos', [] );
$time_info = self::time( $time_infos, $current_date );
if ( ! empty( $time_info ) ) {
$exit = false;
$buffer_time = ABPET_Dates['sale_close_after'] ?? 0;
$now_time = strtotime( current_time( 'Y-m-d H:i' ) );
foreach ( $time_info as $_time ) {
$date = $current_date . ' ' . $_time;
$date = $buffer_time > 0 ? strtotime( $date ) - $buffer_time : strtotime( $date );
if ( $now_time < $date ) {
$exit = true;
}
}
if ( ! $exit ) {
unset( $all_dates[ array_key_first( $all_dates ) ] );
}
}
}
}
return $all_dates;
}
public static function date_list_modify( $start_date, $end_date, $date_infos ): array {
$start_date = is_scalar( $start_date ) ? (string) $start_date : '';
$end_date = is_scalar( $end_date ) ? (string) $end_date : '';
$all_dates = [];
if ( $start_date !== '' && $end_date !== '' && strtotime( $start_date ) <= strtotime( $end_date ) ) {
$now = current_time( 'Y-m-d' );
$off_dates = [];
$date_rule = $date_infos['date_rule'] ?? '';
$date_rule_array = $date_rule ? explode( ',', $date_rule ) : [];
if ( in_array( 'off_date_range', $date_rule_array ) ) {
$off_date_range = $date_infos['off_date_range'] ?? [];
if ( is_array( $off_date_range ) && sizeof( $off_date_range ) > 0 ) {
foreach ( $off_date_range as $off_date ) {
if ( is_array( $off_date ) && isset( $off_date['from'], $off_date['to'] ) && is_string( $off_date['from'] ) && is_string( $off_date['to'] ) && $off_date['from'] !== '' && $off_date['to'] !== '' ) {
$from_date = gmdate( 'Y-m-d', strtotime( $off_date['from'] ) );
$to_date = gmdate( 'Y-m-d', strtotime( $off_date['to'] ) );
$off_date_lists = self::date_separate_period( $from_date, $to_date );
foreach ( $off_date_lists as $off_date_list ) {
$off_dates[] = $off_date_list->format( 'Y-m-d' );
}
}
}
}
}
if ( in_array( 'specific_of_date', $date_rule_array ) ) {
$particular_off_dates = $date_infos['specific_off_dates'] ?? [];
if ( is_array( $particular_off_dates ) && sizeof( $particular_off_dates ) > 0 ) {
foreach ( $particular_off_dates as $particular_off_date ) {
if ( is_scalar( $particular_off_date ) && (string) $particular_off_date !== '' ) {
$particular_off_date = gmdate( 'Y-m-d', strtotime( (string) $particular_off_date ) );
$off_dates[] = $particular_off_date;
}
}
}
}
$off_dates = array_unique( $off_dates );
$off_day_array = [];
if ( in_array( 'weekend', $date_rule_array ) ) {
$off_days = $date_infos['weekend'] ?? '';
$off_day_array = is_string( $off_days ) && $off_days ? explode( ',', $off_days ) : [];
}
$repeat = $date_infos['periodic_after'] ?? 1;
$dates = self::date_separate_period( $start_date, $end_date, $repeat );
foreach ( $dates as $date ) {
$date = $date->format( 'Y-m-d' );
if ( strtotime( $date ) >= strtotime( $now ) ) {
$day = strtolower( gmdate( 'l', strtotime( $date ) ) );
if ( ! in_array( $date, $off_dates ) && ! in_array( $day, $off_day_array ) ) {
$all_dates[] = $date;
}
}
}
//==================//
if ( in_array( 'special_on_dates', $date_rule_array ) ) {
$special_on_dates = $date_infos['special_on_dates'] ?? [];
if ( is_array( $special_on_dates ) && sizeof( $special_on_dates ) > 0 ) {
foreach ( $special_on_dates as $date_item ) {
$date_item = is_array( $date_item ) && isset( $date_item['date'] ) ? $date_item['date'] : $date_item;
if ( is_string( $date_item ) && $date_item !== '' ) {
$date_item = gmdate( 'Y-m-d', strtotime( $date_item ) );
if ( strtotime( $date_item ) >= strtotime( $now ) ) {
$all_dates[] = $date_item;
}
}
}
}
}
}
return array_values( array_unique( $all_dates ) );
}
public static function time( $time_infos, $date ) {
$day_times = $time_infos['day_time'] ?? [];
$date_times = $time_infos['date_times'] ?? [];
$default_time = $time_infos['time'] ?? [];
if ( ! empty( $day_times ) ) {
foreach ( $day_times as $day_key => $day_time ) {
if ( ! empty( $day_time ) ) {
$time_info[ strtolower( $day_key ) ] = $day_time;
}
}
}
if ( ! empty( $date_times ) ) {
foreach ( $date_times as $date_time ) {
$date = $date_time['date'] ?? '';
$time = $date_time['time'] ?? [];
if ( ! empty( $date ) && ! empty( $time ) ) {
$time_info[ $date ] = $time;
}
}
}
if ( ! empty( $time_info[ $date ] ) ) {
return $time_info[ $date ];
}
$day_name = strtolower( gmdate( 'l', strtotime( $date ) ) );
if ( ! empty( $time_info[ $day_name ] ) ) {
return $time_info[ $day_name ];
}
return $default_time;
}
public static function time_difference( $start_time, $end_time ): string {
$text = '';
if ( ! empty( $end_time ) ) {
$start_time = $start_time ?? 0;
$totalMinutes = $end_time - $start_time;
if ( $totalMinutes <= 0 ) {
return __( '0 Min', 'abp-event-ticket' );
}
$days = floor( $totalMinutes / 1440 );
$hours = floor( ( $totalMinutes % 1440 ) / 60 );
$minutes = $totalMinutes % 60;
if ( $days > 0 ) {
$text .= sprintf(
/* translators: %s = Days */
_n( ' %s Day', ' %s Days', $days, 'abp-event-ticket' ), $days );
}
if ( $hours > 0 ) {
$text .= sprintf(
/* translators: %s = Hours */
_n( ' %s Hour', ' %s Hours', $hours, 'abp-event-ticket' ), $hours );
}
if ( $minutes > 0 ) {
$text .= sprintf(
/* translators: %s = Minutes */
_n( ' %s Minute', ' %s Minutes', $minutes, 'abp-event-ticket' ), $minutes );
}
}
return $text;
}
public static function date_format( $date, $format = '' ): string {
if ( ! empty( $date ) ) {
if ( empty( $format ) ) {
$format = ABPET_Function::check_time_exit_date( $date ) ? 'full' : 'date';
}
$date_format = self::date_format_php();
$time_format = ABPET_Time_Format;
$wp_settings = $date_format . ' ' . $time_format;
//$timezone = wp_timezone_string();
$timestamp = strtotime( $date );
if ( $format == 'date' ) {
$date = date_i18n( $date_format, $timestamp );
} elseif ( $format == 'time' ) {
$date = date_i18n( $time_format, $timestamp );
} elseif ( $format == 'full' ) {
$date = date_i18n( $wp_settings, $timestamp );
} elseif ( $format == 'day' ) {
$date = date_i18n( 'd', $timestamp );
} elseif ( $format == 'month' ) {
$date = date_i18n( 'M', $timestamp );
} elseif ( $format == 'year' ) {
$date = date_i18n( 'Y', $timestamp );
} else {
$date = date_i18n( $format, $timestamp );
}
}
return $date;
}
public static function date_format_php(): string {
$formats = [
'yy/mm/dd' => 'Y/m/d',
'yy-dd-mm' => 'Y-d-m',
'yy/dd/mm' => 'Y/d/m',
'dd-mm-yy' => 'd-m-Y',
'dd/mm/yy' => 'd/m/Y',
'mm-dd-yy' => 'm-d-Y',
'mm/dd/yy' => 'm/d/Y',
'd M , yy' => 'j M , Y',
'D d M , yy' => 'D j M , Y',
'M d , yy' => 'M j, Y',
'D M d , yy' => 'D M j, Y',
];
return $formats[ ABPET_JS_Date_Format ] ?? 'Y-m-d';
}
public static function date_format_js() { return ( ABPET_Date_Config['date_format'] ?? null ) ?: 'D d M , yy'; }
public static function date_separate_period( $start_date, $end_date, $repeat = 1 ): DatePeriod {
$start_date = is_scalar( $start_date ) ? (string) $start_date : '';
$end_date = is_scalar( $end_date ) ? (string) $end_date : '';
$repeat = max( (int) $repeat, 1 );
$_interval = 'P' . $repeat . 'D';
$end_date = gmdate( 'Y-m-d', strtotime( $end_date . ' +1 day' ) );
return new DatePeriod( new DateTime( $start_date ), new DateInterval( $_interval ), new DateTime( $end_date ) );
}
public static function check_time_exit_date( $date ): bool {
if ( $date ) {
$parse_date = date_parse( $date );
if ( ( $parse_date['hour'] && $parse_date['hour'] > 0 ) || ( $parse_date['minute'] && $parse_date['minute'] > 0 ) || ( $parse_date['second'] && $parse_date['second'] > 0 ) ) {
return true;
}
}
return false;
}
public static function sort_date( $a, $b ): int { return strtotime( $a ) - strtotime( $b ); }
public static function sort_date_array( $a, $b ): int {
$dateA = strtotime( $a['time'] );
$dateB = strtotime( $b['time'] );
if ( $dateA == $dateB ) {
return 0;
} elseif ( $dateA > $dateB ) {
return 1;
} else {
return - 1;
}
}
public static function get_date_time_difference( $start_time, $end_time ) {
$text = '';
if ( ! empty( $start_time ) && ! empty( $end_time ) && strtotime( $start_time ) <= strtotime( $end_time ) ) {
$date1 = date_create( $start_time );
$date2 = date_create( $end_time );
$diff = date_diff( $date1, $date2 );
$years = $diff->y;
$months = $diff->m;
$days = $diff->d;
$hours = $diff->h;
$minutes = $diff->i;
$seconds = $diff->s;
if ( $years > 0 ) {
$text .= sprintf(
/* translators: %s =Years */
_n( ' %s Year', ' %s Years', $years, 'abp-event-ticket' ), $years );
}
if ( $months > 0 ) {
$text .= sprintf(
/* translators: %s = Months */
_n( ' %s Month', ' %s Months', $months, 'abp-event-ticket' ), $months );
}
if ( $days > 0 ) {
$text .= sprintf(
/* translators: %s = Days */
_n( ' %s Day', ' %s Days', $days, 'abp-event-ticket' ), $days );
}
if ( $hours > 0 ) {
$text .= sprintf(
/* translators: %s = Hours */
_n( ' %s Hour', ' %s Hours', $hours, 'abp-event-ticket' ), $hours );
}
if ( $minutes > 0 ) {
$text .= sprintf(
/* translators: %s = Minutes */
_n( ' %s Minute', ' %s Minutes', $minutes, 'abp-event-ticket' ), $minutes );
}
if ( $seconds > 0 ) {
$text .= sprintf(
/* translators: %s = Seconds */
_n( ' %s Second', ' %s Seconds', $seconds, 'abp-event-ticket' ), $seconds );
}
}
return $text;
}
public static function check_time_slot_exit( $main_slots, $input_slots ): bool {
if ( ! empty( $main_slots ) && ! empty( $input_slots ) ) {
$main_slots = explode( '-', $main_slots );
if ( isset( $main_slots[0] ) && isset( $main_slots[1] ) ) {
$main_start = strtotime( $main_slots[0] );
$main_end = strtotime( $main_slots[1] );
$input_slots = strtotime( $input_slots );
if ( $main_start <= $input_slots && $main_end >= $input_slots ) {
return true;
}
}
}
return false;
}
public static function booking_buffer( $time, $end = '' ): string {
$date_infos = ABPET_Dates;
if ( ! empty( $end ) ) {
$buffer_time = $date_infos['sale_close_after'] ?? 0;
$buffer_time = $buffer_time * 60;
$time = gmdate( 'Y-m-d H:i', strtotime( $time ) + $buffer_time );
} else {
$buffer_time = $date_infos['sale_close_before'] ?? 0;
$buffer_time = $buffer_time * 60;
$time = gmdate( 'Y-m-d H:i', strtotime( $time ) - $buffer_time );
}
return $time;
}
//=============Price Function================//
public static function tax_with_price( $post_id, $price ): string {
$num_of_decimal = get_option( 'woocommerce_price_num_decimals', 2 );
$_product = self::get_post_info( $post_id, 'link_wc_id', $post_id );
$product = wc_get_product( $_product );
$tax_display = get_option( 'woocommerce_tax_display_shop' );
if ( '' === $price ) {
return '';
}
$return_price = (float) $price;
if ( $product && $product->is_taxable() ) {
$tax_rates = WC_Tax::get_rates( $product->get_tax_class() );
if ( ! empty( $tax_rates ) ) {
$taxes = WC_Tax::calc_tax( $return_price, $tax_rates, false );
$tax_total = 'yes' === get_option( 'woocommerce_tax_round_at_subtotal' ) ? array_sum( $taxes ) : array_sum( array_map( 'wc_round_tax_total', $taxes ) );
if ( ! empty( WC()->customer ) && WC()->customer->get_is_vat_exempt() ) {
$return_price = round( $return_price, $num_of_decimal );
} else {
$return_price = $tax_display === 'excl' ? round( $return_price, $num_of_decimal ) : round( $return_price + $tax_total, $num_of_decimal );
}
}
}
return $return_price;
}
public static function get_price( $post_infos, $type = 'price', $date = '' ): bool|int|string|null {
if ( ! empty( $type ) && ! empty( $post_infos ) ) {
$price = 0;
$post_id = absint( $post_infos['post_id'] ?? 0 );
if ( ! empty( $post_id ) && $post_id > 0 ) {
$display_ticket_type = $post_infos['display_ticket_type'] ?? ABPET_Function::get_post_info( $post_id, 'display_ticket_type', 'on' );
$display_ticket_type = ABPET_Function::on_off( 'ticket_type' ) ? $display_ticket_type : 'off';
$type = $display_ticket_type == 'on' ? $type : 'price';
$price_infos = $post_infos['ticket_infos'] ?? ABPET_Function::get_post_info( $post_id, 'ticket_infos', [] );
if ( ! empty( $price_infos ) && array_key_exists( $type, $price_infos ) ) {
$price = $price_infos[ $type ]['price'] ?? ( current( $price_infos['price'] ) ?? 0 );
$price = $price > 0 ? apply_filters( 'abpet_filter_price', $price, $date ) : $price;
}
}
return $price > 0 ? self::tax_with_price( $post_id, $price ) : 0;
}
return null;
}
public static function get_additional_price( $post_infos = [], $i_d = '' ): int|string {
$services = ABPET_Function::additional_data( $post_infos );
$price = 0;
$post_id = $post_infos['post_id'] ?? '';
if ( ! empty( $services ) && is_array( $services ) && ! empty( $i_d ) ) {
foreach ( $services as $id => $service ) {
if ( $id == $i_d ) {
$price = $service['price'] ?? 0;
break;
}
}
}
return $price > 0 ? self::tax_with_price( $post_id, $price ) : 0;
}
public static function get_min_price( $post_id = 0 ): int|string {
$price = 0;
if ( ! empty( $post_id ) && $post_id > 0 ) {
$price_infos = ABPET_Function::get_post_info( $post_id, 'ticket_infos', [] );
$all_price = [];
if ( ! empty( $price_infos ) ) {
foreach ( $price_infos as $id => $price_info ) {
$all_price[] = $price_info['price'] ?? 0;
};
}
$price = min( $all_price );
}
return $price > 0 ? self::tax_with_price( $post_id, $price ) : 0;
}
//=============================//
public static function get_total_qty( $post_id, $post_infos = [] ) {
$total_qty = 0;
if ( ! empty( $post_id ) && $post_id > 0 ) {
if ( ! empty( $post_infos ) ) {
$seat_type = $post_infos['seat_type'] ?? 'sp';
$ticket_infos = $post_infos['ticket_infos'] ?? [];
$sp_infos = $post_infos['sp_infos'] ?? [];
} else {
$seat_type = ABPET_Function::get_post_info( $post_id, 'seat_type', 'sp' );
$ticket_infos = ABPET_Function::get_post_info( $post_id, 'ticket_infos', [] );
$sp_infos = ABPET_Function::get_post_info( $post_id, 'sp_infos', [] );
}
$seat_type = ABPET_Function::on_off( 'sp' ) ? $seat_type : 'ticket';
if ( $seat_type === 'ticket' ) {
if ( ! empty( $ticket_infos ) ) {
foreach ( $ticket_infos as $ticket_info ) {
$total_qty += $ticket_info['qty'] ?? 0;
}
}
} else {
if ( ! empty( $sp_infos ) ) {
$ids = [];
foreach ( $sp_infos as $ticket_info ) {
$id = $ticket_info['id'] ?? '';
if ( ! empty( $id ) ) {
$ids[] = $id;
}
}
$total_qty = self::get_sp_ticket( $ids, true );
}
}
}
return $total_qty;
}
public static function get_sp_ticket( array $ids = [], bool $count = false ) {
if ( empty( $ids ) ) {
return $count ? 0 : [];
}
$tickets = [];
$total = 0;
foreach ( $ids as $id ) {
$seat_infos = ABPET_Ticket_SP[ $id ] ?? null;
if ( empty( $seat_infos ) ) {
continue;
}
if ( $count ) {
$total += $seat_infos['total'] ?? 0;
} else {
$seat_info = $seat_infos['type'] ?? [];
if ( ! empty( $seat_info ) ) {
$tickets = array_merge( $tickets, array_keys( $seat_info ) );
}
}
}
return $count ? $total : array_values( array_unique( $tickets ) );
}
public static function get_sp_seat( $sp_id = '' ): array {
$all_seat = [];
if ( ! empty( $sp_id ) && $sp_id > 0 ) {
$row = ABPET_Query::get_sp( $sp_id );
$sp_info = [];
if ( ! empty( $row ) ) {
$sp_info = current( $row );
}
if ( ! empty( $sp_info ) ) {
$layout = json_decode( $sp_info['layout_data'] ?? '', true ) ?: [];
foreach ( $layout as $cell ) {
if ( ( $cell['type'] ?? '' ) == 'seat' ) {
$all_seat[] = $cell['name'] ?? '';
}
}
}
}
return $all_seat;
}
//=============================//
public static function client_data( $post_infos = [] ) {
$data = [];
if ( ABPET_Function::on_off( 'client_info' ) && ! empty( $post_infos ) ) {
$display = $post_infos['display_client_form'] ?? 'on';
if ( $display === 'on' ) {
$active_global = $post_infos['active_global_form'] ?? 'on';
if ( $active_global === 'on' ) {
$data = ABPET_Function::get_option( 'abpet_form' );
} else {
$data = $post_infos['abpet_form'] ?? [];
}
}
}
return $data;
}
public static function additional_data( $post_infos = [] ) {
$data = [];
if ( ABPET_Function::on_off( 'additional_info' ) && ! empty( $post_infos ) ) {
$display = $post_infos['display_additional_services'] ?? 'on';
if ( $display === 'on' ) {
$active_global = $post_infos['active_global_additional'] ?? 'on';
if ( $active_global === 'on' ) {
$data = ABPET_Function::get_option( 'abpet_additional' );
} else {
$data = $post_infos['additional_services'] ?? [];
}
}
}
return $data;
}
//=============================//
public static function related_info_js( $_post_id = '' ): array {
$all_info = [];
if ( ! empty( $_post_id ) && $_post_id > 0 ) {
if ( ! empty( ABPET_ids ) ) {
$active_icon = ABPET_Function::on_off( 'post_icon' );
foreach ( ABPET_ids as $post_id ) {
if ( $post_id !== $_post_id ) {
$icon = $active_icon ? ABPET_Function::get_post_info( $post_id, 'post_icon' ) : '';
$all_info[] = [ 'id' => $post_id, 'icon' => $icon, 'label' => get_the_title( $post_id ) ];
}
}
}
}
return $all_info;
}
public static function option_js( $post_id, $option ): array {
$data = [];
if ( ! empty( $post_id ) && $post_id > 0 && ! empty( $option ) ) {
$options = ABPET_Function::get_option( $option );
$options = is_array( $options ) ? $options : [];
if ( sizeof( $options ) > 0 ) {
foreach ( $options as $key => $item ) {
$data[] = [ 'id' => $key, 'icon' => ( $item['icon'] ?? '' ), 'label' => ( $item['label'] ?? '' ), 'value' => ( $item['value'] ?? '' ) ];
}
}
}
return $data;
}
}
new ABPET_Function();
}