diff --git a/wp-modules/app/app.php b/wp-modules/app/app.php
index 3608ddae..af52724a 100644
--- a/wp-modules/app/app.php
+++ b/wp-modules/app/app.php
@@ -27,6 +27,7 @@ function get_app_state() {
'patterns' => \PatternManager\PatternDataHandlers\get_theme_patterns_with_editor_links(),
'patternCategories' => \WP_Block_Pattern_Categories_Registry::get_instance()->get_all_registered(),
'apiNonce' => wp_create_nonce( 'wp_rest' ),
+ 'previewNonce' => wp_create_nonce( 'pm_action_pattern_preview' ),
'apiEndpoints' => array(
'deletePatternEndpoint' => get_rest_url( false, 'pattern-manager/v1/delete-pattern/' ),
'updateDismissedSitesEndpoint' => get_rest_url( false, 'pattern-manager/v1/update-dismissed-sites/' ),
diff --git a/wp-modules/app/js/src/components/Patterns/PatternGrid.tsx b/wp-modules/app/js/src/components/Patterns/PatternGrid.tsx
index 8263ae12..f2ae527e 100644
--- a/wp-modules/app/js/src/components/Patterns/PatternGrid.tsx
+++ b/wp-modules/app/js/src/components/Patterns/PatternGrid.tsx
@@ -59,11 +59,7 @@ export default function PatternGrid( {
get_rest_url( false, 'pattern-manager/v1/get-pattern-names/' ),
),
'apiNonce' => wp_create_nonce( 'wp_rest' ),
+ 'previewNonce' => wp_create_nonce( 'pm_action_pattern_preview' ),
'patternCategories' => \WP_Block_Pattern_Categories_Registry::get_instance()->get_all_registered(),
'patternNames' => get_pattern_names(),
'patterns' => \PatternManager\PatternDataHandlers\get_theme_patterns_with_editor_links(),
diff --git a/wp-modules/editor/js/src/components/SidebarPanels/ViewportWidthPanel.tsx b/wp-modules/editor/js/src/components/SidebarPanels/ViewportWidthPanel.tsx
index 46facf83..794aa10e 100644
--- a/wp-modules/editor/js/src/components/SidebarPanels/ViewportWidthPanel.tsx
+++ b/wp-modules/editor/js/src/components/SidebarPanels/ViewportWidthPanel.tsx
@@ -51,11 +51,7 @@ export default function ViewportWidthPanel( {
/>
) : (
) ) }
diff --git a/wp-modules/editor/js/src/types.ts b/wp-modules/editor/js/src/types.ts
index 98c4f6aa..fa86f9e2 100644
--- a/wp-modules/editor/js/src/types.ts
+++ b/wp-modules/editor/js/src/types.ts
@@ -58,6 +58,7 @@ export type Patterns = {
export type InitialPatternManager = {
activeTheme: string;
apiNonce: string;
+ previewNonce: string;
apiEndpoints: {
getPatternNamesEndpoint: string;
};
diff --git a/wp-modules/editor/model.php b/wp-modules/editor/model.php
index e2ed7a07..558c7b7c 100644
--- a/wp-modules/editor/model.php
+++ b/wp-modules/editor/model.php
@@ -188,10 +188,12 @@ function redirect_pattern_actions() {
}
if ( 'duplicate' === filter_input( INPUT_GET, 'action' ) ) {
+ check_admin_referer( 'pm-pattern-duplicate' );
duplicate_pattern( filter_input( INPUT_GET, 'name' ) );
}
if ( 'edit-pattern' === filter_input( INPUT_GET, 'action' ) ) {
+ check_admin_referer( 'pm-pattern-edit' );
edit_pattern( filter_input( INPUT_GET, 'name' ) );
}
}
diff --git a/wp-modules/pattern-data-handlers/pattern-data-handlers.php b/wp-modules/pattern-data-handlers/pattern-data-handlers.php
index 31823c77..a6e87ec8 100644
--- a/wp-modules/pattern-data-handlers/pattern-data-handlers.php
+++ b/wp-modules/pattern-data-handlers/pattern-data-handlers.php
@@ -166,18 +166,37 @@ function get_theme_patterns_with_editor_links() {
);
$post = empty( $query->posts[0] ) ? false : $query->posts[0];
- $pattern['editorLink'] = $post && $post->name === $pattern['name']
- ? get_edit_post_link( $post, 'localized_data' )
- : add_query_arg(
- [
- 'post_type' => get_pattern_post_type(),
- 'action' => 'edit-pattern',
- 'name' => $pattern['name'],
- ],
- admin_url()
- );
-
- $all_patterns[ $pattern_name ] = $pattern;
+ $duplicate_nonce_action = 'pm-pattern-duplicate';
+ $edit_nonce_action = 'pm-pattern-edit';
+ $new_pattern = array_merge(
+ $pattern,
+ [
+ 'editorLink' => $post && $post->name === $pattern['name']
+ ? add_query_arg(
+ [ '_wpnonce' => wp_create_nonce( $edit_nonce_action ) ],
+ get_edit_post_link( $post, 'localized_data' ),
+ )
+ : add_query_arg(
+ [
+ 'post_type' => get_pattern_post_type(),
+ 'action' => 'edit-pattern',
+ 'name' => $pattern['name'],
+ '_wpnonce' => wp_create_nonce( $edit_nonce_action ),
+ ]
+ ),
+ 'duplicateLink' => add_query_arg(
+ [
+ 'post_type' => get_pattern_post_type(),
+ 'action' => 'duplicate',
+ 'name' => $pattern['name'],
+ '_wpnonce' => wp_create_nonce( $duplicate_nonce_action ),
+ ],
+ admin_url()
+ ),
+ ]
+ );
+
+ $all_patterns[ $pattern_name ] = $new_pattern;
}
}
diff --git a/wp-modules/pattern-data-handlers/tests/PatternDataHandlersTest.php b/wp-modules/pattern-data-handlers/tests/PatternDataHandlersTest.php
index 7447c952..a239be0b 100644
--- a/wp-modules/pattern-data-handlers/tests/PatternDataHandlersTest.php
+++ b/wp-modules/pattern-data-handlers/tests/PatternDataHandlersTest.php
@@ -250,6 +250,12 @@ public function test_get_theme_patterns_with_editor_links() {
$patterns = get_theme_patterns_with_editor_links();
$this->assertCount( 2, array_values( $patterns ) );
+ $this->assertTrue(
+ array_key_exists(
+ 'duplicateLink',
+ $patterns['my-new-pattern']
+ )
+ );
$this->assertTrue(
array_key_exists(
'editorLink',
diff --git a/wp-modules/pattern-preview-renderer/pattern-preview-renderer.php b/wp-modules/pattern-preview-renderer/pattern-preview-renderer.php
index 0adb4c2b..a980dc23 100644
--- a/wp-modules/pattern-preview-renderer/pattern-preview-renderer.php
+++ b/wp-modules/pattern-preview-renderer/pattern-preview-renderer.php
@@ -20,15 +20,14 @@
* Receive pattern id in the URL and display its content. Useful for pattern previews and thumbnails.
*/
function display_block_pattern_preview() {
-
- // Nonce not required as the user is not taking any action here.
- if ( ! isset( $_GET['pm_pattern_preview'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
+ if ( ! isset( $_GET['pm_pattern_preview'] ) ) {
return;
}
- $pattern_name = sanitize_text_field( wp_unslash( $_GET['pm_pattern_preview'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
+ check_admin_referer( 'pm_action_pattern_preview' );
- $pattern = \PatternManager\PatternDataHandlers\get_pattern_by_name( $pattern_name );
+ $pattern_name = sanitize_text_field( wp_unslash( $_GET['pm_pattern_preview'] ) );
+ $pattern = \PatternManager\PatternDataHandlers\get_pattern_by_name( $pattern_name );
if ( ! isset( $pattern['content'] ) ) {
$pattern['content'] = '';