diff options
author | Yury German <blueknight@gentoo.org> | 2016-02-12 22:22:00 -0500 |
---|---|---|
committer | Yury German <blueknight@gentoo.org> | 2016-02-12 22:22:00 -0500 |
commit | 657cafe0e955cf88033597f131aa50835140c617 (patch) | |
tree | cf21a30d319cb2a238a6cfb8b4eb3b20b1b5dcff /plugins/jetpack/class.json-api-endpoints.php | |
parent | Adding New Mantra version 2.4.1.1 - Bug 574468 (diff) | |
download | blogs-gentoo-657cafe0e955cf88033597f131aa50835140c617.tar.gz blogs-gentoo-657cafe0e955cf88033597f131aa50835140c617.tar.bz2 blogs-gentoo-657cafe0e955cf88033597f131aa50835140c617.zip |
Updating plugins easy-table, jetpack, openid, public-post preview, talbe-of-contents-plus, wordress-mobile-pack - Bug 574468
Diffstat (limited to 'plugins/jetpack/class.json-api-endpoints.php')
-rw-r--r-- | plugins/jetpack/class.json-api-endpoints.php | 539 |
1 files changed, 309 insertions, 230 deletions
diff --git a/plugins/jetpack/class.json-api-endpoints.php b/plugins/jetpack/class.json-api-endpoints.php index 25716ab8..1943d272 100644 --- a/plugins/jetpack/class.json-api-endpoints.php +++ b/plugins/jetpack/class.json-api-endpoints.php @@ -5,37 +5,37 @@ require_once( dirname( __FILE__ ) . '/json-api-config.php' ); // Endpoint abstract class WPCOM_JSON_API_Endpoint { // The API Object - var $api; + public $api; - var $pass_wpcom_user_details = false; - var $can_use_user_details_instead_of_blog_membership = false; + public $pass_wpcom_user_details = false; + public $can_use_user_details_instead_of_blog_membership = false; // One liner. - var $description; + public $description; // Object Grouping For Documentation (Users, Posts, Comments) - var $group; + public $group; // Stats extra value to bump - var $stat; + public $stat; // HTTP Method - var $method = 'GET'; + public $method = 'GET'; // Minimum version of the api for which to serve this endpoint - var $min_version = '0'; + public $min_version = '0'; // Maximum version of the api for which to serve this endpoint - var $max_version = WPCOM_JSON_API__CURRENT_VERSION; + public $max_version = WPCOM_JSON_API__CURRENT_VERSION; // Path at which to serve this endpoint: sprintf() format. - var $path = ''; + public $path = ''; // Identifiers to fill sprintf() formatted $path - var $path_labels = array(); + public $path_labels = array(); // Accepted query parameters - var $query = array( + public $query = array( // Parameter name 'context' => array( // Default value => description @@ -45,7 +45,7 @@ abstract class WPCOM_JSON_API_Endpoint { ), 'http_envelope' => array( 'false' => '', - 'true' => 'Some environments (like in-browser Javascript or Flash) block or divert responses with a non-200 HTTP status code. Setting this parameter will force the HTTP status code to always be 200. The JSON response is wrapped in an "envelope" containing the "real" HTTP status code and headers.', + 'true' => 'Some environments (like in-browser JavaScript or Flash) block or divert responses with a non-200 HTTP status code. Setting this parameter will force the HTTP status code to always be 200. The JSON response is wrapped in an "envelope" containing the "real" HTTP status code and headers.', ), 'pretty' => array( 'false' => '', @@ -58,51 +58,56 @@ abstract class WPCOM_JSON_API_Endpoint { ); // Response format - var $response_format = array(); + public $response_format = array(); // Request format - var $request_format = array(); + public $request_format = array(); // Is this endpoint still in testing phase? If so, not available to the public. - var $in_testing = false; + public $in_testing = false; // Is this endpoint still allowed if the site in question is flagged? - var $allowed_if_flagged = false; + public $allowed_if_flagged = false; /** * @var string Version of the API */ - var $version = ''; + public $version = ''; /** * @var string Example request to make */ - var $example_request = ''; + public $example_request = ''; /** * @var string Example request data (for POST methods) */ - var $example_request_data = ''; + public $example_request_data = ''; /** * @var string Example response from $example_request */ - var $example_response = ''; + public $example_response = ''; /** * @var bool Set to true if the endpoint implements its own filtering instead of the standard `fields` query method */ - var $custom_fields_filtering = false; + 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. */ - var $allow_cross_origin_request = false; + public $allow_cross_origin_request = false; /** * @var bool Set to true if the endpoint can recieve unauthorized POST requests. */ - var $allow_unauthorized_request = false; + public $allow_unauthorized_request = false; + + /** + * @var bool Set to true if the endpoint should accept site based (not user based) authentication. + */ + public $allow_jetpack_site_auth = false; function __construct( $args ) { $defaults = array( @@ -132,6 +137,7 @@ abstract class WPCOM_JSON_API_Endpoint { 'custom_fields_filtering' => false, 'allow_cross_origin_request' => false, 'allow_unauthorized_request' => false, + 'allow_jetpack_site_auth' => false, ); $args = wp_parse_args( $args, $defaults ); @@ -159,8 +165,8 @@ abstract class WPCOM_JSON_API_Endpoint { $this->can_use_user_details_instead_of_blog_membership = $args['can_use_user_details_instead_of_blog_membership']; $this->allow_cross_origin_request = (bool) $args['allow_cross_origin_request']; - $this->allow_unauthorized_request = (bool) $args['allow_unauthorized_request']; + $this->allow_jetpack_site_auth = (bool) $args['allow_jetpack_site_auth']; $this->version = $args['version']; @@ -345,8 +351,8 @@ abstract class WPCOM_JSON_API_Endpoint { $return[$key] = (string) esc_url_raw( $value ); break; case 'string' : - // Fallback string -> array - if ( is_array( $value ) ) { + // Fallback string -> array, or string -> object + if ( is_array( $value ) || is_object( $value ) ) { if ( !empty( $types[0] ) ) { $next_type = array_shift( $types ); return $this->cast_and_filter_item( $return, $next_type, $key, $value, $types, $for_output ); @@ -462,7 +468,7 @@ abstract class WPCOM_JSON_API_Endpoint { case 'tag' : case 'category' : $docs = array( - 'ID' => '(int)', + 'ID' => '(int)', 'name' => '(string)', 'slug' => '(string)', 'description' => '(HTML)', @@ -477,10 +483,10 @@ abstract class WPCOM_JSON_API_Endpoint { case 'post_reference' : case 'comment_reference' : $docs = array( - 'ID' => '(int)', - 'type' => '(string)', + 'ID' => '(int)', + 'type' => '(string)', 'title' => '(string)', - 'link' => '(URL)', + 'link' => '(URL)', ); $return[$key] = (object) $this->cast_and_filter( $value, $docs, false, $for_output ); break; @@ -494,13 +500,27 @@ abstract class WPCOM_JSON_API_Endpoint { break; case 'author' : $docs = array( - 'ID' => '(int)', - 'user_login' => '(string)', - 'email' => '(string|false)', - 'name' => '(string)', - 'URL' => '(URL)', - 'avatar_URL' => '(URL)', - 'profile_URL' => '(URL)', + 'ID' => '(int)', + 'user_login' => '(string)', + 'login' => '(string)', + 'email' => '(string|false)', + 'name' => '(string)', + 'first_name' => '(string)', + 'last_name' => '(string)', + 'nice_name' => '(string)', + 'URL' => '(URL)', + 'avatar_URL' => '(URL)', + 'profile_URL' => '(URL)', + 'is_super_admin' => '(bool)', + 'roles' => '(array:string)' + ); + $return[$key] = (object) $this->cast_and_filter( $value, $docs, false, $for_output ); + break; + case 'role' : + $docs = array( + 'name' => '(string)', + 'display_name' => '(string)', + 'capabilities' => '(object:boolean)', ); $return[$key] = (object) $this->cast_and_filter( $value, $docs, false, $for_output ); break; @@ -514,7 +534,21 @@ abstract class WPCOM_JSON_API_Endpoint { 'height' => '(int)', 'duration' => '(int)', ); - $return[$key] = (object) $this->cast_and_filter( $value, apply_filters( 'wpcom_json_api_attachment_cast_and_filter', $docs ), false, $for_output ); + $return[$key] = (object) $this->cast_and_filter( + $value, + /** + * Filter the documentation returned for a post attachment. + * + * @module json-api + * + * @since 1.9.0 + * + * @param array $docs Array of documentation about a post attachment. + */ + apply_filters( 'wpcom_json_api_attachment_cast_and_filter', $docs ), + false, + $for_output + ); break; case 'metadata' : $docs = array( @@ -524,7 +558,13 @@ abstract class WPCOM_JSON_API_Endpoint { 'previous_value' => '(string)', 'operation' => '(string)', ); - $return[$key] = (object) $this->cast_and_filter( $value, apply_filters( 'wpcom_json_api_attachment_cast_and_filter', $docs ), false, $for_output ); + $return[$key] = (object) $this->cast_and_filter( + $value, + /** This filter is documented in class.json-api-endpoints.php */ + apply_filters( 'wpcom_json_api_attachment_cast_and_filter', $docs ), + false, + $for_output + ); break; case 'plugin' : $docs = array( @@ -542,7 +582,21 @@ abstract class WPCOM_JSON_API_Endpoint { 'autoupdate' => '(boolean) Whether the plugin is auto updated', 'log' => '(array:safehtml) An array of update log strings.', ); - $return[$key] = (object) $this->cast_and_filter( $value, apply_filters( 'wpcom_json_api_plugin_cast_and_filter', $docs ), false, $for_output ); + $return[$key] = (object) $this->cast_and_filter( + $value, + /** + * Filter the documentation returned for a plugin. + * + * @module json-api + * + * @since 3.1.0 + * + * @param array $docs Array of documentation about a plugin. + */ + apply_filters( 'wpcom_json_api_plugin_cast_and_filter', $docs ), + false, + $for_output + ); break; case 'jetpackmodule' : $docs = array( @@ -556,7 +610,13 @@ abstract class WPCOM_JSON_API_Endpoint { 'free' => '(boolean) The module\'s Free or Paid status.', 'module_tags' => '(array) The module\'s tags.' ); - $return[$key] = (object) $this->cast_and_filter( $value, apply_filters( 'wpcom_json_api_plugin_cast_and_filter', $docs ), false, $for_output ); + $return[$key] = (object) $this->cast_and_filter( + $value, + /** This filter is documented in class.json-api-endpoints.php */ + apply_filters( 'wpcom_json_api_plugin_cast_and_filter', $docs ), + false, + $for_output + ); break; case 'sharing_button' : $docs = array( @@ -588,7 +648,13 @@ abstract class WPCOM_JSON_API_Endpoint { } if ( ! empty( $docs ) ) { - $return[$key] = (object) $this->cast_and_filter( $value, apply_filters( 'wpcom_json_api_plugin_cast_and_filter', $docs ), false, $for_output ); + $return[$key] = (object) $this->cast_and_filter( + $value, + /** This filter is documented in class.json-api-endpoints.php */ + apply_filters( 'wpcom_json_api_plugin_cast_and_filter', $docs ), + false, + $for_output + ); } else { trigger_error( "Unknown API casting type {$type['type']}", E_USER_WARNING ); } @@ -628,6 +694,7 @@ abstract class WPCOM_JSON_API_Endpoint { * Echoes HTML. */ function document( $show_description = true ) { + global $wpdb; $original_post = isset( $GLOBALS['post'] ) ? $GLOBALS['post'] : 'unset'; unset( $GLOBALS['post'] ); @@ -646,28 +713,46 @@ abstract class WPCOM_JSON_API_Endpoint { <p><strong>This endpoint is deprecated in favor of version <?php echo floatval( $this->new_version ); ?></strong></p> <?php } ?> -<section class="resource-url"> - <h2 id="apidoc-resource-url">Resource URL</h2> +<section class="resource-info"> + <h2 id="apidoc-resource-info">Resource Information</h2> + <table class="api-doc api-doc-resource-parameters api-doc-resource"> - <thead> - <tr> - <th class="api-index-title" scope="column">Type</th> - <th class="api-index-title" scope="column">URL and Format</th> - </tr> - </thead> - <tbody> - <tr class="api-index-item"> - <th scope="row" class="parameter api-index-item-title"><?php echo wp_kses_post( $doc['method'] ); ?></th> - <?php - $version = WPCOM_JSON_API__CURRENT_VERSION; - if ( !empty( $this->max_version ) ) { - $version = $this->max_version; - } - ?> - <td class="type api-index-item-title" style="white-space: nowrap;">https://public-api.wordpress.com/rest/v<?php echo floatval( $version ); ?><?php echo wp_kses_post( $doc['path_labeled'] ); ?></td> - </tr> - </tbody> + + <thead> + <tr> + <th class="api-index-title" scope="column"> </th> + <th class="api-index-title" scope="column"> </th> + </tr> + </thead> + <tbody> + + <tr class="api-index-item"> + <th scope="row" class="parameter api-index-item-title">Method</th> + <td class="type api-index-item-title"><?php echo wp_kses_post( $doc['method'] ); ?></td> + </tr> + + <tr class="api-index-item"> + <th scope="row" class="parameter api-index-item-title">URL</th> + <?php + $version = WPCOM_JSON_API__CURRENT_VERSION; + if ( !empty( $this->max_version ) ) { + $version = $this->max_version; + } + ?> + <td class="type api-index-item-title">https://public-api.wordpress.com/rest/v<?php echo floatval( $version ); ?><?php echo wp_kses_post( $doc['path_labeled'] ); ?></td> + </tr> + + <tr class="api-index-item"> + <th scope="row" class="parameter api-index-item-title">Requires authentication?</th> + <?php + $requires_auth = $wpdb->get_row( $wpdb->prepare( "SELECT requires_authentication FROM rest_api_documentation WHERE `version` = %s AND `path` = %s AND `method` = %s LIMIT 1", $version, untrailingslashit( $doc['path_labeled'] ), $doc['method'] ) ); + ?> + <td class="type api-index-item-title"><?php echo ( true === (bool) $requires_auth->requires_authentication ? 'Yes' : 'No' ); ?></td> + </tr> + + </tbody> </table> + </section> <?php @@ -720,146 +805,6 @@ abstract class WPCOM_JSON_API_Endpoint { <?php endforeach; ?> <?php - // If no example was hardcoded in the doc, try to get some - if ( empty( $this->example_response ) ) { - - // Examples for endpoint documentation response - $response_key = 'dev_example_response_' . $this->version . '_' . $this->method . '_' . sanitize_key( $this->path ); - $response_body = wp_cache_get( $response_key ); - - // Response doesn't exist, so run the request - if ( false === $response_body ) { - - // Only trust GET request - if ( 'GET' === $this->method ) { - $response = wp_remote_get( $this->example_request ); - $response_body = wp_remote_retrieve_body( $response ); - - // Only cache if there's a result - if ( ! is_wp_error( $response ) && strlen( $response_body ) ) { - wp_cache_set( $response_key, $response_body ); - } else { - wp_cache_delete( $response_key ); - } - } - } - - // Example response was passed into the constructor via params - } else { - $response_body = $this->example_response; - } - - // Wrap the response in a sourcecode shortcode - if ( !empty( $response_body ) && !is_wp_error( $response ) ) { - $response_body = '[sourcecode language="javascript" wraplines="false" light="true" autolink="false" htmlscript="false"]' . $response_body . '[/sourcecode]'; - $response_body = apply_filters( 'the_content', $response_body ); - $this->example_response = $response_body; - } - - $curl = 'curl'; - - $php_opts = array( 'ignore_errors' => true ); - - if ( 'GET' !== $this->method ) { - $php_opts['method'] = $this->method; - } - - if ( $this->example_request_data ) { - if ( isset( $this->example_request_data['headers'] ) && is_array( $this->example_request_data['headers'] ) ) { - $php_opts['header'] = array(); - foreach ( $this->example_request_data['headers'] as $header => $value ) { - $curl .= " \\\n -H " . escapeshellarg( "$header: $value" ); - $php_opts['header'][] = "$header: $value"; - } - } - - if ( isset( $this->example_request_data['body'] ) && is_array( $this->example_request_data['body'] ) ) { - $php_opts['content'] = $this->example_request_data['body']; - $php_opts['header'][] = 'Content-Type: application/x-www-form-urlencoded'; - foreach ( $this->example_request_data['body'] as $key => $value ) { - $curl .= " \\\n --data-urlencode " . escapeshellarg( "$key=$value" ); - } - } - } - - if ( $php_opts ) { - $php_opts_exported = var_export( array( 'http' => $php_opts ), true ); - if ( !empty( $php_opts['content'] ) ) { - $content_exported = preg_quote( var_export( $php_opts['content'], true ), '/' ); - $content_exported = '\\s*' . str_replace( "\n", "\n\\s*", $content_exported ) . '\\s*'; - $php_opts_exported = preg_replace_callback( "/$content_exported/", array( $this, 'add_http_build_query_to_php_content_example' ), $php_opts_exported ); - } - $php = <<<EOPHP -<?php - -\$options = $php_opts_exported; - -\$context = stream_context_create( \$options ); -\$response = file_get_contents( - '$this->example_request', - false, - \$context -); -\$response = json_decode( \$response ); - -?> -EOPHP; - } else { - $php = <<<EOPHP -<?php - -\$response = file_get_contents( '$this->example_request' ); -\$response = json_decode( \$response ); - -?> -EOPHP; - } - - if ( false !== strpos( $curl, "\n" ) ) { - $curl .= " \\\n"; - } - - // Escape square brackets to prevent curl "[globbing] bad range specification" errors - $example_request = strtr( $this->example_request, array( '[' => '\[', ']' => '\]' ) ); - - $curl .= ' ' . escapeshellarg( $example_request ); - - $curl = '[sourcecode language="bash" wraplines="false" light="true" autolink="false" htmlscript="false"]' . $curl . '[/sourcecode]'; - $curl = apply_filters( 'the_content', $curl ); - - $php = '[sourcecode language="php" wraplines="false" light="true" autolink="false" htmlscript="false"]' . $php . '[/sourcecode]'; - $php = apply_filters( 'the_content', $php ); -?> - -<?php if ( ! empty( $this->example_request ) || ! empty( $this->example_request_data ) || ! empty( $this->example_response ) ) : ?> - - <section class="example-response"> - <h2 id="apidoc-example">Example</h2> - - <section> - <h3>cURL</h3> - <?php echo wp_kses_post( $curl ); ?> - </section> - - <section> - <h3>PHP</h3> - <?php echo wp_kses_post( $php ); ?> - </section> - - <?php if ( ! empty( $this->example_response ) ) : ?> - - <section> - <h3>Response Body</h3> - <?php echo $this->example_response; ?> - </section> - - <?php endif; ?> - - </section> - -<?php endif; ?> - -<?php if ( 'unset' !== $original_post ) { $GLOBALS['post'] = $original_post; } @@ -1019,7 +964,24 @@ EOPHP; } } - if ( -1 == get_option( 'blog_public' ) && ! apply_filters( 'wpcom_json_api_user_can_view_post', current_user_can( 'read_post', $post->ID ), $post ) ) { + if ( + -1 == get_option( 'blog_public' ) && + /** + * Filter access to a specific post. + * + * @module json-api + * + * @since 3.4.0 + * + * @param bool current_user_can( 'read_post', $post->ID ) Can the current user access the post. + * @param WP_Post $post Post data. + */ + ! apply_filters( + 'wpcom_json_api_user_can_view_post', + current_user_can( 'read_post', $post->ID ), + $post + ) + ) { return new WP_Error( 'unauthorized', 'User cannot view post', array( 'status_code' => 403, 'error' => 'private_blog' ) ); } @@ -1044,6 +1006,8 @@ EOPHP; $login = ''; $email = $author->comment_author_email; $name = $author->comment_author; + $first_name = ''; + $last_name = ''; $URL = $author->comment_author_url; $profile_URL = 'http://en.gravatar.com/' . md5( strtolower( trim( $email ) ) ); $nice = ''; @@ -1059,15 +1023,27 @@ EOPHP; // then $author is a Post Object. if ( 0 == $author->post_author ) return null; + /** + * Filter whether the current site is a Jetpack site. + * + * @module json-api + * + * @since 3.3.0 + * + * @param bool false Is the current site a Jetpack site. Default to false. + * @param int get_current_blog_id() Blog ID. + */ $is_jetpack = true === apply_filters( 'is_jetpack_site', false, get_current_blog_id() ); $post_id = $author->ID; if ( $is_jetpack && ( defined( 'IS_WPCOM' ) && IS_WPCOM ) ) { - $ID = get_post_meta( $post_id, '_jetpack_post_author_external_id', true ); - $email = get_post_meta( $post_id, '_jetpack_author_email', true ); - $login = ''; - $name = get_post_meta( $post_id, '_jetpack_author', true ); - $URL = ''; - $nice = ''; + $ID = get_post_meta( $post_id, '_jetpack_post_author_external_id', true ); + $email = get_post_meta( $post_id, '_jetpack_author_email', true ); + $login = ''; + $name = get_post_meta( $post_id, '_jetpack_author', true ); + $first_name = ''; + $last_name = ''; + $URL = ''; + $nice = ''; } else { $author = $author->post_author; } @@ -1084,12 +1060,14 @@ EOPHP; return null; } - $ID = $user->ID; - $email = $user->user_email; - $login = $user->user_login; - $name = $user->display_name; - $URL = $user->user_url; - $nice = $user->user_nicename; + $ID = $user->ID; + $email = $user->user_email; + $login = $user->user_login; + $name = $user->display_name; + $first_name = $user->first_name; + $last_name = $user->last_name; + $URL = $user->user_url; + $nice = $user->user_nicename; } if ( defined( 'IS_WPCOM' ) && IS_WPCOM && ! $is_jetpack ) { $active_blog = get_active_blog_for_user( $ID ); @@ -1110,6 +1088,8 @@ EOPHP; 'login' => (string) $login, '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 ), @@ -1185,23 +1165,51 @@ EOPHP; if ( in_array( $ext, array( 'jpg', 'jpeg', 'png', 'gif' ) ) ) { $metadata = wp_get_attachment_metadata( $media_item->ID ); - $response['height'] = $metadata['height']; - $response['width'] = $metadata['width']; - foreach ( $metadata['sizes'] as $size => $size_details ) { - $response['thumbnails'][ $size ] = dirname( $response['URL'] ) . '/' . $size_details['file']; + if ( isset( $metadata['height'], $metadata['width'] ) ) { + $response['height'] = $metadata['height']; + $response['width'] = $metadata['width']; + } + + if ( isset( $metadata['sizes'] ) ) { + /** + * Filter the thumbnail sizes available for each attachment ID. + * + * @module json-api + * + * @since 3.9.0 + * + * @param array $metadata['sizes'] Array of thumbnail sizes available for a given attachment ID. + * @param string $media_id Attachment ID. + */ + $sizes = apply_filters( 'rest_api_thumbnail_sizes', $metadata['sizes'], $media_id ); + if ( is_array( $sizes ) ) { + foreach ( $sizes as $size => $size_details ) { + $response['thumbnails'][ $size ] = dirname( $response['URL'] ) . '/' . $size_details['file']; + } + } + } + + if ( isset( $metadata['image_meta'] ) ) { + $response['exif'] = $metadata['image_meta']; } - $response['exif'] = $metadata['image_meta']; } if ( in_array( $ext, array( 'mp3', 'm4a', 'wav', 'ogg' ) ) ) { $metadata = wp_get_attachment_metadata( $media_item->ID ); + $response['length'] = $metadata['length']; $response['exif'] = $metadata; } if ( in_array( $ext, array( 'ogv', 'mp4', 'mov', 'wmv', 'avi', 'mpg', '3gp', '3g2', 'm4v' ) ) ) { $metadata = wp_get_attachment_metadata( $media_item->ID ); - $response['height'] = $metadata['height']; - $response['width'] = $metadata['width']; + if ( isset( $metadata['height'], $metadata['width'] ) ) { + $response['height'] = $metadata['height']; + $response['width'] = $metadata['width']; + } + + if ( isset( $metadata['length'] ) ) { + $response['length'] = $metadata['length']; + } // add VideoPress info if ( function_exists( 'video_get_info_by_blogpostid' ) ) { @@ -1271,7 +1279,6 @@ EOPHP; return new WP_Error( 'unauthorized', 'User cannot edit taxonomy', 403 ); break; case 'display' : - $tax = get_taxonomy( $taxonomy_type ); if ( -1 == get_option( 'blog_public' ) && ! current_user_can( 'read' ) ) { return new WP_Error( 'unauthorized', 'User cannot view taxonomy', 403 ); } @@ -1410,9 +1417,20 @@ EOPHP; // Load the functions.php file for the current theme to get its post formats, CPTs, etc. function load_theme_functions() { - // the theme info we care about is found either within functions.php or one of the jetpack files. it might also make sense to load inc/wpcom.php and includes/wpcom.php if there is a need for it + // bail if we've done this already (can happen when calling /batch endpoint) + if ( defined( 'REST_API_THEME_FUNCTIONS_LOADED' ) ) + 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. $function_files = array( '/functions.php', '/inc/jetpack.compat.php', '/inc/jetpack.php', '/includes/jetpack.compat.php' ); + $copy_dirs = array( get_template_directory() ); + if ( wpcom_is_vip() ) { + $copy_dirs[] = WP_CONTENT_DIR . '/themes/vip/plugins/'; + } + // Is this a child theme? Load the child theme's functions file. if ( get_stylesheet_directory() !== get_template_directory() && wpcom_is_child_theme() ) { foreach ( $function_files as $function_file ) { @@ -1420,6 +1438,7 @@ EOPHP; require_once( get_stylesheet_directory() . $function_file ); } } + $copy_dirs[] = get_stylesheet_directory(); } foreach ( $function_files as $function_file ) { @@ -1428,14 +1447,43 @@ EOPHP; } } + // add inc/wpcom.php and/or includes/wpcom.php + wpcom_load_theme_compat_file(); + // 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', WP_CONTENT_DIR . '/themes' ); + $this->copy_hooks( 'after_setup_theme', 'restapi_theme_after_setup_theme', $copy_dirs ); + + /** + * Fires functions hooked onto `after_setup_theme` by the theme for the purpose of the REST API. + * + * The REST API does not load the theme when processing requests. + * To enable theme-based functionality, the API will load the '/functions.php', + * '/inc/jetpack.compat.php', '/inc/jetpack.php', '/includes/jetpack.compat.php files + * of the theme (parent and child) and copy functions hooked onto 'after_setup_theme' within those files. + * + * @module json-api + * + * @since 3.2.0 + */ do_action( 'restapi_theme_after_setup_theme' ); - $this->copy_hooks( 'init', 'restapi_theme_init', WP_CONTENT_DIR . '/themes' ); + $this->copy_hooks( 'init', 'restapi_theme_init', $copy_dirs ); + + /** + * Fires functions hooked onto `init` by the theme for the purpose of the REST API. + * + * The REST API does not load the theme when processing requests. + * To enable theme-based functionality, the API will load the '/functions.php', + * '/inc/jetpack.compat.php', '/inc/jetpack.php', '/includes/jetpack.compat.php files + * of the theme (parent and child) and copy functions hooked onto 'init' within those files. + * + * @module json-api + * + * @since 3.2.0 + */ do_action( 'restapi_theme_init' ); } - function copy_hooks( $from_hook, $to_hook, $base_path = '' ) { + function copy_hooks( $from_hook, $to_hook, $base_paths ) { global $wp_filter; foreach ( $wp_filter as $hook => $actions ) { if ( $from_hook <> $hook ) @@ -1446,8 +1494,10 @@ EOPHP; $reflection = $this->get_reflection( $callback ); // use reflection api to determine filename where function is defined if ( false !== $reflection ) { $file_name = $reflection->getFileName(); - if ( 0 === strpos( $file_name, $base_path ) ) { // only copy hooks with functions which are part of VIP (the theme, parent theme, or VIP plugins) - $wp_filter[$to_hook][$priority][ 'cph' . $callback_key ] = $callback_data; + foreach( $base_paths as $base_path ) { + if ( 0 === strpos( $file_name, $base_path ) ) { // only copy hooks with functions which are part of the specified files + $wp_filter[ $to_hook ][ $priority ][ 'cph' . $callback_key ] = $callback_data; + } } } } @@ -1645,6 +1695,8 @@ EOPHP; $base = substr( $base, 0, - 1 ) . $api_version; } + // escape any % in the relative path before running it through sprintf again + $relative_path = str_replace( '%', '%%', $relative_path ); // http, WPCOM_JSON_API__BASE, ... , path // %s , %s , $format, %s return esc_url_raw( sprintf( "%s://%s$relative_path", $this->api->public_api_scheme, $base ) ); @@ -1740,6 +1792,15 @@ EOPHP; protected function _get_whitelisted_post_types() { $allowed_types = array( 'post', 'page', 'revision' ); + /** + * Filter the post types Jetpack has access to, and can synchronize with WordPress.com. + * + * @module json-api + * + * @since 2.2.3 + * + * @param array $allowed_types Array of whitelisted post types. Default to `array( 'post', 'page', 'revision' )`. + */ $allowed_types = apply_filters( 'rest_api_allowed_post_types', $allowed_types ); return array_unique( $allowed_types ); @@ -1899,6 +1960,15 @@ EOPHP; // lets whitelist to only specific clients right now $clients_allowed_video_uploads = array(); + /** + * Filter the list of whitelisted video clients. + * + * @module json-api + * + * @since 3.2.0 + * + * @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 ) ) { return $mimes; @@ -1907,6 +1977,15 @@ EOPHP; $mime_list = wp_get_mime_types(); $video_exts = explode( ' ', get_site_option( 'video_upload_filetypes', false, false ) ); + /** + * Filter the video filetypes allowed on the site. + * + * @module json-api + * + * @since 3.2.0 + * + * @param array $video_exts Array of video filetypes allowed on the site. + */ $video_exts = apply_filters( 'video_upload_filetypes', $video_exts ); $video_mimes = array(); |