<?php namespace PrestoPlayer\Services\API; use PrestoPlayer\Models\Video; use PrestoPlayer\Playlist; class RestVideosController extends \WP_REST_Controller { /** * Our namespace * * @var string */ protected $namespace = 'presto-player'; /** * API Version * * @var string */ protected $version = 'v1'; /** * Endpoint base * * @var string */ protected $base = 'videos'; /** * Register controller * * @return void */ public function register() { add_action('rest_api_init', [$this, 'register_routes']); } /** * Register videos routes * * @return void */ public function register_routes() { // create register_rest_route("{$this->namespace}/{$this->version}", '/' . $this->base, [ [ 'methods' => \WP_REST_Server::CREATABLE, 'callback' => [$this, 'create_item'], 'permission_callback' => [$this, 'create_item_permissions_check'], 'args' => $this->get_endpoint_args_for_item_schema(true), ], [ 'methods' => \WP_REST_Server::READABLE, 'callback' => [$this, 'get_items'], 'permission_callback' => [$this, 'get_items_permissions_check'], 'args' => [], ], 'schema' => [$this, 'get_schema'] ]); // get item register_rest_route("{$this->namespace}/{$this->version}", '/' . $this->base . '/(?P<id>\d+)', [ [ 'methods' => \WP_REST_Server::READABLE, 'callback' => [$this, 'get_item'], 'permission_callback' => [$this, 'get_item_permissions_check'], 'args' => [ 'id' => [ 'validate_callback' => function ($param) { return is_numeric($param); } ], 'context' => [ 'default' => 'view', ], ], ], [ 'methods' => \WP_REST_Server::EDITABLE, 'callback' => [$this, 'update_item'], 'permission_callback' => [$this, 'update_item_permissions_check'], 'args' => $this->get_endpoint_args_for_item_schema(false), ], 'schema' => [$this, 'get_schema'] ]); register_rest_field( 'pp_video_block', 'details', array( 'get_callback' => array($this, 'get_video_details'), 'schema' => null, ) ); } /** * Get Video Details * * @since x.x.x * @param string $object Rest Object. * @param string $field_name Rest Field. * @param array $request Rest Request. * @return string Site type either Free or Premium. */ public function get_video_details($object = '', $field_name = '', $request = array()) { $post_id = (int) $object['id']; return (new Playlist())->get_playlist_details($post_id); } /** * API Schema * * @return array */ public function get_schema() { return [ '$schema' => 'http://json-schema.org/draft-04/schema#', 'title' => 'video', 'type' => 'object', 'properties' => [ 'id' => [ 'description' => esc_html__('Unique identifier for the object.', 'presto-player'), 'type' => 'integer', 'context' => array('view', 'edit', 'embed'), 'readonly' => true, ], 'title' => [ 'description' => esc_html__('Title of the video.', 'presto-player'), 'type' => 'string', 'validate_callback' => 'is_string', 'sanitize_callback' => 'sanitize_text_field' ], 'type' => [ 'description' => esc_html__('Slug for the video type (one of youtube, vimeo, attachment, link)', 'presto-player'), 'type' => 'string', 'required' => true, 'validate_callback' => 'is_string', 'sanitize_callback' => 'sanitize_text_field' ], 'external_id' => [ 'description' => esc_html__('External unique id.', 'presto-player'), 'type' => 'string', 'validate_callback' => 'is_string', 'sanitize_callback' => 'sanitize_text_field' ], 'attachment_id' => [ 'description' => esc_html__('The id of the attachment.', 'presto-player'), 'type' => 'integer', ], 'post_id' => [ 'description' => esc_html__('The post the video is attached to.', 'presto-player'), 'type' => 'integer', ], 'src' => [ 'description' => esc_html__('Video source url.', 'presto-player'), 'type' => 'string', 'validate_callback' => 'is_string', 'sanitize_callback' => 'esc_url_raw' ], 'deleted_at' => [ 'type' => 'string', 'readonly' => true ], 'updated_at' => [ 'type' => 'string', 'readonly' => true ], 'created_at' => [ 'type' => 'string', 'readonly' => true ] ], ]; } /** * Create item * * @param WP_REST_Request $request Full data about the request. * @return WP_Error|WP_REST_Response */ public function create_item($request) { $item = $this->prepare_item_for_database($request); // which video to first or create? $where = ['src' => $item['src']]; // if there's an external video id if ($item['external_id']) { $where = ['external_id' => $item['external_id']]; } elseif ($item['attachment_id']) { $where = ['attachment_id' => $item['attachment_id']]; } // create video $video = new Video(); $video->updateOrCreate($where, $item); $data = $this->prepare_item_for_response($video->toArray(), $request); if (is_wp_error($data)) { return $data; } if (!empty($data)) { return new \WP_REST_Response($data, 200); } return new \WP_Error('cant-create', __('Cannot create video.', 'presto-player'), ['status' => 500]); } /** * Get item * * @param WP_REST_Request $request Full data about the request. * @return WP_Error|WP_REST_Response */ public function get_item($request) { // get video $video = new Video($request['id']); if (!$video->created_at) { return new \WP_Error('not_found', 'This video does not exist', 404); } $data = $this->prepare_item_for_response($video->toArray(), $request); if (is_wp_error($data)) { return $data; } if (!empty($data)) { return new \WP_REST_Response($data, 200); } return new \WP_Error('cant-get', __('Cannot get video.', 'presto-player'), ['status' => 500]); } /** * Get a collection of items * Update one item from the collection * * @param WP_REST_Request $request Full data about the request. * @return WP_Error|WP_REST_Response */ public function get_items($request) { $video = new Video(); $items = $video->fetch([ 'per_page' => 10000, 'order_by' => [ 'created_at' => 'ASC', ] ]); if (is_wp_error($items)) { return $items; } if (!isset($items->data)) { return new \WP_Error('error', 'Something went wrong'); } foreach ($items->data as $item) { $itemdata = $this->prepare_item_for_response($item->toArray(), $request); $data[] = $this->prepare_response_for_collection($itemdata); } return new \WP_REST_Response($data, 200); } public function update_item($request) { $item = $this->prepare_item_for_database($request); $video = new Video($request['id']); $updated = $video->update($item); // bail early on error if (is_wp_error($updated)) { return $updated; } $data = $this->prepare_item_for_response($video->toArray(), $request); if (is_wp_error($data)) { return $data; } if (!empty($data)) { return new \WP_REST_Response($data, 200); } return new \WP_Error('cant-update', __('Cannot update video.', 'presto-player'), ['status' => 500]); } /** * Check if a given request has access to create items * * @param WP_REST_Request $request Full data about the request. * @return WP_Error|bool */ public function create_item_permissions_check($request) { return current_user_can('upload_files'); } /** * Check if a given request has access to update a specific item * * @param WP_REST_Request $request Full data about the request. * @return WP_Error|bool */ public function update_item_permissions_check($request) { return current_user_can('upload_files'); } /** * Check if a given request has access to get items * * @param WP_REST_Request $request Full data about the request. * @return WP_Error|bool */ public function get_items_permissions_check($request) { return $this->get_item_permissions_check($request); } /** * Check if a given request has access to get items * * @param WP_REST_Request $request Full data about the request. * @return WP_Error|bool */ public function get_item_permissions_check($request) { return current_user_can('upload_files'); } /** * Prepare the item for create or update operation * Ensures we're only passing specific fields and double-checks sanitization * * @param WP_REST_Request $request Request object * @return WP_Error|object $prepared_item */ protected function prepare_item_for_database($request) { $prepared = [ 'type' => sanitize_text_field($request['type']), 'external_id' => sanitize_text_field($request['external_id']), 'attachment_id' => (int) $request['attachment_id'], 'post_id' => (int) $request['post_id'], 'src' => esc_url_raw($request['src']) ]; if (!empty($request['title'])) { $prepared['title'] = sanitize_text_field($request['title']); } return apply_filters('presto_player_rest_prepared_database_item', $prepared); } /** * Prepare the item for the REST response * * @param mixed $item WordPress representation of the item. * @param WP_REST_Request $request Request object. * @return mixed */ public function prepare_item_for_response($item, $request) { $schema = $this->get_schema(); $prepared = []; foreach ($item as $name => $value) { if (!empty($schema['properties'][$name])) { $prepared[$name] = rest_sanitize_value_from_schema($value, $schema['properties'][$name], $name); } } return apply_filters('presto_player_rest_prepared_response_item', $prepared); } /** * Get the query params for collections * * @return array */ public function get_collection_params() { return [ 'page' => [ 'description' => 'Current page of the collection.', 'type' => 'integer', 'default' => 1, 'sanitize_callback' => 'absint', ], 'per_page' => [ 'description' => 'Maximum number of items to be returned in result set.', 'type' => 'integer', 'default' => 10, 'sanitize_callback' => 'absint', ], 'search' => [ 'description' => 'Limit results to those matching a string.', 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', ], ]; } }