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