web-dev-qa-db-fra.com

Passer tous les champs personnalisés à travers le même filtre lors du post-chargement?

Existe-t-il un moyen de filtrer tous les champs personnalisés d'une publication?

Supposons pour une simplicité très élémentaire que j'ai:

champs standard de:

  • titre
  • corps de poste

les champs personnalisés:

  • auteur
  • ISBN
  • citation

Supposons au chargement de la page que je veux ajouter 123456 à la fin de chaque valeur de champs personnalisés, mais que je souhaite le faire avec un filtre. Quel add_filter pourrait accomplir cela? Un petit texte de code serait utile.

Modifiez selon la réponse actuelle:

Après avoir travaillé sur la première réponse, je me suis heurté à un problème qui ne fonctionnerait que sur le premier champ. J'ai alors réalisé que je devais passer en revue chaque élément et c'est ce que j'ai. Ce qui est étrange, c’est que les données semblent intactes, mais la page n’affiche pas les nouvelles données. J'ai des commentaires dans mon code ci-dessous:

function my_post_meta_filters($null, $post_id, $key, $single){
    if(is_admin() || (substr($key, 0, 8) != '_author_' && substr($key, 0, 7) != '_quote_')){
        return $null;
    }

    static $filtered_values = NULL;

    if(is_null($filtered_values)){
        $cache = update_postmeta_cache(array($post_id));
        $values = $cache[$post_id];

        //must loop through all the fields or else only the first field is affected
        foreach($values AS $valkey => $value){                                   
            if(substr($key, 0, 8) == '_author_' || substr($key, 0, 7) == '_quote_'){
                $filtered[$valkey] = filtered($values[$valkey][0]);
                $filtered[$valkey] = maybe_serialize($filtered[$valkey]); //at this point the data is correct and even reserialized where expected
                $filtered_values[$valkey] = $filtered[$valkey];
            }
        }
        return $filtered_values;
    }
}
add_filter('get_post_metadata', 'my_post_meta_filters', 0, 4);

function filtered($it){
    if(!is_array($it) && !is_serialized($it)){
        $filtered = apply_filters('number_filter', $it); //adds numbers to the end
    } else {       
        //otherwise we ran into a serialized array so lets unserialize and run each part through our function
        $unserialized = maybe_unserialize($it);
        $filtered = array_map('filtered', $unserialized);
    }

    return $filtered;
}
5
Shawn

En interne, les méta sont gérés via un cache d’objets difficilement filtrable.

La seule possibilité de filtrer les métadonnées de publication consiste à utiliser le 'get_post_metadata' , mais ce filtre est déclenché lorsque les métadonnées ne sont pas disponibles. Il n'y a donc rien à filtrer. il était destiné à court-circuiter le résultat plus qu'à le filtrer.

La solution que je propose est donc:

  1. lance une fonction qui s'exécute sur ce filtre et manuellement récupère les métadonnées
  2. après la récupération, déclencher un filtre personnalisé pour pouvoir filtrer les données qui viennent d'être récupérées
  3. stocker la valeur ainsi filtrée dans une variable statique, pour éviter d'exécuter à nouveau la requête de la base de données lors d'appels suivants
  4. enfin, ajoutez un rappel à notre hook personnalisé (ajouté au point 2) et filtrez les données

Alors, commencez par ajouter le filtre:

add_filter( 'get_post_metadata', 'my_post_meta_filters', 0, 4 );

Puis écrivez le rappel de hooking

function my_post_meta_filters( $null, $pid, $key, $single ) {
  if ( ! in_array( $key, array( 'author', 'ISBN', 'quote', '' ), TRUE ) || is_admin() ) {
    return $null;
  };
  static $filtered_values = NULL;
  if ( is_null( $filtered_values ) ) {
    $cache = update_meta_cache( 'post', array( $pid ) );
    $values = $cache[$pid];
    $raw = array(
      'author' => isset( $values['author'] ) ? $values['author'] : NULL,
      'ISBN'   => isset( $values['ISBN'] )   ? $values['ISBN']   : NULL,
      'quote'  => isset( $values['quote'] )  ? $values['quote']  : NULL,
    );
    // this is the filter you'll use to filter your values
    $filtered = (array) apply_filters( 'my_post_meta_values', $raw, $pid );
    foreach ( array( 'author', 'ISBN', 'quote' ) as $k ) {
      if ( isset( $filtered[$k] ) ) $values[$k] = $filtered[$k];
    }
    $filtered_values = $values;
  }
  if ( $key === '' )
     $filtered_values;
  if ( ! isset( $filtered_values[$key] ) )
     return;
  return $single
    ? maybe_unserialize( $filtered_values[$key][0] )
    : array_map( 'maybe_unserialize', $filtered_values[$key] );
}

En ayant cette fonction dans votre code, vous pourrez filtrer vos champs personnalisés à l'aide du filtre personnalisé 'my_post_meta_values'.

Juste un exemple:

add_filter( 'my_post_meta_values', function( $values, $post_id ) {

  // append '123456' to all values

  if ( is_array( $values['author'] ) ) {
    $values['author'][0] .= ' 123456';
  }
  if ( is_array( $values['ISBN'] ) ) {
    $values['ISBN'][0] .= ' 123456';
  }
  if ( is_array( $values['quote'] ) ) {
    $values['quote'][0] .= ' 123456';
  }

  return $values;

}, 10, 2 );

Avec ce filtre actif, si vous le faites:

echo get_post_meta( $post_id, 'author', TRUE );

et votre champ personnalisé "auteur" est défini sur "Shawn" alors que le résultat est "Shawn 123456".

Notez que my_post_meta_filters est également compatible avec get_post_custom sans effort supplémentaire.

2
gmazzap