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..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,10 +2,17 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { PluginDocumentSettingPanel } from '@wordpress/edit-post'; import { ComboboxControl, FormTokenField, TextControl, TextareaControl } from '@wordpress/components'; import { useDispatch, useSelect } from '@wordpress/data'; -import { store as editorStore } from '@wordpress/editor'; +// `PluginDocumentSettingPanel` moved from `@wordpress/edit-post` to `@wordpress/editor`. +// Import from both and use whichever the running WordPress version provides. +import { + PluginDocumentSettingPanel as PluginDocumentSettingPanelFromEditor, + store as editorStore, +} from '@wordpress/editor'; +import { PluginDocumentSettingPanel as PluginDocumentSettingPanelFromEditPost } from '@wordpress/edit-post'; + +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 5ab72c2a1..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,9 +2,11 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { PluginPostStatusInfo } from '@wordpress/edit-post'; import { Button } from '@wordpress/components'; -import { store as editorStore } from '@wordpress/editor'; +// `PluginPostStatusInfo` moved from `@wordpress/edit-post` to `@wordpress/editor`. +// Import from both and use whichever the running WordPress version provides. +import { PluginPostStatusInfo as PluginPostStatusInfoFromEditor, store as editorStore } from '@wordpress/editor'; +import { PluginPostStatusInfo as PluginPostStatusInfoFromEditPost } from '@wordpress/edit-post'; import { useDispatch, useSelect } from '@wordpress/data'; import { useState } from '@wordpress/element'; @@ -15,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(); @@ -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 } ) => { ) }