Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SL-264 - Include Seating info in Attendee REST response #3467

Merged
merged 7 commits into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions changelog/SL-264
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: feat

Include Seating information in Attendee archive REST API response.
1 change: 1 addition & 0 deletions src/Tickets/Seating/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ function () {
}

$this->container->register( QR::class );
$this->container->register( REST::class );

$this->container->register( Health::class );
}
Expand Down
92 changes: 92 additions & 0 deletions src/Tickets/Seating/REST.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php
/**
* Modifies REST API responses as required by the Seating feature.
*
* @since TBD
*
* @package TEC\Tickets\Seating;
*/

namespace TEC\Tickets\Seating;

use TEC\Common\Contracts\Provider\Controller as Controller_Contract;

/**
* Class REST.
*
* @since TBD
*
* @package TEC\Tickets\Seating;
*/
class REST extends Controller_Contract{
Camwyn marked this conversation as resolved.
Show resolved Hide resolved

/**
* Subscribes the controller to relevant hooks, binds implementations.
*
* @since TBD
*
* @return void
*/
protected function do_register(): void {
add_filter( 'tec_tickets_rest_attendee_archive_data', [ $this, 'inject_attendee_data' ] );
}

/**
* Unsubscribes the controller from all registered hooks.
*
* @since TBD
*
* @return void
*/
public function unregister(): void {
remove_filter( 'tec_tickets_rest_attendee_archive_data', [ $this, 'inject_attendee_data' ] );
}

/**
* Injects ASC related data in the Attendee REST response.
*
* @since TBD
*
* @param array<string,mixed> $data The Attendee archcive REST API response data.
*
* @return array<string,mixed> The Attendee archcive REST API response data modified to include ASC related data.
*/
public function inject_attendee_data( $data ) {
Camwyn marked this conversation as resolved.
Show resolved Hide resolved
Camwyn marked this conversation as resolved.
Show resolved Hide resolved
if ( ! is_array( $data ) ) {
return $data;
}

if ( ! tribe( 'tickets.rest-v1.main' )->request_has_manage_access() ) {
return $data;
}


$attendees = $data['attendees'] ?? [];

if ( ! is_array( $attendees ) ) {
return $data;
}

array_walk( $attendees, function ( &$attendee ) {
Camwyn marked this conversation as resolved.
Show resolved Hide resolved
if ( ! ( is_array( $attendee ) && isset( $attendee['id'], $attendee['ticket_id'] ) ) ) {
return;
}

// Let's check the ticket of this Attendee is an ASC one.
$ticket_id = $attendee['ticket_id'];
$uses_assigned_seating = get_post_meta( $ticket_id, Meta::META_KEY_ENABLED, true );

if ( ! $uses_assigned_seating ) {
return;
}

$seat_label = get_post_meta( $attendee['id'], Meta::META_KEY_ATTENDEE_SEAT_LABEL, true );
$attendee['asc_ticket'] = true;
$attendee['seat_label'] = $seat_label ?: '';
} );

$data['attendees'] = $attendees;

return $data;
}
}
12 changes: 11 additions & 1 deletion src/Tribe/REST/V1/Endpoints/Attendee_Archive.php
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,17 @@ public function get( WP_REST_Request $request ) {
'X-ET-TOTAL-PAGES' => $data['total_pages'],
];

return new WP_REST_Response( $data, 200, $headers );
/**
* Filters the data in the Attendee Archive REST response.
*
* @since TBD
*
* @param array<string,mixed> $data The data in the Attendee Archive REST response.
* @param WP_REST_Request $request The request object for this endpoint.
*/
$data = apply_filters( 'tec_tickets_rest_attendee_archive_data', $data, $request );

return new WP_REST_Response( $data, 200, $headers );
Camwyn marked this conversation as resolved.
Show resolved Hide resolved
}

/**
Expand Down
95 changes: 95 additions & 0 deletions tests/slr_integration/REST_Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?php

namespace TEC\Tickets\Seating;

use TEC\Common\Tests\Provider\Controller_Test_Case;
use Tribe\Tickets\Test\Commerce\Attendee_Maker;
use Tribe\Tickets\Test\Commerce\TicketsCommerce\Ticket_Maker;

class QR_Test extends Controller_Test_Case {
use Ticket_Maker;
use Attendee_Maker;

protected string $controller_class = REST::class;

public function test_inject_attendee_data(): void {
$non_asc_post = self::factory()->post->create();
$ticket_1 = $this->create_tc_ticket( $non_asc_post, 10 );
$attendee_1 = $this->create_attendee_for_ticket( $ticket_1, $non_asc_post );
$asc_post = self::factory()->post->create();
update_post_meta( $asc_post, Meta::META_KEY_ENABLED, true );
update_post_meta( $asc_post, Meta::META_KEY_LAYOUT_ID, 'layout-uuid-1' );
$ticket_2 = $this->create_tc_ticket( $asc_post, 20 );
update_post_meta( $ticket_2, Meta::META_KEY_SEAT_TYPE, 'seat-type-uuid-1' );
update_post_meta( $ticket_2, Meta::META_KEY_ENABLED, true );
[ $attendee_2, $attendee_3 ] = $this->create_many_attendees_for_ticket( 2, $ticket_2, $asc_post );
update_post_meta( $attendee_2, Meta::META_KEY_SEAT_TYPE, 'seat-type-uuid-1' );
update_post_meta( $attendee_2, Meta::META_KEY_RESERVATION_ID, 'reservation-uuid-1' );
update_post_meta( $attendee_2, Meta::META_KEY_ATTENDEE_SEAT_LABEL, 'A-23' );
update_post_meta( $attendee_3, Meta::META_KEY_SEAT_TYPE, 'seat-type-uuid-1' );
update_post_meta( $attendee_3, Meta::META_KEY_RESERVATION_ID, 'reservation-uuid-2' );
delete_post_meta( $attendee_3, Meta::META_KEY_ATTENDEE_SEAT_LABEL );
$controller = $this->make_controller();

// Attendee data is not an array.
$this->assertEquals( 'foo', $controller->inject_attendee_data( 'foo' ) );

// Attendee data is an empty array.
$this->assertEquals( [], $controller->inject_attendee_data( [] ) );

$good_attendee_1_data = [
'id' => $attendee_1,
'ticket_id' => $ticket_1,
];

// User is has not manage access: data is not modified.
wp_set_current_user( 0 );
$this->assertEquals(
[ 'attendees' => [ $good_attendee_1_data ] ],
$controller->inject_attendee_data( [ 'attendees' => [ $good_attendee_1_data ] ] )
);

// Set to a user that could edit them.
wp_set_current_user( static::factory()->user->create( [ 'role' => 'administrator' ] ) );

// Attendee data is not an array.
$this->assertEquals(
[ 'attendees' => 'not-an-array' ],
$controller->inject_attendee_data( [ 'attendees' => 'not-an-array' ] )
);

// Attendee data is an array, but attendees are not.
$this->assertEquals(
[ 'attendees' => [ 'not-an-array', 'another-thing' ] ],
$controller->inject_attendee_data( [ 'attendees' => [ 'not-an-array', 'another-thing' ] ] )
);

// Attendee data is an array, but attendee is missing id.
$this->assertEquals(
[ 'attendees' => [ [ 'ticket_id' => $ticket_2 ] ] ],
$controller->inject_attendee_data( [ 'attendees' => [ [ 'ticket_id' => $ticket_2 ] ] ] )
);

// Attendee data is an array, but attendee is missing ticket_id.
$this->assertEquals(
[ 'attendees' => [ [ 'id' => $attendee_2 ] ] ],
$controller->inject_attendee_data( [ 'attendees' => [ [ 'id' => $attendee_2 ] ] ] )
);

// Attendee data is correct.
$this->assertEquals(
[
'attendees' => [
[ 'id' => $attendee_2, 'ticket_id' => $ticket_2, 'asc_ticket' => true, 'seat_label' => 'A-23' ],
[ 'id' => $attendee_3, 'ticket_id' => $ticket_2, 'asc_ticket' => true, 'seat_label' => '' ]
]
],
$controller->inject_attendee_data( [
'attendees' => [
[ 'id' => $attendee_2, 'ticket_id' => $ticket_2 ],
[ 'id' => $attendee_3, 'ticket_id' => $ticket_2 ]
]
] )
);
}
}
Loading