PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 15.3.2
Jetpack – WP Security, Backup, Speed, & Growth v15.3.2
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 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 14.3.1 14.4.2 All 500 releases
jetpack / extensions / blocks / subscriptions / class-jetpack-subscription-site.php
class-jetpack-subscription-site.php
334 lines 9.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 }
334