-
Notifications
You must be signed in to change notification settings - Fork 0
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
add standalone jw player adapter and api logic #10
Changes from 12 commits
3dde99b
8c57df8
31c3aeb
1bc6198
dcd3f22
6e57ffb
5b66892
8d24cc1
1cfbed8
4a728e9
400d6c6
91d61c9
55c36fc
97b5f7b
910760d
b15d7a2
0bb364a
020ded3
f54af24
e7e8ce0
3ad4dd5
7397082
31a0135
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
<?php | ||
/** | ||
* WP Video Sync: JW Player Adapter. | ||
* | ||
* @package wp-video-sync | ||
*/ | ||
|
||
namespace Alley\WP\WP_Video_Sync\Adapters; | ||
|
||
use Alley\WP\WP_Video_Sync\API\JW_Player_API; | ||
use Alley\WP\WP_Video_Sync\API\Request; | ||
use Alley\WP\WP_Video_Sync\Interfaces\Adapter; | ||
use Alley\WP\WP_Video_Sync\Last_Modified_Date; | ||
use DateTimeImmutable; | ||
|
||
/** | ||
* JW Player Adapter. | ||
*/ | ||
class JW_Player extends Last_Modified_Date implements Adapter { | ||
|
||
/** | ||
* The JW Player API. | ||
* | ||
* @var JW_Player_API | ||
*/ | ||
public JW_Player_API $jw_player_api; | ||
|
||
/** | ||
* Constructor. | ||
* | ||
* @param JW_Player_API $api Instance of the JW Player API object. | ||
*/ | ||
public function __construct( JW_Player_API $api ) { | ||
$this->jw_player_api = $api; | ||
} | ||
|
||
/** | ||
* Fetches videos from JW Player that were modified after the provided DateTime. | ||
* | ||
* @param DateTimeImmutable $updated_after Return videos modified after this date. | ||
* @param int $batch_size The number of videos to fetch in each batch. | ||
* | ||
* @return array<mixed> An array of video data objects. | ||
*/ | ||
public function get_videos( DateTimeImmutable $updated_after, int $batch_size ): array { | ||
// Set the request URL based on the arguments. | ||
$this->jw_player_api->set_request_url( | ||
$updated_after->format( 'Y-m-d' ), | ||
$batch_size | ||
); | ||
|
||
// Perform the request. | ||
$videos = ( new Request( $this->jw_player_api ) )->get(); | ||
|
||
// Check for an API error. | ||
if ( ! empty( $videos['error'] ) ) { | ||
return []; | ||
} | ||
|
||
// Validate the media property. | ||
if ( ! is_array( $videos['media'] ) ) { | ||
return []; | ||
} | ||
|
||
// Attempt to set the last modified date. | ||
if ( | ||
! empty( $videos['media'][ count( $videos['media'] ) - 1 ] ) | ||
&& isset( $videos['media'][ count( $videos['media'] ) - 1 ]->last_modified ) | ||
) { | ||
$this->set_last_modified_date( $videos['media'][ count( $videos ) - 1 ]->last_modified ); | ||
} | ||
|
||
// Return the videos. | ||
return ! empty( $videos['media'] ) ? $videos['media'] : []; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
<?php | ||
/** | ||
* WP Video Sync: JW Player API integration. | ||
* | ||
* @package wp-video-sync | ||
*/ | ||
|
||
namespace Alley\WP\WP_Video_Sync\API; | ||
|
||
use Alley\WP\WP_Video_Sync\Interfaces\API_Requester; | ||
|
||
/** | ||
* JW Player API. | ||
*/ | ||
class JW_Player_API implements API_Requester { | ||
|
||
/** | ||
* The API URL. | ||
* | ||
* @var string | ||
*/ | ||
public string $api_url = 'https://api.jwplayer.com/v2/sites'; | ||
|
||
/** | ||
* The API public key. | ||
* | ||
* @var string | ||
*/ | ||
public string $api_key; | ||
|
||
/** | ||
* The API v2 secret key. | ||
* | ||
* @var string | ||
*/ | ||
public string $api_secret; | ||
|
||
/** | ||
* The request URL. | ||
* | ||
* @var string | ||
*/ | ||
public string $request_url; | ||
|
||
/** | ||
* Constructor. | ||
* | ||
* @param string $api_key The API key. | ||
* @param string $api_secret The API secret. | ||
*/ | ||
public function __construct( string $api_key, string $api_secret ) { | ||
$this->api_key = $api_key; | ||
$this->api_secret = $api_secret; | ||
} | ||
|
||
/** | ||
* Generate the request URL. | ||
* | ||
* @param string $last_modified_date The date of the last modification to the last batch of videos. | ||
* @param int $batch_size The number of videos to fetch in each batch. | ||
*/ | ||
public function set_request_url( string $last_modified_date, int $batch_size ): void { | ||
$request_url = $this->api_url . '/' . $this->api_key . '/media/'; | ||
|
||
$this->request_url = add_query_arg( | ||
[ | ||
'q' => 'last_modified:[' . $last_modified_date . ' TO *]', | ||
'page' => 1, | ||
'sort' => 'last_modified:asc', | ||
'page_length' => $batch_size, | ||
], | ||
$request_url | ||
); | ||
} | ||
|
||
/** | ||
* Get the request URL. | ||
* | ||
* @return string | ||
*/ | ||
public function get_request_url(): string { | ||
return $this->request_url; | ||
} | ||
|
||
/** | ||
* Get the request arguments. | ||
* | ||
* @return array<string, array<string, string>> | ||
*/ | ||
public function get_request_args(): array { | ||
return [ | ||
'headers' => [ | ||
'Authorization' => 'Bearer ' . $this->api_secret, | ||
'Content-Type' => 'application/json', | ||
], | ||
]; | ||
} | ||
|
||
/** | ||
* Parse the API error response. | ||
* | ||
* @param array<mixed> $response_object The API response object. | ||
* | ||
* @return array<string, string> | ||
*/ | ||
public function parse_error( array $response_object ): array { | ||
return ! empty( $response_object['errors'] ) | ||
&& is_array( $response_object['errors'] ) | ||
&& isset( $response_object['errors'][0]->description ) | ||
? [ 'error' => $response_object['errors'][0]->description ] | ||
: []; | ||
} | ||
|
||
/** | ||
* Parse the API successful response. | ||
* | ||
* @param array<mixed> $response_object The API response object. | ||
* | ||
* @return array<string, mixed> | ||
*/ | ||
public function parse_success( array $response_object ): array { | ||
return ! empty( $response_object['media'] ) | ||
&& is_array( $response_object['media'] ) | ||
? [ 'media' => $response_object['media'] ] | ||
: []; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,151 @@ | ||||||||||||||||||||||||||||||||||||||||||||
<?php | ||||||||||||||||||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||||||||||||||||||
* WP Video Sync: API request integration. | ||||||||||||||||||||||||||||||||||||||||||||
* | ||||||||||||||||||||||||||||||||||||||||||||
* @package wp-video-sync | ||||||||||||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
namespace Alley\WP\WP_Video_Sync\API; | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
use Alley\WP\WP_Video_Sync\Interfaces\API_Requester; | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||||||||||||||||||
* Perform an API request. | ||||||||||||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||||||||||||
class Request { | ||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is interesting - I've always implemented API adapters as self-contained, rather than passing them as dependencies using DI into a generic request class. Is this a pattern that we're using elsewhere? I can see how it would cut down on repeated code, but I can also see how it would introduce some confusion into utilization (you have to set the properties of the API object including request URL, then pass it to the request class for execution, versus calling a method on the API class to get the data). A way to make this a bit more user friendly would be to encapsulate this functionality in the JW Player API class like so: public function get_videos_after( DateTimeImmutable $updated_after, int $batch_size ): array {
$this->set_request_url(
$updated_after->format( 'Y-m-d' ),
$batch_size
);
return ( new Request( $this ) )->get();
} That code could be moved out of the adapter and into the API wrapper, and then the adapter would call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This has been updated in the latest commit: 7397082 |
||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||||||||||||||||||
* The API requester. | ||||||||||||||||||||||||||||||||||||||||||||
* | ||||||||||||||||||||||||||||||||||||||||||||
* @var API_Requester | ||||||||||||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||||||||||||
public API_Requester $api_requester; | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||||||||||||||||||
* Constructor. | ||||||||||||||||||||||||||||||||||||||||||||
* | ||||||||||||||||||||||||||||||||||||||||||||
* @param API_Requester $api_requester The API requester. | ||||||||||||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||||||||||||
public function __construct( API_Requester $api_requester ) { | ||||||||||||||||||||||||||||||||||||||||||||
$this->api_requester = $api_requester; | ||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 |
||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||||||||||||||||||
* Set the user agent in the request headers for identification purposes. | ||||||||||||||||||||||||||||||||||||||||||||
* | ||||||||||||||||||||||||||||||||||||||||||||
* @return string | ||||||||||||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||||||||||||
public function user_agent(): string { | ||||||||||||||||||||||||||||||||||||||||||||
global $wp_version; | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
return 'WordPress/' . $wp_version . ' WPVideoSync/' . WP_VIDEO_SYNC_VERSION . ' PHP/' . phpversion(); | ||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||||||||||||||||||
* Get the request arguments. | ||||||||||||||||||||||||||||||||||||||||||||
* | ||||||||||||||||||||||||||||||||||||||||||||
* @return array<string, mixed> | ||||||||||||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||||||||||||
public function get_request_args(): array { | ||||||||||||||||||||||||||||||||||||||||||||
$requester_args = $this->api_requester->get_request_args(); | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
if ( empty( $requester_args['user-agent'] ) ) { | ||||||||||||||||||||||||||||||||||||||||||||
$requester_args['user-agent'] = $this->user_agent(); | ||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||||||||||||||||||
* Allow the request arguments to be filtered before the request is made. | ||||||||||||||||||||||||||||||||||||||||||||
* | ||||||||||||||||||||||||||||||||||||||||||||
* @param array<string, string|float|int|bool|array> $requester_args The request arguments. | ||||||||||||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||||||||||||
return apply_filters( 'wp_video_sync_request_args', $requester_args ); | ||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||||||||||||||||||
* Parse the API response. | ||||||||||||||||||||||||||||||||||||||||||||
* | ||||||||||||||||||||||||||||||||||||||||||||
* @param mixed $response The API response. | ||||||||||||||||||||||||||||||||||||||||||||
* | ||||||||||||||||||||||||||||||||||||||||||||
* @return array<string, mixed> | ||||||||||||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||||||||||||
private function parse_response( mixed $response ): array { | ||||||||||||||||||||||||||||||||||||||||||||
// Failed request expressed as a WP_Error. | ||||||||||||||||||||||||||||||||||||||||||||
if ( is_wp_error( $response ) || empty( $response ) || ! is_array( $response ) ) { | ||||||||||||||||||||||||||||||||||||||||||||
return []; | ||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
// Condition for when the response body is empty. | ||||||||||||||||||||||||||||||||||||||||||||
$response_body = wp_remote_retrieve_body( $response ); | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
if ( empty( $response_body ) ) { | ||||||||||||||||||||||||||||||||||||||||||||
return []; | ||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
// Assign the response object for further evaluation. | ||||||||||||||||||||||||||||||||||||||||||||
$response_object = (array) json_decode( $response_body ); | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
// Explicitly state the results based on response code. | ||||||||||||||||||||||||||||||||||||||||||||
return 200 === wp_remote_retrieve_response_code( $response ) | ||||||||||||||||||||||||||||||||||||||||||||
? $this->api_requester->parse_success( $response_object ) | ||||||||||||||||||||||||||||||||||||||||||||
: $this->api_requester->parse_error( $response_object ); | ||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||||||||||||||||||
* Perform a GET request. | ||||||||||||||||||||||||||||||||||||||||||||
* | ||||||||||||||||||||||||||||||||||||||||||||
* @return array<string, mixed> | ||||||||||||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||||||||||||
public function get(): array { | ||||||||||||||||||||||||||||||||||||||||||||
if ( function_exists( 'vip_safe_wp_remote_get' ) ) { | ||||||||||||||||||||||||||||||||||||||||||||
$api_request = vip_safe_wp_remote_get( | ||||||||||||||||||||||||||||||||||||||||||||
$this->api_requester->get_request_url(), | ||||||||||||||||||||||||||||||||||||||||||||
'', | ||||||||||||||||||||||||||||||||||||||||||||
3, | ||||||||||||||||||||||||||||||||||||||||||||
5, | ||||||||||||||||||||||||||||||||||||||||||||
3, | ||||||||||||||||||||||||||||||||||||||||||||
$this->get_request_args() | ||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||
// Get the base request arguments. | ||||||||||||||||||||||||||||||||||||||||||||
$custom_args = $this->get_request_args(); | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
// Explicitly define the request arguments. | ||||||||||||||||||||||||||||||||||||||||||||
// NOTE: this is addressing an error stemming from PHPStan where the passed arguments to the `wp_remote_get()` were not accepted. | ||||||||||||||||||||||||||||||||||||||||||||
$request_args = []; | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
// Request method. | ||||||||||||||||||||||||||||||||||||||||||||
if ( ! empty( $custom_args['method'] ) && is_string( $custom_args['method'] ) ) { | ||||||||||||||||||||||||||||||||||||||||||||
$request_args['method'] = $custom_args['method']; | ||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
// Request headers. | ||||||||||||||||||||||||||||||||||||||||||||
if ( | ||||||||||||||||||||||||||||||||||||||||||||
! empty( $custom_args['headers'] ) | ||||||||||||||||||||||||||||||||||||||||||||
&& ( | ||||||||||||||||||||||||||||||||||||||||||||
is_string( $custom_args['headers'] ) | ||||||||||||||||||||||||||||||||||||||||||||
|| is_array( $custom_args['headers'] ) | ||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||
) { | ||||||||||||||||||||||||||||||||||||||||||||
$request_args['headers'] = $custom_args['headers']; | ||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
// Request timeout. | ||||||||||||||||||||||||||||||||||||||||||||
if ( ! empty( $custom_args['timeout'] ) && is_float( $custom_args['timeout'] ) ) { | ||||||||||||||||||||||||||||||||||||||||||||
$request_args['timeout'] = $custom_args['timeout']; | ||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
// Request user agent. | ||||||||||||||||||||||||||||||||||||||||||||
if ( ! empty( $custom_args['user-agent'] ) && is_string( $custom_args['user-agent'] ) ) { | ||||||||||||||||||||||||||||||||||||||||||||
$request_args['user-agent'] = $custom_args['user-agent']; | ||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
// Perform the request. | ||||||||||||||||||||||||||||||||||||||||||||
$api_request = wp_remote_get( // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.wp_remote_get_wp_remote_get | ||||||||||||||||||||||||||||||||||||||||||||
$this->api_requester->get_request_url(), | ||||||||||||||||||||||||||||||||||||||||||||
array_filter( $request_args ) | ||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
return $this->parse_response( $api_request ); | ||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's make this a modern PHP constructor: