PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 15.1.2
Jetpack – WP Security, Backup, Speed, & Growth v15.1.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 11 months ago
donations.php
297 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 if ( ! defined( 'ABSPATH' ) ) {
18 exit( 0 );
19 }
20
21 /**
22 * Registers the block for use in Gutenberg
23 * This is done via an action so that we can disable
24 * registration if we need to.
25 */
26 function register_block() {
27
28 require_once JETPACK__PLUGIN_DIR . '/modules/memberships/class-jetpack-memberships.php';
29 if ( \Jetpack_Memberships::should_enable_monetize_blocks_in_editor() ) {
30 Blocks::jetpack_register_block(
31 __DIR__,
32 array(
33 'render_callback' => __NAMESPACE__ . '\render_block',
34 )
35 );
36 }
37 // Add a meta field to the user to track if the donation warning has been dismissed.
38 \register_meta(
39 'user',
40 'jetpack_donation_warning_dismissed',
41 array(
42 'type' => 'boolean',
43 'single' => true,
44 'show_in_rest' => true,
45 'default' => false,
46 )
47 );
48 }
49 add_action( 'init', __NAMESPACE__ . '\register_block' );
50
51 /**
52 * Donations block dynamic rendering.
53 *
54 * @param array $attr Array containing the Donations block attributes.
55 * @param string $content String containing the Donations block content.
56 *
57 * @return string
58 */
59 function render_block( $attr, $content ) {
60 // Keep content as-is if rendered in other contexts than frontend (i.e. feed, emails, API, etc.).
61 if ( ! Request::is_frontend() ) {
62 $parsed = parse_blocks( $content );
63 if ( ! empty( $parsed[0] ) ) {
64 // Inject the link of the current post from the server side as the fallback link to make sure the donations block
65 // points to the correct post when it's inserted from the synced pattern (aka “My Pattern”).
66 $post_link = get_permalink();
67 $parsed[0]['attrs']['fallbackLinkUrl'] = $post_link;
68 $content = \render_block( $parsed[0] );
69 if ( preg_match( '/<a\s+class="jetpack-donations-fallback-link"\s+href="([^"]*)"/', $content, $matches ) ) {
70 $content = str_replace( $matches[1], $post_link, $content );
71 }
72 }
73
74 return $content;
75 }
76
77 require_once JETPACK__PLUGIN_DIR . 'modules/memberships/class-jetpack-memberships.php';
78
79 // If stripe isn't connected don't show anything to potential donors - they can't actually make a donation.
80 if ( ! \Jetpack_Memberships::has_connected_account() ) {
81 return '';
82 }
83
84 Jetpack_Gutenberg::load_assets_as_required( __DIR__ );
85
86 require_once JETPACK__PLUGIN_DIR . '/_inc/lib/class-jetpack-currencies.php';
87
88 $default_texts = get_default_texts();
89
90 $donations = array(
91 'one-time' => array_merge(
92 array(
93 'planId' => null,
94 'title' => __( 'One-Time', 'jetpack' ),
95 'class' => 'donations__one-time-item',
96 'heading' => $default_texts['oneTimeDonation']['heading'],
97 'buttonText' => $default_texts['oneTimeDonation']['buttonText'],
98 ),
99 $attr['oneTimeDonation']
100 ),
101 );
102 if ( $attr['monthlyDonation']['show'] ) {
103 $donations['1 month'] = array_merge(
104 array(
105 'planId' => null,
106 'title' => __( 'Monthly', 'jetpack' ),
107 'class' => 'donations__monthly-item',
108 'heading' => $default_texts['monthlyDonation']['heading'],
109 'buttonText' => $default_texts['monthlyDonation']['buttonText'],
110 ),
111 $attr['monthlyDonation']
112 );
113 }
114 if ( $attr['annualDonation']['show'] ) {
115 $donations['1 year'] = array_merge(
116 array(
117 'planId' => null,
118 'title' => __( 'Yearly', 'jetpack' ),
119 'class' => 'donations__annual-item',
120 'heading' => $default_texts['annualDonation']['heading'],
121 'buttonText' => $default_texts['annualDonation']['buttonText'],
122 ),
123 $attr['annualDonation']
124 );
125 }
126
127 $choose_amount_text = isset( $attr['chooseAmountText'] ) && ! empty( $attr['chooseAmountText'] ) ? $attr['chooseAmountText'] : $default_texts['chooseAmountText'];
128 $custom_amount_text = isset( $attr['customAmountText'] ) && ! empty( $attr['customAmountText'] ) ? $attr['customAmountText'] : $default_texts['customAmountText'];
129 $currency = $attr['currency'];
130 $nav = '';
131 $headings = '';
132 $amounts = '';
133 $extra_text = '';
134 $buttons = '';
135 foreach ( $donations as $interval => $donation ) {
136 $plan_id = (int) $donation['planId'];
137 $plan = get_post( $plan_id );
138 if ( ! $plan || is_wp_error( $plan ) ) {
139 continue;
140 }
141
142 if ( count( $donations ) > 1 ) {
143 if ( ! $nav ) {
144 $nav .= '<div class="donations__nav">';
145 }
146 $nav .= sprintf(
147 '<div role="button" tabindex="0" class="donations__nav-item" data-interval="%1$s">%2$s</div>',
148 esc_attr( $interval ),
149 esc_html( $donation['title'] )
150 );
151 }
152 $headings .= sprintf(
153 '<h4 class="%1$s">%2$s</h4>',
154 esc_attr( $donation['class'] ),
155 wp_kses_post( $donation['heading'] )
156 );
157 $amounts .= sprintf(
158 '<div class="donations__amounts %s">',
159 esc_attr( $donation['class'] )
160 );
161 foreach ( $donation['amounts'] as $amount ) {
162 $amounts .= sprintf(
163 '<div class="donations__amount" data-amount="%1$s">%2$s</div>',
164 esc_attr( $amount ),
165 esc_html( \Jetpack_Currencies::format_price( $amount, $currency ) )
166 );
167 }
168 $amounts .= '</div>';
169 $extra_text .= sprintf(
170 '<p class="%1$s">%2$s</p>',
171 esc_attr( $donation['class'] ),
172 wp_kses_post( $donation['extraText'] ?? $default_texts['extraText'] )
173 );
174 $buttons .= sprintf(
175 '<a class="wp-block-button__link donations__donate-button %1$s" href="%2$s">%3$s</a>',
176 esc_attr( $donation['class'] ),
177 esc_url( \Jetpack_Memberships::get_instance()->get_subscription_url( $plan_id ) ),
178 wp_kses_post( $donation['buttonText'] )
179 );
180 }
181 if ( $nav ) {
182 $nav .= '</div>';
183 }
184
185 $custom_amount = '';
186 if ( $attr['showCustomAmount'] ) {
187 $custom_amount .= sprintf(
188 '<p>%s</p>',
189 wp_kses_post( $custom_amount_text )
190 );
191 $default_custom_amount = ( \Jetpack_Memberships::SUPPORTED_CURRENCIES[ $currency ] ?? 1 ) * 100;
192 $custom_amount .= sprintf(
193 '<div class="donations__amount donations__custom-amount">
194 %1$s
195 <div class="donations__amount-value" data-currency="%2$s" data-empty-text="%3$s"></div>
196 </div>',
197 esc_html( \Jetpack_Currencies::CURRENCIES[ $currency ]['symbol'] ?? '¤' ),
198 esc_attr( $currency ),
199 esc_attr( \Jetpack_Currencies::format_price( $default_custom_amount, $currency, false ) )
200 );
201 }
202
203 return sprintf(
204 '
205 <div class="%1$s">
206 <div class="donations__container">
207 %2$s
208 <div class="donations__content">
209 <div class="donations__tab">
210 %3$s
211 <p>%4$s</p>
212 %5$s
213 %6$s
214 <hr class="donations__separator">
215 %7$s
216 %8$s
217 </div>
218 </div>
219 </div>
220 </div>
221 ',
222 esc_attr( Blocks::classes( Blocks::get_block_feature( __DIR__ ), $attr ) ),
223 $nav,
224 $headings,
225 $choose_amount_text,
226 $amounts,
227 $custom_amount,
228 $extra_text,
229 $buttons
230 );
231 }
232
233 /**
234 * Get the default texts for the block.
235 *
236 * @return array
237 */
238 function get_default_texts() {
239 return array(
240 'chooseAmountText' => __( 'Choose an amount', 'jetpack' ),
241 'customAmountText' => __( 'Or enter a custom amount', 'jetpack' ),
242 'extraText' => __( 'Your contribution is appreciated.', 'jetpack' ),
243 'oneTimeDonation' => array(
244 'heading' => __( 'Make a one-time donation', 'jetpack' ),
245 'buttonText' => __( 'Donate', 'jetpack' ),
246 ),
247 'monthlyDonation' => array(
248 'heading' => __( 'Make a monthly donation', 'jetpack' ),
249 'buttonText' => __( 'Donate monthly', 'jetpack' ),
250 ),
251 'annualDonation' => array(
252 'heading' => __( 'Make a yearly donation', 'jetpack' ),
253 'buttonText' => __( 'Donate yearly', 'jetpack' ),
254 ),
255 );
256 }
257
258 /**
259 * Make default texts available to the editor.
260 */
261 function load_editor_scripts() {
262 // Only relevant to the editor right now.
263 if ( ! is_admin() ) {
264 return;
265 }
266
267 $data = array(
268 'defaultTexts' => get_default_texts(),
269 );
270
271 wp_add_inline_script(
272 'jetpack-blocks-editor',
273 'var Jetpack_DonationsBlock = ' . wp_json_encode( $data, JSON_HEX_TAG | JSON_HEX_AMP ) . ';',
274 'before'
275 );
276 }
277 add_action( 'enqueue_block_assets', __NAMESPACE__ . '\load_editor_scripts', 11 );
278
279 /**
280 * Determine if AMP should be disabled on posts having Donations blocks.
281 *
282 * @param bool $skip Skipped.
283 * @param int $post_id Post ID.
284 * @param WP_Post $post Post.
285 *
286 * @return bool Whether to skip the post from AMP.
287 */
288 function amp_skip_post( $skip, $post_id, $post ) {
289 // When AMP is on standard mode, there are no non-AMP posts to link to where the donation can be completed, so let's
290 // prevent the post from being available in AMP.
291 if ( function_exists( 'amp_is_canonical' ) && \amp_is_canonical() && has_block( Blocks::get_block_name( __DIR__ ), $post->post_content ) ) {
292 return true;
293 }
294 return $skip;
295 }
296 add_filter( 'amp_skip_post', __NAMESPACE__ . '\amp_skip_post', 10, 3 );
297