@automattic/newspack-blocks 4.28.0 → 4.28.1-hotfix-blocks-input-validation.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/includes/class-modal-checkout.php +31 -2
- package/newspack-blocks.php +2 -2
- package/package.json +1 -1
- package/src/blocks/author-list/class-wp-rest-newspack-author-list-controller.php +12 -1
- package/src/blocks/author-profile/class-wp-rest-newspack-authors-controller.php +42 -0
- package/src/blocks/iframe/class-wp-rest-newspack-iframe-controller.php +116 -4
- package/src/modal-checkout/templates/thankyou.php +7 -1
- package/vendor/composer/installed.php +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## @automattic/newspack-blocks [4.28.1-hotfix-blocks-input-validation.1](https://github.com/Automattic/newspack-workspace/compare/newspack-blocks@4.28.0...newspack-blocks@4.28.1-hotfix-blocks-input-validation.1) (2026-07-31)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **blocks:** keep author list and checkout fallbacks intact ([53012be](https://github.com/Automattic/newspack-workspace/commit/53012be987c2001aa8a855dfbf6b857b70c4463b))
|
|
7
|
+
* **blocks:** keep iframe imports inside the uploads directory ([a0118cc](https://github.com/Automattic/newspack-workspace/commit/a0118cc501ca0bfbb851c9e0fdb0f005702b99da))
|
|
8
|
+
* **blocks:** restrict author contact fields to user managers ([c872eb9](https://github.com/Automattic/newspack-workspace/commit/c872eb90589d056a354228adc0a2a65afa6245d3))
|
|
9
|
+
* **blocks:** validate post-checkout redirect destinations ([f418142](https://github.com/Automattic/newspack-workspace/commit/f418142055e14fc6e8fe82726996c7a7028452d5))
|
|
10
|
+
|
|
1
11
|
# @automattic/newspack-blocks [4.28.0](https://github.com/Automattic/newspack-workspace/compare/newspack-blocks@4.27.1...newspack-blocks@4.28.0) (2026-07-20)
|
|
2
12
|
|
|
3
13
|
|
|
@@ -1188,6 +1188,27 @@ final class Modal_Checkout {
|
|
|
1188
1188
|
ob_end_flush();
|
|
1189
1189
|
}
|
|
1190
1190
|
|
|
1191
|
+
/**
|
|
1192
|
+
* Reduce a post-checkout destination to one this site is willing to send readers to.
|
|
1193
|
+
*
|
|
1194
|
+
* The destination reaches the thank-you page through the request, whether it came from
|
|
1195
|
+
* the block's own settings or from the link the reader followed, and by that point the
|
|
1196
|
+
* two are indistinguishable. Core's redirect validation decides: this site's host is
|
|
1197
|
+
* always allowed, and a publisher who wants to send readers somewhere else adds that
|
|
1198
|
+
* host through the standard `allowed_redirect_hosts` filter.
|
|
1199
|
+
*
|
|
1200
|
+
* @param string $url The requested destination.
|
|
1201
|
+
*
|
|
1202
|
+
* @return string The destination, or an empty string if it is not allowed.
|
|
1203
|
+
*/
|
|
1204
|
+
public static function sanitize_after_success_url( $url ) {
|
|
1205
|
+
if ( empty( $url ) ) {
|
|
1206
|
+
return '';
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
return (string) wp_validate_redirect( $url, '' );
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1191
1212
|
/**
|
|
1192
1213
|
* Get after success button params.
|
|
1193
1214
|
*/
|
|
@@ -1201,14 +1222,22 @@ final class Modal_Checkout {
|
|
|
1201
1222
|
\wp_parse_str( $referrer_query, $request_params );
|
|
1202
1223
|
}
|
|
1203
1224
|
}
|
|
1204
|
-
|
|
1225
|
+
$params = array_filter(
|
|
1205
1226
|
[
|
|
1206
1227
|
'after_success_behavior' => isset( $request_params['after_success_behavior'] ) ? sanitize_text_field( wp_unslash( $request_params['after_success_behavior'] ) ) : '', // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
|
1207
|
-
'after_success_url' => isset( $request_params['after_success_url'] ) ? sanitize_url( wp_unslash( $request_params['after_success_url'] ) ) : '', // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
|
1228
|
+
'after_success_url' => isset( $request_params['after_success_url'] ) ? self::sanitize_after_success_url( sanitize_url( wp_unslash( $request_params['after_success_url'] ) ) ) : '', // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
|
1208
1229
|
'after_success_button_label' => isset( $request_params['after_success_button_label'] ) ? sanitize_text_field( wp_unslash( $request_params['after_success_button_label'] ) ) : '', // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
|
1209
1230
|
'action_type' => isset( $request_params['action_type'] ) ? sanitize_text_field( wp_unslash( $request_params['action_type'] ) ) : '', // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
|
1210
1231
|
]
|
|
1211
1232
|
);
|
|
1233
|
+
|
|
1234
|
+
// A custom destination this site won't redirect to falls back to closing the modal, so
|
|
1235
|
+
// the reader gets a finished checkout rather than an empty destination.
|
|
1236
|
+
if ( 'custom' === ( $params['after_success_behavior'] ?? '' ) && empty( $params['after_success_url'] ) ) {
|
|
1237
|
+
unset( $params['after_success_behavior'] );
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
return $params;
|
|
1212
1241
|
}
|
|
1213
1242
|
|
|
1214
1243
|
/**
|
package/newspack-blocks.php
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Author URI: https://newspack.com/
|
|
8
8
|
* Text Domain: newspack-blocks
|
|
9
9
|
* Domain Path: /languages
|
|
10
|
-
* Version: 4.28.
|
|
10
|
+
* Version: 4.28.1-hotfix-blocks-input-validation.1
|
|
11
11
|
*
|
|
12
12
|
* @package Newspack_Blocks
|
|
13
13
|
*/
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
define( 'NEWSPACK_BLOCKS__PLUGIN_FILE', __FILE__ );
|
|
16
16
|
define( 'NEWSPACK_BLOCKS__BLOCKS_DIRECTORY', 'dist/' );
|
|
17
17
|
define( 'NEWSPACK_BLOCKS__PLUGIN_DIR', plugin_dir_path( NEWSPACK_BLOCKS__PLUGIN_FILE ) );
|
|
18
|
-
define( 'NEWSPACK_BLOCKS__VERSION', '4.28.
|
|
18
|
+
define( 'NEWSPACK_BLOCKS__VERSION', '4.28.1-hotfix-blocks-input-validation.1' );
|
|
19
19
|
|
|
20
20
|
require_once NEWSPACK_BLOCKS__PLUGIN_DIR . 'includes/class-newspack-blocks.php';
|
|
21
21
|
require_once NEWSPACK_BLOCKS__PLUGIN_DIR . 'includes/class-newspack-blocks-api.php';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automattic/newspack-blocks",
|
|
3
|
-
"version": "4.28.
|
|
3
|
+
"version": "4.28.1-hotfix-blocks-input-validation.1",
|
|
4
4
|
"author": "Automattic",
|
|
5
5
|
"description": "=== Newspack Blocks === Contributors: (this should be a list of wordpress.org userid's) Donate link: https://example.com/ Tags: comments, spam Requires at least: 4.5 Tested up to: 5.1.1 Stable tag: 0.1.0 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html",
|
|
6
6
|
"repository": {
|
|
@@ -12,6 +12,13 @@
|
|
|
12
12
|
class WP_REST_Newspack_Author_List_Controller extends WP_REST_Newspack_Authors_Controller {
|
|
13
13
|
// phpcs:enable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Fields returned when a caller doesn't ask for a specific set.
|
|
17
|
+
*
|
|
18
|
+
* @var string[]
|
|
19
|
+
*/
|
|
20
|
+
const DEFAULT_FIELDS = [ 'id', 'name', 'bio', 'email', 'social', 'avatar', 'url' ];
|
|
21
|
+
|
|
15
22
|
/**
|
|
16
23
|
* Constructs the controller.
|
|
17
24
|
*
|
|
@@ -136,6 +143,10 @@ class WP_REST_Newspack_Author_List_Controller extends WP_REST_Newspack_Authors_C
|
|
|
136
143
|
$options['fields'] = explode( ',', $request->get_param( 'fields' ) );
|
|
137
144
|
}
|
|
138
145
|
|
|
146
|
+
// Restricted here rather than in get_all_authors(), which also renders the block on
|
|
147
|
+
// the front end for visitors and must keep returning whatever a publisher publishes.
|
|
148
|
+
$options['fields'] = self::restrict_fields( $options['fields'] ?? self::DEFAULT_FIELDS );
|
|
149
|
+
|
|
139
150
|
$combined_authors = $this->get_all_authors( $options );
|
|
140
151
|
$response = new \WP_REST_Response( $combined_authors );
|
|
141
152
|
$response->header( 'x-wp-total', count( $combined_authors ) );
|
|
@@ -157,7 +168,7 @@ class WP_REST_Newspack_Author_List_Controller extends WP_REST_Newspack_Authors_C
|
|
|
157
168
|
'avatar_hide_default' => false,
|
|
158
169
|
'exclude' => [], // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude
|
|
159
170
|
'exclude_empty' => false,
|
|
160
|
-
'fields' =>
|
|
171
|
+
'fields' => self::DEFAULT_FIELDS,
|
|
161
172
|
'per_page' => 10,
|
|
162
173
|
];
|
|
163
174
|
$options = wp_parse_args( $options, $default_options );
|
|
@@ -12,6 +12,14 @@
|
|
|
12
12
|
class WP_REST_Newspack_Authors_Controller extends WP_REST_Controller {
|
|
13
13
|
// phpcs:enable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Fields carrying contact details that WordPress reserves for people who manage users.
|
|
17
|
+
*
|
|
18
|
+
* These endpoints are open to anyone who can edit posts, which is a much wider audience
|
|
19
|
+
* than core allows to read an address.
|
|
20
|
+
*/
|
|
21
|
+
const USER_MANAGEMENT_FIELDS = [ 'email' ];
|
|
22
|
+
|
|
15
23
|
/**
|
|
16
24
|
* Constructs the controller.
|
|
17
25
|
*
|
|
@@ -22,6 +30,39 @@ class WP_REST_Newspack_Authors_Controller extends WP_REST_Controller {
|
|
|
22
30
|
$this->rest_base = 'authors';
|
|
23
31
|
}
|
|
24
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Whether the current user may read author contact details.
|
|
35
|
+
*
|
|
36
|
+
* Matches the capabilities core requires before exposing a user's address.
|
|
37
|
+
*
|
|
38
|
+
* @return boolean
|
|
39
|
+
*/
|
|
40
|
+
public static function can_read_user_management_fields() {
|
|
41
|
+
return current_user_can( 'list_users' ) || current_user_can( 'edit_users' );
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Drop any requested fields the current user is not allowed to read.
|
|
46
|
+
*
|
|
47
|
+
* Applied per request rather than inside the formatting helpers, which also render the
|
|
48
|
+
* front-end author blocks for visitors and must keep returning whatever a publisher has
|
|
49
|
+
* chosen to publish there.
|
|
50
|
+
*
|
|
51
|
+
* `false` is the helpers' "every field" convention, used by the front-end blocks; it is
|
|
52
|
+
* passed through untouched so those renders are unaffected.
|
|
53
|
+
*
|
|
54
|
+
* @param array|false $fields Requested fields, or false for every field.
|
|
55
|
+
*
|
|
56
|
+
* @return array|false Fields the current user may receive.
|
|
57
|
+
*/
|
|
58
|
+
public static function restrict_fields( $fields ) {
|
|
59
|
+
if ( ! is_array( $fields ) || self::can_read_user_management_fields() ) {
|
|
60
|
+
return $fields;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return array_values( array_diff( $fields, self::USER_MANAGEMENT_FIELDS ) );
|
|
64
|
+
}
|
|
65
|
+
|
|
25
66
|
/**
|
|
26
67
|
* Registers the necessary REST API routes.
|
|
27
68
|
*
|
|
@@ -84,6 +125,7 @@ class WP_REST_Newspack_Authors_Controller extends WP_REST_Controller {
|
|
|
84
125
|
$per_page = ! empty( $request->get_param( 'perPage' ) ) ? $request->get_param( 'perPage' ) : 10; // Number of results to return per page. This is applied to each query, so the actual number of results returned may be up to 2x this number.
|
|
85
126
|
$avatar_hide_default = ! empty( $request->get_param( 'avatar_hide_default' ) ) ? true : false; // Hide the default avatar if the user has no custom avatar.
|
|
86
127
|
$fields = ! empty( $request->get_param( 'fields' ) ) ? explode( ',', $request->get_param( 'fields' ) ) : [ 'id' ]; // Fields to get. Will return at least id.
|
|
128
|
+
$fields = self::restrict_fields( $fields );
|
|
87
129
|
$include = ! empty( $request->get_param( 'include' ) ) ? explode( ',', $request->get_param( 'include' ) ) : null; // Fetch authors by multiple IDs.
|
|
88
130
|
$post_id = ! empty( $request->get_param( 'post_id' ) ) ? $request->get_param( 'post_id' ) : 0; // Fetch authors for a specific post (contextual mode).
|
|
89
131
|
|
|
@@ -246,6 +246,88 @@ class WP_REST_Newspack_Iframe_Controller extends WP_REST_Controller {
|
|
|
246
246
|
return in_array( $mime_type, array_keys( self::iframe_archive_accepted_file_mimes() ), true );
|
|
247
247
|
}
|
|
248
248
|
|
|
249
|
+
/**
|
|
250
|
+
* Reduce a caller-supplied name to a single safe path segment.
|
|
251
|
+
*
|
|
252
|
+
* Used for names this plugin generates but builds out of caller-supplied parts, such as
|
|
253
|
+
* the destination folder derived from an attachment title.
|
|
254
|
+
*
|
|
255
|
+
* @param string $segment The name to reduce.
|
|
256
|
+
*
|
|
257
|
+
* @return string|false The safe segment, or false if nothing usable is left.
|
|
258
|
+
*/
|
|
259
|
+
private function sanitize_path_segment( $segment ) {
|
|
260
|
+
$segment = sanitize_file_name( basename( str_replace( '\\', '/', (string) $segment ) ) );
|
|
261
|
+
|
|
262
|
+
if ( '' === $segment || '.' === $segment || '..' === $segment ) {
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return $segment;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Reduce a caller-supplied relative path to safe segments, keeping subdirectories.
|
|
271
|
+
*
|
|
272
|
+
* Archive entries may legitimately sit in subdirectories and are referenced by name from
|
|
273
|
+
* the archive's own markup, so the segments are checked rather than rewritten: renaming
|
|
274
|
+
* them would break those references. Anything that could point outside the destination —
|
|
275
|
+
* an upward segment, an absolute path, a drive letter or a null byte — is refused
|
|
276
|
+
* outright rather than stripped, since stripping is what makes layered payloads such as
|
|
277
|
+
* `....//` work.
|
|
278
|
+
*
|
|
279
|
+
* @param string $path The relative path to reduce.
|
|
280
|
+
*
|
|
281
|
+
* @return string|false The safe relative path, or false if it is not usable.
|
|
282
|
+
*/
|
|
283
|
+
private function sanitize_relative_path( $path ) {
|
|
284
|
+
$path = str_replace( '\\', '/', (string) $path );
|
|
285
|
+
|
|
286
|
+
if ( '' === $path || false !== strpos( $path, "\0" ) ) {
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Absolute paths, including Windows drive letters.
|
|
291
|
+
if ( '/' === $path[0] || preg_match( '#^[a-zA-Z]:#', $path ) ) {
|
|
292
|
+
return false;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
$segments = [];
|
|
296
|
+
foreach ( explode( '/', $path ) as $segment ) {
|
|
297
|
+
if ( '' === $segment || '.' === $segment ) {
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
if ( '..' === $segment ) {
|
|
301
|
+
return false;
|
|
302
|
+
}
|
|
303
|
+
$segments[] = $segment;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return empty( $segments ) ? false : implode( '/', $segments );
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Confirm that a destination resolves inside a directory.
|
|
311
|
+
*
|
|
312
|
+
* A last check on the resolved paths, after the destination's parent exists, so that a
|
|
313
|
+
* symlink or a gap in the checks above still cannot place a file outside the directory.
|
|
314
|
+
*
|
|
315
|
+
* @param string $directory Absolute path to the directory the write must stay inside.
|
|
316
|
+
* @param string $destination Absolute path to the intended destination.
|
|
317
|
+
*
|
|
318
|
+
* @return boolean
|
|
319
|
+
*/
|
|
320
|
+
private function is_inside_directory( $directory, $destination ) {
|
|
321
|
+
$directory = realpath( $directory );
|
|
322
|
+
$destination = realpath( dirname( $destination ) );
|
|
323
|
+
|
|
324
|
+
if ( ! $directory || ! $destination ) {
|
|
325
|
+
return false;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
return 0 === strpos( trailingslashit( $destination ), trailingslashit( $directory ) );
|
|
329
|
+
}
|
|
330
|
+
|
|
249
331
|
/**
|
|
250
332
|
* Receive the iframe content, handle it, and returns the URL and the folder name.
|
|
251
333
|
*
|
|
@@ -363,7 +445,11 @@ class WP_REST_Newspack_Iframe_Controller extends WP_REST_Controller {
|
|
|
363
445
|
* @return WP_REST_Response
|
|
364
446
|
*/
|
|
365
447
|
private function process_iframe_document( $request, $document_filename, $media_source_path ) {
|
|
366
|
-
|
|
448
|
+
// The filename is built from the source attachment's title, so it is only a name once
|
|
449
|
+
// it has been reduced to a single segment.
|
|
450
|
+
$document_filename = $this->sanitize_path_segment( $document_filename );
|
|
451
|
+
|
|
452
|
+
if ( ! $document_filename || ! $this->validate_file_extension( $document_filename, false ) ) {
|
|
367
453
|
return new WP_Error(
|
|
368
454
|
'newspack_blocks',
|
|
369
455
|
sprintf(
|
|
@@ -393,6 +479,14 @@ class WP_REST_Newspack_Iframe_Controller extends WP_REST_Controller {
|
|
|
393
479
|
}
|
|
394
480
|
}
|
|
395
481
|
|
|
482
|
+
if ( ! $this->is_inside_directory( $iframe_upload_dir, $iframe_path ) ) {
|
|
483
|
+
return new WP_Error(
|
|
484
|
+
'newspack_blocks',
|
|
485
|
+
__( 'Could not upload your document.', 'newspack-blocks' ),
|
|
486
|
+
[ 'status' => '400' ]
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
|
|
396
490
|
// Copy uploaded document file to destination.
|
|
397
491
|
if ( copy( $media_source_path, $iframe_path ) ) {
|
|
398
492
|
return [
|
|
@@ -434,6 +528,13 @@ class WP_REST_Newspack_Iframe_Controller extends WP_REST_Controller {
|
|
|
434
528
|
}
|
|
435
529
|
global $wp_filesystem;
|
|
436
530
|
|
|
531
|
+
// The folder is built from the source attachment's title, so it is only a name once it
|
|
532
|
+
// has been reduced to a single segment.
|
|
533
|
+
$iframe_folder = $this->sanitize_path_segment( $iframe_folder );
|
|
534
|
+
if ( ! $iframe_folder ) {
|
|
535
|
+
return $invalid_file_error;
|
|
536
|
+
}
|
|
537
|
+
|
|
437
538
|
$wp_upload_dir = wp_upload_dir();
|
|
438
539
|
$iframe_upload_dir = $wp_upload_dir['path'] . self::IFRAME_UPLOAD_DIR;
|
|
439
540
|
$iframe_path = trailingslashit( $iframe_upload_dir . $iframe_folder );
|
|
@@ -464,10 +565,21 @@ class WP_REST_Newspack_Iframe_Controller extends WP_REST_Controller {
|
|
|
464
565
|
}
|
|
465
566
|
$stat = $zip->statIndex( $file_index );
|
|
466
567
|
if ( $stat && isset( $stat['name'] ) ) {
|
|
467
|
-
|
|
468
|
-
|
|
568
|
+
// An entry names its own destination, so it decides where the write lands.
|
|
569
|
+
$entry_relative_path = $this->sanitize_relative_path( $stat['name'] );
|
|
570
|
+
if ( ! $entry_relative_path ) {
|
|
571
|
+
return $invalid_file_error;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
$destination = $iframe_path . $entry_relative_path;
|
|
575
|
+
if ( ! file_exists( dirname( $destination ) ) ) {
|
|
576
|
+
wp_mkdir_p( dirname( $destination ) );
|
|
469
577
|
}
|
|
470
|
-
|
|
578
|
+
if ( ! $this->is_inside_directory( $iframe_upload_dir, $destination ) ) {
|
|
579
|
+
return $invalid_file_error;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
$put = $wp_filesystem->put_contents( $destination, $contents );
|
|
471
583
|
if ( ! $put ) {
|
|
472
584
|
return $invalid_file_error;
|
|
473
585
|
}
|
|
@@ -47,9 +47,15 @@ if ( ! $is_valid ) {
|
|
|
47
47
|
|
|
48
48
|
$is_success = ! $order->has_status( 'failed' );
|
|
49
49
|
$after_success_behavior = isset( $_GET['after_success_behavior'] ) ? \sanitize_text_field( \wp_unslash( $_GET['after_success_behavior'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
|
50
|
-
$after_success_url = isset( $_GET['after_success_url'] ) ? esc_url( \sanitize_url( \wp_unslash( $_GET['after_success_url'] ) ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
|
50
|
+
$after_success_url = isset( $_GET['after_success_url'] ) ? esc_url( \Newspack_Blocks\Modal_Checkout::sanitize_after_success_url( \sanitize_url( \wp_unslash( $_GET['after_success_url'] ) ) ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
|
51
51
|
$after_success_label = isset( $_GET['after_success_button_label'] ) ? \sanitize_text_field( \wp_unslash( $_GET['after_success_button_label'] ) ) : \Newspack_Blocks\Modal_Checkout::get_modal_checkout_labels( 'after_success' ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
|
52
52
|
$checkout_data = Checkout_Data::get_checkout_data( $order );
|
|
53
|
+
|
|
54
|
+
// A custom destination this site won't redirect to falls back to closing the modal, so the
|
|
55
|
+
// reader gets a finished checkout rather than an empty destination.
|
|
56
|
+
if ( 'custom' === $after_success_behavior && empty( $after_success_url ) ) {
|
|
57
|
+
$after_success_behavior = '';
|
|
58
|
+
}
|
|
53
59
|
?>
|
|
54
60
|
<div class="woocommerce-order">
|
|
55
61
|
<?php if ( $is_success ) : ?>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
'name' => 'automattic/newspack-blocks',
|
|
4
4
|
'pretty_version' => 'dev-main',
|
|
5
5
|
'version' => 'dev-main',
|
|
6
|
-
'reference' => '
|
|
6
|
+
'reference' => '53012be987c2001aa8a855dfbf6b857b70c4463b',
|
|
7
7
|
'type' => 'wordpress-plugin',
|
|
8
8
|
'install_path' => __DIR__ . '/../../',
|
|
9
9
|
'aliases' => array(),
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
'automattic/newspack-blocks' => array(
|
|
14
14
|
'pretty_version' => 'dev-main',
|
|
15
15
|
'version' => 'dev-main',
|
|
16
|
-
'reference' => '
|
|
16
|
+
'reference' => '53012be987c2001aa8a855dfbf6b857b70c4463b',
|
|
17
17
|
'type' => 'wordpress-plugin',
|
|
18
18
|
'install_path' => __DIR__ . '/../../',
|
|
19
19
|
'aliases' => array(),
|