Comments form custom fields order

Demo – Setup

Here’s a demo how we could control the display of comment fields and their order:

Let’s create a custom class:

$mycf = new MyCommentFields;

Then we define our extra fields:

$myfields = [];

$myfields['myaddress'] = sprintf(
    '<p class="comment-form-myaddress">
         <label for="myaddress">%s <span class="required">*</span></label>
         <input id="myaddress" name="myaddress" type="text" size="30" tabindex="5" />
     </p>', 
    esc_html__( 'Address', 'kvkoolitus' )
); 

$myfields['myphone'] = sprintf(
    '<p class="comment-form-myphone">
         <label for="myphone">%s <span class="required">*</span></label>
         <input id="myphone" name="myphone" type="text" size="30" tabindex="5" />
     </p>', 
    esc_html__( 'Phone', 'kvkoolitus' )
);

and set it with:

$mycf->set_extra_fields_logged_in(  $myfields );
$mycf->set_extra_fields_logged_out( $myfields );

Next we set the display-order for those fields:

$mycf->set_fields_order_logged_in( 
    [ 
        'myaddress', 
        'myphone', 
        'comment', 
    ] 
);

and:

$mycf->set_fields_order_logged_out( 
    [ 
        'author', 
        'email', 
        'url', 
        'myaddress', 
        'myphone', 
        'comment' 
    ] 
);

Then we initialize it:

$mycf->init();

We could then hook this into the comment_form_before action.

Demo – Class

Here’s our demo class (PHP 5.4+):

class MyCommentFields
{
    private $extra_fields_logged_in;
    private $extra_fields_logged_out;
    private $fields_order_logged_in;
    private $fields_order_logged_out;

    public function init()
    {
        // logged-out case
        add_filter( 'comment_form_fields',          [ $this, 'comment_form_fields' ] );

        // logged-in case
        add_filter( 'comment_form_field_comment',   [ $this, 'comment_form_field_comment' ] );      
    }

    public function set_extra_fields_logged_in( array $extra_fields_logged_in )
    {
        $this->extra_fields_logged_in = $extra_fields_logged_in;
    }

    public function set_extra_fields_logged_out( array $extra_fields_logged_out )
    {
        $this->extra_fields_logged_out = $extra_fields_logged_out;
    }

    public function set_fields_order_logged_in( array $fields_order_logged_in )
    {
        $this->fields_order_logged_in = $fields_order_logged_in;
    }

    public function set_fields_order_logged_out( array $fields_order_logged_out )
    {
        $this->fields_order_logged_out = $fields_order_logged_out;
    }

    public function comment_form_field_comment( $field )
    {
        // logged-in case
        if( is_user_logged_in() && ! empty( $this->extra_fields_logged_in ) ) 
        {
            $tmp = '';
            foreach( $this->fields_order_logged_in as $key )
            {
                if( 'comment' === $key  )
                    $tmp .= $field;
                elseif( isset( $this->extra_fields_logged_in[$key] ) )
                    $tmp .= $this->extra_fields_logged_in[$key];
            }
            if( $tmp )
                $field = $tmp;
        }
        return $field;
    }

    public function comment_form_fields( $fields )
    {
        // logged-out case
        if( ! is_user_logged_in() && ! empty( $this->extra_fields_logged_out ) ) 
        {
            $tmp = [];
            foreach( $this->fields_order_logged_out as $key )
            {
                if( isset( $fields[$key] ) )
                    $tmp[$key] = $fields[$key];             
                elseif( isset( $this->extra_fields_logged_out[$key] ) )
                    $tmp[$key] = $this->extra_fields_logged_out[$key];
            }   
            if( ! empty( $tmp ) ) 
                $fields = $tmp;
        }       
        return $fields;
    }

} // end class

Hopefully you can adjust the demo to your needs.

Previous answer:

Here’s one hack, to prepend extra fields, that should work for both logged-in and logged-out case:

add_filter( 'comment_form_fields', function( $fields )
{
      echo '<p class="comment-form-code">'.
           '<label for="code">' . __( 'Personal code', 'kvkoolitus' ) . ' <span class="required">*</span> </label>'.
           '<input id="code" name="code" type="text" size="30"  tabindex="5" /></p>';

      echo '<p class="comment-form-phone">'.
           '<label for="phone">' . __( 'Phone','kvkoolitus' ) . ' <span class="required">*</span> </label>'. 
           '<input id="phone" name="phone" type="text" size="30"  tabindex="5" /></p>';

      echo '<p class="comment-form-address">'.
           '<label for="address">' . __( 'Address','kvkoolitus' ) . '</label>'.
           '<input id="address" name="address" type="text" size="30"  tabindex="5" /></p>';

      echo '<p class="comment-form-company">'.
           '<label for="company">' . __( 'Company','kvkoolitus' ) . '</label>'.
           '<input id="company" name="company" type="text" size="30"  tabindex="5" /></p>';

      echo '<p class="comment-form-profession">'.
           '<label for="profession">' . __( 'Profession','kvkoolitus' ) . '</label>'.
           '<input id="profession" name="profession" type="text" size="30"  tabindex="5" /></p>'; 

    return $fields;
} );

Note that the dynamic comment_form_field_{$name} filter for the logged-out case will not be available for those fields.

Otherwise one could inject the new fields into the $comments_fields within the comment_form_fields filter and make sure they come before the default fields. This will only display for the logged-out case. Then for the logged-out case the comment_form_logged_in_after hook is available.

Leave a Comment