J'essaie d'afficher un WP_List_table
à l'intérieur d'une metabox. Le metabox correspond à une taxonomie personnalisée appelée service
qui est enregistrée dans un type de publication personnalisé appelé office
. Les colonnes de la table contiennent des champs de saisie qui manipulent la taxonomie et me permettent de lier des données supplémentaires à chaque terme de taxonomie. Je ne pense pas que le fait que j'essaye d'utiliser une taxonomie personnalisée qui se trouve sur un écran d'édition de type d'article personnalisé soit pertinent. Je ne fais que mentionner que par souci de clarté.
En réalité, tout semble aller jusqu'à ce que je clique sur le bouton Publier/Mettre à jour de l'écran d'édition de type de message personnalisé. Si le WP_List_Table
a des actions en bloc, il sera redirigé vers la page /wp-admin/edit.php
, il le supprime, puis il affiche un avis d'échec de Wordpress "Êtes-vous sûr de vouloir le faire? - Veuillez réessayer", ce qui est une erreur de validation nonce . Et dans les deux cas, aucune des données que je modifie pour le message n'est enregistrée.
J'ai inclus un lien ci-dessous vers le script complet qui enregistre la taxonomie, crée la table et enregistre les données Metabox. N'hésitez pas à le tripoter pour le faire fonctionner si vous le souhaitez.
http://www.writeurl.com/text/aawwgq1od5913fmyfjyu/0y84g3vcyptvrkvvfxq4/0dow449a06lj6ctkqjqo
AVIS AUX ÉDITEURS DE STACKOVERFLOW: J'ai déjà vérifié les questions suggérées pendant que je saisis les miennes, ainsi que toutes les questions marquées avec wp-list-table plus sur Google et aucune d'entre elles ne semble pertinente pour ma situation. .
UPDATE: Si possible, je préférerais ne pas avoir à utiliser bulk_actions. Je n'ai pas besoin d'eux sur cette table. J'ai seulement ajouté l'action delete à des fins de test. Et la méthode de classe process_bulk_action
n'est même pas appelée lors de la soumission.
<?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 .= " ";
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 .= " ";
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);
Il vous suffit de remplacer la fonction display_tablenav()
par une fonction vierge dans votre classe parente.
C'est expliqué ici .
Je viens de rencontrer ce problème récemment.
Si vous utilisez une table de liste personnalisée (A/K/A WP Table de liste) dans une méta-boîte (située sur l'écran d'édition postérieure post.php
ou post-new.php
.)
La raison pour laquelle vous êtes redirigé vers l'écran de liste de publications (edit.php
) est due au fait que vous êtes une liste de liste personnalisée génère un champ nonce masqué, qui est également généré par les pages post.php
ou post-new.php
. Ils portent tous les deux le même nom, là… pour des problèmes inattendus.
Une solution simple consisterait à remplacer la fonction créant le champ nonce dans votre table de liste personnalisée.
Le problème dans votre table de liste personnalisée est que votre pagination crée un nonce.
Si vous ouvrez la classe list-table.php
et recherchez function display_tablenav(
, vous trouverez la fonction qui crée le nonce.
Je suis sûr qu'il existe une meilleure approche à cet égard, mais j'ai simplement copié cette fonction dans son intégralité, puis je l'ai collée dans ma classe Custom List Table et commenté la partie qui crée le champ nonce.
Exemple:
/**
* 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
}
Si vous commentez cette section de code, votre page de publication devrait à nouveau être soumise comme d'habitude.