diff --git a/lib/blocks.php b/lib/blocks.php index 3f0e8a547a8686..4abcfe37e014ba 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -63,6 +63,7 @@ function gutenberg_reregister_core_block_types() { 'comments-pagination-numbers.php' => 'core/comments-pagination-numbers', 'comments-pagination-previous.php' => 'core/comments-pagination-previous', 'comments-title.php' => 'core/comments-title', + 'comments.php' => 'core/comments-query-loop', 'file.php' => 'core/file', 'home-link.php' => 'core/home-link', 'image.php' => 'core/image', diff --git a/packages/block-library/src/comments/block.json b/packages/block-library/src/comments/block.json index fbdfdd253b278b..3083652ee7d3ea 100644 --- a/packages/block-library/src/comments/block.json +++ b/packages/block-library/src/comments/block.json @@ -25,5 +25,6 @@ } } }, - "editorStyle": "wp-block-comments-editor" + "editorStyle": "wp-block-comments-editor", + "usesContext": [ "postId", "postType" ] } diff --git a/packages/block-library/src/comments/edit/index.js b/packages/block-library/src/comments/edit/index.js new file mode 100644 index 00000000000000..3de7f14daa5419 --- /dev/null +++ b/packages/block-library/src/comments/edit/index.js @@ -0,0 +1,129 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + +/** + * WordPress dependencies + */ +import { + AlignmentControl, + BlockControls, + Warning, + useBlockProps, + useInnerBlocksProps, + store as blockEditorStore, +} from '@wordpress/block-editor'; +import { __, sprintf } from '@wordpress/i18n'; +import { useSelect } from '@wordpress/data'; +import { useEntityProp, store as coreStore } from '@wordpress/core-data'; + +/** + * Internal dependencies + */ +import CommentsInspectorControls from './comments-inspector-controls'; +import Placeholder from './placeholder'; + +export default function PostCommentsEdit( { + attributes, + setAttributes, + context: { postType, postId }, + clientId, +} ) { + const { tagName: TagName, textAlign } = attributes; + + const [ commentStatus ] = useEntityProp( + 'postType', + postType, + 'comment_status', + postId + ); + + const { defaultCommentStatus } = useSelect( + ( select ) => + select( blockEditorStore ).getSettings() + .__experimentalDiscussionSettings + ); + + const innerBlocks = useSelect( ( select ) => + select( blockEditorStore ).getBlocks( clientId ) + ); + + const isSiteEditor = postType === undefined || postId === undefined; + + const postTypeSupportsComments = useSelect( ( select ) => + postType + ? !! select( coreStore ).getPostType( postType )?.supports.comments + : false + ); + + let warning = __( + 'Post Comments block: This is just a placeholder, not a real comment. The final styling may differ because it also depends on the current theme. For better compatibility with the Block Editor, please consider replacing this block with the "Comments Query Loop" block.' + ); + let showPlacholder = true; + + if ( ! isSiteEditor && 'open' !== commentStatus ) { + if ( 'closed' === commentStatus ) { + warning = sprintf( + /* translators: 1: Post type (i.e. "post", "page") */ + __( + 'Post Comments block: Comments to this %s are not allowed.' + ), + postType + ); + showPlacholder = false; + } else if ( ! postTypeSupportsComments ) { + warning = sprintf( + /* translators: 1: Post type (i.e. "post", "page") */ + __( + 'Post Comments block: Comments for this post type (%s) are not enabled.' + ), + postType + ); + showPlacholder = false; + } else if ( 'open' !== defaultCommentStatus ) { + warning = __( 'Post Comments block: Comments are not enabled.' ); + showPlacholder = false; + } + } + + const blockProps = useBlockProps( { + className: classnames( { + [ `has-text-align-${ textAlign }` ]: textAlign, + } ), + } ); + const innerBlocksProps = useInnerBlocksProps( blockProps ); + + if ( innerBlocks.length > 0 ) { + return ( + <> + + + + ); + } + + return ( + <> + + { + setAttributes( { textAlign: nextAlign } ); + } } + /> + + +
+ { warning } + + { showPlacholder && ( + + ) } +
+ + ); +} diff --git a/packages/block-library/src/comments/edit/placeholder.js b/packages/block-library/src/comments/edit/placeholder.js new file mode 100644 index 00000000000000..07556f6d52396a --- /dev/null +++ b/packages/block-library/src/comments/edit/placeholder.js @@ -0,0 +1,121 @@ +/** + * WordPress dependencies + */ +import { store as blockEditorStore } from '@wordpress/block-editor'; +import { __ } from '@wordpress/i18n'; +import { useSelect } from '@wordpress/data'; +import { useEntityProp } from '@wordpress/core-data'; +import { useDisabled } from '@wordpress/compose'; + +/** + * Internal dependencies + */ +import CommentsForm from '../../post-comments-form/form'; + +export default function PostCommentsPlaceholder( { postType, postId } ) { + let [ postTitle ] = useEntityProp( 'postType', postType, 'title', postId ); + postTitle = postTitle || __( 'Post Title' ); + + const { avatarURL } = useSelect( + ( select ) => + select( blockEditorStore ).getSettings() + .__experimentalDiscussionSettings + ); + + const disabledRef = useDisabled(); + + return ( +
+

+ { __( 'One response to' ) } “{ postTitle }” +

+ +
+
+ « { __( 'Older Comments' ) } +
+
+ { __( 'Newer Comments' ) } » +
+
+ +
    +
  1. + +
  2. +
+ +
+
+ « { __( 'Older Comments' ) } +
+
+ { __( 'Newer Comments' ) } » +
+
+ + +
+ ); +} diff --git a/packages/block-library/src/comments/edit.js b/packages/block-library/src/comments/edit/template.js similarity index 60% rename from packages/block-library/src/comments/edit.js rename to packages/block-library/src/comments/edit/template.js index 14303fe7c54584..2c0b53399f003f 100644 --- a/packages/block-library/src/comments/edit.js +++ b/packages/block-library/src/comments/edit/template.js @@ -1,13 +1,3 @@ -/** - * WordPress dependencies - */ -import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor'; - -/** - * Internal dependencies - */ -import CommentsInspectorControls from './edit/comments-inspector-controls'; - const TEMPLATE = [ [ 'core/comments-title' ], [ @@ -68,21 +58,4 @@ const TEMPLATE = [ [ 'core/post-comments-form' ], ]; -export default function CommentsEdit( { attributes, setAttributes } ) { - const { tagName: TagName } = attributes; - - const blockProps = useBlockProps(); - const innerBlocksProps = useInnerBlocksProps( blockProps, { - template: TEMPLATE, - } ); - - return ( - <> - - - - ); -} +export default TEMPLATE; diff --git a/packages/block-library/src/comments/index.js b/packages/block-library/src/comments/index.js index 1743783286c744..573e7a99011ba7 100644 --- a/packages/block-library/src/comments/index.js +++ b/packages/block-library/src/comments/index.js @@ -9,6 +9,7 @@ import { postComments as icon } from '@wordpress/icons'; import metadata from './block.json'; import edit from './edit'; import save from './save'; +import TEMPLATE from './edit/template'; const { name } = metadata; export { metadata, name }; @@ -17,4 +18,12 @@ export const settings = { icon, edit, save, + variations: [ + { + name: 'default', + isDefault: true, + innerBlocks: TEMPLATE, + scope: [ 'inserter' ], + }, + ], }; diff --git a/packages/block-library/src/comments/index.php b/packages/block-library/src/comments/index.php new file mode 100644 index 00000000000000..49253bfbf30912 --- /dev/null +++ b/packages/block-library/src/comments/index.php @@ -0,0 +1,97 @@ +inner_blocks ) > 0 ) { + $inner_blocks_html = ''; + foreach ( $block->inner_blocks as $inner_block ) { + $inner_blocks_html .= $inner_block->render(); + } + return $inner_blocks_html; + } + + $post_id = $block->context['postId']; + if ( ! isset( $post_id ) ) { + return ''; + } + + $comment_args = array( + 'post_id' => $post_id, + 'count' => true, + ); + // Return early if there are no comments and comments are closed. + if ( ! comments_open( $post_id ) && get_comments( $comment_args ) === 0 ) { + return ''; + } + + $post_before = $post; + $post = get_post( $post_id ); + setup_postdata( $post ); + + ob_start(); + // There's a deprecation warning generated by WP Core. + // Ideally this deprecation is removed from Core. + // In the meantime, this removes it from the output. + add_filter( 'deprecated_file_trigger_error', '__return_false' ); + comments_template(); + remove_filter( 'deprecated_file_trigger_error', '__return_false' ); + $post = $post_before; + + $classes = ''; + if ( isset( $attributes['textAlign'] ) ) { + $classes .= 'has-text-align-' . $attributes['textAlign']; + } + + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => $classes ) ); + $output = ob_get_clean(); + + wp_enqueue_script( 'comment-reply' ); + + return sprintf( '
%2$s
', $wrapper_attributes, $output ); +} + +/** + * Registers the `core/comments-query-loop` block on the server. + */ +function register_block_core_comments_query_loop() { + register_block_type_from_metadata( + __DIR__ . '/comments', + array( + 'render_callback' => 'render_block_core_comments_query_loop', + 'skip_inner_blocks' => true, + ) + ); +} +add_action( 'init', 'register_block_core_comments_query_loop' ); + +/** + * Use the button block classes for the form-submit button. + * + * @param array $fields The default comment form arguments. + * + * @return array Returns the modified fields. + */ +function comments_query_loop_block_form_defaults( $fields ) { + if ( wp_is_block_theme() ) { + $fields['submit_button'] = ''; + $fields['submit_field'] = '

%1$s %2$s

'; + } + + return $fields; +} +add_filter( 'comment_form_defaults', 'comments_query_loop_block_form_defaults' ); diff --git a/packages/block-library/src/comments/save.js b/packages/block-library/src/comments/save.js index 47c774fc4b9bb1..69a44f77dc9f2b 100644 --- a/packages/block-library/src/comments/save.js +++ b/packages/block-library/src/comments/save.js @@ -1,12 +1,20 @@ /** * WordPress dependencies */ -import { InnerBlocks, useBlockProps } from '@wordpress/block-editor'; +import { useInnerBlocksProps, useBlockProps } from '@wordpress/block-editor'; +import { Children } from '@wordpress/element'; -export default function CommentsSave( { attributes: { tagName: Tag } } ) { - return ( - - - - ); +export default function save( { attributes: { tagName: Tag } } ) { + const blockProps = useBlockProps.save(); + const innerBlocksProps = useInnerBlocksProps.save( blockProps ); + + // The `save` function always returns a RawHTML element wrapping the + // serialized content. We check whether the serialized content is empty or + // not. + const rawHTML = Children.only( innerBlocksProps.children ); + if ( ! rawHTML.props.children ) { + return null; + } + + return ; } diff --git a/packages/blocks/src/api/parser/convert-legacy-block.js b/packages/blocks/src/api/parser/convert-legacy-block.js index 9789c0ed0a1e47..c8b7094d1b8180 100644 --- a/packages/blocks/src/api/parser/convert-legacy-block.js +++ b/packages/blocks/src/api/parser/convert-legacy-block.js @@ -67,5 +67,11 @@ export function convertLegacyBlockNameAndAttributes( name, attributes ) { name = 'core/comment-date'; } + // Checks needed after merging core/comments-query-loop and core/post-comments. + + if ( name === 'core/post-comments' ) { + name = 'core/comments-query-loop'; + } + return [ name, newAttributes ]; }