web-dev-qa-db-ja.com

カスタムメタボックステキストエリアにテキストを貼り付けると403エラーが発生する

みんなが素晴らしい一日を過ごしていることを願っています!

私は一日中この問題に立ち往生しているので私はこの質問を作成しています、そして私はいくらかの友好的な助言が必要です。

Proposalというカスタム投稿タイプのリピーターカスタムメタボックスアイテムを作成しました。リピーターは正常に動作し、コンテンツを保存してそれを私が望むように表示しています。ただし、テキスト領域にコンテンツを貼り付けると、投稿を更新または公開したときに403エラーページが表示され、繰り返しオプションが1つ以上になります。

奇妙なのは、textareaにテキストを追加しても問題なく動作するコンテンツを貼り付けない場合です。明らかに、これは私が世界にプラグインをリリースする前に私が修正する必要がある問題です。これが私が持っているコードです。何か問題があることに気づいたら、バックエンド開発が初めてなので改善できるように私に知らせてください。

<div id="wpp_meta_inner">
<?php
//get the saved meta as an array
$service = get_post_meta($post->ID,'service',false);
$service_title = get_post_meta($post->ID, 'wpp_service_title', true);
?>
    <div>

          <div class="wpp-input-container">
              <label><?php _e('Title') ?></label>
              <input type="text" name="wpp_service_title" id="wpp_service_title" value="<?php echo $service_title; ?>" />
              <p><?php _e('Will display default "Scope of Services" if empty.') ?></p>
          </div>

          <div class="wpp-input-container">
              <label class="wpp-label-repeater"><?php _e('Service Items') ?></label>
              <?php
              wp_nonce_field ( 'c_nonce_field', 'c_wpnonce');
                  $c = 0;
                  if ( count( $service ) > 0 ) {
                      if(!empty($service)) {
                          foreach( $service as $service_item_val ) {
                              foreach( $service_item_val as $service_item ) {
                                  if ( isset( $service_item['title'] ) || isset( $service_item['service_item'] ) ) {
                                      printf( '<div class="wpp-repeater-wrapper service">Title: <input class="wpp-repeater-input service" type="text" name="service[%1$s][title]" value="%2$s" />Description: <textarea class="wpp-repeater-input service" name="service[%1$s][service_item]" data-gramm_editor="false" value="">%3$s</textarea><span class="wpp-item-remove service">%4$s</span></div>', $c, $service_item['title'], $service_item['service_item'], __( 'Remove' ) );
                                      $c = $c +1;
                                  }
                              }
                          }
                      }
                  }
              ?>
              <span id="services_here"></span>
              <div class="wpp-item-add services" style="visibility: hidden; margin-bottom: -20px;"><?php _e('Add Item'); ?></div>
              <div class="wpp-item-add services add-button"><?php _e('Add Service'); ?></div>
              </div>

    </div>

    <script>
    var $ =jQuery.noConflict();
    $(document).ready(function() {
        var count = <?php echo $c; ?>;
        $(".wpp-item-add.services").click(function() {
            count = count + 1;
            $('#services_here').append('<div class="wpp-repeater-wrapper service">Title: <input class="wpp-repeater-input service" type="text" name="service['+count+'][title]" value="" placeholder="" />Description: <textarea class="wpp-repeater-input service" name="service['+count+'][service_item]" data-gramm_editor="false" value="" placeholder=""></textarea><span class="wpp-item-remove service">Remove</span></div>' );
            return false;
        });
        $(".wpp-item-remove.service").live('click', function() {
            $(this).parent().remove();
        });
    });
    </script>

</div>

<?php }
/* When the post is saved, saves our data */
function wpp_save_services_data( $post_id ) {
if(defined("DOING_AJAX") AND DOING_AJAX)
  return;
  if(!current_user_can('edit_post', $post_id ))
  return;
  if(!isset($_POST['c_wpnonce']) || !wp_verify_nonce( $_POST['c_wpnonce'], 'c_nonce_field'))
  return;
  $allowed_html = array(
          'a' => array(
              'href' => array()
          ));
  $service = $_POST['service'];
  update_post_meta ($post_id, 'wpp_service_title', wp_kses( $_POST['wpp_service_title'], $allowed_html));
  update_post_meta ($post_id,'service',$service);
 }
1
Kevin W.

私はあなたのコードを見渡し、そして適切なエスケープと衛生管理を含むようにそれを更新しました。私は問題がエスケープの欠如から生じたのではないかと思います。私はまた、いくつかのフォーマットとWPベストプラクティスを適用しましたが、それ以外はコードは同じです。

/**
 * Meta box display callback.
 *
 * @param WP_Post $post Current post object.
 */
function wpse_metabox_callback( $post ) {
    $service_title = get_post_meta( $post->ID, 'wpp_service_title', true );
    $service       = get_post_meta( $post->ID, 'service', false ); // get as an array ?>

    <div id="wpp_meta_inner">
    <div>
            <div class="wpp-input-container">
                <label><?php esc_html_e( 'Title', 'textdomain' ); ?></label>
                <input type="text" name="wpp_service_title" id="wpp_service_title" value="<?php echo esc_attr( $service_title ); ?>" />
                <p><?php esc_html_e( 'Will display default "Scope of Services" if empty.', 'textdomain' ); ?></p>
            </div>

            <div class="wpp-input-container">
                <label class="wpp-label-repeater"><?php _e( 'Service Items', 'textdomain' ); ?></label>
                <?php
                    wp_nonce_field( 'c_nonce_field', 'c_wpnonce' );
                    $c = 0;
                    if ( count( $service ) > 0 ) {
                        if ( ! empty( $service ) ) {
                            foreach( $service as $service_item_val ) {
                                foreach( $service_item_val as $service_item ) {
                                    if ( isset( $service_item['title'] ) || isset( $service_item['service_item'] ) ) {
                                        printf(
                                            '<div class="wpp-repeater-wrapper service">' .
                                                'Title: <input class="wpp-repeater-input service" type="text" name="service[%1$s][title]" value="%2$s" />' .
                                                'Description: <textarea class="wpp-repeater-input service" name="service[%1$s][service_item]" data-gramm_editor="false" value="">%3$s</textarea><span class="wpp-item-remove service">%4$s</span>' . 
                                            '</div>',
                                            esc_attr( $c ),
                                            esc_html( $service_item['title'] ),
                                            esc_textarea( $service_item['service_item'] ),
                                            esc_html( __( 'Remove', 'textdomain' ) )
                                        );
                                        $c += 1;
                                    }
                                }
                            }
                        }
                    }
                ?>
                <span id="services_here"></span>
                <div class="wpp-item-add services" style="visibility: hidden; margin-bottom: -20px;"><?php esc_html_e( 'Add Item', 'textdomain' ); ?></div>
                <div class="wpp-item-add services add-button"><?php esc_html_e( 'Add Service', 'textdomain' ); ?></div>
            </div>
        </div>

        <script>
            var $ =jQuery.noConflict();
            $(document).ready(function() {
                    var count = <?php echo esc_js( $c ); ?>;
                    $(".wpp-item-add.services").click(function() {
                            count = count + 1;
                            $('#services_here').append('<div class="wpp-repeater-wrapper service">Title: <input class="wpp-repeater-input service" type="text" name="service['+count+'][title]" value="" placeholder="" />Description: <textarea class="wpp-repeater-input service" name="service['+count+'][service_item]" data-gramm_editor="false" value="" placeholder=""></textarea><span class="wpp-item-remove service">Remove</span></div>' );
                            return false;
                    });
                    $(".wpp-item-remove.service").live('click', function() {
                            $(this).parent().remove();
                    });
            });
        </script>
    </div><?php
}

メタボックスデータを保存するとき、wp_kses_post()$services配列の各要素に適用されます。

/**
 * Sanitize and save metabox data.
 */
add_action( 'save_post', 'wpse_save_meta_box' );
function wpse_save_meta_box( $post_id ) {
    if ( defined( 'DOING_AJAX' ) AND DOING_AJAX ) {
        return;
    }

    if ( ! current_user_can( 'edit_post', $post_id ) ) {
        return;
    }

    if ( ! isset( $_POST['c_wpnonce'] ) || ! wp_verify_nonce( $_POST['c_wpnonce'], 'c_nonce_field' ) ) {
        return;
    }

    $allowed_html = array (
        'a' => array(
            'href' => array()
    ) );

    $service = isset( $_POST['service'] ) && ! empty( $_POST['service'] ) ? array_map( 'wp_kses_post', $_POST['service'] ) : array();

    update_post_meta( $post_id, 'wpp_service_title', wp_kses( $_POST['wpp_service_title'], $allowed_html ) );
    update_post_meta( $post_id, 'service', $service );
}

完全を期すために、以下はproposalポストタイプを登録するコードです。

/**
 * Register proposal post type.
 */
add_action( 'init', 'wpse_register_post_type_proposal' );
function wpse_register_post_type_proposal() {
    $args = [
            'label'             => __( 'Proposals', 'textdomain' ),
            'public'             => true,
            'publicly_queryable' => true,
            'show_ui'            => true,
            'show_in_menu'       => true,
            'query_var'          => true,
            'rewrite'            => [ 'slug' => 'proposal' ],
            'capability_type'    => 'post',
            'has_archive'        => true,
            'hierarchical'       => false,
            'menu_position'      => null,
            'supports'           => [ 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' ],
    ];
    register_post_type( 'proposal', $args );
}

そしてメタボックス:

/**
 * Register meta box
 */
function wpse_register_meta_boxes() {
    add_meta_box( 'meta-box-id', __( 'My Meta Box', 'textdomain' ), 'wpse_metabox_callback', 'proposal' );
}
add_action( 'add_meta_boxes', 'wpse_register_meta_boxes' );
1
Dave Romsey