web-dev-qa-db-fra.com

Remplir une méta-boîte avec une liste de sélection de publications existantes et l'assigner à des types de publication personnalisés

Ma question est en partie basée sur cette réponse: https://wordpress.stackexchange.com/a/5778/27135

La réponse de Mike est vraiment excellente et la solution a bien fonctionné jusqu'à ce que je devais inclure ma méta-boîte dans un type de message personnalisé. J'ai essayé de modifier le code jusqu'à ce que cela fonctionne, mais je n'ai pas réussi. De plus, je n'ai pas besoin de plus d'une boîte de méta-sélection par page (le code de Mike en ajoute 3).

Alors j'ai commencé à partir de zéro, en enlevant tout. Cela fonctionne jusqu'au point où j'ai besoin de sauvegarder les données dans mon formulaire.

Mon principal problème en ce moment est que je ne sais pas comment enregistrer le tag d'option actuellement sélectionné lorsque je publie/enregistre. Je ne suis pas sûr des données à saisir dans les balises d'option et des éléments à saisir dans update_post_meta ()

J'ai aussi essayé de créer ma propre boucle en utilisant query_posts (), dans l'espoir de pouvoir mieux contrôler les données que je devais sauvegarder .. mais pas de chance là-bas non plus.

Le code ci-dessous est une version très simpliste du code de Mike. Mon but était de le dépouiller pour qu'il ne contienne que l'essentiel. Ironiquement, je dois l'avoir trop dépouillé et je ne peux pas trouver quoi. J'aimerais savoir ce que je dois ajouter pour sauvegarder la sélection actuelle. :)

add_action( 'add_meta_boxes', 'select_box_add_meta_box' );
add_action( 'save_post', 'select_box_save_postdata' );

// Create the meta box
function select_box_add_meta_box() {
      add_meta_box(
          'select_item',
          'Select Item',
          'select_box_content',
          'custom_post_type'
      );
}

// Create the meta box content
function select_box_content() {
    $static_args = array(
        'post_type' => 'another_custom_post_type', 
        'show_option_none' => 'Choose item'
    );
    $selected_item = get_post_meta($post->ID,'_selected_item', true);
    for($i=0; $i<=2; $i++) {
        $incrementing_args = array(
            'id' => "selected_item_{$i}",
            'name' => 'selected_item[]',
            'selected' => (empty($selected_item[$i]) ? 0 : $selected_item[$i]),
        );
    }   

    wp_dropdown_pages(array_merge($static_args,$incrementing_args));


}

// Save the selection
function select_box_save_postdata($data, $postarr) {    
    update_post_meta($postarr['ID'], '_selected_item', $postarr['selected_item']);
    return $data;
}
2
ragdollpanda

Je crois que c'est ce que vous cherchiez.

Je suis retourné à l'utilisation d'une classe car ce que vous utilisiez serait très facilement en conflit avec le code de quelqu'un d'autre qui a décidé d'utiliser les noms de fonction select_box_add_meta_box(), select_box_content() et/ou select_box_save_postdata(), ce qui est raisonnablement probable. Le nom de classe WPSE_85107 est uniquement susceptible d'entrer en conflit avec une autre personne répondant à cette question! Bien sûr, je suggérerais de choisir un meilleur nom pour votre plugin, mais au moins, choisissez quelque chose qui ne ressemble pas à un conflit.

L'utilisation d'une classe nous permet également d'utiliser des noms de méthodes courts et clairs que (généralement) _ ne peut que correspondre au nom du hook. Cela facilite à la fois l’écriture et la compréhension du code, OMI. C’est un peu plus complexe lorsque vous utilisez add_action() mais vous n’avez qu’à apprendre comment:

add_action( 'add_meta_boxes', 'select_box_add_meta_box' );

contre:

add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ) );

Et vous avez mal utilisé 'save_post'; il a besoin de deux paramètres, raison pour laquelle il y a un 2 après le 10, où 10 est simplement la priorité par défaut et n'est nécessaire que parce que nous avons dû spécifier le nombre de paramètres:

add_action( 'save_post', array( $this, 'save_post' ), 10, 2 );

Les paramètres corrects pour save_post() sont les suivants:

function save_post( $post_id, $post )

vs ceci:

function select_box_save_postdata($data, $postarr) 

Également dans la méthode save_post() que j'ai testée pour vérifier que c'est le type de publication qui nous intéresse et qu'il existe en effet un élément valide de $_POST['selected_post'] qui devrait contenir l'ID de publication sélectionné.

J'ai choisi de créer des (pseudo-) constantes et des variables d'instance de manière à ce qu'il vous soit plus facile de voir quels paramètres sont requis pour les différentes fonctions telles que add_meta_box() et wp_dropdown_pages(). Je n'ai pas ajouté de commentaires parce que je pense que si vous le faisiez, vous le verriez comme étant plus compliqué et donc écrasant, à l'instar de l'autre exemple.

Notez que la wp_dropdown_pages() nécessite un type de message 'hierarchical', c’est pourquoi j’ai dû le pirater ici pour l’obtenir à la liste $post_type=='post'. Le site de test que j'ai utilisé pour tester cet exemple ne contient que des types d'articles 'post' et 'page'; vous devriez pouvoir changer les deux lignes avec $FOR_POST_TYPE et $SELECT_POST_TYPE pour obtenir les types de publication que vous souhaitez.

J'ai utilisé la fonction de traduction __() pour les libellés au cas où vous créez un plug-in devant fonctionner dans d'autres langues.

J'ai utilisé admin_init() pour que l'autre code ne soit exécuté que dans l'administrateur mais pas dans l'interface. Ce n'est pas grave, mais chaque petit geste compte.

Et c'est à peu près tout. Voici le code:

<?php
/**
 * Plugin Name: @WPSE 85107
 * Description: <a target="_blank" href="http://wordpress.stackexchange.com/q/85107/89">WPSE 85107</a>
 */

class WPSE_85107 {
  var $FOR_POST_TYPE = 'page';
  var $SELECT_POST_TYPE = 'post';
  var $SELECT_POST_LABEL = 'Post';
  var $box_id;
  var $box_label;
  var $field_id;
  var $field_label;
  var $field_name;
  var $meta_key;
  function __construct() {
    add_action( 'admin_init', array( $this, 'admin_init' ) );
  }
  function admin_init() {
    add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ) );
    add_action( 'save_post', array( $this, 'save_post' ), 10, 2 );
    $this->meta_key     = "_selected_{$this->SELECT_POST_TYPE}";
    $this->box_id       = "select-{$this->SELECT_POST_TYPE}-metabox";
    $this->field_id     = "selected-{$this->SELECT_POST_TYPE}";
    $this->field_name   = "selected_{$this->SELECT_POST_TYPE}";
    $this->box_label    = __( "Select {$this->SELECT_POST_LABEL}", 'wpse-85107' );
    $this->field_label  = __( "Choose {$this->SELECT_POST_LABEL}", 'wpse-85107' );
  }
  function add_meta_boxes() {
    add_meta_box(
      $this->box_id,
      $this->box_label,
      array( $this, 'select_box' ),
      $this->FOR_POST_TYPE,
      'side'
    );
  }
  function select_box( $post ) {
    $selected_post_id = get_post_meta( $post->ID, $this->meta_key, true );
    global $wp_post_types;
    $save_hierarchical = $wp_post_types[$this->SELECT_POST_TYPE]->hierarchical;
    $wp_post_types[$this->SELECT_POST_TYPE]->hierarchical = true;
    wp_dropdown_pages( array(
      'id' => $this->field_id,
      'name' => $this->field_name,
      'selected' => empty( $selected_post_id ) ? 0 : $selected_post_id,
      'post_type' => $this->SELECT_POST_TYPE,
      'show_option_none' => $this->field_label,
    ));
    $wp_post_types[$this->SELECT_POST_TYPE]->hierarchical = $save_hierarchical;
  }
  function save_post( $post_id, $post ) {
    if ( $post->post_type == $this->FOR_POST_TYPE && isset( $_POST[$this->field_name] ) ) {
      update_post_meta( $post_id, $this->meta_key, $_POST[$this->field_name] );
    }
  }
}
new WPSE_85107();

Je sais que vous vouliez que ce soit simple afin que vous puissiez le comprendre, mais c'est à peu près le strict minimum que vous souhaitez pour votre plugin, compte tenu de la fonctionnalité que vous demandez. Rien de moins et vous couperez la viande et non le gras.

Ce que je n’ai pas fait, c’est d’ajouter plusieurs fonctionnalités qui, à mon avis, sont vraiment indispensables si vous construisez un plugin que quelqu'un d'autre pourrait utiliser. Mais vous pouvez en savoir plus sur ces fonctionnalités ici .

4
MikeSchinkel

L'action save_post appellera votre fonction et lui enverra le $ post_id, et non pas $ data et $ postarr.

Votre fonction select_box_save_postdata doit accepter $ post_id comme seul paramètre:

add_action( 'save_post', 'select_box_save_postdata' );

function select_box_save_postdata( $post_id ) {
    $selected_item = null;

    // your form data is in the $_POST array
    if ( isset( $_POST['selected_item'] ) && $_POST['selected_item'] ) {
        $selected_item = $_POST['selected_item'];
    }

    // then use the $post_id to save your post meta
    update_post_meta( $post_id, '_selected_item', $selected_item );
}

Voir page codex pour save_post pour plus d’informations.

1
jevets