web-dev-qa-db-ja.com

WP_List_Tableメタボックス内部で送信が機能しない

メタボックス内にWP_List_tableを表示しようとしています。メタボックスはserviceと呼ばれるカスタム投稿タイプに登録されているofficeと呼ばれるカスタム分類法用です。テーブルの列には分類法を操作する入力フィールドがあり、追加のデータを個々の分類法用語にリンクさせることができます。カスタム投稿タイプの編集画面にあるカスタム分類法のためにこれを実行しようとしているという事実は関係ありません。私は単に明快さのために言及するだけです。

カスタム投稿タイプの編集画面で[公開/更新]ボタンをクリックするまで、すべてうまくいきます。 WP_List_Table/wp-admin/edit.phpページにリダイレクトする一括アクションを持っているならば、それは私が一括アクションを削除しますそしてそれはWordpress失敗通知を表示しますこれは一回限りの検証エラーです。どちらの場合も、投稿に対して変更したデータは保存されません。

分類を登録し、テーブルを作成し、メタボックスデータを保存する完全なスクリプトへのリンクを以下に含めました。あなたが好きならそれを動作させるためにそれをいじって自由に感じなさい。

http://www.writeurl.com/text/aawwgq1od5913fmyfjyu/0y84g3vcyptvrkvvfxq4/0dow449a06lj6ctkqjqo

スタックオーバーフロー編集者へのメモ:私が入力している間に提案された質問とwp-list-tableでタグ付けされたすべての質問を調べた私の状況に。

UPDATE:可能であれば、bulk_actionsを使用しないでください。私はこのテーブルでそれらを必要としません。テスト目的で削除アクションを追加しただけです。とにかく、クラスメソッドprocess_bulk_actionは送信時に呼び出されることすらありません。

<?php
if(!class_exists('WP_List_Table')) {
    require_once(ABSPATH.'wp-admin/includes/class-wp-list-table.php');
}

class servicesTable extends WP_List_Table {
    private $allServices;
    private $currentServices;
    private $currentServicesData;

    public function __construct(){
        parent::__construct(
            array(
                'singular' => 'service',
                'plural' => 'services',
                'ajax' => false
            )
        );
    }

    private function table_data() {
        $this->currentServices = wp_get_object_terms(get_the_ID(),array('service'),array('fields' => 'ids'));
        $this->currentServicesData = (array) maybe_unserialize(get_post_meta(get_the_ID(),'currentServices',true));
        $this->allServices = array();
        foreach((array) get_terms(array('service'),array('hide_empty' => false)) as $service) {
            $this->allServices[] = array(
                'id' => $service->term_id,
                'serviceTitle' => $service->name,
                'attachments' => array_key_exists($service->term_id,$this->currentServicesData) ? explode(',',$this->currentServicesData[$service->term_id]['attachments']) : array(),
                'lastServiced' =>  (array_key_exists($service->term_id,$this->currentServicesData) && strlen($this->currentServicesData[$service->term_id]['last_serviced']) > 0) ? date('Y-m-d',strtotime($this->currentServicesData[$service->term_id]['last_serviced'])) : '',
                'nextService' =>  (array_key_exists($service->term_id,$this->currentServicesData) && strlen($this->currentServicesData[$service->term_id]['next_service']) > 0) ? date('Y-m-d',strtotime($this->currentServicesData[$service->term_id]['next_service'])) : '',
                'invoices' => ''
            );
        }
        return $this->allServices;
    }

    public function column_default($item,$columnName) {
        return array_key_exists($columnName,$item) ? $item[$columnName] : print_r($item,true);
    }

    public function get_columns(){
        return array(
            'cb' => '<input type="checkbox" />',
            'id' => 'ID',
            'serviceTitle' => __('Title','brokertech'),
            'attachments' => __('Attachments','brokertech'),
            'lastServiced' => __('Last Service Date','brokertech'),
            'nextService' => __('Next Service Date','brokertech'),
            'invoices' => __('Invoices','brokertech')
        );
    }

    public function get_hidden_columns() {
        return array('id');
    }

    public function get_sortable_columns() {
        return array(
            'lastServiced' => array('lastServiced',true),
            'nextService' => array('nextService',true)
        );
    }

    private function sort_data($a,$b) {
        $orderby = empty($_GET['orderby']) ? 'nextService' : $_GET['orderby'];
        $order = empty($_GET['order']) ? 'asc' : $_GET['order'];
        $result = strcmp($a[$orderby],$b[$orderby]);
        return ($order === 'asc') ? $result : -$result;
    }

    public function prepare_items() {
        usort($this->table_data(),array(&$this,'sort_data'));
        $this->_column_headers = array($this->get_columns(),$this->get_hidden_columns(),$this->get_sortable_columns());
        $this->items = $this->allServices;
        wp_enqueue_script('services',JS_URI.'servicesSelector.js',array('thickbox','media-upload'));
        wp_enqueue_style('thickbox');
        wp_localize_script(
        'services',
        'servicesData',
            array(
                'editAttachment' => __('Edit'),
                'removeAttachment' => __('Remove')
            )
        );
    }

    public function column_cb($item) {
        return sprintf('<input type="checkbox" name="services[%s][enable]" value="%s" %s />',$item['id'],$item['serviceTitle'],checked(true,in_array($item['id'],$this->currentServices),false));
    }

    public function column_id($item) {
        return sprintf('<input type="hidden" name="services[%s][id]" value="%s" />',$item['id'],$item['id']);
    }

    public function column_attachments($item) {
        $html  = sprintf(
            '<input type="hidden" name="services[%s][attachments]" value="%s" class="listAttachments" />',
            $item['id'],
            empty($item['attachments']) ? '' : implode(',',$item['attachments'])
        );
        $html .= sprintf('<input type="button" value="%s" class="button button-secondary addServiceAttachment" data-service-id="%s" />',__('Add'),$item['id']);
        $html .= "&nbsp;";
        if(empty($item['attachments'])) {
            $html .= sprintf('<input type="button" value="%s" class="button button-secondary clearAll" data-service-id="%s" disabled="disabled" />',__('Clear'),$item['id']);
        }
        else {
            $html .= sprintf('<input type="button" value="%s" class="button button-secondary clearAll" data-service-id="%s" />',__('Clear'),$item['id']);
            $html .= "<br /><br />";
            foreach($item['attachments'] as $attachment) {
                if(is_numeric($attachment)) {
                    $html .= sprintf(
                        "<div class='serviceAttachment' style='margin-bottom: 1em;'><span>%s</span><br /><a href='%s' target='_blank' class='button button-secondary'>%s</a><input type='button' class='removeServiceAttachment button button-secondary' value='%s' style='float:right;' /><div style='clear:both;'></div></div>",
                        get_the_title($attachment),
                        get_admin_url(get_current_blog_id(),'post.php?post='.$attachment.'&action=edit'),
                        __('Edit'),
                        __('Remove')
                    );
                }
            }
        }
        return $html;
    }

    public function column_lastServiced($item) {
        return sprintf('<input type="date" name="services[%s][last_serviced]" value="%s" />',$item['id'],$item['lastServiced']);
    }

    public function column_nextService($item) {
        return sprintf('<input type="date" name="services[%s][next_service]" value="%s" />',$item['id'],$item['nextService']);
    }

    public function column_invoices($item) {
        $html  = sprintf(
            '<input type="hidden" name="services[%s][invoices]" value="%s" class="listInvoices" />',
            $item['id'],
            empty($item['invoices']) ? '' : implode(',',$item['invoices'])
        );
        $html .= sprintf('<input type="button" value="%s" class="button button-secondary addInvoice" data-service-id="%s" />',__('Add'),$item['id']);
        $html .= "&nbsp;";
        if(!empty($item['invoices'])) {
            $html .= "<br /><br />";
            foreach($item['invoices'] as $invoice) {
                if(is_numeric($invoice)) {
                    $html .= sprintf(
                        "<div class='serviceInvoice' style='margin-bottom: 1em;'><span>%s</span><br /><a href='%s' target='_blank' class='button button-secondary'>%s</a><input type='button' class='removeInvoice button button-secondary' value='%s' style='float:right;' /><div style='clear:both;'></div></div>",
                        get_the_title($invoice),
                        get_admin_url(get_current_blog_id(),'post.php?post='.$attachment.'&action=edit'),
                        __('Edit'),
                        __('Remove')
                    );
                }
            }
        }
        return $html;
    }
}

function saveServices($postID) {
    if(empty($_POST) || (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)) {
        return;
    }
    $servicesData = array();
    $services = array();
    foreach($_POST['services'] as $service) {
        if(isset($service['enable'])) {
            $services[] = (string) $service['enable'];
                $servicesData[$service['id']] = $service;
        }
    }
    empty($servicesData) ? delete_post_meta($postID,'currentServices') : update_post_meta($postID,'currentServices',$servicesData);
    wp_set_object_terms($postID,$services,'service');
}
add_action('save_post','saveServices');

function servicesMetaBox() {
    $servicesTable = new servicesTable();
    $servicesTable->prepare_items();
    $servicesTable->display();
}

$serviceTaxonomy = new brokertechPostType;
$serviceTaxonomy->createTaxonomy(
    'service',
    array(
        'office'
    ),
    __('Service'),
    __('Services'),
    array(
        'public' => true,
        'hierarchical' => false,
        'query_var' => true,
        'update_count_callback' => '_update_post_term_count',
        'show_ui' => true,
        'rewrite' => array(
            'slug' => __('services')
        ),
        'meta_box_cb' => 'servicesMetaBox'
    )
);

function addServicesTaxonomyPage() {
    add_submenu_page(
        'edit.php?post_type=company',
        __('Services'),
        __('Services'),
        'edit_posts',
        'edit-tags.php?taxonomy=service&post_type=office'
    );
}
add_action('admin_menu','addServicesTaxonomyPage');

function changeServicesMetaBoxPosition() {
    global $wp_meta_boxes;
    unset($wp_meta_boxes['office']['side']['core']['tagsdiv-service']);
    add_meta_box(
        'tagsdiv-service',
        __('Services'),
        'servicesMetaBox',
        'office',
        'normal',
        'low'
    );
}
add_action('add_meta_boxes','changeServicesMetaBoxPosition',0);
3
Ben

あなただけの親クラスの空白の関数で関数display_tablenav()をオーバーライドする必要があります。

ここ で説明されています。

0
user2242022

私は最近この問題に遭遇しました。

メタボックス内のカスタムリストテーブル(A/K/A WPリストテーブル)を使用している場合(投稿編集画面のpost.phpまたはpost-new.phpにあります)

投稿一覧画面(edit.php)にリダイレクトされるのは、カスタムリストテーブルが非表示のnonceフィールドを生成するためで、これもpost.phpページまたはpost-new.phpページによって生成されます。それらは両方とも同じ名前を持っています、そこに...予期しない問題が発生します。

簡単な解決策は、カスタムリストテーブルにナンスフィールドを作成する機能を上書きすることです。

カスタムリストテーブルの問題は、ページネーションがナンスを作成していることです。

list-table.phpクラスを開いてfunction display_tablenav(を検索すると、ナンスを作成している関数が見つかります。

もっと良いアプローチがあると確信していますが、その関数全体を単純にコピーし、それを私のカスタムリストテーブルクラスに貼り付けて、ナンスフィールドを作成する部分をコメントアウトするだけです。

例:

/**
 * Generate the table navigation above or below the table
 *
 * @since 3.1.0
 * @access protected
 *
 * @param string $which
 */
protected function display_tablenav( $which ) {

    // REMOVED NONCE -- INTERFERING WITH SAVING POSTS ON METABOXES
    // Add better detection if this class is used on meta box or not.
    /*
    if ( 'top' == $which ) {
        wp_nonce_field( 'bulk-' . $this->_args['plural'] );
    }
    */

    ?>
    <div class="tablenav <?php echo esc_attr( $which ); ?>">

        <div class="alignleft actions bulkactions">
            <?php $this->bulk_actions( $which ); ?>
        </div>
        <?php
        $this->extra_tablenav( $which );
        $this->pagination( $which );
        ?>

        <br class="clear"/>
    </div>
<?php
}

あなたがコードのそのセクションをコメントアウトした場合、あなたの投稿ページは再び通常どおりに正常に送信されるはずです。

0
Michael Ecklund