File "Single_Event.php"
Full Path: /home/romayxjt/public_html/wp-content/plugins/the-events-calendar/src/Tribe/REST/V1/Endpoints/Single_Event.php
File size: 23.05 KB
MIME-type: text/x-php
Charset: utf-8
<?php
class Tribe__Events__REST__V1__Endpoints__Single_Event
extends Tribe__Events__REST__V1__Endpoints__Base
implements Tribe__REST__Endpoints__READ_Endpoint_Interface,
Tribe__REST__Endpoints__CREATE_Endpoint_Interface,
Tribe__REST__Endpoints__DELETE_Endpoint_Interface,
Tribe__REST__Endpoints__UPDATE_Endpoint_Interface,
Tribe__Documentation__Swagger__Provider_Interface {
/**
* @var Tribe__REST__Main
*/
protected $main;
/**
* @var WP_REST_Request
*/
protected $serving;
/**
* @var Tribe__Events__REST__Interfaces__Post_Repository
*/
protected $post_repository;
/**
* @var Tribe__Events__REST__V1__Validator__Interface
*/
protected $validator;
/**
* @var Tribe__Events__REST__V1__Endpoints__Linked_Post_Endpoint_Interface
*/
protected $venue_endpoint;
/**
* @var Tribe__Events__REST__V1__Endpoints__Linked_Post_Endpoint_Interface
*/
protected $organizer_endpoint;
/**
* Tribe__Events__REST__V1__Endpoints__Single_Event constructor.
*
* @param Tribe__REST__Messages_Interface $messages
* @param Tribe__Events__REST__Interfaces__Post_Repository $post_repository
* @param Tribe__Events__REST__V1__Validator__Interface $validator
* @param Tribe__Events__REST__V1__Endpoints__Linked_Post_Endpoint_Interface $venue_endpoint
* @param Tribe__Events__REST__V1__Endpoints__Linked_Post_Endpoint_Interface $organizer_endpoint
*/
public function __construct(
Tribe__REST__Messages_Interface $messages,
Tribe__Events__REST__Interfaces__Post_Repository $post_repository,
Tribe__Events__REST__V1__Validator__Interface $validator,
Tribe__Events__REST__V1__Endpoints__Linked_Post_Endpoint_Interface $venue_endpoint,
Tribe__Events__REST__V1__Endpoints__Linked_Post_Endpoint_Interface $organizer_endpoint
) {
parent::__construct( $messages );
$this->post_repository = $post_repository;
$this->validator = $validator;
$this->venue_endpoint = $venue_endpoint;
$this->organizer_endpoint = $organizer_endpoint;
}
/**
* @param WP_REST_Request $request
*
* @return WP_REST_Response|WP_Error An array containing the data on success or a WP_Error instance on failure.
*/
public function get( WP_REST_Request $request ) {
$this->serving = $request;
$event = get_post( $request['id'] );
$cap = get_post_type_object( Tribe__Events__Main::POSTTYPE )->cap->read_post;
if ( ! ( 'publish' === $event->post_status || current_user_can( $cap, $request['id'] ) ) ) {
$message = $this->messages->get_message( 'event-not-accessible' );
return new WP_Error( 'event-not-accessible', $message, [ 'status' => 403 ] );
}
if ( ! $this->validator->can_access_password_content( $event, $request ) ) {
$message = $this->messages->get_message( 'event-password-protected' );
return new WP_Error( 'event-password-protected', $message, [ 'status' => 403 ] );
}
$data = $this->post_repository->get_event_data( $request['id'], 'single' );
/**
* Filters the data that will be returned for a single event request.
*
* @since 4.5.13
*
* @param array $data The retrieved data.
* @param WP_REST_Request $request The original request.
*/
$data = apply_filters( 'tribe_rest_single_event_data', $data, $request );
return is_wp_error( $data ) ? $data : new WP_REST_Response( $data );
}
/**
* Returns an array in the format used by Swagger 2.0.
*
* While the structure must conform to that used by v2.0 of Swagger the structure can be that of a full document
* or that of a document part.
* The intelligence lies in the "gatherer" of information rather than in the single "providers" implementing this
* interface.
*
* @link http://swagger.io/
*
* @return array An array description of a Swagger supported component.
*/
public function get_documentation() {
$get_defaults = $delete_defaults = [ 'in' => 'query', 'type' => 'string' ];
$post_args = $this->CREATE_args();
return [
'get' => [
'parameters' => $this->swaggerize_args( $this->READ_args(), $get_defaults ),
'responses' => [
'200' => [
'description' => __( 'Returns the data of the event with the specified post ID', 'the-events-calendar' ),
'content' => [
'application/json' => [
'schema' => [
'$ref' => '#/components/schemas/Event',
]
]
],
],
'400' => [
'description' => __( 'The event post ID is missing.', 'the-events-calendar' ),
],
'403' => [
'description' => __( 'The event with the specified ID is not accessible.', 'the-events-calendar' ),
],
'404' => [
'description' => __( 'An event with the specified ID does not exist.', 'the-events-calendar' ),
],
],
],
'post' => [
'parameters' => $this->swaggerize_args( $this->READ_args(), [] ),
'requestBody' => $this->swaggerize_post_args( 'application/x-www-form-urlencoded', $post_args ),
'responses' => [
'200' => [
'description' => __( 'Returns the data of the updated event', 'the-events-calendar' ),
'content' => [
'application/json' => [
'schema' => [
'$ref' => '#/components/schemas/Event',
]
]
],
],
'201' => [
'description' => __( 'Returns the data of the created event', 'the-events-calendar' ),
'content' => [
'application/json' => [
'schema' => [
'$ref' => '#/components/schemas/Event',
]
]
],
],
'400' => [
'description' => __( 'A required parameter is missing or an input parameter is in the wrong format', 'the-events-calendar' ),
],
'403' => [
'description' => __( 'The user is not authorized to create events', 'the-events-calendar' ),
],
],
],
'delete' => [
'parameters' => $this->swaggerize_args( $this->DELETE_args(), $delete_defaults ),
'responses' => [
'200' => [
'description' => __( 'Deletes an event and returns its data', 'the-events-calendar' ),
'content' => [
'application/json' => [
'schema' => [
'$ref' => '#/components/schemas/Event',
]
]
],
],
'400' => [
'description' => __( 'The event post ID is missing or does not exist.', 'the-events-calendar' ),
],
'403' => [
'description' => __( 'The current user cannot delete the event with the specified ID.', 'the-events-calendar' ),
],
'410' => [
'description' => __( 'The event with the specified ID has been deleted already.', 'the-events-calendar' ),
],
'500' => [
'description' => __( 'The event with the specified ID could not be deleted.', 'the-events-calendar' ),
],
],
],
];
}
/**
* Provides the content of the `args` array to register the endpoint support for GET requests.
*
* @return array
*/
public function READ_args() {
return [
'id' => [
'in' => 'path',
'type' => 'integer',
'description' => __( 'the event post ID', 'the-events-calendar' ),
'required' => true,
'validate_callback' => [ $this->validator, 'is_event_id' ],
],
'password' => [
'in' => 'path',
'type' => 'string',
'description' => __( 'The event password', 'the-events-calendar' ),
'required' => false,
'validate_callback' => [ $this->validator, 'is_string' ],
],
];
}
/**
* Returns the content of the `args` array that should be used to register the endpoint
* with the `register_rest_route` function.
*
* @return array
*/
public function CREATE_args() {
return [
// Post fields
'author' => [
'required' => false,
'validate_callback' => [ $this->validator, 'is_user_id' ],
'type' => 'integer',
'description' => __( 'The event author ID', 'the-events-calendar' ),
],
'date' => [
'required' => false,
'validate_callback' => [ $this->validator, 'is_time' ],
'type' => 'string',
'description' => __( 'The event publication date', 'the-events-calendar' ),
],
'date_utc' => [
'required' => false,
'validate_callback' => [ $this->validator, 'is_time' ],
'type' => 'string',
'description' => __( 'The event publication date (UTC time zone)', 'the-events-calendar' ),
],
'title' => [
'required' => true,
'validate_callback' => [ $this->validator, 'is_string' ],
'type' => 'string',
'description' => __( 'The event title', 'the-events-calendar' ),
],
'description' => [
'required' => false,
'validate_callback' => [ $this->validator, 'is_string' ],
'type' => 'string',
'description' => __( 'The event description', 'the-events-calendar' ),
],
'slug' => [
'required' => false,
'validate_callback' => [ $this->validator, 'is_string' ],
'type' => 'string',
'description' => __( 'The event slug', 'the-events-calendar' ),
],
'excerpt' => [
'required' => false,
'validate_callback' => [ $this->validator, 'is_string' ],
'type' => 'string',
'description' => __( 'The event excerpt', 'the-events-calendar' ),
],
'status' => [
'required' => false,
'validate_callback' => [ $this->validator, 'is_post_status' ],
'type' => 'string',
'description' => __( 'The event post status', 'the-events-calendar' ),
],
// Event meta fields
'timezone' => [
'required' => false,
'validate_callback' => [ $this->validator, 'is_timezone_or_empty' ],
'type' => 'string',
'description' => __( 'The event time zone', 'the-events-calendar' ),
],
'all_day' => [
'required' => false,
'default' => false,
'type' => 'boolean',
'description' => __( 'Whether the event lasts the whole day or not', 'the-events-calendar' ),
],
'start_date' => [
'required' => true,
'validate_callback' => [ $this->validator, 'is_time' ],
'type' => 'string',
'description' => __( 'The event start date and time', 'the-events-calendar' ),
],
'end_date' => [
'required' => true,
'validate_callback' => [ $this->validator, 'is_time' ],
'type' => 'string',
'description' => __( 'The event end date and time', 'the-events-calendar' ),
],
'image' => [
'required' => false,
'validate_callback' => [ $this->validator, 'is_image' ],
'type' => 'string',
'description' => __( 'The event featured image ID or URL', 'the-events-calendar' ),
],
'cost' => [
'required' => false,
'swagger_type' => 'string',
'description' => __( 'The event cost', 'the-events-calendar' ),
],
'website' => [
'required' => false,
'validate_callback' => [ $this->validator, 'is_url_or_empty' ],
'swagger_type' => 'string',
'default' => null,
'description' => __( 'The event website URL', 'the-events-calendar' ),
],
// Event presentation data
'show_map' => [
'required' => false,
'type' => 'boolean',
'description' => __( 'Whether the event should show a map or not', 'the-events-calendar' ),
],
'show_map_link' => [
'required' => false,
'type' => 'boolean',
'description' => __( 'Whether the event should show a map link or not', 'the-events-calendar' ),
],
'hide_from_listings' => [
'required' => false,
'type' => 'boolean',
'description' => __( 'Whether events should be hidden in the calendar view or not', 'the-events-calendar' ),
],
'sticky' => [
'required' => false,
'type' => 'boolean',
'description' => __( 'Whether the event should be sticky in the calendar view or not', 'the-events-calendar' ),
],
'featured' => [
'required' => false,
'type' => 'boolean',
'description' => __( 'Whether the event should be featured on the site or not', 'the-events-calendar' ),
],
// Taxonomies
'categories' => [
'required' => false,
'default' => null,
'swagger_type' => 'array',
'items' => [ 'type' => 'integer' ],
'description' => __( 'The event category ID or name', 'the-events-calendar' ),
],
'tags' => [
'required' => false,
'default' => null,
'swagger_type' => 'array',
'items' => [ 'type' => 'integer' ],
'description' => __( 'The event tag ID or name', 'the-events-calendar' ),
],
// Linked Posts
'venue' => [
'required' => false,
'default' => null,
'validate_callback' => [ $this->validator, 'is_venue_id_or_entry_or_empty' ],
'swagger_type' => 'array',
'items' => [ 'type' => 'integer' ],
'description' => __( 'The event venue IDs or data', 'the-events-calendar' ),
],
'organizer' => [
'required' => false,
'default' => null,
'validate_callback' => [ $this->validator, 'is_organizer_id_or_entry_or_empty' ],
'swagger_type' => 'array',
'items' => [ 'type' => 'integer' ],
'description' => __( 'The event organizer IDs or data', 'the-events-calendar' ),
],
];
}
/**
* Handles POST requests on the endpoint.
*
* @param WP_REST_Request $request
* @param bool $return_id Whether the created post ID should be returned or the full response object.
*
* @return WP_Error|WP_REST_Response|int An array containing the data on success or a WP_Error instance on failure.
*/
public function create( WP_REST_Request $request, $return_id = false ) {
$this->serving = $request;
$postarr = $this->prepare_postarr( $request );
if ( is_wp_error( $postarr ) ) {
return $postarr;
}
$id = Tribe__Events__API::createEvent( array_filter( $postarr ) );
if ( is_wp_error( $id ) ) {
return $id;
}
if ( $return_id ) {
return $id;
}
$data = $this->post_repository->get_event_data( $id );
$response = new WP_REST_Response( $data );
$response->set_status( 201 );
return $response;
}
/**
* Whether the current user can create content of the specified type or not.
*
* @return bool Whether the current user can post or not.
*/
public function can_create() {
$cap = get_post_type_object( Tribe__Events__Main::POSTTYPE )->cap->edit_posts;
return current_user_can( $cap );
}
/**
* Returns the content of the `args` array that should be used to register the endpoint
* with the `register_rest_route` function.
*
* @return array
*/
public function DELETE_args() {
return $this->READ_args();
}
/**
* Handles DELETE requests on the endpoint.
*
* @param WP_REST_Request $request
*
* @return WP_Error|WP_REST_Response An array containing the data of the trashed post on
* success or a WP_Error instance on failure.
*/
public function delete( WP_REST_Request $request ) {
$event_id = $request['id'];
$event = get_post( $event_id );
if ( 'trash' === $event->post_status ) {
$message = $this->messages->get_message( 'event-is-in-trash' );
return new WP_Error( 'event-is-in-trash', $message, [ 'status' => 410 ] );
}
/**
* Filters the event delete operation.
*
* Returning a non `null` value here will override the default trashing operation.
*
* @param int|bool $deleted Whether the event was successfully deleted or not.
* @param WP_REST_Request $request The original API request.
*
* @since 4.6
*/
$deleted = apply_filters( 'tribe_events_rest_event_delete', null, $request );
if ( null === $deleted ) {
$deleted = wp_trash_post( $event_id );
}
if ( false === $deleted ) {
$message = $this->messages->get_message( 'could-not-delete-event' );
return new WP_Error( 'could-not-delete-event', $message, [ 'status' => 500 ] );
}
$data = $this->post_repository->get_event_data( $event_id );
return is_wp_error( $data ) ? $data : new WP_REST_Response( $data );
}
/**
* Whether the current user can delete posts of the type managed by the endpoint or not.
*
* @since 4.6
*
* @return bool
*/
public function can_delete() {
$cap = get_post_type_object( Tribe__Events__Main::POSTTYPE )->cap->delete_posts;
return current_user_can( $cap );
}
/**
* Handles UPDATE requests on the endpoint.
*
* @param WP_REST_Request $request
*
* @return WP_Error|WP_REST_Response An array containing the data of the updated post on
* success or a WP_Error instance on failure.
*/
public function update( WP_REST_Request $request ) {
$this->serving = $request;
$postarr = $this->prepare_postarr( $request );
if ( is_wp_error( $postarr ) ) {
return $postarr;
}
$id = Tribe__Events__API::updateEvent( $request['id'], $postarr );
if ( is_wp_error( $id ) ) {
/** @var WP_Error $id */
return $id;
}
if ( false === $id ) {
$message = $this->messages->get_message( 'could-not-update-event' );
return new WP_Error( 'could-not-update-event', $message, [ 'status' => 403 ] );
}
$data = $this->post_repository->get_event_data( $id );
$response = new WP_REST_Response( $data );
$response->set_status( 200 );
return $response;
}
/**
* Returns the content of the `args` array that should be used to register the endpoint
* with the `register_rest_route` function.
*
* @return array
*/
public function EDIT_args() {
// when editing the only required argument is the ID ('id')
$create_args = $this->CREATE_args();
array_walk( $create_args, [ $this, 'unrequire_arg' ] );
return array_merge( $this->READ_args(), $create_args );
}
/**
* Whether the current user can update content of this type or not.
*
* @since 4.6
*
* @return bool Whether the current user can update or not.
*/
public function can_edit() {
return $this->can_create();
}
/**
* Prepares an array with the event data from the specified request.
*
* @param WP_REST_Request $request
*
* @return array|WP_Error An array specifying the event data, a `WP_Error` if an error occurred.
*/
protected function prepare_postarr( WP_REST_Request $request ) {
$events_cat = Tribe__Events__Main::TAXONOMY;
$post_date = isset( $request['date'] )
? Tribe__Date_Utils::build_date_object( $request['date'], $request['timezone'] )->format( 'Y-m-d H:i:s' )
: false;
$post_date_gmt = isset( $request['date_utc'] )
? Tribe__Timezones::localize_date( 'Y-m-d H:i:s', $request['date_utc'], 'UTC' )
: false;
// Resolve our dates based on timezone if available.
$event_start_date = null;
$event_start_time = null;
$event_end_date = null;
$event_end_time = null;
if ( $request['start_date'] ) {
$start_date_obj = Tribe__Date_Utils::build_date_object( $request['start_date'], $request['timezone'] );
$event_start_date = $start_date_obj->format( 'Y-m-d' );
$event_start_time = $start_date_obj->format( 'H:i:s' );
}
if ( $request['end_date'] ) {
$end_date_obj = Tribe__Date_Utils::build_date_object( $request['end_date'], $request['timezone'] );
$event_end_date = $end_date_obj->format( 'Y-m-d' );
$event_end_time = $end_date_obj->format( 'H:i:s' );
}
$postarr = [
// Post fields
'post_author' => $request['author'],
'post_date' => $post_date,
'post_date_gmt' => $post_date_gmt,
'post_title' => $request['title'],
'post_name' => $request['slug'],
'post_content' => $request['description'],
'post_excerpt' => $request['excerpt'],
'post_status' => $this->scale_back_post_status( $request['status'], Tribe__Events__Main::POSTTYPE ),
// Event data
'EventTimezone' => $request['timezone'],
'EventAllDay' => isset( $request['all_day'] ) ? tribe_is_truthy( $request['all_day'] ) : null,
'EventStartDate' => $event_start_date,
'EventStartTime' => $event_start_time,
'EventEndDate' => $event_end_date,
'EventEndTime' => $event_end_time,
'FeaturedImage' => tribe_upload_image( $request['image'] ),
'EventCost' => $request['cost'],
'EventCurrencyPosition' => tribe( 'cost-utils' )->parse_currency_position( $request['cost'] ),
'EventCurrencySymbol' => tribe( 'cost-utils' )->parse_currency_symbol( $request['cost'] ),
'EventURL' => filter_var( $request['website'], FILTER_SANITIZE_URL ),
// Taxonomies
'tax_input' => [],
];
// Check if categories is provided (allowing for empty array to remove categories).
if ( isset( $request['categories'] ) ) {
$postarr['tax_input'][ $events_cat ] = [];
if ( ! empty( $request['categories'] ) ) {
$postarr['tax_input'][ $events_cat ] = Tribe__Terms::translate_terms_to_ids( $request['categories'], $events_cat );
}
}
// Check if tags is provided (allowing for empty array to remove tags).
if ( isset( $request['tags'] ) ) {
$postarr['tax_input']['post_tag'] = [];
if ( ! empty( $request['tags'] ) ) {
$postarr['tax_input']['post_tag'] = Tribe__Terms::translate_terms_to_ids( $request['tags'], 'post_tag' );
}
}
// If an empty EventTimezone was passed, lets unset it so it can be unset during event meta save
if ( empty( $postarr['EventTimezone'] ) ) {
unset( $postarr['EventTimezone'] );
} else {
// If we are changing a timezone, we need to ensure clear EventTimezoneAbbr so it gets correctly set.
$postarr['EventTimezoneAbbr'] = '';
}
$venue = $this->venue_endpoint->insert( $request['venue'] );
if ( is_wp_error( $venue ) ) {
return $venue;
}
$postarr['venue'] = $venue;
$organizer = $this->organizer_endpoint->insert( $request['organizer'] );
if ( is_wp_error( $organizer ) ) {
return $organizer;
}
$postarr['organizer'] = $organizer;
// Event presentation data
$postarr['EventShowMap'] = tribe_is_truthy( $request['show_map'] );
$postarr['EventShowMapLink'] = tribe_is_truthy( $request['show_map_link'] );
if ( tribe_is_truthy( $request['hide_from_listings'] ) ) {
$postarr['EventHideFromUpcoming'] = 'yes';
}
$postarr['EventShowInCalendar'] = tribe_is_truthy( $request['sticky'] );
$postarr['feature_event'] = tribe_is_truthy( $request['featured'] );
// If we are scheduling an event and a date has been provided, WP requires an additional argument
if ( ! empty( $postarr['post_status'] ) && 'future' === $postarr['post_status'] && ! empty( $postarr['post_date'] ) ) {
$postarr['edit_date'] = true;
}
/**
* Allow filtering of $postarr data with additional $request arguments.
*
* @param array $postarr Post array used for create/update
* @param WP_REST_Request $request REST request object
*
* @since 4.6
*/
$postarr = apply_filters( 'tribe_events_rest_event_prepare_postarr', $postarr, $request );
$postarr = array_filter( $postarr, [ $this->validator, 'is_not_null' ] );
return $postarr;
}
}