web-dev-qa-db-fra.com

Fonctions save_post en conflit lors du passage de l'ID de publication et de l'enregistrement de méta-boîtes personnalisées pour différents types de publication

Les fonctions de post-sauvegarde sont en conflit lors de leur ajout au hook d’action save_post.

2 types de publication personnalisés avec 2 méta-boîtes personnalisées différentes (une pour chaque type de publication).

J'inclus seulement le code pour l'une des boîtes à méta. L'autre est très similaire et chacun fonctionne bien séparément mais pas ensemble.

La fonction de rappel 'register_metabox_cb':

function c3m_video_meta() {
    add_meta_box('_c3m_video_embed', __('Enter Video Embed Code In the Box Below') , 'c3m_video_embed', 'video', 'normal', 'low');
    }

Ajouter la meta box à l’écran de post-édition:

function c3m_video_embed($post) {
    global $post;
    wp_nonce_field(__FILE__,'video_nonce');
    $embed-code = get_post_meta($post->ID, '_embed-code', true);
    echo '<input type="text" name="_embed-code" value=""' . $embed-code . '" class="widefat" />' ; 
    }

La fonction de sauvegarde:

  function c3m_save_video_meta( $post_id , $post ) { 

            if ( !wp_verify_nonce( $_POST [ 'video_nonce' ], __FILE__ ) ) { return $post ->ID; 
            }
            if ( !current_user_can( 'edit_post' , $post ->ID )) return $post ->ID; 
            $c3m_video_embed-code [ '_embed-code' ] = $_POST [ '_embed-code' ]; 
                        foreach ( $c3m_video_embed-code as $key => $value ) { 
                        if ( $post ->post_type == 'revision' ) return ; 

                        $value = implode( ',' , ( array ) $value );
                        if (get_post_meta( $post ->ID, $key , FALSE)) { 
                        update_post_meta( $post ->ID, $key , $value ); } else { 
                        add_post_meta( $post ->ID, $key , $value ); } if (! $value ) delete_post_meta( $post ->ID, $key ); 
                        }
}

Les crochets d'action:

add_action( 'admin_menu' , 'c3m_video_meta' );

add_action( 'save_post' , 'c3m_save_video_meta' , 1, 2);

C’est très bien et fonctionne bien, mais lorsque j’ajoute une autre méta-boîte à un type de message différent et que j’utilise une fonction similaire (nom de fonction, nom de clé et clé différents) lorsque le message est sauvegardé, j’obtiens cette erreur:

Avis: Index non défini: _embed-code dans /Applications/MAMP/htdocs/wordpress/wp-content/plugins/ieew-custom-functions/ieew-custom-functions.php à la ligne 181

Avertissement: impossible de modifier les informations d'en-tête - en-têtes déjà envoyés par (sortie démarrée à /Applications/MAMP/htdocs/wordpress/wp-content/plugins/ieew-custom-functions/ieew-custom-functions.php:181) dans/Applications/MAMP/htdocs/wordpress/wp-includes/pluggable.php à la ligne 897

Le _embed-code non défini est lors de l'enregistrement de la publication qui ne contient pas la variable _embed-code.

Comme les messages d'erreur sont inversés en fonction du type de message que j'essaie de sauvegarder, cela me porte à croire que les deux (2 différentes) fonctions de sauvegarde sont ajoutées à l'action save_post. Ils sont également ajoutés lors de la sauvegarde d'un message normal. Si je n'utilise que l'une des fonctions de sauvegarde, il n'y a pas d'erreur lors de la sauvegarde d'un message normal.

Plutôt que cette question étant une question "Corriger mon code" , je préférerais que la réponse contienne le comment et le pourquoi d'ajouter des méta-boîtes personnalisées et d'utiliser les différents nonce. méthodes. Bien sûr, je pourrais utiliser le plug-in More Fields, mais je préférerais connaître le meilleur moyen d'accomplir la personnalisation de l'écran de post-édition avec des types de contenu personnalisés.

J'ai utilisé ce même code et cette même méthode pour ajouter plusieurs méta-boîtes à un seul type d'article personnalisé et cela a toujours fonctionné correctement.

1
Chris_O

Après quelques recherches supplémentaires, j'ai constaté que:

  • Au lieu de relier la fonction add_meta_box à admin_menu, elle devrait être reliée à add_meta_boxes
  • Au lieu de la boucle foreach, utilisez la fonction update_post_meta dans la fonction de sauvegarde.
  • Au lieu d'utiliser le wp_nonce_field, les données peuvent être effacées à l'aide de esc_attr et strip_tags
  • Pour passer l'identifiant de publication à la fonction de sauvegarde de la méta-boîte, vous n'avez pas besoin d'inclure la variable supplémentaire $ post
  • Vous devez ajouter un état conditionnel pour le type de publication dans la fonction de sauvegarde.
  • Vous devez appeler global $post sur la fonction de sauvegarde

Le code nouveau et beaucoup plus simple pour ajouter les deux méta-boîtes:

add_action( 'add_meta_boxes', 'c3m_sponsor_meta' );

function c3m_sponsor_meta() {
    add_meta_box( 'c3m_sponsor_url', 'Sponsor URL Metabox', 'c3m_sponsor_url', 'sponsor', 'side', 'high' );
}

function c3m_sponsor_url( $post ) {
    $sponsor_url = get_post_meta( $post->ID, '_sponsor_url', true);
    echo 'Please enter the sponsors website link below';
    ?>
        <input type="text" name="sponsor_url" value="<?php echo esc_attr( $sponsor_url ); ?>" />
    <?php
}

add_action( 'save_post', 'c3m_save_sponsor_meta' );

function c3m_save_sponsor_meta( $post_id ) {
    global $post;
    if( $post->post_type == "sponsor" ) {
        if (isset( $_POST ) ) {
            update_post_meta( $post_ID, '_sponsor_url', strip_tags( $_POST['sponsor_url'] ) );
        }
    }
}

add_action( 'add_meta_boxes', 'c3m_video_meta' );        

function c3m_video_meta() {
    add_meta_box( 'c3m_video_embed_code', 'Video Embed Code Meta Box', 'c3m_video_embed_code', 'video', 'normal', 'high' );
}

function c3m_video_embed_code( $post ) {
    $embed_code = get_post_meta( $post->ID, '_embed_code', true);
    echo 'Please enter the video embed code below';
    ?>
        <input type="text" name="embed_code" value="<?php echo esc_attr( $embed_code ); ?>" />
    <?php
}

add_action( 'save_post', 'c3m_save_video_meta' );

function c3m_save_video_meta( $post_id ) {
    global $post;
    if( $post->post_type == "video" ) {
        if (isset( $_POST ) ) {
            update_post_meta( $post_ID, '_embed_code', strip_tags( $_POST['embed_code'] ) );
        }
    }
}
3
Chris_O

Au lieu d'utiliser wp_nonce_field, les données peuvent être nettoyées à l'aide de esc_attr et strip_tags

Je ne suis pas la logique d'échapper des données au lieu d'utiliser un nonce? L'exemple donné sur wordpress.org utilise un nonce pour vérifier l'intention et échappe également aux données avant de les insérer. comment ces deux choses sont-elles liées?

1
Milo

vous ne devriez pas avoir besoin de Global Post, vous pouvez certainement le passer dans la fonction.

j'avais 2 actions save_post différentes, une pour l'édition rapide et une pour une metabox sur le même type de message et je les ai combinées pour me débarrasser des notices d'index non définies concernant mes différents nonces comme les 2 éléments couvraient les mêmes données, j’utilisais le même nom non générateur.

de toute façon, je considérerais de combiner vos fonctions save_post dans 1 ... OR en vérifiant le type de message avant de vérifier le nonce.

add_action( 'save_post' , 'c3m_save_meta' , 20, 2); //moved priority to later. you had priority 1 so is possible that WP actions were happening after your code

function c3m_save_meta( $post_id , $post ) {   

   // verify if this is an auto save routine. If it is our form has not been submitted, so we dont want to do anything
   if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) return $post_id;

   //don't save if only a revision
   if ( $post->post_type == 'revision' ) return $post_id;   

   // Check permissions
   if ( 'page' == $post->post_type ) {
    if ( !current_user_can( 'edit_page', $post_id ) ) return $post_id;
   } else {
    if ( !current_user_can( 'edit_post', $post_id ) ) return $post_id;
   }      

  //save video post meta
  if( $post->post_type == "video" && wp_verify_nonce( $_POST [ 'video_nonce' ], __FILE__ )) {
     if (isset( $_POST['_embed_code'] ) ) {
        update_post_meta( $post_ID, '_embed_code', esc_attr( $_POST['embed_code'] ) );
     }
  }

  //save sample bacon post meta
   if( $post->post_type == "bacon" && wp_verify_nonce( $_POST [ 'bacon_nonce' ], __FILE__ )) {
      if (isset( $_POST['_bacon_code'] ) ) {
        update_post_meta( $post_ID, '_bacon_code', esc_attr( $_POST['bacon_code'] ) );
      }
   }
}

ou vous pouvez utiliser le même nom de nonce pour les deux métaboxes. Je ne peux pas commenter sur la sécurité de cette opération, mais cela me semble correct car WP semble faire la même chose avec _wpnonce dans les modes d'édition rapide et normal. WP ne semble pas non plus avoir un nonce distinct pour chaque metabox.

function c3m_save_meta( $post_id , $post ) {   
       if(!wp_verify_nonce( $_POST [ 'c3m_nonce' ], __FILE__ )) return $post_id; //change both nonces to name=c3m_nonce

       // verify if this is an auto save routine. If it is our form has not been submitted, so we dont want to do anything
       if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) return $post_id;  

       //don't save if only a revision
       if ( $post->post_type == 'revision' ) return $post_id; 

       // Check permissions
       if ( 'page' == $post->post_type ) {
        if ( !current_user_can( 'edit_page', $post_id ) ) return $post_id;
       } else {
        if ( !current_user_can( 'edit_post', $post_id ) ) return $post_id;
       }      

      //save video post meta
      if( $post->post_type == "video") {
         if (isset( $_POST['_embed_code'] ) ) {
            update_post_meta( $post_ID, '_embed_code', esc_attr( $_POST['embed_code'] ) );
         }
      }

      //save sample bacon post meta
       if( $post->post_type == "bacon" && wp_verify_nonce( $_POST [ 'bacon_nonce' ], __FILE__ )) {
          if (isset( $_POST['_bacon_code'] ) ) {
            update_post_meta( $post_ID, '_bacon_code', esc_attr( $_POST['bacon_code'] ) );
          }
       }
    }
1
helgatheviking