Automattic / newspack-theme

A theme for Newspack.
https://newspack.com
GNU General Public License v2.0
305 stars 66 forks source link

Add toggle to allow commenters' names to be shown below comments, instead of above them #2310

Open avcascade opened 5 months ago

avcascade commented 5 months ago

A common aesthetic choice for news sites that allow readers to leave comments on articles is for the commenter's name to be shown below the comment they left rather than above it. This facilitates discussion flow and encourages people to read the comments before looking at the names of the people who wrote them.

This is not the default in Newspack and the theme currently makes it difficult to choose this alternative configuration for a comments area. The order cannot easily be changed because class-newspack-walker-comment.php (where the relevant code lives) is being called with a require() statement in functions.php:

* Custom Comment Walker template.
 */
require get_template_directory() . '/classes/class-newspack-walker-comment.php';

While many aspects of Newspack can be successfully modified with a child theme, it's not possible to override a class that's being called with a require() or include() statement. It would be helpful to have a toggle in the theme that allows the positioning of comment meta to be changed from above to below. If this existed, we wouldn't need to modify class-newspack-walker-comment.php to move the div comment-content above the comment-meta div:

<article id="div-comment-<?php comment_ID(); ?>" class="comment-body">
                <div class="comment-content">
                    <?php comment_text(); ?>
                </div><!-- .comment-content -->

                <footer class="comment-meta">

This new setting could be added to the Comments Settings, which currently has three settings:

Some demo code is enclosed, which I've tested on a site running the latest Newspack theme released on 05/28/2028. This just shows the implementation of the idea - I put my function in functions.php so it would be easy for me to find while I was coding. I'm sure this could be more elegant.

Add to functions.php:

function newspack_customize_add_comment_layout_control( $wp_customize ) {
    // Add the new control to the existing section
    $wp_customize->add_setting( 'newspack_comment_order', array(
        'default'           => 'meta_above_content',
        'sanitize_callback' => 'sanitize_text_field',
    ) );

    $wp_customize->add_control( 'newspack_comment_order', array(
        'label'    => __( 'Comment Layout', 'newspack' ),
        'section'  => 'comments_options', // Add to the existing section
        'settings' => 'newspack_comment_order',
        'type'     => 'radio',
        'choices'  => array(
            'meta_above_content' => __( 'Meta above content', 'newspack' ),
            'content_above_meta' => __( 'Content above meta', 'newspack' ),
        ),
    ) );
}

add_action( 'customize_register', 'newspack_customize_add_comment_layout_control' );

Replace class-newspack-walker-comment.php with:

<?php
/**
 * Custom comment walker for this theme
 *
 * @package Newspack
 */

/**
 * This class outputs custom comment walker for HTML5 friendly WordPress comment and threaded replies.
 *
 * @since 1.0.0
 */
class Newspack_Walker_Comment extends Walker_Comment {

    /**
     * Outputs a comment in the HTML5 format.
     *
     * @see wp_list_comments()
     *
     * @param WP_Comment $comment Comment to display.
     * @param int        $depth   Depth of the current comment.
     * @param array      $args    An array of arguments.
     */
    protected function html5_comment( $comment, $depth, $args ) {
        $tag = ( 'div' === $args['style'] ) ? 'div' : 'li';

        // Get the customizer setting
        $comment_order = get_theme_mod( 'newspack_comment_order', 'meta_above_content' );

        ?>
        <<?php echo $tag; ?> id="comment-<?php comment_ID(); ?>" <?php comment_class( $this->has_children ? 'parent' : '', $comment ); ?>>
            <article id="div-comment-<?php comment_ID(); ?>" class="comment-body">
                <?php if ( 'content_above_meta' === $comment_order ) : ?>
                    <div class="comment-content">
                        <?php comment_text(); ?>
                    </div><!-- .comment-content -->

                    <footer class="comment-meta">
                        <div class="comment-author vcard">
                            <?php
                            $comment_author_link = get_comment_author_link( $comment );
                            $comment_author_url  = get_comment_author_url( $comment );
                            $comment_author      = get_comment_author( $comment );
                            $avatar              = get_avatar( $comment, $args['avatar_size'] );
                            if ( 0 != $args['avatar_size'] ) {
                                if ( empty( $comment_author_url ) ) {
                                    echo $avatar;
                                } else {
                                    printf( '<a href="%s" rel="external nofollow" class="url">', $comment_author_url );
                                    echo $avatar;
                                }
                            }

                            printf(
                                wp_kses(
                                    /* translators: %s: comment author link */
                                    __( '%s <span class="screen-reader-text says">says:</span>', 'newspack' ),
                                    array(
                                        'span' => array(
                                            'class' => array(),
                                        ),
                                    )
                                ),
                                '<b class="fn">' . get_comment_author_link( $comment ) . '</b>'
                            );

                            /* Display icon if the commenter is the current post's author. */
                            if ( newspack_is_comment_by_post_author( $comment ) ) {
                                printf( '<span class="post-author-badge" aria-hidden="true">%s</span>', wp_kses( newspack_get_icon_svg( 'person', 24, esc_html__( 'Article author', 'newspack' ) ), newspack_sanitize_svgs() ) );
                            }

                            if ( ! empty( $comment_author_url ) ) {
                                echo '</a>';
                            }
                            ?>
                        </div><!-- .comment-author -->

                        <div class="comment-metadata">
                            <a href="<?php echo esc_url( get_comment_link( $comment, $args ) ); ?>">
                                <?php
                                    /* translators: 1: comment date, 2: comment time */
                                    $comment_timestamp = sprintf( __( '%1$s at %2$s', 'newspack' ), get_comment_date( '', $comment ), get_comment_time() );
                                ?>
                                <time datetime="<?php comment_time( 'c' ); ?>" title="<?php echo $comment_timestamp; ?>">
                                    <?php echo $comment_timestamp; ?>
                                </time>
                            </a>
                            <?php
                                $edit_comment_icon = newspack_get_icon_svg( 'edit', 16 );
                                edit_comment_link( __( 'Edit', 'newspack' ), '<span class="edit-link-sep">&mdash;</span> <span class="edit-link">' . $edit_comment_icon, '</span>' );
                            ?>
                        </div><!-- .comment-metadata -->

                        <?php if ( '0' == $comment->comment_approved ) : ?>
                        <p class="comment-awaiting-moderation"><?php _e( 'Your comment is awaiting moderation.', 'newspack' ); ?></p>
                        <?php endif; ?>
                    </footer><!-- .comment-meta -->
                <?php else : ?>
                    <footer class="comment-meta">
                        <div class="comment-author vcard">
                            <?php
                            $comment_author_link = get_comment_author_link( $comment );
                            $comment_author_url  = get_comment_author_url( $comment );
                            $comment_author      = get_comment_author( $comment );
                            $avatar              = get_avatar( $comment, $args['avatar_size'] );
                            if ( 0 != $args['avatar_size'] ) {
                                if ( empty( $comment_author_url ) ) {
                                    echo $avatar;
                                } else {
                                    printf( '<a href="%s" rel="external nofollow" class="url">', $comment_author_url );
                                    echo $avatar;
                                }
                            }

                            printf(
                                wp_kses(
                                    /* translators: %s: comment author link */
                                    __( '%s <span class="screen-reader-text says:</span>', 'newspack' ),
                                    array(
                                        'span' => array(
                                            'class' => array(),
                                        ),
                                    )
                                ),
                                '<b class="fn">' . get_comment_author_link( $comment ) . '</b>'
                            );

                            /* Display icon if the commenter is the current post's author. */
                            if ( newspack_is_comment_by_post_author( $comment ) ) {
                                printf( '<span class="post-author-badge" aria-hidden="true">%s</span>', wp_kses( newspack_get_icon_svg( 'person', 24, esc_html__( 'Article author', 'newspack' ) ), newspack_sanitize_svgs() ) );
                            }

                            if ( ! empty( $comment_author_url ) ) {
                                echo '</a>';
                            }
                            ?>
                        </div><!-- .comment-author -->

                        <div class="comment-metadata">
                            <a href="<?php echo esc_url( get_comment_link( $comment, $args ) ); ?>">
                                <?php
                                    /* translators: 1: comment date, 2: comment time */
                                    $comment_timestamp = sprintf( __( '%1$s at %2$s', 'newspack' ), get_comment_date( '', $comment ), get_comment_time() );
                                ?>
                                <time datetime="<?php comment_time( 'c' ); ?>" title="<?php echo $comment_timestamp; ?>">
                                    <?php echo $comment_timestamp; ?>
                                </time>
                            </a>
                            <?php
                                $edit_comment_icon = newspack_get_icon_svg( 'edit', 16 );
                                edit_comment_link( __( 'Edit', 'newspack' ), '<span class="edit-link-sep">&mdash;</span> <span class="edit-link">' . $edit_comment_icon, '</span>' );
                            ?>
                        </div><!-- .comment-metadata -->

                        <?php if ( '0' == $comment->comment_approved ) : ?>
                        <p class="comment-awaiting-moderation"><?php _e( 'Your comment is awaiting moderation.', 'newspack' ); ?></p>
                        <?php endif; ?>
                    </footer><!-- .comment-meta -->

                    <div class="comment-content">
                        <?php comment_text(); ?>
                    </div><!-- .comment-content -->
                <?php endif; ?>
            </article><!-- .comment-body -->

            <?php
            comment_reply_link(
                array_merge(
                    $args,
                    array(
                        'add_below' => 'div-comment',
                        'depth'     => $depth,
                        'max_depth' => $args['max_depth'],
                        'before'    => '<div class="comment-reply">',
                        'after'     => '</div>',
                    )
                )
            );
            ?>
        <?php
    }
}
?>