web-dev-qa-db-ja.com

コメントフォームにドロップダウンリストを追加しますか?

新しいユーザが自分のユーザロールを選択できるように、ドロップダウンメニューまたは(ラジオボタン)をWordpressのコメントフォームに作成する手助けをすることができますか(例:教師+生徒)。

  1. ドロップダウンリストまたはラジオボタンからの出力は、コメント領域のどこかに表示されます。
  2. 何よりも最善の方法は、既に自動的に入力されているWordPressでも
    メールアドレス、ログイン名にも新しい追加フィールド情報(ドロップダウンリストまたは
    ラジオボタン)すでに自分のユーザロールが割り当てられているログインユーザ
  3. 私はそのためにプラグインを使いたくありません。
  4. 私は残念ながら重複としてマークされている3つの類似した要求を見つけたこのWebを含むコメントフォームに追加のカスタムフィールドを追加することに関するチュートリアルがたくさんあることを知っています。 (select - dropdown-radio)ボタンとしての既知の値。
2
Daniel Foltynek
  • selectを持つlabel要素を追加するためにcomment_form_field_commentをフィルタリングします。
  • 値を保存するために、アクションcomment_postにコールバックを追加します。
  • コメントの値を表示するには、comment_textをフィルタリングします。

サンプルコード

add_filter( 'comment_form_field_comment', function( $field ) {

    global $wp_roles;

    $user = wp_get_current_user();

    $select = '<p><label for="roleselect">Your role:</label>
    <select name="prefix_role" id="roleselect">
    <option value="">Select a role</option>';

    foreach ( $wp_roles->roles as $key => $role )
        $select .= sprintf(
            '<option value="%1$s" %2$s>%3$s</option>',
            esc_attr( $key ),
            ( in_array( $key, $user->roles) ? 'selected' : '' ),
            esc_html( $role['name'] )
        );

    $select .= '</select></p>';

    return $select . $field;
});

add_action( 'comment_post', function( $comment_ID ) {

    $roles = new WP_Roles;
    $role_keys = array_keys( $roles->roles );

    if ( isset ( $_POST['prefix_role'] ) and in_array( $_POST['prefix_role'], $role_keys ) )
        update_comment_meta( $comment_ID, 'prefix_role', $_POST['prefix_role'] );
});

add_filter( 'comment_text', function( $text, $comment ) {

    if ( $role = get_comment_meta( $comment->comment_ID, 'prefix_role', TRUE ) )
        $text = "Role: $role<br> $text";

    return $text;
}, 10, 2 );

更新

実際のMVCパターンを使用するようにコードを書き直しました。以下の説明GitHubで プラグインとして

プラグインヘッダ

<?php # -*- coding: utf-8 -*-
namespace WPSE;
/**
 * Plugin Name: Comment Meta Demo
 * Description: Create, save and display a comment meta field. Here, a commentator can select a role.
 * Plugin URI:  http://wordpress.stackexchange.com/q/101579/73
 * Version:     2013.06.06
 * Author:      Thomas Scholz
 * Author URI:  http://toscho.de
 * Licence:     MIT
 * License URI: http://opensource.org/licenses/MIT
 */

\add_action(
    'wp_loaded',
    array( __NAMESPACE__ . '\Comment_Meta_Controller', 'init' )
);

コントローラ

/**
 * Controller
 *
 * Assigns Views and models to actions and filters
 */
class Comment_Meta_Controller
{
    /**
     * Callback for add_action(). Creates a new instance.
     *
     * @wp-hook login_init
     */
    public function init()
    {
        return new self;
    }

    /**
     * Set up objects, register footer action callback.
     *
     * @wp-hook login_init
     */
    protected function __construct()
    {

        $data   = new Comment_Meta_Builtin_Roles( '_comment_role' );
        // Use this for custom roles instead
        //$data   = new Comment_Meta_Custom_Roles( '_comment_role' );
        $input  = new Comment_Meta_Role_Selector( $data );
        $output = new Comment_Meta_Role_Display( $data );

        // remove this if you want to show the select field with
        // do_action( 'comment_role_selector' );
        \add_filter( 'comment_form_field_comment', array ( $input, 'show' ), 10, 2 );

        \add_action( 'comment_role_selector', array ( $input, 'print_select' ) );

        // remove this if you want to show the select field with
        // do_action( 'comment_role_selector' );
        \add_filter( 'comment_text', array ( $output, 'show' ), 10, 2 );

        \add_action( 'comment_role_value', array ( $output, 'show_action' ), 10, 2 );

        if ( 'POST' === $_SERVER[ 'REQUEST_METHOD' ] )
            \add_action( 'comment_post', array ( $data, 'save' ) );
    }
}

抽象メタデータベースクラス

/**
 * Base class for handling comment meta data.
 */
abstract class Comment_Meta_Data_Model
{
    /**
     * Meta key
     *
     * @type string
     */
    protected $key;

    /**
     * Constructor
     *
     * @param string $key
     */
    public function __construct( $key )
    {
        $this->key = $key;
    }

    /**
     * Get current key
     *
     * @return string
     */
    public function get_key()
    {
        return $this->key;
    }

    /**
     * Wrapper for the native get_comment_meta()
     *
     * @param  int    $comment_ID
     * @return string
     */
    public function get_comment_meta( $comment_ID )
    {
        $meta    = \get_comment_meta( $comment_ID, $this->key, TRUE );
        $allowed = $this->get_allowed_values();

        // get real display value
        if ( isset ( $allowed[ $meta ] ) )
            return $allowed[ $meta ];

        return '';
    }

    /**
     * Save comment mate data.
     *
     * @param  int  $comment_ID
     * @return bool
     */
    public function save( $comment_ID )
    {
        $role_keys = array_keys( $this->get_allowed_values() );

        if ( ! isset ( $_POST[ $this->key ] ) )
            return;

        if ( ! in_array( $_POST[ $this->key ], $role_keys ) )
            return;

        return \update_comment_meta( $comment_ID, $this->key, $_POST[ $this->key ] );
    }

    /**
     * Get user role.
     */
    public function get_current_value()
    {
        $user = \wp_get_current_user();

        if ( empty ( $user->roles ) )
            return array ();

        return $user->roles;
    }

    /**
     * @return array
     */
    abstract public function get_allowed_values();
}

組み込みロール用の拡張クラス

/**
 * User roles as comment meta.
 */
class Comment_Meta_Builtin_Roles extends Comment_Meta_Data_Model
{
    /**
     * (non-PHPdoc)
     * @see WPSE.Comment_Meta_Data_Model::get_allowed_values()
     */
    public function get_allowed_values()
    {
        global $wp_roles;

        if ( empty ( $wp_roles ) )
            $wp_roles = new \WP_Roles;

        $output = array();

        foreach ( $wp_roles->roles as $identifier => $role )
            $output[ $identifier ] = $role['name'];

        return $output;
    }
}

許可された役割のカスタム選択のための拡張クラス

/**
 * Custom roles for comment meta.
 */
class Comment_Meta_Custom_Roles extends Comment_Meta_Data_Model
{
    /**
     * (non-PHPdoc)
     * @see WPSE.Comment_Meta_Data_Model::get_allowed_values()
     */
    public function get_allowed_values()
    {
        return array (
            'teacher' => 'Teacher',
            'student' => 'Student'
        );
    }
}

基本コメントメタビュー

/**
 * Base class to show comment meta data.
 */
class Comment_Meta_View
{
    /**
     * Model
     *
     * @type Comment_Meta_Data_Model
     */
    protected $data;

    /**
     * Constructor.
     *
     * @param Comment_Meta_Data_Model $data
     */
    public function __construct( Comment_Meta_Data_Model $data )
    {
        $this->data = $data;
    }
}

選択フィールドをビューとして使用する

/**
 * Show role selector from comment meta
 */
class Comment_Meta_Role_Selector extends Comment_Meta_View
{
    /**
     * Add 'select' field before textarea.
     *
     * @param  string $text_field
     * @return string
     */
    public function show( $text_field )
    {
        return $this->get_select() . $text_field;
    }

    /**
     * Select element.
     *
     * @return string
     */
    public function get_select()
    {
        $allowed = $this->data->get_allowed_values();
        $current = $this->data->get_current_value();
        $key     = $this->data->get_key();

        // is the current value part of the allowed values?
        if ( ! empty ( $current ) && array() !== array_intersect( $allowed, $current ) )
            return $this->get_hidden_field( $key, $current[0] );

        $select = '<p>';
        $select .= sprintf( '<label for="%1$s_id">Your role:</label>
            <select name="%1$s" id="%1$s_id">',
            $key
        );
        $select .= '<option value="">Select a role</option>';

        foreach ( $allowed as $internal => $display )
            $select .= sprintf(
                '<option value="%1$s">%2$s</option>',
                \esc_attr( $internal ),
                \esc_html( $display )
            );

        return $select . '</select></p>';
    }

    /**
     * Print preselcted role as hidden input field.
     *
     * @param  string $name Field name
     * @param  string $role Internal role name
     * @return string
     */
    protected function get_hidden_field( $name, $role )
    {
        return sprintf(
            '<input type="hidden" name="%1$s" value="%2$s">',
            $name,
            esc_attr( $role )
        );
    }

    /**
     * Callback for do_action.
     *
     * @wp-hook comment_role_selector
     * @return  void
     */
    public function print_select()
    {
        print $this->get_select();
    }
}

現在の役割をビューとして表示する

/**
 * Show current comment role.
 */
class Comment_Meta_Role_Display extends Comment_Meta_View
{
    /**
     * Add role to comment text.
     *
     * @wp-hook comment_text
     * @param   string $text
     * @param   object $comment
     * @return  string
     */
    public function show( $text, $comment )
    {
        $role = $this->data->get_comment_meta( $comment->comment_ID );

        if ( '' !== $role )
            $text = "Role: $role<br> $text";

        return $text;
    }

    /**
     * Print the comment meta value into a template.
     *
     * Usage: <code>do_action( 'comment_role_value', 'Role: %s<br>', $comment );
     *
     * @wp-hook comment_role_value
     * @param   string $template
     * @param   object $comment
     * @return  void
     */
    public function show_action( $template, $comment )
    {
        $role = $this->data->get_comment_meta( $comment->comment_ID );

        if ( '' !== $role )
            printf( $template, $role );
    }
}

ご覧のとおり、現在7つのクラスがあります。

  1. Comment_Meta_Controller
    ここでは、他のクラスを組み合わせて便利なことをします。
  2. Comment_Meta_Data_Modelコメントデータを扱うための基本クラス。そのまま使用することはできません、拡張する必要があります。
  3. Comment_Meta_Builtin_Roles
    Comment_Meta_Data_Modelを拡張し、すべての組み込みロールを使用します。私はこれを私のテストに使いました。おそらく次のクラスを使うべきです。そうするためにコントローラを変更してください。
  4. Comment_Meta_Custom_Roles
    Comment_Meta_Data_Modelを拡張します。 Comment_Meta_Builtin_Rolesの代替。
    ご覧のとおり、カスタムロールの配列を返すには1つのメソッド(関数)だけを変更する必要があります。
  5. Comment_Meta_View
    出力用の基本クラス。そのまま使用することはできません、拡張する必要があります。
  6. Comment_Meta_Role_Selector
    Comment_Meta_Viewを拡張します。 select要素を作成します。データのソースについては何も知りませんし、その値をビューから正しく取得できます。
  7. Comment_Meta_Role_Display
    Comment_Meta_Viewを拡張します。コメントの現在の値を表示します。

使用法

selectフィールドを表示するどちらか…

  • 何もしないで、私のデフォルトがその仕事をするようにしなさい。その場合、選択フィールドはコメントテキストフィールドの真上に設定されます。
  • または行を削除してください…

    \add_filter( 'comment_form_field_comment', array ( $input, 'show' ), 10, 2 );
    

    …そしてあなたのコメントフォームで次のコードを使ってください:

    do_action( 'comment_role_selector' );
    

許可されたロールにカスタム値を設定するに、行を削除してください…

    $data   = new Comment_Meta_Builtin_Roles( '_comment_role' );

…そして次の行のコメントを外します。それからComment_Meta_Custom_Rolesを編集してください。

にメタキーを変更し、値'_comment_role'を変更するだけです。 WordPressの内蔵キーを使用しないでください。

それで全部です。

6
fuxia