summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYury German <blueknight@gentoo.org>2022-06-15 12:08:35 -0400
committerYury German <blueknight@gentoo.org>2022-06-15 12:08:35 -0400
commit36d7691c33cb64ece817246e47a779ec648d10b0 (patch)
tree08f2fb95303a1d8eeba2c8629a24b35a91fb1cac /plugins/jetpack/class.json-api-endpoints.php
parenttwentyfourteen upg 2.7 to 3.2 and twentysixteen from 2.0 to 2.5 (diff)
downloadblogs-gentoo-36d7691c33cb64ece817246e47a779ec648d10b0.tar.gz
blogs-gentoo-36d7691c33cb64ece817246e47a779ec648d10b0.tar.bz2
blogs-gentoo-36d7691c33cb64ece817246e47a779ec648d10b0.zip
Openid-3.6.1 and jetpack-11.0 upgrade
Signed-off-by: Yury German <blueknight@gentoo.org>
Diffstat (limited to 'plugins/jetpack/class.json-api-endpoints.php')
-rw-r--r--plugins/jetpack/class.json-api-endpoints.php728
1 files changed, 537 insertions, 191 deletions
diff --git a/plugins/jetpack/class.json-api-endpoints.php b/plugins/jetpack/class.json-api-endpoints.php
index 22aeb295..4ee2d303 100644
--- a/plugins/jetpack/class.json-api-endpoints.php
+++ b/plugins/jetpack/class.json-api-endpoints.php
@@ -1,53 +1,109 @@
-<?php
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
+/**
+ * Jetpack API endpoint base class.
+ *
+ * @package automattic/jetpack
+ */
use Automattic\Jetpack\Connection\Client;
-require_once dirname( __FILE__ ) . '/json-api-config.php';
-require_once dirname( __FILE__ ) . '/sal/class.json-api-links.php';
-require_once dirname( __FILE__ ) . '/sal/class.json-api-metadata.php';
-require_once dirname( __FILE__ ) . '/sal/class.json-api-date.php';
+require_once __DIR__ . '/json-api-config.php';
+require_once __DIR__ . '/sal/class.json-api-links.php';
+require_once __DIR__ . '/sal/class.json-api-metadata.php';
+require_once __DIR__ . '/sal/class.json-api-date.php';
-// Endpoint
+/**
+ * Endpoint.
+ */
abstract class WPCOM_JSON_API_Endpoint {
- // The API Object
+ /**
+ * The API Object
+ *
+ * @var WPCOM_JSON_API
+ */
public $api;
- // The link-generating utility class
+ /**
+ * The link-generating utility class
+ *
+ * @var WPCOM_JSON_API_Links
+ */
public $links;
+ /**
+ * Whether to pass wpcom user details.
+ *
+ * @var bool
+ */
public $pass_wpcom_user_details = false;
- // One liner.
+ /**
+ * One liner.
+ *
+ * @var string
+ */
public $description;
- // Object Grouping For Documentation (Users, Posts, Comments)
+ /**
+ * Object Grouping For Documentation (Users, Posts, Comments)
+ *
+ * @var string
+ */
public $group;
- // Stats extra value to bump
+ /**
+ * Stats extra value to bump
+ *
+ * @var mixed
+ */
public $stat;
- // HTTP Method
+ /**
+ * HTTP Method
+ *
+ * @var string
+ */
public $method = 'GET';
- // Minimum version of the api for which to serve this endpoint
+ /**
+ * Minimum version of the api for which to serve this endpoint
+ *
+ * @var string
+ */
public $min_version = '0';
- // Maximum version of the api for which to serve this endpoint
+ /**
+ * Maximum version of the api for which to serve this endpoint
+ *
+ * @var string
+ */
public $max_version = WPCOM_JSON_API__CURRENT_VERSION;
- // Path at which to serve this endpoint: sprintf() format.
+ /**
+ * Path at which to serve this endpoint: sprintf() format.
+ *
+ * @var string
+ */
public $path = '';
- // Identifiers to fill sprintf() formatted $path
+ /**
+ * Identifiers to fill sprintf() formatted $path
+ *
+ * @var array
+ */
public $path_labels = array();
- // Accepted query parameters
+ /**
+ * Accepted query parameters
+ *
+ * @var array
+ */
public $query = array(
- // Parameter name
+ // Parameter name.
'context' => array(
- // Default value => description
+ // Default value => description.
'display' => 'Formats the output as HTML for display. Shortcodes are parsed, paragraph tags are added, etc..',
- // Other possible values => description
+ // Other possible values => description.
'edit' => 'Formats the output for editing. Shortcodes are left unparsed, significant whitespace is kept, etc..',
),
'http_envelope' => array(
@@ -60,75 +116,119 @@ abstract class WPCOM_JSON_API_Endpoint {
),
'meta' => "(string) Optional. Loads data from the endpoints found in the 'meta' part of the response. Comma-separated list. Example: meta=site,likes",
'fields' => '(string) Optional. Returns specified fields only. Comma-separated list. Example: fields=ID,title',
- // Parameter name => description (default value is empty)
+ // Parameter name => description (default value is empty).
'callback' => '(string) An optional JSONP callback function.',
);
- // Response format
+ /**
+ * Response format
+ *
+ * @var array
+ */
public $response_format = array();
- // Request format
+ /**
+ * Request format
+ *
+ * @var array
+ */
public $request_format = array();
- // Is this endpoint still in testing phase? If so, not available to the public.
+ /**
+ * Is this endpoint still in testing phase? If so, not available to the public.
+ *
+ * @var bool
+ */
public $in_testing = false;
- // Is this endpoint still allowed if the site in question is flagged?
+ /**
+ * Is this endpoint still allowed if the site in question is flagged?
+ *
+ * @var bool
+ */
public $allowed_if_flagged = false;
- // Is this endpoint allowed if the site is red flagged?
+ /**
+ * Is this endpoint allowed if the site is red flagged?
+ *
+ * @var bool
+ */
public $allowed_if_red_flagged = false;
- // Is this endpoint allowed if the site is deleted?
+ /**
+ * Is this endpoint allowed if the site is deleted?
+ *
+ * @var bool
+ */
public $allowed_if_deleted = false;
/**
- * @var string Version of the API
+ * Version of the API
+ *
+ * @var string
*/
public $version = '';
/**
- * @var string Example request to make
+ * Example request to make
+ *
+ * @var string
*/
public $example_request = '';
/**
- * @var string Example request data (for POST methods)
+ * Example request data (for POST methods)
+ *
+ * @var string
*/
public $example_request_data = '';
/**
- * @var string Example response from $example_request
+ * Example response from $example_request
+ *
+ * @var string
*/
public $example_response = '';
/**
- * @var bool Set to true if the endpoint implements its own filtering instead of the standard `fields` query method
+ * Set to true if the endpoint implements its own filtering instead of the standard `fields` query method
+ *
+ * @var bool
*/
public $custom_fields_filtering = false;
/**
- * @var bool Set to true if the endpoint accepts all cross origin requests. You probably should not set this flag.
+ * Set to true if the endpoint accepts all cross origin requests. You probably should not set this flag.
+ *
+ * @var bool
*/
public $allow_cross_origin_request = false;
/**
- * @var bool Set to true if the endpoint can recieve unauthorized POST requests.
+ * Set to true if the endpoint can recieve unauthorized POST requests.
+ *
+ * @var bool
*/
public $allow_unauthorized_request = false;
/**
- * @var bool Set to true if the endpoint should accept site based (not user based) authentication.
+ * Set to true if the endpoint should accept site based (not user based) authentication.
+ *
+ * @var bool
*/
public $allow_jetpack_site_auth = false;
/**
- * @var bool Set to true if the endpoint should accept auth from an upload token.
+ * Set to true if the endpoint should accept auth from an upload token.
+ *
+ * @var bool
*/
public $allow_upload_token_auth = false;
/**
- * @var bool Set to true if the endpoint should require auth from a Rewind auth token.
+ * Set to true if the endpoint should require auth from a Rewind auth token.
+ *
+ * @var bool
*/
public $require_rewind_auth = false;
@@ -139,7 +239,12 @@ abstract class WPCOM_JSON_API_Endpoint {
*/
public $allow_fallback_to_jetpack_blog_token = false;
- function __construct( $args ) {
+ /**
+ * Constructor.
+ *
+ * @param string|array|object $args Args.
+ */
+ public function __construct( $args ) {
$defaults = array(
'in_testing' => false,
'allowed_if_flagged' => false,
@@ -195,7 +300,7 @@ abstract class WPCOM_JSON_API_Endpoint {
$this->deprecated = $args['deprecated'];
$this->new_version = $args['new_version'];
- // Ensure max version is not less than min version
+ // Ensure max version is not less than min version.
if ( version_compare( $this->min_version, $this->max_version, '>' ) ) {
$this->max_version = $this->min_version;
}
@@ -232,12 +337,12 @@ abstract class WPCOM_JSON_API_Endpoint {
$this->query = array_filter( array_merge( $this->query, $args['query_parameters'] ) );
}
- $this->api = WPCOM_JSON_API::init(); // Auto-add to WPCOM_JSON_API
+ $this->api = WPCOM_JSON_API::init(); // Auto-add to WPCOM_JSON_API.
$this->links = WPCOM_JSON_API_Links::getInstance();
/** Example Request/Response */
- // Examples for endpoint documentation request
+ // Examples for endpoint documentation request.
$this->example_request = $args['example_request'];
$this->example_request_data = $args['example_request_data'];
$this->example_response = $args['example_response'];
@@ -245,8 +350,14 @@ abstract class WPCOM_JSON_API_Endpoint {
$this->api->add( $this );
}
- // Get all query args. Prefill with defaults
- function query_args( $return_default_values = true, $cast_and_filter = true ) {
+ /**
+ * Get all query args. Prefill with defaults.
+ *
+ * @param bool $return_default_values Whether to include default values in the response.
+ * @param bool $cast_and_filter Whether to cast and filter input according to the documentation.
+ * @return array
+ */
+ public function query_args( $return_default_values = true, $cast_and_filter = true ) {
$args = array_intersect_key( $this->api->query, $this->query );
if ( ! $cast_and_filter ) {
@@ -256,8 +367,14 @@ abstract class WPCOM_JSON_API_Endpoint {
return $this->cast_and_filter( $args, $this->query, $return_default_values );
}
- // Get POST body data
- function input( $return_default_values = true, $cast_and_filter = true ) {
+ /**
+ * Get POST body data.
+ *
+ * @param bool $return_default_values Whether to include default values in the response.
+ * @param bool $cast_and_filter Whether to cast and filter input according to the documentation.
+ * @return mixed
+ */
+ public function input( $return_default_values = true, $cast_and_filter = true ) {
$input = trim( (string) $this->api->post_body );
$content_type = (string) $this->api->content_type;
if ( $content_type ) {
@@ -278,20 +395,21 @@ abstract class WPCOM_JSON_API_Endpoint {
return null;
}
} else {
- if ( is_null( $return ) && json_encode( null ) !== $input ) {
+ if ( $return === null && wp_json_encode( null ) !== $input ) {
return null;
}
}
break;
case 'multipart/form-data':
+ // phpcs:ignore WordPress.Security.NonceVerification.Missing
$return = array_merge( stripslashes_deep( $_POST ), $_FILES );
break;
case 'application/x-www-form-urlencoded':
- // attempt JSON first, since probably a curl command
+ // attempt JSON first, since probably a curl command.
$return = json_decode( $input, true );
- if ( is_null( $return ) ) {
+ if ( $return === null ) {
wp_parse_str( $input, $return );
}
@@ -315,7 +433,12 @@ abstract class WPCOM_JSON_API_Endpoint {
return $return;
}
-
+ /**
+ * Fetch a body via secure request.
+ *
+ * @param string $secure_key Key for the request.
+ * @return mixed|null API response, or null if the request failed.
+ */
protected function get_secure_body( $secure_key ) {
$response = Client::wpcom_json_api_request_as_blog(
sprintf( '/sites/%d/secure-request', Jetpack_Options::get_option( 'id' ) ),
@@ -329,7 +452,16 @@ abstract class WPCOM_JSON_API_Endpoint {
return json_decode( $response['body'], true );
}
- function cast_and_filter( $data, $documentation, $return_default_values = false, $for_output = false ) {
+ /**
+ * Cast and filter data.
+ *
+ * @param mixed $data Data to cast and filter.
+ * @param array $documentation Documentation for keys in `$data` to keep and cast.
+ * @param bool $return_default_values Set default values from `$documentation` to process.
+ * @param bool $for_output See `$this->cast_and_filter_item()`.
+ * @return mixed Filtered data.
+ */
+ public function cast_and_filter( $data, $documentation, $return_default_values = false, $for_output = false ) {
$return_as_object = false;
if ( is_object( $data ) ) {
// @todo this should probably be a deep copy if $data can ever have nested objects
@@ -346,21 +478,21 @@ abstract class WPCOM_JSON_API_Endpoint {
foreach ( $documentation as $key => $description ) {
if ( is_array( $description ) ) {
- // String or boolean array keys only
+ // String or boolean array keys only.
$whitelist = array_keys( $description );
if ( $whitelist === $boolean_arg || $whitelist === $naeloob_arg ) {
- // Truthiness
+ // Truthiness.
if ( isset( $data[ $key ] ) ) {
$return[ $key ] = (bool) WPCOM_JSON_API::is_truthy( $data[ $key ] );
} elseif ( $return_default_values ) {
$return[ $key ] = $whitelist === $naeloob_arg; // Default to true for naeloob_arg and false for boolean_arg.
}
} elseif ( isset( $data[ $key ] ) && isset( $description[ $data[ $key ] ] ) ) {
- // String Key
+ // String Key.
$return[ $key ] = (string) $data[ $key ];
} elseif ( $return_default_values ) {
- // Default value
+ // Default value.
$return[ $key ] = (string) current( $whitelist );
}
@@ -370,7 +502,7 @@ abstract class WPCOM_JSON_API_Endpoint {
$types = $this->parse_types( $description );
$type = array_shift( $types );
- // Explicit default - string and int only for now. Always set these reguardless of $return_default_values
+ // Explicit default - string and int only for now. Always set these reguardless of $return_default_values.
if ( isset( $type['default'] ) ) {
if ( ! isset( $data[ $key ] ) ) {
$data[ $key ] = $type['default'];
@@ -402,8 +534,15 @@ abstract class WPCOM_JSON_API_Endpoint {
* object:category means a hash of categories
*
* Handles object typing - object>post means an object of type post
+ *
+ * @param array $return Array to assign the value into.
+ * @param string|array $type Type to cast.
+ * @param string|int $key Key in `$return` to assign the value to.
+ * @param mixed $value Value to cast.
+ * @param array $types Fallback types.
+ * @param bool $for_output Appears to affect formatting of 'date' types.
*/
- function cast_and_filter_item( &$return, $type, $key, $value, $types = array(), $for_output = false ) {
+ public function cast_and_filter_item( &$return, $type, $key, $value, $types = array(), $for_output = false ) {
if ( is_string( $type ) ) {
$type = compact( 'type' );
}
@@ -423,7 +562,7 @@ abstract class WPCOM_JSON_API_Endpoint {
$return[ $key ] = (string) esc_url_raw( $value );
break;
case 'string':
- // Fallback string -> array, or for string -> object
+ // Fallback string -> array, or for string -> object.
if ( is_array( $value ) || is_object( $value ) ) {
if ( ! empty( $types[0] ) ) {
$next_type = array_shift( $types );
@@ -431,7 +570,7 @@ abstract class WPCOM_JSON_API_Endpoint {
}
}
- // Fallback string -> false
+ // Fallback string -> false.
if ( ! is_string( $value ) ) {
if ( ! empty( $types[0] ) && 'false' === $types[0]['type'] ) {
$next_type = array_shift( $types );
@@ -451,7 +590,7 @@ abstract class WPCOM_JSON_API_Endpoint {
if ( is_array( $value ) ) {
if ( isset( $value['name'] ) && is_array( $value['name'] ) ) {
// It's a $_FILES array
- // Reformat into array of $_FILES items
+ // Reformat into array of $_FILES items.
$files = array();
foreach ( $value['name'] as $k => $v ) {
@@ -464,12 +603,10 @@ abstract class WPCOM_JSON_API_Endpoint {
$return[ $key ] = $files;
break;
}
- } else {
- // no break - treat as 'array'
}
- // nobreak
+ // no break - treat as 'array'.
case 'array':
- // Fallback array -> string
+ // Fallback array -> string.
if ( is_string( $value ) ) {
if ( ! empty( $types[0] ) ) {
$next_type = array_shift( $types );
@@ -510,8 +647,8 @@ abstract class WPCOM_JSON_API_Endpoint {
$return[ $key ] = (bool) WPCOM_JSON_API::is_truthy( $value );
break;
case 'object':
- // Fallback object -> false
- if ( is_scalar( $value ) || is_null( $value ) ) {
+ // Fallback object -> false.
+ if ( is_scalar( $value ) || $value === null ) {
if ( ! empty( $types[0] ) && 'false' === $types[0]['type'] ) {
return $this->cast_and_filter_item( $return, 'false', $key, $value, $types, $for_output );
}
@@ -768,10 +905,10 @@ abstract class WPCOM_JSON_API_Endpoint {
break;
case 'visibility':
- // This is needed to fix a bug in WPAndroid where `public: "PUBLIC"` is sent in place of `public: 1`
+ // This is needed to fix a bug in WPAndroid where `public: "PUBLIC"` is sent in place of `public: 1`.
if ( 'public' === strtolower( $value ) ) {
$return[ $key ] = 1;
- } else if ( 'private' === strtolower( $value ) ) {
+ } elseif ( 'private' === strtolower( $value ) ) {
$return[ $key ] = -1;
} else {
$return[ $key ] = (int) $value;
@@ -793,12 +930,19 @@ abstract class WPCOM_JSON_API_Endpoint {
$for_output
);
} else {
+ // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error, WordPress.Security.EscapeOutput.OutputNotEscaped
trigger_error( "Unknown API casting type {$type['type']}", E_USER_WARNING );
}
}
}
- function parse_types( $text ) {
+ /**
+ * Parse types from text.
+ *
+ * @param string $text Text.
+ * @return array Types.
+ */
+ public function parse_types( $text ) {
if ( ! preg_match( '#^\(([^)]+)\)#', ltrim( $text ), $matches ) ) {
return 'none';
}
@@ -828,16 +972,20 @@ abstract class WPCOM_JSON_API_Endpoint {
/**
* Checks if the endpoint is publicly displayable
+ *
+ * @return bool
*/
- function is_publicly_documentable() {
+ public function is_publicly_documentable() {
return '__do_not_document' !== $this->group && true !== $this->in_testing;
}
/**
* Auto generates documentation based on description, method, path, path_labels, and query parameters.
* Echoes HTML.
+ *
+ * @param bool $show_description Whether to show the description.
*/
- function document( $show_description = true ) {
+ public function document( $show_description = true ) {
global $wpdb;
$original_post = isset( $GLOBALS['post'] ) ? $GLOBALS['post'] : 'unset';
unset( $GLOBALS['post'] );
@@ -915,11 +1063,11 @@ abstract class WPCOM_JSON_API_Endpoint {
$param_label = strtolower( str_replace( ' ', '-', $label ) );
?>
-<section class="<?php echo $param_label; ?>">
+<section class="<?php echo esc_attr( $param_label ); ?>">
<h2 id="apidoc-<?php echo esc_attr( $doc_section_key ); ?>"><?php echo wp_kses_post( $label ); ?></h2>
-<table class="api-doc api-doc-<?php echo $param_label; ?>-parameters api-doc-<?php echo strtolower( str_replace( ' ', '-', $doc['group'] ) ); ?>">
+<table class="api-doc api-doc-<?php echo esc_attr( $param_label ); ?>-parameters api-doc-<?php echo esc_attr( strtolower( str_replace( ' ', '-', $doc['group'] ) ) ); ?>">
<thead>
<tr>
@@ -952,11 +1100,19 @@ abstract class WPCOM_JSON_API_Endpoint {
<?php
if ( 'unset' !== $original_post ) {
- $GLOBALS['post'] = $original_post;
+ $GLOBALS['post'] = $original_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
}
}
- function add_http_build_query_to_php_content_example( $matches ) {
+ /**
+ * `preg_replace_callback` callback to add http_build_query to php content example.
+ *
+ * @todo Is this used anywhere?
+ *
+ * @param array $matches Matches.
+ * @return string
+ */
+ public function add_http_build_query_to_php_content_example( $matches ) {
$trimmed_match = ltrim( $matches[0] );
$pad = substr( $matches[0], 0, -1 * strlen( $trimmed_match ) );
$pad = ltrim( $pad, ' ' );
@@ -967,8 +1123,10 @@ abstract class WPCOM_JSON_API_Endpoint {
/**
* Recursively generates the <dl>'s to document item descriptions.
* Echoes HTML.
+ *
+ * @param string|array $item Post data to output, or an array of key => data mappings.
*/
- function generate_doc_description( $item ) {
+ public function generate_doc_description( $item ) {
if ( is_array( $item ) ) :
?>
@@ -992,7 +1150,7 @@ abstract class WPCOM_JSON_API_Endpoint {
* Auto generates documentation based on description, method, path, path_labels, and query parameters.
* Echoes HTML.
*/
- function generate_documentation() {
+ public function generate_documentation() {
$format = str_replace( '%d', '%s', $this->path );
$path_labeled = $format;
if ( ! empty( $this->path_labels ) ) {
@@ -1033,7 +1191,7 @@ abstract class WPCOM_JSON_API_Endpoint {
}
if ( 'response_format' !== $_property ) {
- // hack - don't show "(default)" in response format
+ // hack - don't show "(default)" in response format.
reset( $description );
$description_key = key( $description );
$description[ $description_key ] = "(default) {$description[$description_key]}";
@@ -1043,7 +1201,7 @@ abstract class WPCOM_JSON_API_Endpoint {
$type = array();
$default = '';
- if ( 'none' == $types ) {
+ if ( 'none' === $types ) {
$types = array();
$types[]['type'] = 'none';
}
@@ -1057,10 +1215,9 @@ abstract class WPCOM_JSON_API_Endpoint {
}
}
}
- $type = '(' . join( '|', $type ) . ')';
- $noop = ''; // skip an index in list below
- list( $noop, $description ) = explode( ')', $description, 2 );
- $description = trim( $description );
+ $type = '(' . join( '|', $type ) . ')';
+ list( , $description ) = explode( ')', $description, 2 );
+ $description = trim( $description );
if ( $default ) {
$description .= " Default: $default.";
}
@@ -1079,7 +1236,13 @@ abstract class WPCOM_JSON_API_Endpoint {
return $doc;
}
- function user_can_view_post( $post_id ) {
+ /**
+ * Can the user view the post?
+ *
+ * @param int $post_id Post ID.
+ * @return bool|WP_Error
+ */
+ public function user_can_view_post( $post_id ) {
$post = get_post( $post_id );
if ( ! $post || is_wp_error( $post ) ) {
return false;
@@ -1102,12 +1265,12 @@ abstract class WPCOM_JSON_API_Endpoint {
if ( ! current_user_can( 'read_post', $post->ID ) ) {
return new WP_Error( 'unauthorized', 'User cannot view post', 403 );
}
- } elseif ( in_array( $post->post_status, array( 'inherit', 'trash' ) ) ) {
+ } elseif ( in_array( $post->post_status, array( 'inherit', 'trash' ), true ) ) {
if ( ! current_user_can( 'edit_post', $post->ID ) ) {
return new WP_Error( 'unauthorized', 'User cannot view post', 403 );
}
- } elseif ( 'auto-draft' === $post->post_status ) {
- // allow auto-drafts
+ } elseif ( 'auto-draft' === $post->post_status ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedElseif
+ // allow auto-drafts.
} else {
return new WP_Error( 'unauthorized', 'User cannot view post', 403 );
}
@@ -1117,7 +1280,7 @@ abstract class WPCOM_JSON_API_Endpoint {
}
if (
- -1 == get_option( 'blog_public' ) &&
+ -1 === (int) get_option( 'blog_public' ) &&
/**
* Filter access to a specific post.
*
@@ -1161,12 +1324,12 @@ abstract class WPCOM_JSON_API_Endpoint {
/**
* Returns author object.
*
- * @param object $author user ID, user row, WP_User object, comment row, post row
- * @param bool $show_email_and_ip output the author's email address and IP address?
+ * @param object $author user ID, user row, WP_User object, comment row, post row.
+ * @param bool $show_email_and_ip output the author's email address and IP address?.
*
* @return object
*/
- function get_author( $author, $show_email_and_ip = false ) {
+ public function get_author( $author, $show_email_and_ip = false ) {
$ip_address = isset( $author->comment_author_IP ) ? $author->comment_author_IP : '';
if ( isset( $author->comment_author_email ) ) {
@@ -1176,15 +1339,15 @@ abstract class WPCOM_JSON_API_Endpoint {
$name = $author->comment_author;
$first_name = '';
$last_name = '';
- $URL = $author->comment_author_url;
- $avatar_URL = $this->api->get_avatar_url( $author );
- $profile_URL = 'https://en.gravatar.com/' . md5( strtolower( trim( $email ) ) );
+ $url = $author->comment_author_url;
+ $avatar_url = $this->api->get_avatar_url( $author );
+ $profile_url = 'https://en.gravatar.com/' . md5( strtolower( trim( $email ) ) );
$nice = '';
$site_id = -1;
// Comment author URLs and Emails are sent through wp_kses() on save, which replaces "&" with "&amp;"
- // "&" is the only email/URL character altered by wp_kses()
- foreach ( array( 'email', 'URL' ) as $field ) {
+ // "&" is the only email/URL character altered by wp_kses().
+ foreach ( array( 'email', 'url' ) as $field ) {
$$field = str_replace( '&amp;', '&', $$field );
}
} else {
@@ -1194,7 +1357,7 @@ abstract class WPCOM_JSON_API_Endpoint {
$author = $author->ID;
} elseif ( isset( $author->post_author ) ) {
// then $author is a Post Object.
- if ( 0 == $author->post_author ) {
+ if ( ! $author->post_author ) {
return null;
}
/**
@@ -1216,7 +1379,7 @@ abstract class WPCOM_JSON_API_Endpoint {
$name = get_post_meta( $post_id, '_jetpack_author', true );
$first_name = '';
$last_name = '';
- $URL = '';
+ $url = '';
$nice = '';
} else {
$author = $author->post_author;
@@ -1226,7 +1389,7 @@ abstract class WPCOM_JSON_API_Endpoint {
if ( ! isset( $id ) ) {
$user = get_user_by( 'id', $author );
if ( ! $user || is_wp_error( $user ) ) {
- trigger_error( 'Unknown user', E_USER_WARNING );
+ trigger_error( 'Unknown user', E_USER_WARNING ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error
return null;
}
@@ -1236,7 +1399,7 @@ abstract class WPCOM_JSON_API_Endpoint {
$name = $user->display_name;
$first_name = $user->first_name;
$last_name = $user->last_name;
- $URL = $user->user_url;
+ $url = $user->user_url;
$nice = $user->user_nicename;
}
if ( defined( 'IS_WPCOM' ) && IS_WPCOM && ! $is_jetpack ) {
@@ -1244,17 +1407,17 @@ abstract class WPCOM_JSON_API_Endpoint {
$site_id = $active_blog->blog_id;
if ( $site_id > -1 ) {
$site_visible = (
- -1 != $active_blog->public ||
+ -1 !== (int) $active_blog->public ||
is_private_blog_user( $site_id, get_current_user_id() )
);
}
- $profile_URL = "https://en.gravatar.com/{$login}";
+ $profile_url = "https://en.gravatar.com/{$login}";
} else {
- $profile_URL = 'https://en.gravatar.com/' . md5( strtolower( trim( $email ) ) );
+ $profile_url = 'https://en.gravatar.com/' . md5( strtolower( trim( $email ) ) );
$site_id = -1;
}
- $avatar_URL = $this->api->get_avatar_url( $email );
+ $avatar_url = $this->api->get_avatar_url( $email );
}
if ( $show_email_and_ip ) {
@@ -1268,15 +1431,15 @@ abstract class WPCOM_JSON_API_Endpoint {
$author = array(
'ID' => (int) $id,
'login' => (string) $login,
- 'email' => $email, // (string|bool)
+ 'email' => $email, // string|bool.
'name' => (string) $name,
'first_name' => (string) $first_name,
'last_name' => (string) $last_name,
'nice_name' => (string) $nice,
- 'URL' => (string) esc_url_raw( $URL ),
- 'avatar_URL' => (string) esc_url_raw( $avatar_URL ),
- 'profile_URL' => (string) esc_url_raw( $profile_URL ),
- 'ip_address' => $ip_address, // (string|bool)
+ 'URL' => (string) esc_url_raw( $url ),
+ 'avatar_URL' => (string) esc_url_raw( $avatar_url ),
+ 'profile_URL' => (string) esc_url_raw( $profile_url ),
+ 'ip_address' => $ip_address, // string|bool.
);
if ( $site_id > -1 ) {
@@ -1287,7 +1450,13 @@ abstract class WPCOM_JSON_API_Endpoint {
return (object) $author;
}
- function get_media_item( $media_id ) {
+ /**
+ * Get a media item.
+ *
+ * @param int $media_id Media post ID.
+ * @return object|WP_Error Media item data, or WP_Error.
+ */
+ public function get_media_item( $media_id ) {
$media_item = get_post( $media_id );
if ( ! $media_item || is_wp_error( $media_item ) ) {
@@ -1322,7 +1491,15 @@ abstract class WPCOM_JSON_API_Endpoint {
return (object) $response;
}
- function get_media_item_v1_1( $media_id, $media_item = null, $file = null ) {
+ /**
+ * Get a v1.1 media item.
+ *
+ * @param int $media_id Media post ID.
+ * @param WP_Post|null $media_item Media item.
+ * @param string|null $file File path.
+ * @return object|WP_Error Media item data, or WP_Error.
+ */
+ public function get_media_item_v1_1( $media_id, $media_item = null, $file = null ) {
if ( ! $media_item ) {
$media_item = get_post( $media_id );
@@ -1345,7 +1522,10 @@ abstract class WPCOM_JSON_API_Endpoint {
? $attachment_metadata['filesize']
: 0;
} else {
- $filesize = filesize( $attachment_file );
+ // For VideoPress videos, $attachment_file is the video URL.
+ $filesize = file_exists( $attachment_file )
+ ? filesize( $attachment_file )
+ : 0;
}
$response = array(
@@ -1408,7 +1588,7 @@ abstract class WPCOM_JSON_API_Endpoint {
}
}
- if ( in_array( $ext, array( 'mp3', 'm4a', 'wav', 'ogg' ) ) ) {
+ if ( in_array( $ext, array( 'mp3', 'm4a', 'wav', 'ogg' ), true ) ) {
$metadata = wp_get_attachment_metadata( $media_item->ID );
$response['length'] = $metadata['length'];
$response['exif'] = $metadata;
@@ -1417,9 +1597,8 @@ abstract class WPCOM_JSON_API_Endpoint {
$is_video = false;
if (
- in_array( $ext, array( 'ogv', 'mp4', 'mov', 'wmv', 'avi', 'mpg', '3gp', '3g2', 'm4v' ) )
- ||
- $response['mime_type'] === 'video/videopress'
+ in_array( $ext, array( 'ogv', 'mp4', 'mov', 'wmv', 'avi', 'mpg', '3gp', '3g2', 'm4v' ), true )
+ || 'video/videopress' === $response['mime_type']
) {
$is_video = true;
}
@@ -1436,7 +1615,7 @@ abstract class WPCOM_JSON_API_Endpoint {
$response['length'] = $metadata['length'];
}
- // add VideoPress info
+ // add VideoPress info.
if ( function_exists( 'video_get_info_by_blogpostid' ) ) {
$info = video_get_info_by_blogpostid( $this->api->get_blog_id_for_output(), $media_item->ID );
@@ -1465,7 +1644,19 @@ abstract class WPCOM_JSON_API_Endpoint {
$response['allow_download'] = (string) (int) $metadata['videopress']['allow_download'];
}
- // Thumbnails
+ if ( isset( $info->thumbnail_generating ) ) {
+ $response['thumbnail_generating'] = (bool) intval( $info->thumbnail_generating );
+ } elseif ( isset( $metadata['videopress']['thumbnail_generating'] ) ) {
+ $response['thumbnail_generating'] = (bool) intval( $metadata['videopress']['thumbnail_generating'] );
+ }
+
+ if ( isset( $info->privacy_setting ) ) {
+ $response['privacy_setting'] = (int) $info->privacy_setting;
+ } elseif ( isset( $metadata['videopress']['privacy_setting'] ) ) {
+ $response['privacy_setting'] = (int) $metadata['videopress']['privacy_setting'];
+ }
+
+ // Thumbnails.
if ( function_exists( 'video_format_done' ) && function_exists( 'video_image_url_by_guid' ) ) {
$response['thumbnails'] = array(
'fmt_hd' => '',
@@ -1503,7 +1694,7 @@ abstract class WPCOM_JSON_API_Endpoint {
),
);
- // add VideoPress link to the meta
+ // add VideoPress link to the meta.
if ( isset( $response['videopress_guid'] ) ) {
if ( function_exists( 'video_get_info_by_blogpostid' ) ) {
$response['meta']->links->videopress = (string) $this->links->get_link( '/videos/%s', $response['videopress_guid'], '' );
@@ -1517,10 +1708,18 @@ abstract class WPCOM_JSON_API_Endpoint {
return (object) $response;
}
- function get_taxonomy( $taxonomy_id, $taxonomy_type, $context ) {
+ /**
+ * Get a formatted taxonomy.
+ *
+ * @param int $taxonomy_id Taxonomy ID.
+ * @param string $taxonomy_type Name of taxonomy.
+ * @param string $context Context, 'edit' or 'display'.
+ * @return object|WP_Error
+ */
+ public function get_taxonomy( $taxonomy_id, $taxonomy_type, $context ) {
$taxonomy = get_term_by( 'slug', $taxonomy_id, $taxonomy_type );
- // keep updating this function
+ // keep updating this function.
if ( ! $taxonomy || is_wp_error( $taxonomy ) ) {
return new WP_Error( 'unknown_taxonomy', 'Unknown taxonomy', 404 );
}
@@ -1528,8 +1727,16 @@ abstract class WPCOM_JSON_API_Endpoint {
return $this->format_taxonomy( $taxonomy, $taxonomy_type, $context );
}
- function format_taxonomy( $taxonomy, $taxonomy_type, $context ) {
- // Permissions
+ /**
+ * Format a taxonomy.
+ *
+ * @param WP_Term $taxonomy Taxonomy.
+ * @param string $taxonomy_type Name of taxonomy.
+ * @param string $context Context, 'edit' or 'display'.
+ * @return object|WP_Error
+ */
+ public function format_taxonomy( $taxonomy, $taxonomy_type, $context ) {
+ // Permissions.
switch ( $context ) {
case 'edit':
$tax = get_taxonomy( $taxonomy_type );
@@ -1538,7 +1745,7 @@ abstract class WPCOM_JSON_API_Endpoint {
}
break;
case 'display':
- if ( -1 == get_option( 'blog_public' ) && ! current_user_can( 'read' ) ) {
+ if ( -1 === (int) get_option( 'blog_public' ) && ! current_user_can( 'read' ) ) {
return new WP_Error( 'unauthorized', 'User cannot view taxonomy', 403 );
}
break;
@@ -1572,12 +1779,11 @@ abstract class WPCOM_JSON_API_Endpoint {
/**
* Returns ISO 8601 formatted datetime: 2011-12-08T01:15:36-08:00
*
- * @param $date_gmt (string) GMT datetime string.
- * @param $date (string) Optional. Used to calculate the offset from GMT.
- *
+ * @param string $date_gmt GMT datetime string.
+ * @param string $date Optional. Used to calculate the offset from GMT.
* @return string
*/
- function format_date( $date_gmt, $date = null ) {
+ public function format_date( $date_gmt, $date = null ) {
return WPCOM_JSON_API_Date::format_date( $date_gmt, $date );
}
@@ -1624,23 +1830,33 @@ abstract class WPCOM_JSON_API_Endpoint {
);
}
- // Load the functions.php file for the current theme to get its post formats, CPTs, etc.
- function load_theme_functions() {
+ /**
+ * Load the functions.php file for the current theme to get its post formats, CPTs, etc.
+ */
+ public function load_theme_functions() {
if ( false === defined( 'STYLESHEETPATH' ) ) {
wp_templating_constants();
}
- // bail if we've done this already (can happen when calling /batch endpoint)
+ // bail if we've done this already (can happen when calling /batch endpoint).
if ( defined( 'REST_API_THEME_FUNCTIONS_LOADED' ) ) {
return;
}
// VIP context loading is handled elsewhere, so bail to prevent
- // duplicate loading. See `switch_to_blog_and_validate_user()`
+ // duplicate loading. See `switch_to_blog_and_validate_user()`.
if ( defined( 'WPCOM_IS_VIP_ENV' ) && WPCOM_IS_VIP_ENV ) {
return;
}
+ $do_check_theme =
+ defined( 'REST_API_TEST_REQUEST' ) && REST_API_TEST_REQUEST ||
+ defined( 'IS_WPCOM' ) && IS_WPCOM;
+
+ if ( $do_check_theme && ! wpcom_should_load_theme_files_on_rest_api() ) {
+ return;
+ }
+
define( 'REST_API_THEME_FUNCTIONS_LOADED', true );
// the theme info we care about is found either within functions.php or one of the jetpack files.
@@ -1664,13 +1880,13 @@ abstract class WPCOM_JSON_API_Endpoint {
}
}
- // add inc/wpcom.php and/or includes/wpcom.php
+ // add inc/wpcom.php and/or includes/wpcom.php.
wpcom_load_theme_compat_file();
- // Enable including additional directories or files in actions to be copied
+ // Enable including additional directories or files in actions to be copied.
$copy_dirs = apply_filters( 'restapi_theme_action_copy_dirs', $copy_dirs );
- // since the stuff we care about (CPTS, post formats, are usually on setup or init hooks, we want to load those)
+ // since the stuff we care about (CPTS, post formats, are usually on setup or init hooks, we want to load those).
$this->copy_hooks( 'after_setup_theme', 'restapi_theme_after_setup_theme', $copy_dirs );
/**
@@ -1703,11 +1919,18 @@ abstract class WPCOM_JSON_API_Endpoint {
do_action( 'restapi_theme_init' );
}
- function copy_hooks( $from_hook, $to_hook, $base_paths ) {
+ /**
+ * Copy hook functions.
+ *
+ * @param string $from_hook Hook to copy from.
+ * @param string $to_hook Hook to copy to.
+ * @param array $base_paths Only copy hooks defined in the specified paths.
+ */
+ public function copy_hooks( $from_hook, $to_hook, $base_paths ) {
global $wp_filter;
foreach ( $wp_filter as $hook => $actions ) {
- if ( $from_hook != $hook ) {
+ if ( $from_hook !== $hook ) {
continue;
}
if ( ! has_action( $hook ) ) {
@@ -1715,17 +1938,17 @@ abstract class WPCOM_JSON_API_Endpoint {
}
foreach ( $actions as $priority => $callbacks ) {
- foreach ( $callbacks as $callback_key => $callback_data ) {
+ foreach ( $callbacks as $callback_data ) {
$callback = $callback_data['function'];
- // use reflection api to determine filename where function is defined
+ // use reflection api to determine filename where function is defined.
$reflection = $this->get_reflection( $callback );
if ( false !== $reflection ) {
$file_name = $reflection->getFileName();
foreach ( $base_paths as $base_path ) {
- // only copy hooks with functions which are part of the specified files
+ // only copy hooks with functions which are part of the specified files.
if ( 0 === strpos( $file_name, $base_path ) ) {
add_action(
$to_hook,
@@ -1741,7 +1964,13 @@ abstract class WPCOM_JSON_API_Endpoint {
}
}
- function get_reflection( $callback ) {
+ /**
+ * Get a ReflectionMethod or ReflectionFunction for the callback.
+ *
+ * @param callable $callback Callback.
+ * @return ReflectionMethod|ReflectionFunction|false
+ */
+ public function get_reflection( $callback ) {
if ( is_array( $callback ) ) {
list( $class, $method ) = $callback;
return new ReflectionMethod( $class, $method );
@@ -1752,11 +1981,11 @@ abstract class WPCOM_JSON_API_Endpoint {
return new ReflectionMethod( $class, $method );
}
- if ( method_exists( $callback, "__invoke" ) ) {
- return new ReflectionMethod( $callback, "__invoke" );
+ if ( method_exists( $callback, '__invoke' ) ) {
+ return new ReflectionMethod( $callback, '__invoke' );
}
- if ( is_string( $callback ) && strpos( $callback, '::' ) == false && function_exists( $callback ) ) {
+ if ( is_string( $callback ) && strpos( $callback, '::' ) === false && function_exists( $callback ) ) {
return new ReflectionFunction( $callback );
}
@@ -1764,13 +1993,13 @@ abstract class WPCOM_JSON_API_Endpoint {
}
/**
- * Check whether a user can view or edit a post type
+ * Check whether a user can view or edit a post type.
*
- * @param string $post_type post type to check
- * @param string $context 'display' or 'edit'
+ * @param string $post_type post type to check.
+ * @param string $context 'display' or 'edit'.
* @return bool
*/
- function current_user_can_access_post_type( $post_type, $context = 'display' ) {
+ public function current_user_can_access_post_type( $post_type, $context = 'display' ) {
$post_type_object = get_post_type_object( $post_type );
if ( ! $post_type_object ) {
return false;
@@ -1786,23 +2015,30 @@ abstract class WPCOM_JSON_API_Endpoint {
}
}
- function is_post_type_allowed( $post_type ) {
- // if the post type is empty, that's fine, WordPress will default to post
+ /**
+ * Is the post type allowed?
+ *
+ * @param string $post_type Post type.
+ * @return bool
+ */
+ public function is_post_type_allowed( $post_type ) {
+ // if the post type is empty, that's fine, WordPress will default to post.
if ( empty( $post_type ) ) {
return true;
}
- // allow special 'any' type
- if ( 'any' == $post_type ) {
+ // allow special 'any' type.
+ if ( 'any' === $post_type ) {
return true;
}
- // check for allowed types
- if ( in_array( $post_type, $this->_get_whitelisted_post_types() ) ) {
+ // check for allowed types.
+ if ( in_array( $post_type, $this->_get_whitelisted_post_types(), true ) ) {
return true;
}
- if ( $post_type_object = get_post_type_object( $post_type ) ) {
+ $post_type_object = get_post_type_object( $post_type );
+ if ( $post_type_object ) {
if ( ! empty( $post_type_object->show_in_rest ) ) {
return $post_type_object->show_in_rest;
}
@@ -1819,7 +2055,7 @@ abstract class WPCOM_JSON_API_Endpoint {
*
* @return array Whitelisted post types.
*/
- protected function _get_whitelisted_post_types() {
+ protected function _get_whitelisted_post_types() { // phpcs:ignore PSR2.Methods.MethodDeclaration.Underscore -- Legacy.
$allowed_types = array( 'post', 'page', 'revision' );
/**
@@ -1836,30 +2072,105 @@ abstract class WPCOM_JSON_API_Endpoint {
return array_unique( $allowed_types );
}
- function handle_media_creation_v1_1( $media_files, $media_urls, $media_attrs = array(), $force_parent_id = false ) {
+ /**
+ * Mobile apps are allowed free video uploads, but limited to 5 minutes in length.
+ *
+ * @param array $media_item the media item to evaluate.
+ *
+ * @return bool true if the media item is a video that was uploaded via the mobile
+ * app that is longer than 5 minutes.
+ */
+ public function media_item_is_free_video_mobile_upload_and_too_long( $media_item ) {
+ if ( ! $media_item ) {
+ return false;
+ }
+
+ // Verify file is a video.
+ $is_video = preg_match( '@^video/@', $media_item['type'] );
+ if ( ! $is_video ) {
+ return false;
+ }
+
+ // Check if the request is from a mobile app, where we allow free video uploads at limited length.
+ if ( ! in_array( $this->api->token_details['client_id'], VIDEOPRESS_ALLOWED_REST_API_CLIENT_IDS, true ) ) {
+ return false;
+ }
+
+ // We're only worried about free sites.
+ require_once WP_CONTENT_DIR . '/admin-plugins/wpcom-billing.php';
+ $current_plan = WPCOM_Store_API::get_current_plan( get_current_blog_id() );
+ if ( ! $current_plan['is_free'] ) {
+ return false;
+ }
+
+ // Check if video is longer than 5 minutes.
+ $video_meta = wp_read_video_metadata( $media_item['tmp_name'] );
+ if (
+ false !== $video_meta &&
+ isset( $video_meta['length'] ) &&
+ 5 * MINUTE_IN_SECONDS < $video_meta['length']
+ ) {
+ videopress_log(
+ 'videopress_app_upload_length_block',
+ 'Mobile app upload on free site blocked because length was longer than 5 minutes.',
+ null,
+ null,
+ null,
+ null,
+ array(
+ 'blog_id' => get_current_blog_id(),
+ 'user_id' => get_current_user_id(),
+ )
+ );
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Handle a v1.1 media creation.
+ *
+ * Only one of $media_files and $media_urls should be non-empty.
+ *
+ * @param array $media_files File upload data.
+ * @param array $media_urls URLs to fetch.
+ * @param array $media_attrs Attributes corresponding to each entry in `$media_files`/`$media_urls`.
+ * @param int|false $force_parent_id Force the parent ID, overriding `$media_attrs[]['parent_id']`.
+ * @return array Two items:
+ * - media_ids: IDs created, by index in `$media_files`/`$media_urls`.
+ * - errors: Errors encountered, by index in `$media_files`/`$media_urls`.
+ */
+ public function handle_media_creation_v1_1( $media_files, $media_urls, $media_attrs = array(), $force_parent_id = false ) {
add_filter( 'upload_mimes', array( $this, 'allow_video_uploads' ) );
- $media_ids = $errors = array();
+ $media_ids = array();
+ $errors = array();
$user_can_upload_files = current_user_can( 'upload_files' ) || $this->api->is_authorized_with_upload_token();
- $media_attrs = array_values( $media_attrs ); // reset the keys
+ $media_attrs = array_values( $media_attrs ); // reset the keys.
$i = 0;
if ( ! empty( $media_files ) ) {
$this->api->trap_wp_die( 'upload_error' );
foreach ( $media_files as $media_item ) {
$_FILES['.api.media.item.'] = $media_item;
+
if ( ! $user_can_upload_files ) {
$media_id = new WP_Error( 'unauthorized', 'User cannot upload media.', 403 );
} else {
- if ( $force_parent_id ) {
- $parent_id = absint( $force_parent_id );
- } elseif ( ! empty( $media_attrs[ $i ] ) && ! empty( $media_attrs[ $i ]['parent_id'] ) ) {
- $parent_id = absint( $media_attrs[ $i ]['parent_id'] );
+ if ( $this->media_item_is_free_video_mobile_upload_and_too_long( $media_item ) ) {
+ $media_id = new WP_Error( 'upload_video_length', 'Video uploads longer than 5 minutes require a paid plan.', 400 );
} else {
- $parent_id = 0;
+ if ( $force_parent_id ) {
+ $parent_id = absint( $force_parent_id );
+ } elseif ( ! empty( $media_attrs[ $i ] ) && ! empty( $media_attrs[ $i ]['parent_id'] ) ) {
+ $parent_id = absint( $media_attrs[ $i ]['parent_id'] );
+ } else {
+ $parent_id = 0;
+ }
+ $media_id = media_handle_upload( '.api.media.item.', $parent_id );
}
- $media_id = media_handle_upload( '.api.media.item.', $parent_id );
}
if ( is_wp_error( $media_id ) ) {
$errors[ $i ]['file'] = $media_item['name'];
@@ -1912,7 +2223,7 @@ abstract class WPCOM_JSON_API_Endpoint {
$attrs = $media_attrs[ $index ];
$insert = array();
- // Attributes: Title, Caption, Description
+ // Attributes: Title, Caption, Description.
if ( isset( $attrs['title'] ) ) {
$insert['post_title'] = $attrs['title'];
@@ -1931,14 +2242,14 @@ abstract class WPCOM_JSON_API_Endpoint {
wp_update_post( (object) $insert );
}
- // Attributes: Alt
+ // Attributes: Alt.
if ( isset( $attrs['alt'] ) ) {
$alt = wp_strip_all_tags( $attrs['alt'], true );
update_post_meta( $media_id, '_wp_attachment_image_alt', $alt );
}
- // Attributes: Artist, Album
+ // Attributes: Artist, Album.
$id3_meta = array();
@@ -1949,7 +2260,7 @@ abstract class WPCOM_JSON_API_Endpoint {
}
if ( ! empty( $id3_meta ) ) {
- // Before updating metadata, ensure that the item is audio
+ // Before updating metadata, ensure that the item is audio.
$item = $this->get_media_item_v1_1( $media_id );
if ( 0 === strpos( $item->mime_type, 'audio/' ) ) {
wp_update_attachment_metadata( $media_id, $id3_meta );
@@ -1965,12 +2276,20 @@ abstract class WPCOM_JSON_API_Endpoint {
}
- function handle_media_sideload( $url, $parent_post_id = 0, $type = 'any' ) {
+ /**
+ * Handle a media sideload.
+ *
+ * @param string $url URL.
+ * @param int $parent_post_id Parent post ID.
+ * @param string $type Type.
+ * @return int|WP_Error|false Media post ID, or error, or false if nothing was sideloaded.
+ */
+ public function handle_media_sideload( $url, $parent_post_id = 0, $type = 'any' ) {
if ( ! function_exists( 'download_url' ) || ! function_exists( 'media_handle_sideload' ) ) {
return false;
}
- // if we didn't get a URL, let's bail
+ // if we didn't get a URL, let's bail.
$parsed = wp_parse_url( $url );
if ( empty( $parsed ) ) {
return false;
@@ -1984,11 +2303,11 @@ abstract class WPCOM_JSON_API_Endpoint {
// First check to see if we get a mime-type match by file, otherwise, check to
// see if WordPress supports this file as an image. If neither, then it is not supported.
if ( ! $this->is_file_supported_for_sideloading( $tmp ) || 'image' === $type && ! file_is_displayable_image( $tmp ) ) {
- @unlink( $tmp );
+ @unlink( $tmp ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
return new WP_Error( 'invalid_input', 'Invalid file type.', 403 );
}
- // emulate a $_FILES entry
+ // emulate a $_FILES entry.
$file_array = array(
'name' => basename( wp_parse_url( $url, PHP_URL_PATH ) ),
'tmp_name' => $tmp,
@@ -1996,7 +2315,7 @@ abstract class WPCOM_JSON_API_Endpoint {
$id = media_handle_sideload( $file_array, $parent_post_id );
if ( file_exists( $tmp ) ) {
- @unlink( $tmp );
+ @unlink( $tmp ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
}
if ( is_wp_error( $id ) ) {
@@ -2021,23 +2340,29 @@ abstract class WPCOM_JSON_API_Endpoint {
return jetpack_is_file_supported_for_sideloading( $file );
}
- function allow_video_uploads( $mimes ) {
- // if we are on Jetpack, bail - Videos are already allowed
+ /**
+ * Filter for `upload_mimes`.
+ *
+ * @param array $mimes Allowed mime types.
+ * @return array Allowed mime types.
+ */
+ public function allow_video_uploads( $mimes ) {
+ // if we are on Jetpack, bail - Videos are already allowed.
if ( ! defined( 'IS_WPCOM' ) || ! IS_WPCOM ) {
return $mimes;
}
- // extra check that this filter is only ever applied during REST API requests
+ // extra check that this filter is only ever applied during REST API requests.
if ( ! defined( 'REST_API_REQUEST' ) || ! REST_API_REQUEST ) {
return $mimes;
}
// bail early if they already have the upgrade..
- if ( get_option( 'video_upgrade' ) == '1' ) {
+ if ( wpcom_site_has_videopress() ) {
return $mimes;
}
- // lets whitelist to only specific clients right now
+ // lets whitelist to only specific clients right now.
$clients_allowed_video_uploads = array();
/**
* Filter the list of whitelisted video clients.
@@ -2049,7 +2374,7 @@ abstract class WPCOM_JSON_API_Endpoint {
* @param array $clients_allowed_video_uploads Array of whitelisted Video clients.
*/
$clients_allowed_video_uploads = apply_filters( 'rest_api_clients_allowed_video_uploads', $clients_allowed_video_uploads );
- if ( ! in_array( $this->api->token_details['client_id'], $clients_allowed_video_uploads ) ) {
+ if ( ! in_array( $this->api->token_details['client_id'], $clients_allowed_video_uploads ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict -- Check what types are expected here.
return $mimes;
}
@@ -2071,7 +2396,7 @@ abstract class WPCOM_JSON_API_Endpoint {
if ( ! empty( $video_exts ) ) {
foreach ( $video_exts as $ext ) {
foreach ( $mime_list as $ext_pattern => $mime ) {
- if ( $ext != '' && strpos( $ext_pattern, $ext ) !== false ) {
+ if ( '' !== $ext && strpos( $ext_pattern, $ext ) !== false ) {
$video_mimes[ $ext_pattern ] = $mime;
}
}
@@ -2083,7 +2408,12 @@ abstract class WPCOM_JSON_API_Endpoint {
return $mimes;
}
- function is_current_site_multi_user() {
+ /**
+ * Is the current site multi-user?
+ *
+ * @return bool
+ */
+ public function is_current_site_multi_user() {
$users = wp_cache_get( 'site_user_count', 'WPCOM_JSON_API_Endpoint' );
if ( false === $users ) {
$user_query = new WP_User_Query(
@@ -2098,12 +2428,24 @@ abstract class WPCOM_JSON_API_Endpoint {
return $users > 1;
}
- function allows_cross_origin_requests() {
- return 'GET' == $this->method || $this->allow_cross_origin_request;
+ /**
+ * Whether cross-origin requests are allowed.
+ *
+ * @return bool
+ */
+ public function allows_cross_origin_requests() {
+ return 'GET' === $this->method || $this->allow_cross_origin_request;
}
- function allows_unauthorized_requests( $origin, $complete_access_origins ) {
- return 'GET' == $this->method || ( $this->allow_unauthorized_request && in_array( $origin, $complete_access_origins ) );
+ /**
+ * Whether unauthorized requests are allowed.
+ *
+ * @param string $origin Origin.
+ * @param string[] $complete_access_origins Access origins.
+ * @return bool
+ */
+ public function allows_unauthorized_requests( $origin, $complete_access_origins ) {
+ return 'GET' === $this->method || ( $this->allow_unauthorized_request && in_array( $origin, $complete_access_origins, true ) );
}
/**
@@ -2119,7 +2461,12 @@ abstract class WPCOM_JSON_API_Endpoint {
$this->api->is_jetpack_authorized_for_site();
}
- function get_platform() {
+ /**
+ * Get platform.
+ *
+ * @return WPORG_Platform
+ */
+ public function get_platform() {
return wpcom_get_sal_platform( $this->api->token_details );
}
@@ -2129,10 +2476,10 @@ abstract class WPCOM_JSON_API_Endpoint {
*
* Override this method if you want to do something different.
*
- * @param int $blog_id
+ * @param int $blog_id Blog ID.
* @return bool
*/
- function force_wpcom_request( $blog_id ) {
+ public function force_wpcom_request( $blog_id ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
return false;
}
@@ -2143,7 +2490,7 @@ abstract class WPCOM_JSON_API_Endpoint {
* @return array
*/
public function get_amp_cache_origins( $siteurl ) {
- $host = parse_url( $siteurl, PHP_URL_HOST );
+ $host = wp_parse_url( $siteurl, PHP_URL_HOST );
/*
* From AMP docs:
@@ -2182,7 +2529,6 @@ abstract class WPCOM_JSON_API_Endpoint {
*/
abstract public function callback( $path = '' );
-
}
-require_once dirname( __FILE__ ) . '/json-endpoints.php';
+require_once __DIR__ . '/json-endpoints.php';