PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 14.9.2
Jetpack – WP Security, Backup, Speed, & Growth v14.9.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 14.5.1 14.6.1 14.7.1 14.8.1 14.9.2 15.0.3 15.1.2 15.2.1 15.3.2 15.4.1 15.5.1 15.6.1 15.7.2 15.8.1 15.9.2 16.0.2 16.1.3 16.2-a.5 16.2-a.3 16.1.2 16.2-a.1 16.1.1 16.1 16.1-beta 16.1-beta.2 16.1-beta.3 16.1-a.5 16.1-a.3 16.0.1 16.1-a.1 16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / extensions / blocks / donations / donations.php
jetpack / extensions / blocks / donations Last commit date
donations.php 1 year ago
donations.php
293 lines
1 <?php
2 /**
3 * Donations Block.
4 *
5 * @since 8.x
6 *
7 * @package automattic/jetpack
8 */
9
10 namespace Automattic\Jetpack\Extensions\Donations;
11
12 use Automattic\Jetpack\Blocks;
13 use Automattic\Jetpack\Status\Request;
14 use Jetpack_Gutenberg;
15 use WP_Post;
16
17 /**
18 * Registers the block for use in Gutenberg
19 * This is done via an action so that we can disable
20 * registration if we need to.
21 */
22 function register_block() {
23
24 require_once JETPACK__PLUGIN_DIR . '/modules/memberships/class-jetpack-memberships.php';
25 if ( \Jetpack_Memberships::should_enable_monetize_blocks_in_editor() ) {
26 Blocks::jetpack_register_block(
27 __DIR__,
28 array(
29 'render_callback' => __NAMESPACE__ . '\render_block',
30 )
31 );
32 }
33 // Add a meta field to the user to track if the donation warning has been dismissed.
34 \register_meta(
35 'user',
36 'jetpack_donation_warning_dismissed',
37 array(
38 'type' => 'boolean',
39 'single' => true,
40 'show_in_rest' => true,
41 'default' => false,
42 )
43 );
44 }
45 add_action( 'init', __NAMESPACE__ . '\register_block' );
46
47 /**
48 * Donations block dynamic rendering.
49 *
50 * @param array $attr Array containing the Donations block attributes.
51 * @param string $content String containing the Donations block content.
52 *
53 * @return string
54 */
55 function render_block( $attr, $content ) {
56 // Keep content as-is if rendered in other contexts than frontend (i.e. feed, emails, API, etc.).
57 if ( ! Request::is_frontend() ) {
58 $parsed = parse_blocks( $content );
59 if ( ! empty( $parsed[0] ) ) {
60 // Inject the link of the current post from the server side as the fallback link to make sure the donations block
61 // points to the correct post when it's inserted from the synced pattern (aka “My Pattern”).
62 $post_link = get_permalink();
63 $parsed[0]['attrs']['fallbackLinkUrl'] = $post_link;
64 $content = \render_block( $parsed[0] );
65 if ( preg_match( '/<a\s+class="jetpack-donations-fallback-link"\s+href="([^"]*)"/', $content, $matches ) ) {
66 $content = str_replace( $matches[1], $post_link, $content );
67 }
68 }
69
70 return $content;
71 }
72
73 require_once JETPACK__PLUGIN_DIR . 'modules/memberships/class-jetpack-memberships.php';
74
75 // If stripe isn't connected don't show anything to potential donors - they can't actually make a donation.
76 if ( ! \Jetpack_Memberships::has_connected_account() ) {
77 return '';
78 }
79
80 Jetpack_Gutenberg::load_assets_as_required( __DIR__ );
81
82 require_once JETPACK__PLUGIN_DIR . '/_inc/lib/class-jetpack-currencies.php';
83
84 $default_texts = get_default_texts();
85
86 $donations = array(
87 'one-time' => array_merge(
88 array(
89 'planId' => null,
90 'title' => __( 'One-Time', 'jetpack' ),
91 'class' => 'donations__one-time-item',
92 'heading' => $default_texts['oneTimeDonation']['heading'],
93 'buttonText' => $default_texts['oneTimeDonation']['buttonText'],
94 ),
95 $attr['oneTimeDonation']
96 ),
97 );
98 if ( $attr['monthlyDonation']['show'] ) {
99 $donations['1 month'] = array_merge(
100 array(
101 'planId' => null,
102 'title' => __( 'Monthly', 'jetpack' ),
103 'class' => 'donations__monthly-item',
104 'heading' => $default_texts['monthlyDonation']['heading'],
105 'buttonText' => $default_texts['monthlyDonation']['buttonText'],
106 ),
107 $attr['monthlyDonation']
108 );
109 }
110 if ( $attr['annualDonation']['show'] ) {
111 $donations['1 year'] = array_merge(
112 array(
113 'planId' => null,
114 'title' => __( 'Yearly', 'jetpack' ),
115 'class' => 'donations__annual-item',
116 'heading' => $default_texts['annualDonation']['heading'],
117 'buttonText' => $default_texts['annualDonation']['buttonText'],
118 ),
119 $attr['annualDonation']
120 );
121 }
122
123 $choose_amount_text = isset( $attr['chooseAmountText'] ) && ! empty( $attr['chooseAmountText'] ) ? $attr['chooseAmountText'] : $default_texts['chooseAmountText'];
124 $custom_amount_text = isset( $attr['customAmountText'] ) && ! empty( $attr['customAmountText'] ) ? $attr['customAmountText'] : $default_texts['customAmountText'];
125 $currency = $attr['currency'];
126 $nav = '';
127 $headings = '';
128 $amounts = '';
129 $extra_text = '';
130 $buttons = '';
131 foreach ( $donations as $interval => $donation ) {
132 $plan_id = (int) $donation['planId'];
133 $plan = get_post( $plan_id );
134 if ( ! $plan || is_wp_error( $plan ) ) {
135 continue;
136 }
137
138 if ( count( $donations ) > 1 ) {
139 if ( ! $nav ) {
140 $nav .= '<div class="donations__nav">';
141 }
142 $nav .= sprintf(
143 '<div role="button" tabindex="0" class="donations__nav-item" data-interval="%1$s">%2$s</div>',
144 esc_attr( $interval ),
145 esc_html( $donation['title'] )
146 );
147 }
148 $headings .= sprintf(
149 '<h4 class="%1$s">%2$s</h4>',
150 esc_attr( $donation['class'] ),
151 wp_kses_post( $donation['heading'] )
152 );
153 $amounts .= sprintf(
154 '<div class="donations__amounts %s">',
155 esc_attr( $donation['class'] )
156 );
157 foreach ( $donation['amounts'] as $amount ) {
158 $amounts .= sprintf(
159 '<div class="donations__amount" data-amount="%1$s">%2$s</div>',
160 esc_attr( $amount ),
161 esc_html( \Jetpack_Currencies::format_price( $amount, $currency ) )
162 );
163 }
164 $amounts .= '</div>';
165 $extra_text .= sprintf(
166 '<p class="%1$s">%2$s</p>',
167 esc_attr( $donation['class'] ),
168 wp_kses_post( $donation['extraText'] ?? $default_texts['extraText'] )
169 );
170 $buttons .= sprintf(
171 '<a class="wp-block-button__link donations__donate-button %1$s" href="%2$s">%3$s</a>',
172 esc_attr( $donation['class'] ),
173 esc_url( \Jetpack_Memberships::get_instance()->get_subscription_url( $plan_id ) ),
174 wp_kses_post( $donation['buttonText'] )
175 );
176 }
177 if ( $nav ) {
178 $nav .= '</div>';
179 }
180
181 $custom_amount = '';
182 if ( $attr['showCustomAmount'] ) {
183 $custom_amount .= sprintf(
184 '<p>%s</p>',
185 wp_kses_post( $custom_amount_text )
186 );
187 $default_custom_amount = ( \Jetpack_Memberships::SUPPORTED_CURRENCIES[ $currency ] ?? 1 ) * 100;
188 $custom_amount .= sprintf(
189 '<div class="donations__amount donations__custom-amount">
190 %1$s
191 <div class="donations__amount-value" data-currency="%2$s" data-empty-text="%3$s"></div>
192 </div>',
193 esc_html( \Jetpack_Currencies::CURRENCIES[ $currency ]['symbol'] ?? '¤' ),
194 esc_attr( $currency ),
195 esc_attr( \Jetpack_Currencies::format_price( $default_custom_amount, $currency, false ) )
196 );
197 }
198
199 return sprintf(
200 '
201 <div class="%1$s">
202 <div class="donations__container">
203 %2$s
204 <div class="donations__content">
205 <div class="donations__tab">
206 %3$s
207 <p>%4$s</p>
208 %5$s
209 %6$s
210 <hr class="donations__separator">
211 %7$s
212 %8$s
213 </div>
214 </div>
215 </div>
216 </div>
217 ',
218 esc_attr( Blocks::classes( Blocks::get_block_feature( __DIR__ ), $attr ) ),
219 $nav,
220 $headings,
221 $choose_amount_text,
222 $amounts,
223 $custom_amount,
224 $extra_text,
225 $buttons
226 );
227 }
228
229 /**
230 * Get the default texts for the block.
231 *
232 * @return array
233 */
234 function get_default_texts() {
235 return array(
236 'chooseAmountText' => __( 'Choose an amount', 'jetpack' ),
237 'customAmountText' => __( 'Or enter a custom amount', 'jetpack' ),
238 'extraText' => __( 'Your contribution is appreciated.', 'jetpack' ),
239 'oneTimeDonation' => array(
240 'heading' => __( 'Make a one-time donation', 'jetpack' ),
241 'buttonText' => __( 'Donate', 'jetpack' ),
242 ),
243 'monthlyDonation' => array(
244 'heading' => __( 'Make a monthly donation', 'jetpack' ),
245 'buttonText' => __( 'Donate monthly', 'jetpack' ),
246 ),
247 'annualDonation' => array(
248 'heading' => __( 'Make a yearly donation', 'jetpack' ),
249 'buttonText' => __( 'Donate yearly', 'jetpack' ),
250 ),
251 );
252 }
253
254 /**
255 * Make default texts available to the editor.
256 */
257 function load_editor_scripts() {
258 // Only relevant to the editor right now.
259 if ( ! is_admin() ) {
260 return;
261 }
262
263 $data = array(
264 'defaultTexts' => get_default_texts(),
265 );
266
267 wp_add_inline_script(
268 'jetpack-blocks-editor',
269 'var Jetpack_DonationsBlock = ' . wp_json_encode( $data, JSON_HEX_TAG | JSON_HEX_AMP ) . ';',
270 'before'
271 );
272 }
273 add_action( 'enqueue_block_assets', __NAMESPACE__ . '\load_editor_scripts', 11 );
274
275 /**
276 * Determine if AMP should be disabled on posts having Donations blocks.
277 *
278 * @param bool $skip Skipped.
279 * @param int $post_id Post ID.
280 * @param WP_Post $post Post.
281 *
282 * @return bool Whether to skip the post from AMP.
283 */
284 function amp_skip_post( $skip, $post_id, $post ) {
285 // When AMP is on standard mode, there are no non-AMP posts to link to where the donation can be completed, so let's
286 // prevent the post from being available in AMP.
287 if ( function_exists( 'amp_is_canonical' ) && \amp_is_canonical() && has_block( Blocks::get_block_name( __DIR__ ), $post->post_content ) ) {
288 return true;
289 }
290 return $skip;
291 }
292 add_filter( 'amp_skip_post', __NAMESPACE__ . '\amp_skip_post', 10, 3 );
293