Tribe__Tickets__Admin__Move_Tickets::move_tickets( array $ticket_ids, int $tgt_ticket_type_id, int $src_event_id, int $tgt_event_id )

Moves tickets to a new ticket type.

The target ticket type must belong to the same provider as the tickets being moved (ie, you cannot move RSVP tickets to a WooCommerce ticket type, nor can a mix of RSVP and WooCommerce tickets be moved to a new ticket type).


Parameters

$ticket_ids

(array) (Required)

$tgt_ticket_type_id

(int) (Required)

$src_event_id

(int) (Required)

$tgt_event_id

(int) (Required)


Top ↑

Return

(int) number of successfully moved tickets (zero upon failure to move any)


Top ↑

Source

File: src/Tribe/Admin/Move_Tickets.php

	public function move_tickets( array $ticket_ids, $tgt_ticket_type_id, $src_event_id, $tgt_event_id ) {
		$ticket_ids       = array_map( 'intval', $ticket_ids );
		$instigator_id    = get_current_user_id();
		$ticket_type      = Tribe__Tickets__Tickets::load_ticket_object( $tgt_ticket_type_id );
		$successful_moves = 0;

		if ( ! $ticket_type ) {
			return 0;
		}

		$ticket_objects = [];
		$providers      = [];

		$args = [
			'in' => $ticket_ids,
		];

		$attendee_data = Tribe__Tickets__Tickets::get_event_attendees_by_args( $src_event_id, $args );

		foreach ( $attendee_data['attendees'] as $issued_ticket ) {
			$ticket_objects[] = $issued_ticket;

			$providers[ $issued_ticket['provider'] ] = call_user_func( array( $issued_ticket['provider'], 'get_instance' ) );
		}

		// We expect to have found as many tickets as were specified
		if ( count( $ticket_objects ) !== count( $ticket_ids ) ) {
			return 0;
		}

		// Check that the tickets are homogeneous in relation to the ticket provider.
		if ( 1 !== count( $providers ) ) {
			return 0;
		}

		$provider_class   = key( $providers );
		$ticket_type_key  = constant( $provider_class . '::ATTENDEE_PRODUCT_KEY' );
		$ticket_event_key = constant( $provider_class . '::ATTENDEE_EVENT_KEY' );

		if ( empty( $ticket_type_key ) || empty( $ticket_event_key ) ) {
			return 0;
		}

		foreach ( $ticket_objects as $ticket ) {
			$ticket_id          = $ticket['attendee_id'];
			$product_id         = $ticket['product_id'];
			$src_ticket_type_id = get_post_meta( $ticket_id, $ticket_type_key, true );
			$src_qty_sold       = (int) get_post_meta( $src_ticket_type_id, 'total_sales', true );
			$tgt_qty_sold       = (int) get_post_meta( $tgt_ticket_type_id, 'total_sales', true );

			//get stock levels for RSVP Tickets
			if ( 'Tribe__Tickets__RSVP' === $ticket['provider'] ) {
				$src_stock = (int) get_post_meta( $src_ticket_type_id, '_stock', true );
				$tgt_stock = (int) get_post_meta( $tgt_ticket_type_id, '_stock', true );
			}

			/**
			 * Fires immediately before a ticket is moved.
			 *
			 * @param int $ticket_type_id
			 * @param int $tgt_ticket_type_id
			 * @param int $tgt_event_id
			 * @param int $instigator_id
			 */
			do_action( 'tribe_tickets_ticket_before_move', $ticket_id, $tgt_ticket_type_id, $tgt_event_id, $instigator_id );

			/**
			 * Actual moving happens
			 */
			$tgt_event_cap = new Tribe__Tickets__Global_Stock( $tgt_event_id );

			$src_mode = get_post_meta( $product_id, Tribe__Tickets__Global_Stock::TICKET_STOCK_MODE, true );

			// When the Mode is not `own` we have to check and modify some stuff
			if ( Tribe__Tickets__Global_Stock::OWN_STOCK_MODE !== $src_mode ) {
				// If we have Source cap and not on Target, we set it up
				if ( ! $tgt_event_cap->is_enabled() ) {
					$src_event_capacity = tribe_tickets_get_capacity( $src_event_id );

					// Activate Shared Capacity on the Ticket
					$tgt_event_cap->enable();

					// Setup the Stock level to match Source capacity
					$tgt_event_cap->set_stock_level( $src_event_capacity );

					// Update the Target event with the Capacity from the Source
					update_post_meta( $tgt_event_id, tribe( 'tickets.handler' )->key_capacity, $src_event_capacity );
				} elseif ( Tribe__Tickets__Global_Stock::CAPPED_STOCK_MODE === $src_mode || Tribe__Tickets__Global_Stock::GLOBAL_STOCK_MODE === $src_mode ) {
					// Check if we have capped to avoid ticket cap over event cap
					$src_ticket_capacity = tribe_tickets_get_capacity( $product_id );
					$tgt_event_capacity = tribe_tickets_get_capacity( $tgt_event_id );

					// Don't allow ticket capacity to be bigger than Target Event Cap
					if ( $src_ticket_capacity > $tgt_event_capacity ) {
						update_post_meta( $ticket_id, tribe( 'tickets.handler' )->key_capacity, $tgt_event_capacity );
					}
				}
			}

			update_post_meta( $ticket_id, $ticket_type_key, $tgt_ticket_type_id );
			update_post_meta( $ticket_id, $ticket_event_key, $tgt_event_id );

			// adjust sales numbers - don't allow negatives
			$src_qty_sold--;
			$tgt_qty_sold++;
			update_post_meta( $src_ticket_type_id, 'total_sales', $src_qty_sold );
			update_post_meta( $tgt_ticket_type_id, 'total_sales', $tgt_qty_sold );

			//adjust stock numbers for RSVP Tickets
			if ( 'Tribe__Tickets__RSVP' === $ticket['provider'] ) {
				$src_stock ++;
				$tgt_stock --;
				update_post_meta( $src_ticket_type_id, '_stock', $src_stock );
				update_post_meta( $tgt_ticket_type_id, '_stock', $tgt_stock );
			}

			$history_message = sprintf(
				__( 'This ticket was moved to %1$s %2$s from %3$s %4$s', 'event-tickets' ),
				'<a href="' . esc_url( get_the_permalink( $tgt_event_id ) ) . '" target="_blank">' . get_the_title( $tgt_event_id ) . '</a>',
				'<a href="' . esc_url( get_the_permalink( $tgt_ticket_type_id ) ) . '" target="_blank">(' . get_the_title( $tgt_ticket_type_id ) . ')</a>',
				'<a href="' . esc_url( get_the_permalink( $src_event_id ) ) . '" target="_blank">' . get_the_title( $src_event_id ) . '</a>',
				'<a href="' . esc_url( get_the_permalink( $src_ticket_type_id ) ) . '" target="_blank">(' . get_the_title( $src_ticket_type_id ) . ')</a>'
			);

			$history_data = array(
				'ticket_ids' => $ticket_ids,
				'src_event_id' => $src_event_id,
				'tgt_event_id' => $tgt_event_id,
				'tgt_ticket_type_id' => $tgt_ticket_type_id,
			);

			Tribe__Post_History::load( $ticket_id )->add_entry( $history_message, $history_data );

			/**
			 * Fires when a ticket is relocated from ticket type to another, which may be in
			 * a different post altogether.
			 *
			 * @param int $ticket_id                the ticket which has been moved
			 * @param int $src_ticket_type_id       the ticket type it belonged to originally
			 * @param int $tgt_ticket_type_id       the ticket type it now belongs to
			 * @param int $src_event_id             the event/post which the ticket originally belonged to
			 * @param int $tgt_event_id             the event/post which the ticket now belongs to
			 * @param int $instigator_id            the user who initiated the change
			 */
			do_action( 'tribe_tickets_ticket_moved', $ticket_id, $src_ticket_type_id, $tgt_ticket_type_id, $src_event_id, $tgt_event_id, $instigator_id );

			$successful_moves++;
		}

		// Clear attendee cache now that the attendees have moved.
		foreach ( $providers as $provider ) {
			$provider->clear_attendees_cache( $src_event_id );
			$provider->clear_attendees_cache( $tgt_event_id );
		}

		/**
		 * Fires when all of the specified ticket IDs have been moved
		 *
		 * @param array $ticket_ids          each ticket ID
		 * @param int   $tgt_ticket_type_id  the ticket type they were moved to
		 * @param int   $src_event_id        the event they belonged to prior to the move
		 * @param int   $tgt_event_id        the event they belong to after the move
		 */
		do_action( 'tribe_tickets_all_tickets_moved', $ticket_ids, $tgt_ticket_type_id, $src_event_id, $tgt_event_id );

		return $successful_moves;
	}