it-swarm.com.de

WP_List_Table Inside Metabox funktioniert nicht beim Senden

Ich versuche, einen WP_List_table in einer Metabox anzuzeigen. Die Metabox ist für eine benutzerdefinierte Taxonomie mit dem Namen service bestimmt, die für einen benutzerdefinierten Beitragstyp mit dem Namen office registriert ist. Die Tabellenspalten enthalten Eingabefelder, die die Taxonomie manipulieren und es mir ermöglichen, zusätzliche Daten mit jedem einzelnen Taxonomiebegriff zu verknüpfen. Ich denke nicht, dass die Tatsache, dass ich dies für eine benutzerdefinierte Taxonomie versuche, die sich auf einem benutzerdefinierten Bearbeitungsbildschirm für Beitragstypen befindet, relevant ist. Ich erwähne es nur aus Gründen der Klarheit.

Was passiert ist, dass alles gut aussieht, bis ich auf die Schaltfläche Veröffentlichen/Aktualisieren im Bearbeitungsbildschirm für benutzerdefinierte Beitragstypen klicke. Wenn der WP_List_Table Massenaktionen enthält, die zur /wp-admin/edit.php-Seite zurückgeleitet werden, werden die Massenaktionen entfernt und die Meldung "Sind Sie sicher, dass Sie dies tun möchten? - Bitte versuchen Sie es erneut" angezeigt. Dies ist ein Fehler bei der Nonce-Validierung . In beiden Fällen werden die Daten, die ich für den Beitrag ändere, nicht gespeichert.

Ich habe unten einen Link zum vollständigen Skript eingefügt, mit dem die Taxonomie registriert, die Tabelle erstellt und die Metaboxdaten gespeichert werden. Fühlen Sie sich frei, damit zu spielen, um es zum Laufen zu bringen, wenn Sie möchten.

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

EIN HINWEIS AN DIE STACKOVERFLOW-EDITOREN: Ich habe bereits Fragen durchgesehen, während ich meine eingebe, und auch alle Fragen, die mit wp-list-table markiert sind, sowie die Tiefen von Google durchforstet, und keine davon scheint für meine Situation relevant zu sein .

UPDATE: Wenn möglich, würde ich es vorziehen, keine bulk_actions zu verwenden. Ich brauche sie auf diesem Tisch nicht. Ich habe die Löschaktion nur zu Testzwecken hinzugefügt. Und die Klassenmethode process_bulk_action wird ohnehin nicht einmal beim Senden aufgerufen.

<?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

Sie müssen nur die Funktion display_tablenav() mit einer leeren Funktion in Ihrer übergeordneten Klasse überschreiben.

Es wird hier erklärt.

0
user2242022

Ich bin gerade auf dieses Problem gestoßen.

Wenn Sie eine benutzerdefinierte Listentabelle (A/K/A WP Listentabelle) in einer Meta-Box verwenden (befindet sich auf dem Post-Edit-Bildschirm post.php oder post-new.php.)

Der Grund, warum Sie zum Bildschirm mit der Auflistung der Posts (edit.php) umgeleitet werden, ist, dass Sie als Benutzerdefinierte Listentabelle ein ausgeblendetes Nonce-Feld generieren, das auch von den Seiten post.php oder post-new.php generiert wird. Sie haben beide den gleichen Namen, da für ... unerwartete Probleme auftreten.

Eine einfache Lösung wäre, die Funktion zu überschreiben, die das Nonce-Feld in Ihrer benutzerdefinierten Listentabelle erstellt.

Das Problem in Ihrer benutzerdefinierten Listentabelle ist, dass Ihre Paginierung eine Nonce erstellt.

Wenn Sie die Klasse list-table.php öffnen und nach function display_tablenav( suchen, finden Sie die Funktion, die die Nonce erstellt.

Ich bin mir sicher, dass es einen besseren Ansatz dafür gibt, aber ich habe einfach die gesamte Funktion kopiert, sie dann in meine Custom List Table-Klasse eingefügt und den Teil auskommentiert, der das Nonce-Feld erstellt.

Beispiel:

/**
 * 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
}

Wenn Sie diesen Codeabschnitt auskommentieren, sollte Ihre Post-Seite erneut wie gewohnt erfolgreich gesendet werden.

0
Michael Ecklund