PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-beta
Jetpack – WP Security, Backup, Speed, & Growth v16.3-beta
16.3 16.3-beta 16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 All 508 releases
← All changes | _inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-email-preview.php +183 -0 16.2-beta → 16.3-beta View file →
@@ -1,0 +1,183 @@
1 +<?php
2 +/**
3 + * Email Preview endpoint for the WordPress.com REST API.
4 + *
5 + * @package automattic/jetpack
6 + */
7 +
8 +use Automattic\Jetpack\Connection\Manager;
9 +use Automattic\Jetpack\Connection\Traits\WPCOM_REST_API_Proxy_Request;
10 +use Automattic\Jetpack\Status\Host;
11 +
12 +if ( ! defined( 'ABSPATH' ) ) {
13 + exit( 0 );
14 +}
15 +
16 +/**
17 + * Class WPCOM_REST_API_V2_Endpoint_Email_Preview
18 + *
19 + * Returns an email preview given a post id.
20 + */
21 +class WPCOM_REST_API_V2_Endpoint_Email_Preview extends WP_REST_Controller {
22 +
23 + use WPCOM_REST_API_Proxy_Request;
24 +
25 + /**
26 + * Constructor.
27 + */
28 + public function __construct() {
29 + $this->base_api_path = 'wpcom';
30 + $this->version = 'v2';
31 + $this->namespace = $this->base_api_path . '/' . $this->version;
32 + $this->rest_base = '/email-preview';
33 + $this->wpcom_is_wpcom_only_endpoint = true;
34 + $this->wpcom_is_site_specific_endpoint = true;
35 +
36 + add_action( 'rest_api_init', array( $this, 'register_routes' ) );
37 + }
38 +
39 + /**
40 + * Registers the routes for email preview.
41 + *
42 + * @see register_rest_route()
43 + */
44 + public function register_routes() {
45 + $options = array(
46 + 'show_in_index' => true,
47 + 'methods' => 'GET',
48 + 'callback' => array( $this, 'email_preview' ),
49 + 'permission_callback' => array( $this, 'permissions_check' ),
50 + 'args' => array(
51 + 'post_id' => array(
52 + 'description' => __( 'Unique identifier for the post.', 'jetpack' ),
53 + 'type' => 'integer',
54 + ),
55 + 'access' => array(
56 + 'description' => __( 'Access level.', 'jetpack' ),
57 + 'enum' => array( 'everybody', 'subscribers', 'paid_subscribers' ),
58 + 'default' => 'everybody',
59 + 'validate_callback' => function ( $param ) {
60 + return in_array(
61 + $param,
62 + array( 'everybody', 'subscribers', 'paid_subscribers' ),
63 + true
64 + );
65 + },
66 + ),
67 + ),
68 + );
69 +
70 + register_rest_route(
71 + $this->namespace,
72 + $this->rest_base,
73 + $options
74 + );
75 + }
76 +
77 + /**
78 + * Checks whether the request may render an email preview.
79 + *
80 + * The preview only renders the site's own post, so it needs the site to be connected
81 + * but not the requesting user. The `edit_post` capability check is the authorization.
82 + *
83 + * @param WP_REST_Request $request Full data about the request.
84 + *
85 + * @return true|WP_Error True if the request may render the preview, WP_Error object otherwise.
86 + */
87 + public function permissions_check( $request ) {
88 + $is_wpcom_simple = ( new Host() )->is_wpcom_simple();
89 +
90 + // On a self-hosted site, the site must be connected before we can proxy the preview to WordPress.com.
91 + // This uses its own error code (not the user-connection one) so the client can tell the two apart.
92 + if ( ! $is_wpcom_simple && ! ( new Manager() )->is_connected() ) {
93 + return new WP_Error(
94 + 'rest_cannot_view_email_preview',
95 + __( 'Please connect your site to WordPress.com to preview emails.', 'jetpack' ),
96 + array( 'status' => rest_authorization_required_code() )
97 + );
98 + }
99 +
100 + $post = get_post( $request->get_param( 'post_id' ) );
101 +
102 + if ( ! $post ) {
103 + return new \WP_Error(
104 + 'post_not_found',
105 + __( 'Post not found.', 'jetpack' ),
106 + array( 'status' => 404 )
107 + );
108 + }
109 +
110 + // Authorize any user who can edit the post: the local editor on self-hosted, a user-token request on WordPress.com.
111 + if ( current_user_can( 'edit_post', $post->ID ) ) {
112 + return true;
113 + }
114 +
115 + // On WordPress.com, a blog-token proxy authenticates as user 0 and fails the edit_post check
116 + // above, so authorize it by site ownership instead. The self-hosted endpoint already verified a
117 + // local editor could edit the post, and the blog token never reaches the browser.
118 + if ( $is_wpcom_simple && $this->is_authorized_blog_token_request() ) {
119 + return true;
120 + }
121 +
122 + return new WP_Error(
123 + 'rest_forbidden_context',
124 + __( 'Sorry, you are not allowed to preview emails on this site.', 'jetpack' ),
125 + array( 'status' => rest_authorization_required_code() )
126 + );
127 + }
128 +
129 + /**
130 + * Whether the request is a valid blog-token request authorized for the current site.
131 + *
132 + * Runs on WordPress.com, where a proxied blog token authenticates as user 0.
133 + *
134 + * @return bool True if the request is authorized for the current Jetpack site.
135 + */
136 + private function is_authorized_blog_token_request() {
137 + if ( ! is_jetpack_site( get_current_blog_id() ) ) {
138 + return false;
139 + }
140 +
141 + if ( ! class_exists( 'WPCOM_REST_API_V2_Endpoint_Jetpack_Auth' ) ) {
142 + require_once dirname( __DIR__ ) . '/rest-api-plugins/endpoints/jetpack-auth.php';
143 + }
144 +
145 + $jp_auth_endpoint = new WPCOM_REST_API_V2_Endpoint_Jetpack_Auth();
146 +
147 + return true === $jp_auth_endpoint->is_jetpack_authorized_for_site();
148 + }
149 +
150 + /**
151 + * Returns an email preview of a post, or proxies the request to WordPress.com on non-wpcom sites.
152 + *
153 + * @param WP_REST_Request $request Full data about the request.
154 + *
155 + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
156 + */
157 + public function email_preview( $request ) {
158 + // On a non-wpcom site, proxy to WordPress.com with the user's token, falling back to the site's blog token.
159 + if ( ! ( new Host() )->is_wpcom_simple() ) {
160 + return $this->proxy_request_to_wpcom( $request, '', 'user', true );
161 + }
162 +
163 + $post_id = $request['post_id'];
164 + $access = $request['access'];
165 + $post = get_post( $post_id );
166 + return rest_ensure_response(
167 + array(
168 + /**
169 + * Filters the generated email preview HTML.
170 + *
171 + * @since 13.8
172 + *
173 + * @param string $html The generated HTML for the email preview.
174 + * @param WP_Post $post The post object.
175 + * @param string $access The access level.
176 + */
177 + 'html' => apply_filters( 'jetpack_generate_email_preview_html', '', $post, $access ),
178 + )
179 + );
180 + }
181 +}
182 +
183 +wpcom_rest_api_v2_load_plugin( 'WPCOM_REST_API_V2_Endpoint_Email_Preview' );