From bdd43227221a6e087375039583df8179688613b2 Mon Sep 17 00:00:00 2001 From: Maggie Cabrera Date: Thu, 4 Jun 2026 15:37:49 +0200 Subject: [PATCH 1/2] fix the unlist button and the modal and add the text to the email sent to the user --- .../includes/notifications.php | 39 +++++++++++++++++++ .../src/pattern-post-type/details.js | 7 +++- .../pattern-post-type/unlist-button/index.js | 9 ++++- .../pattern-post-type/unlist-button/modal.js | 8 ++-- 4 files changed, 56 insertions(+), 7 deletions(-) diff --git a/public_html/wp-content/plugins/pattern-directory/includes/notifications.php b/public_html/wp-content/plugins/pattern-directory/includes/notifications.php index e61fac045..ebd5c862e 100644 --- a/public_html/wp-content/plugins/pattern-directory/includes/notifications.php +++ b/public_html/wp-content/plugins/pattern-directory/includes/notifications.php @@ -8,11 +8,44 @@ defined( 'WPINC' ) || die(); +/** + * The post meta key holding the moderator's message to the author, which is + * included in the "pattern unlisted" email. + */ +const UNLISTED_DETAIL_META = '_wporg_unlist_reason_detail'; + /** * Actions and filters. */ add_action( 'wp_after_insert_post', __NAMESPACE__ . '\trigger_notifications', 20, 4 ); add_action( 'wporg_unlist_pattern', __NAMESPACE__ . '\notify_pattern_flagged' ); +add_action( 'init', __NAMESPACE__ . '\register_unlisted_meta' ); + +/** + * Register the post meta used to store the moderator's message to the author. + * + * Editable by anyone who can edit the pattern (i.e. moderators), so it can be + * set from the Unlist modal in the block editor and read back when sending the + * "pattern unlisted" email. + * + * @return void + */ +function register_unlisted_meta() { + register_post_meta( + PATTERN, + UNLISTED_DETAIL_META, + array( + 'type' => 'string', + 'description' => 'A message from the moderator, included in the email sent to the author when a pattern is unlisted.', + 'single' => true, + 'show_in_rest' => true, + 'sanitize_callback' => 'sanitize_textarea_field', + 'auth_callback' => function( $allowed, $meta_key, $object_id ) { + return current_user_can( 'edit_post', $object_id ); + }, + ) + ); +} /** * Fire off relevant notification when a post is finished updating. @@ -211,6 +244,12 @@ function notify_pattern_unlisted( $post ) { $reason = get_default_reason_description(); } + // Append the moderator's message to the author, if one was provided. + $detail = get_post_meta( $post->ID, UNLISTED_DETAIL_META, true ); + if ( $detail ) { + $reason .= "\n\n" . $detail; + } + $subject = esc_html__( 'Pattern unlisted', 'wporg-patterns' ); $message = sprintf( diff --git a/public_html/wp-content/plugins/pattern-directory/src/pattern-post-type/details.js b/public_html/wp-content/plugins/pattern-directory/src/pattern-post-type/details.js index 7c9a923f4..dd1a96819 100644 --- a/public_html/wp-content/plugins/pattern-directory/src/pattern-post-type/details.js +++ b/public_html/wp-content/plugins/pattern-directory/src/pattern-post-type/details.js @@ -2,7 +2,12 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { PluginDocumentSettingPanel } from '@wordpress/edit-post'; +// `PluginDocumentSettingPanel` moved from `@wordpress/edit-post` to `@wordpress/editor`. +// Import from both and use whichever the running WordPress version provides. +import { PluginDocumentSettingPanel as PluginDocumentSettingPanelFromEditor } from '@wordpress/editor'; +import { PluginDocumentSettingPanel as PluginDocumentSettingPanelFromEditPost } from '@wordpress/edit-post'; +const PluginDocumentSettingPanel = + PluginDocumentSettingPanelFromEditor || PluginDocumentSettingPanelFromEditPost; import { ComboboxControl, FormTokenField, TextControl, TextareaControl } from '@wordpress/components'; import { useDispatch, useSelect } from '@wordpress/data'; import { store as editorStore } from '@wordpress/editor'; diff --git a/public_html/wp-content/plugins/pattern-directory/src/pattern-post-type/unlist-button/index.js b/public_html/wp-content/plugins/pattern-directory/src/pattern-post-type/unlist-button/index.js index 5ab72c2a1..2a9dd5aba 100644 --- a/public_html/wp-content/plugins/pattern-directory/src/pattern-post-type/unlist-button/index.js +++ b/public_html/wp-content/plugins/pattern-directory/src/pattern-post-type/unlist-button/index.js @@ -2,7 +2,11 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { PluginPostStatusInfo } from '@wordpress/edit-post'; +// `PluginPostStatusInfo` moved from `@wordpress/edit-post` to `@wordpress/editor`. +// Import from both and use whichever the running WordPress version provides. +import { PluginPostStatusInfo as PluginPostStatusInfoFromEditor } from '@wordpress/editor'; +import { PluginPostStatusInfo as PluginPostStatusInfoFromEditPost } from '@wordpress/edit-post'; +const PluginPostStatusInfo = PluginPostStatusInfoFromEditor || PluginPostStatusInfoFromEditPost; import { Button } from '@wordpress/components'; import { store as editorStore } from '@wordpress/editor'; import { useDispatch, useSelect } from '@wordpress/data'; @@ -23,10 +27,11 @@ export const UnlistButton = () => { const { editPost, savePost } = useDispatch( editorStore ); const [ showModal, setShowModal ] = useState( false ); - const onSubmit = ( reasonId ) => { + const onSubmit = ( reasonId, details = '' ) => { editPost( { status: UNLISTED_STATUS, 'wporg-pattern-flag-reason': [ reasonId ], + meta: { _wporg_unlist_reason_detail: details }, } ); savePost(); }; diff --git a/public_html/wp-content/plugins/pattern-directory/src/pattern-post-type/unlist-button/modal.js b/public_html/wp-content/plugins/pattern-directory/src/pattern-post-type/unlist-button/modal.js index e3838641c..80b34b8ec 100644 --- a/public_html/wp-content/plugins/pattern-directory/src/pattern-post-type/unlist-button/modal.js +++ b/public_html/wp-content/plugins/pattern-directory/src/pattern-post-type/unlist-button/modal.js @@ -74,7 +74,7 @@ const UnlistModal = ( { onClose, onSubmit } ) => { }, [] ); const submittedText = __( - 'The pattern has been unlisted, and your internal note has been saved.', + 'The pattern has been unlisted, and the author has been notified by email.', 'wporg-patterns' ); @@ -101,7 +101,7 @@ const UnlistModal = ( { onClose, onSubmit } ) => { note: details ? `UNLISTED: ${ reason.label } — ${ details }` : `UNLISTED: ${ reason.label }`, onSuccess: () => { if ( 'function' === typeof onSubmit ) { - onSubmit( selectedOption ); + onSubmit( selectedOption, details ); } dispatch( { status: 'NOTE_RECIEVED' } ); speak( submittedText ); @@ -155,9 +155,9 @@ const UnlistModal = ( { onClose, onSubmit } ) => { ) } Date: Thu, 4 Jun 2026 15:51:35 +0200 Subject: [PATCH 2/2] Fix lint: merge duplicate @wordpress/editor imports Combine the editor-package imports so there is a single import per package (no-duplicate-imports) and let prettier format them. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../src/pattern-post-type/details.js | 14 ++++++++------ .../src/pattern-post-type/unlist-button/index.js | 8 ++++---- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/public_html/wp-content/plugins/pattern-directory/src/pattern-post-type/details.js b/public_html/wp-content/plugins/pattern-directory/src/pattern-post-type/details.js index dd1a96819..333a7f4e6 100644 --- a/public_html/wp-content/plugins/pattern-directory/src/pattern-post-type/details.js +++ b/public_html/wp-content/plugins/pattern-directory/src/pattern-post-type/details.js @@ -2,15 +2,17 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; +import { ComboboxControl, FormTokenField, TextControl, TextareaControl } from '@wordpress/components'; +import { useDispatch, useSelect } from '@wordpress/data'; // `PluginDocumentSettingPanel` moved from `@wordpress/edit-post` to `@wordpress/editor`. // Import from both and use whichever the running WordPress version provides. -import { PluginDocumentSettingPanel as PluginDocumentSettingPanelFromEditor } from '@wordpress/editor'; +import { + PluginDocumentSettingPanel as PluginDocumentSettingPanelFromEditor, + store as editorStore, +} from '@wordpress/editor'; import { PluginDocumentSettingPanel as PluginDocumentSettingPanelFromEditPost } from '@wordpress/edit-post'; -const PluginDocumentSettingPanel = - PluginDocumentSettingPanelFromEditor || PluginDocumentSettingPanelFromEditPost; -import { ComboboxControl, FormTokenField, TextControl, TextareaControl } from '@wordpress/components'; -import { useDispatch, useSelect } from '@wordpress/data'; -import { store as editorStore } from '@wordpress/editor'; + +const PluginDocumentSettingPanel = PluginDocumentSettingPanelFromEditor || PluginDocumentSettingPanelFromEditPost; const KEYWORD_SLUG = 'wpop_keywords'; const DESCRIPTION_SLUG = 'wpop_description'; diff --git a/public_html/wp-content/plugins/pattern-directory/src/pattern-post-type/unlist-button/index.js b/public_html/wp-content/plugins/pattern-directory/src/pattern-post-type/unlist-button/index.js index 2a9dd5aba..087476063 100644 --- a/public_html/wp-content/plugins/pattern-directory/src/pattern-post-type/unlist-button/index.js +++ b/public_html/wp-content/plugins/pattern-directory/src/pattern-post-type/unlist-button/index.js @@ -2,13 +2,11 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; +import { Button } from '@wordpress/components'; // `PluginPostStatusInfo` moved from `@wordpress/edit-post` to `@wordpress/editor`. // Import from both and use whichever the running WordPress version provides. -import { PluginPostStatusInfo as PluginPostStatusInfoFromEditor } from '@wordpress/editor'; +import { PluginPostStatusInfo as PluginPostStatusInfoFromEditor, store as editorStore } from '@wordpress/editor'; import { PluginPostStatusInfo as PluginPostStatusInfoFromEditPost } from '@wordpress/edit-post'; -const PluginPostStatusInfo = PluginPostStatusInfoFromEditor || PluginPostStatusInfoFromEditPost; -import { Button } from '@wordpress/components'; -import { store as editorStore } from '@wordpress/editor'; import { useDispatch, useSelect } from '@wordpress/data'; import { useState } from '@wordpress/element'; @@ -19,6 +17,8 @@ import { UNLISTED_STATUS } from '../settings'; import UnlistModal from './modal'; import './unlist.scss'; +const PluginPostStatusInfo = PluginPostStatusInfoFromEditor || PluginPostStatusInfoFromEditPost; + export const UnlistButton = () => { const status = useSelect( ( select ) => { const _post = select( editorStore ).getCurrentPost();