PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3
Jetpack – WP Security, Backup, Speed, & Growth v16.3
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 | extensions/blocks/subscriptions/class-jetpack-subscription-site.php +333 -0 16.2-beta → 16.3 View file →
@@ -1,0 +1,333 @@
1 +<?php
2 +/**
3 + * Adds support for Jetpack Subscription Site feature.
4 + *
5 + * @package automattic/jetpack
6 + * @since 13.2
7 + */
8 +
9 +namespace Automattic\Jetpack\Extensions\Subscriptions;
10 +
11 +use Jetpack_Memberships;
12 +use WP_Block_Template;
13 +use WP_Post;
14 +
15 +/**
16 + * Jetpack_Subscription_Site class.
17 + */
18 +class Jetpack_Subscription_Site {
19 + /**
20 + * Jetpack_Subscription_Site singleton instance.
21 + *
22 + * @var Jetpack_Subscription_Site|null
23 + */
24 + private static $instance;
25 +
26 + /**
27 + * Jetpack_Subscription_Site instance init.
28 + */
29 + public static function init() {
30 + if ( self::$instance === null ) {
31 + self::$instance = new Jetpack_Subscription_Site();
32 + }
33 +
34 + return self::$instance;
35 + }
36 +
37 + /**
38 + * Handles Subscribe block placements.
39 + *
40 + * @return void
41 + */
42 + public function handle_subscribe_block_placements() {
43 + $this->handle_subscribe_block_post_end_placement();
44 + $this->handle_subscribe_block_navigation_placement();
45 + }
46 +
47 + /**
48 + * Returns true if current user can view the post.
49 + *
50 + * @return bool
51 + */
52 + protected function user_can_view_post() {
53 + if ( ! class_exists( 'Jetpack_Memberships' ) ) {
54 + return true;
55 + }
56 +
57 + return Jetpack_Memberships::user_can_view_post();
58 + }
59 +
60 + /**
61 + * Returns post end placement hooked block attributes.
62 + *
63 + * @param array $default_attrs Deafult attributes.
64 + * @param array $anchor_block The anchor block, in parsed block array format.
65 + *
66 + * @return array
67 + */
68 + protected function get_post_end_placement_block_attributes( $default_attrs, $anchor_block ) {
69 + if ( ! empty( $anchor_block['attrs']['layout']['type'] ) ) {
70 + return array_merge(
71 + $default_attrs,
72 + array(
73 + 'layout' => array(
74 + 'type' => $anchor_block['attrs']['layout']['type'],
75 + ),
76 + )
77 + );
78 + }
79 +
80 + if ( ! empty( $anchor_block['attrs']['layout']['inherit'] ) ) {
81 + return array_merge(
82 + $default_attrs,
83 + array(
84 + 'layout' => array(
85 + 'inherit' => $anchor_block['attrs']['layout']['inherit'],
86 + ),
87 + )
88 + );
89 + }
90 +
91 + return $default_attrs;
92 + }
93 +
94 + /**
95 + * Returns true if context is recognized as a header element.
96 + *
97 + * @param WP_Block_Template|WP_Post|array $context The block template, template part, or pattern the anchor block belongs to.
98 + *
99 + * @return bool
100 + */
101 + protected function is_header_context( $context ) {
102 + if ( $context instanceof WP_Post && $context->post_type === 'wp_navigation' ) {
103 + return true;
104 + }
105 +
106 + if ( $context instanceof WP_Block_Template && $context->area === 'header' ) {
107 + return true;
108 + }
109 +
110 + return false;
111 + }
112 +
113 + /**
114 + * Returns true if context is recognized as a single post element.
115 + *
116 + * @param WP_Block_Template|WP_Post|array $context The block template, template part, or pattern the anchor block belongs to.
117 + *
118 + * @return bool
119 + */
120 + protected function is_single_post_context( $context ) {
121 + /**
122 + * Some themes are not returning a WP_Block_Template. In that case, we need to check with is_singular function.
123 + */
124 + if ( is_array( $context ) ) {
125 + return is_singular( 'post' );
126 + }
127 +
128 + return $context instanceof WP_Block_Template && $context->slug === 'single';
129 + }
130 +
131 + /**
132 + * Handles Subscription block navigation placement.
133 + *
134 + * @return void
135 + */
136 + protected function handle_subscribe_block_navigation_placement() {
137 + $is_enabled = get_option( 'jetpack_subscriptions_subscribe_navigation_enabled', false );
138 + if ( ! $is_enabled ) {
139 + return;
140 + }
141 +
142 + if ( ! wp_is_block_theme() ) { // TODO Fallback for classic themes.
143 + return;
144 + }
145 +
146 + add_filter(
147 + 'hooked_block_types',
148 + function ( $hooked_blocks, $relative_position, $anchor_block, $context ) {
149 + if (
150 + $anchor_block === 'core/navigation' &&
151 + $relative_position === 'last_child' &&
152 + self::is_header_context( $context )
153 + ) {
154 + $hooked_blocks[] = 'jetpack/subscriptions';
155 + }
156 +
157 + return $hooked_blocks;
158 + },
159 + 10,
160 + 4
161 + );
162 +
163 + add_filter(
164 + 'hooked_block_jetpack/subscriptions',
165 + function ( $hooked_block, $hooked_block_type, $relative_position, $anchor_block ) {
166 + $is_navigation_anchor_block = isset( $anchor_block['blockName'] ) && $anchor_block['blockName'] === 'core/navigation';
167 +
168 + if ( $is_navigation_anchor_block ) {
169 + $class_name = ( ! empty( $hooked_block['attrs'] ) && ! empty( $hooked_block['attrs']['className'] ) )
170 + ? $hooked_block['attrs']['className'] . ' is-style-button'
171 + : 'is-style-button';
172 +
173 + $hooked_block['attrs']['className'] = $class_name;
174 + $hooked_block['attrs']['appSource'] = 'subscribe-block-navigation';
175 + }
176 +
177 + return $hooked_block;
178 + },
179 + 10,
180 + 4
181 + );
182 + }
183 +
184 + /**
185 + * Handles Subscribe block placement at the end of each post.
186 + *
187 + * @return void
188 + */
189 + protected function handle_subscribe_block_post_end_placement() {
190 + $subscribe_post_end_enabled = get_option( 'jetpack_subscriptions_subscribe_post_end_enabled', false );
191 + if ( ! $subscribe_post_end_enabled ) {
192 + return;
193 + }
194 +
195 + if ( ! wp_is_block_theme() ) { // Fallback for classic themes.
196 + add_filter(
197 + 'the_content',
198 + function ( $content ) {
199 + // Check if we're inside the main loop in a single Post.
200 + if (
201 + is_single() &&
202 + in_the_loop() &&
203 + is_main_query() &&
204 + $this->user_can_view_post()
205 + ) {
206 + // translators: %s is the name of the site.
207 + $discover_more_from_text = sprintf( __( 'Discover more from %s', 'jetpack' ), get_bloginfo( 'name' ) );
208 + $subscribe_text = __( 'Subscribe to get the latest posts sent to your email.', 'jetpack' );
209 +
210 + return $content . do_blocks(
211 + <<<HTML
212 +<!-- wp:group {"style":{"spacing":{"padding":{"top":"0px","bottom":"0px","left":"0px","right":"0px"},"margin":{"top":"32px","bottom":"32px"}},"border":{"width":"0px","style":"none"}},"className":"has-border-color","layout":{"type":"default"}} -->
213 +<div class="wp-block-group has-border-color" style="border-style:none;border-width:0px;margin-top:32px;margin-bottom:32px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px">
214 + <!-- wp:separator {"style":{"spacing":{"margin":{"bottom":"24px"}}},"className":"is-style-wide"} -->
215 + <hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-bottom:24px"/>
216 + <!-- /wp:separator -->
217 +
218 + <!-- wp:heading {"textAlign":"center","level":3,"style":{"layout":{"selfStretch":"fit","flexSize":null},"spacing":{"margin":{"top":"4px","bottom":"10px"}}}} -->
219 + <h3 class="wp-block-heading has-text-align-center" style="margin-top:4px;margin-bottom:10px">$discover_more_from_text</h3>
220 + <!-- /wp:heading -->
221 +
222 + <!-- wp:paragraph {"align":"center","style":{"typography":{"fontSize":"15px"},"spacing":{"margin":{"top":"10px","bottom":"10px"}}}} -->
223 + <p class="has-text-align-center" style="margin-top:10px;margin-bottom:10px;font-size:15px">$subscribe_text</p>
224 + <!-- /wp:paragraph -->
225 +
226 + <!-- wp:group {"layout":{"type":"constrained","contentSize":"480px"}} -->
227 + <div class="wp-block-group">
228 + <!-- wp:jetpack/subscriptions {"appSource":"subscribe-block-post-end"} /-->
229 + </div>
230 + <!-- /wp:group -->
231 +</div>
232 +<!-- /wp:group -->
233 +HTML
234 + );
235 + }
236 +
237 + return $content;
238 + },
239 + 100, // To insert it after the sharing blocks.
240 + 1
241 + );
242 +
243 + return;
244 + }
245 +
246 + add_filter(
247 + 'hooked_block_types',
248 + function ( $hooked_blocks, $relative_position, $anchor_block, $context ) {
249 + if (
250 + $anchor_block === 'core/post-content' &&
251 + $relative_position === 'after' &&
252 + self::is_single_post_context( $context ) &&
253 + $this->user_can_view_post()
254 + ) {
255 + $hooked_blocks[] = 'jetpack/subscriptions';
256 + }
257 +
258 + return $hooked_blocks;
259 + },
260 + 10,
261 + 4
262 + );
263 +
264 + add_filter(
265 + 'hooked_block_jetpack/subscriptions',
266 + function ( $hooked_block, $hooked_block_type, $relative_position, $anchor_block ) {
267 + $is_post_content_anchor_block = isset( $anchor_block['blockName'] ) && $anchor_block['blockName'] === 'core/post-content';
268 + if ( $is_post_content_anchor_block && ( $relative_position === 'after' || $relative_position === 'before' ) ) {
269 + $attrs = $this->get_post_end_placement_block_attributes(
270 + array(
271 + 'style' => array(
272 + 'spacing' => array(
273 + 'margin' => array(
274 + 'top' => '48px',
275 + 'bottom' => '48px',
276 + ),
277 + 'padding' => array(
278 + 'top' => '5px',
279 + 'bottom' => '5px',
280 + ),
281 + ),
282 + ),
283 + ),
284 + $anchor_block
285 + );
286 +
287 + // translators: %s is the name of the site.
288 + $discover_more_from_text = sprintf( __( 'Discover more from %s', 'jetpack' ), get_bloginfo( 'name' ) );
289 + $subscribe_text = __( 'Subscribe to get the latest posts sent to your email.', 'jetpack' );
290 + $inner_content_begin = <<<HTML
291 +<div class="wp-block-group" style="margin-top:48px;margin-bottom:48px;padding-top:5px;padding-bottom:5px">
292 + <!-- wp:separator {"style":{"spacing":{"margin":{"bottom":"36px"}}},"className":"is-style-wide"} -->
293 + <hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-bottom:36px"/>
294 + <!-- /wp:separator -->
295 +
296 + <!-- wp:heading {"textAlign":"center","level":3,"style":{"layout":{"selfStretch":"fit","flexSize":null},"spacing":{"margin":{"top":"4px","bottom":"10px"}}}} -->
297 + <h3 class="wp-block-heading has-text-align-center" style="margin-top:4px;margin-bottom:10px">$discover_more_from_text</h3>
298 + <!-- /wp:heading -->
299 +
300 + <!-- wp:paragraph {"align":"center","style":{"typography":{"fontSize":"15px"},"spacing":{"margin":{"top":"4px","bottom":"0px"}}}} -->
301 + <p class="has-text-align-center" style="margin-top:4px;margin-bottom:0px;font-size:15px">$subscribe_text</p>
302 + <!-- /wp:paragraph -->
303 +
304 + <!-- wp:group {"layout":{"type":"constrained","contentSize":"480px"}} -->
305 + <div class="wp-block-group">
306 +HTML;
307 + $inner_content_end = <<<'HTML'
308 + </div>
309 + <!-- /wp:group -->
310 +</div>
311 +HTML;
312 +
313 + $hooked_block['attrs']['appSource'] = 'subscribe-block-post-end';
314 +
315 + return array(
316 + 'blockName' => 'core/group',
317 + 'attrs' => $attrs,
318 + 'innerBlocks' => array( $hooked_block ),
319 + 'innerContent' => array(
320 + $inner_content_begin,
321 + null,
322 + $inner_content_end,
323 + ),
324 + );
325 + }
326 +
327 + return $hooked_block;
328 + },
329 + 10,
330 + 4
331 + );
332 + }
333 +}