web-dev-qa-db-fra.com

flush_rewrite_rules sur save_post ne fonctionne pas sur le premier post

Je développe un plugin pour mon propre développement rapide qui crée un type de publication personnalisé. La "liste" de ce type de message est affichée sur une page spécifique créée et gérée par le plug-in. Cette page peut être placée n'importe où dans la hiérarchie des pages du site. Par conséquent, le slug des publications individuelles doit être mis à jour si l'administrateur du site modifie l'emplacement de la page.

Lors de la création du type de publication pendant la init, j'accomplis cette tâche en affectant les règles de réécriture suivantes au type de publication personnalisé (code ajusté pour des raisons de brièveté):

$post_type_slug = "/" . get_page_uri( $page_id );
register_post_type( 'post_type_name',
        ... 
        'rewrite'   => array( 'slug' => $post_type_slug, 'with_front' => true),
        ...
      )
);  

Cela semble fonctionner parfaitement pour tout mettre en place au départ. Lorsque l'utilisateur enregistre la page 'liste', j'exécute le code suivant pour mettre à jour les règles de réécriture:

add_action( 'save_post', array(__CLASS__, 'flush_permalinks'), 2000 );
function flush_permalinks( $post_id ) {
  if($post_id == get_option( $custom_page_id )){
    flush_rewrite_rules(false);
  }
}

Toutefois, lorsque l'utilisateur modifie l'emplacement de la page, les permaliens nouvellement mis à jour renvoient 404 (même si la page de liste affiche les liens correctement). Mais si je sauvegarde la page une seconde fois, cela fonctionne parfaitement! J'ai tenté de modifier la priorité de l'action save_post (de 1 à 2000), mais cela ne semble pas en changer le sens. J'ai également essayé de supprimer les règles de réécriture, à la fois brutalement et en douceur, mais cela ne modifie pas le comportement de deux sauvegardes (la première sauvegarde ne modifie pas les règles de réécriture, mais le second le fait).

Des suggestions sur ce que je pourrais faire mal?

3
Eric K

Je sais que cela a déjà été répondu, mais j’ai eu l’impression que la solution réelle n’était pas claire à 100%.

Voici ma réponse pour ajouter quelques précisions.

Il a raison ... Vous ne pouvez pas vider les règles de réécriture sur save_post, car ce crochet d'action est activé APRÈS que le crochet d'action init ait été activé.

Comme vous le savez, les types de poste et les taxonomies sont enregistrés sur le crochet init.

TLDR; Vous ne pouvez pas flush_rewrite_rules(); sur le hook d'action save_post.

Il y a une solution de contournement ...

Vous devez définir une valeur d'option sur 1 sur le crochet d'action save_post. Puis cochez cette option pour la valeur 1 et effacez les règles de réécriture sur le crochet d’action init.

Exemple:

function mbe_late_init_example() {

    if ( ! $option = get_option( 'my-plugin-flush-rewrite-rules' ) ) {
        return false;
    }

    if ( $option == 1 ) {

        flush_rewrite_rules();
        update_option( 'my-plugin-flush-rewrite-rules', 0 );

    }

    return true;

}

add_action( 'init', 'mbe_late_init_example', 999999 );


function mbe_save_post_example( Int $post_id = null, \WP_Post $post_object = null ) {

    if ( ! $post_id || ! $post_object ) {
        return false;
    }

    # Specific Post Type
    if ( $post_object->post_type != 'my-plugin-settings' ) {
        return false;
    }

    # Specific Post Object (OPTIONAL)
    if ( $post_object->post_name != 'general-settings' ) {
        return false;
    }

    update_option( 'my-plugin-flush-rewrite-rules', 1 );

    return true;

}

add_action( 'save_post', 'mbe_save_post_example', 10, 2 );
3
Michael Ecklund

J'ai pu résoudre ce problème. Il semblerait que l'action 'save_post' se produise avant la init qui enregistre le type de publication personnalisé. Par conséquent, le slug de réécriture du type d'article n'est pas mis à jour avant la demande à flush_rewrite_rules, ce qui entraîne essentiellement l'absence de mise à jour. Cela explique également pourquoi cela fonctionne si la publication est enregistrée une seconde fois, car le type de publication a une chance de mettre à jour ses règles de réécriture.

Par conséquent, je le résous en modifiant mon code en tant que tel:

add_action( 'save_post', array(__CLASS__, 'flush_permalinks'));
function flush_permalinks( $post_id ) { 
  if($post_id == get_option( $custom_page_id )){
    update_option( 'unique_page_updated_key', 'true');
  }
}

J'ai ensuite ajouté ce qui suit juste en dessous de mon code register_post_type:

if((bool)get_option( 'unique_page_updated_key' )){
  flush_rewrite_rules(); 
  update_option( 'unique_page_updated_key', 'false');
}

Cela empêche les règles de réécriture d'être vidées sur chaque init.

1
Eric K