Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 89
0.00% covered (danger)
0.00%
0 / 5
CRAP
n/a
0 / 0
Automattic\Jetpack\Extensions\Premium_Content\register_block
0.00% covered (danger)
0.00%
0 / 38
0.00% covered (danger)
0.00%
0 / 1
6
Automattic\Jetpack\Extensions\Premium_Content\render_block
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
12
Automattic\Jetpack\Extensions\Premium_Content\render_stripe_nudge
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
12
Automattic\Jetpack\Extensions\Premium_Content\stripe_nudge
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
Automattic\Jetpack\Extensions\Premium_Content\add_paid_content_post_meta
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
30
1<?php
2/**
3 * Premium Content Block.
4 *
5 * @package automattic/jetpack
6 */
7
8namespace Automattic\Jetpack\Extensions\Premium_Content;
9
10use Automattic\Jetpack\Blocks;
11use Jetpack_Gutenberg;
12use WP_Post;
13use const Automattic\Jetpack\Extensions\Subscriptions\META_NAME_CONTAINS_PAID_CONTENT;
14
15require_once __DIR__ . '/_inc/access-check.php';
16require_once __DIR__ . '/logged-out-view/logged-out-view.php';
17require_once __DIR__ . '/subscriber-view/subscriber-view.php';
18require_once __DIR__ . '/buttons/buttons.php';
19require_once __DIR__ . '/login-button/login-button.php';
20require_once JETPACK__PLUGIN_DIR . 'extensions/blocks/subscriptions/constants.php';
21
22/**
23 * Registers the block for use in Gutenberg
24 * This is done via an action so that we can disable
25 * registration if we need to.
26 */
27function register_block() {
28
29    require_once JETPACK__PLUGIN_DIR . '/modules/memberships/class-jetpack-memberships.php';
30    if ( \Jetpack_Memberships::should_enable_monetize_blocks_in_editor() ) {
31        Blocks::jetpack_register_block(
32            __DIR__,
33            array(
34                'render_callback'  => __NAMESPACE__ . '\render_block',
35                'provides_context' => array(
36                    'premium-content/planId'  => 'selectedPlanId', // Deprecated.
37                    'premium-content/planIds' => 'selectedPlanIds',
38                    'isPremiumContentChild'   => 'isPremiumContentChild',
39                ),
40            )
41        );
42    }
43
44    register_post_meta(
45        'post',
46        META_NAME_CONTAINS_PAID_CONTENT,
47        array(
48            'show_in_rest'  => true,
49            'single'        => true,
50            'type'          => 'boolean',
51            /* translators: Keep the quoted values, block names and meta keys in English. */
52            'description'   => __( 'Computed on every save: true when the content has a Paid Content block (premium-content/container). Any value sent here is overwritten; add or remove the block instead.', 'jetpack' ),
53            'auth_callback' => function () {
54                return wp_get_current_user()->has_cap( 'edit_posts' );
55            },
56        )
57    );
58
59    // This ensures Jetpack will sync this post meta to WPCOM.
60    add_filter(
61        'jetpack_sync_post_meta_whitelist',
62        function ( $allowed_meta ) {
63            return array_merge(
64                $allowed_meta,
65                array(
66                    META_NAME_CONTAINS_PAID_CONTENT,
67                )
68            );
69        }
70    );
71
72    add_action( 'wp_after_insert_post', __NAMESPACE__ . '\add_paid_content_post_meta', 99, 2 );
73}
74add_action( 'init', __NAMESPACE__ . '\register_block' );
75add_action( 'template_redirect', __NAMESPACE__ . '\prewarm_premium_content_session_cookie' );
76
77/**
78 * Render callback.
79 *
80 * @param array  $attributes Array containing the block attributes.
81 * @param string $content    String containing the block content.
82 *
83 * @return string
84 */
85function render_block( $attributes, $content ) {
86    if ( ! pre_render_checks() ) {
87        return '';
88    }
89
90    // Render the Stripe nudge when Stripe is unconnected
91    if ( ! membership_checks() ) {
92        $stripe_nudge = render_stripe_nudge();
93        return $stripe_nudge . $content;
94    }
95
96    // We don't use FEATURE_NAME here because styles are not in /container folder.
97    Jetpack_Gutenberg::load_assets_as_required( 'premium-content' );
98    return $content;
99}
100
101/**
102 * Server-side rendering for the stripe connection nudge.
103 *
104 * @return string Final content to render.
105 */
106function render_stripe_nudge() {
107    if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
108        \require_lib( 'memberships' );
109        $blog_id  = get_current_blog_id();
110        $settings = (array) \get_memberships_settings_for_site( $blog_id );
111
112        return stripe_nudge(
113            $settings['connect_url'],
114            __( 'Connect to Stripe to use this block on your site.', 'jetpack' ),
115            __( 'Connect', 'jetpack' )
116        );
117    } else {
118        // On WoA sites, the Stripe connection url is not easily available
119        // server-side, so we redirect them to the post in the editor in order
120        // to connect.
121        return stripe_nudge(
122            get_edit_post_link( get_the_ID() ),
123            __( 'Connect to Stripe in the editor to use this block on your site.', 'jetpack' ),
124            __( 'Edit post', 'jetpack' )
125        );
126    }
127}
128
129/**
130 * Render the stripe nudge.
131 *
132 * @param string $checkout_url Url for the CTA.
133 * @param string $description  Text of the nudge.
134 * @param string $button_text  Text of the button.
135 *
136 * @return string Final content to render.
137 */
138function stripe_nudge( $checkout_url, $description, $button_text ) {
139    require_once JETPACK__PLUGIN_DIR . '_inc/lib/components.php';
140    return \Jetpack_Components::render_frontend_nudge(
141        array(
142            'checkoutUrl' => $checkout_url,
143            'description' => $description,
144            'buttonText'  => $button_text,
145        )
146    );
147}
148
149/**
150 * Add a meta to prevent publication on firehose, ES AI or Reader
151 *
152 * @param int     $post_id Post id.
153 * @param WP_Post $post Post being saved.
154 * @return void
155 */
156function add_paid_content_post_meta( int $post_id, WP_Post $post ) {
157    if ( $post->post_type !== 'post' && $post->post_type !== 'page' ) {
158        return;
159    }
160
161    $contains_paid_content = has_block( 'premium-content/container', $post );
162    if ( $contains_paid_content ) {
163        update_post_meta(
164            $post_id,
165            META_NAME_CONTAINS_PAID_CONTENT,
166            $contains_paid_content
167        );
168    }
169    if ( ! $contains_paid_content ) {
170        delete_post_meta(
171            $post_id,
172            META_NAME_CONTAINS_PAID_CONTENT
173        );
174    }
175}