Rechercher

Ajouter des colonnes dans les listes de posts de l’admin de WordPress

Placeholder image
/* =============================================
===============. ADMIN COLUMN .=================
============================================= */
// Ajouter les colonnes "Statut" et "Slug" dans le tableau des articles
function ajouter_custom_colonnes_posts($columns) {
	$new_columns = array(
        'thumbnail'   => __('Miniature'),
    );
	$new_after_columns = array(
        'post_status' => __('Statut'),
        'post_slug'   => __('Slug'),
    );
    
    // Insérer les nouvelles colonnes au début du tableau
    return array_merge($new_columns, $columns, $new_after_columns);
}
add_filter('manage_posts_columns', 'ajouter_custom_colonnes_posts');
add_filter('manage_pages_columns', 'ajouter_custom_colonnes_posts');

// Afficher le contenu des colonnes "Statut" et "Slug"
function afficher_contenu_custom_colonnes($column, $post_id) {
    switch ($column) {
        case 'post_status':
			$color = "#000";
			if(get_post_status($post_id) == "publish") {
				$color = "green";
			}
			if(get_post_status($post_id) == "draft") {
				$color = "grey";
			}
            echo '<b style="color: '.$color.'">' . get_post_status($post_id) . '</b>';
            break;
        case 'post_slug':
            $post = get_post($post_id);
            echo $post->post_name;
            break;
        case 'thumbnail':
            $thumbnail = get_the_post_thumbnail($post_id, array(50, 50));
        	echo $thumbnail;
            break;
    }
}
add_action('manage_posts_custom_column', 'afficher_contenu_custom_colonnes', 10, 2);
add_action('manage_pages_custom_column', 'afficher_contenu_custom_colonnes', 10, 2);

Synchroniser deux champs ACF relationship

Placeholder image

Dans un projet WordPress, nous avions besoin d’utiliser deux types de contenu personnalisé (CPT) qui doivent être liés entre eux. L’objectif est d’établir une relation bidirectionnelle entre ces deux CPT. Cela signifie que lorsqu’un utilisateur associe un élément du premier CPT à un autre élément dans le second CPT via un champ de relation, cette association doit être répercutée dans l’autre sens.

Exemple :

  • Si tu as deux CPT : « Professeurs » et « Cours ».
  • Si tu associes un professeur à un cours, il faut que le cours soit aussi automatiquement lié au professeur.

Explication des parties importantes du code :

  1. Détection de l’enregistrement automatique : La première condition empêche l’exécution de la fonction lors d’une sauvegarde automatique pour éviter les mises à jour inutiles ou non souhaitées.
  2. Récupération du type de post : get_post_type($post_id) et get_the_terms($post_id, 'format') sont utilisés pour identifier le type de post et le format associé (si applicable).
  3. Premier bloc de synchronisation :
    • Si le post appartient au type custom_post_type_1 (nom générique), il récupère les relations stockées dans related_field_1 (premier champ relationnel).
    • Pour chaque relation, il vérifie si le post lié a bien l’ID du post actuel dans son propre champ relationnel (related_field_2).
    • Si ce n’est pas le cas, il ajoute cette relation et met à jour le champ avec update_field().
  4. Deuxième bloc de synchronisation :
    • Ce bloc fait exactement la même chose, mais dans l’autre sens : s’il s’agit d’un post de type custom_post_type_2, il synchronise les relations du champ related_field_2 avec related_field_1 dans le post lié.
  5. Attachement au hook acf/save_post : La fonction est exécutée à chaque fois qu’un post est sauvegardé via ACF, en utilisant le hook avec une priorité de 20 pour s’assurer que cela se passe après les autres opérations.

Noms génériques :

  • custom_post_type_1 et custom_post_type_2 représentent les deux types de contenu personnalisé (CPT).
  • related_field_1 et related_field_2 représentent les champs de relation entre ces deux types de CPT.
function sync_acf_relationship_fields($post_id) {
  // Empêcher l'exécution du code pendant une sauvegarde automatique
  if (is_admin() && defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
    return;
  }

  // Récupérer le type de contenu personnalisé (CPT) du post actuel
  $post_type = get_post_type($post_id);

  // Récupérer les termes associés à la taxonomie 'format' du post actuel
  $post_format = get_the_terms($post_id, 'format');

  // Vérifier si le post appartient au premier type de CPT ('cpt_slug')
  // et que le format correspond (si applicable)
  if ($post_type == 'custom_post_type_1' && $post_format[0]->slug == 'format_slug') {
    // Récupérer les relations à synchroniser pour le premier champ personnalisé
    $related_posts_1 = get_field('related_field_1', $post_id);
    
    if ($related_posts_1) {
      // Parcourir chaque relation pour les synchroniser dans l'autre sens
      foreach ($related_posts_1 as $related_post_id) {
        // Récupérer les relations existantes dans le second champ du post lié
        $existing_related_posts = get_field('related_field_2', $related_post_id);
        if (!$existing_related_posts) {
          $existing_related_posts = array(); // Initialiser si vide
        }

        // Si le post actuel n'est pas déjà dans les relations, l'ajouter
        if (!in_array($post_id, $existing_related_posts)) {
          $existing_related_posts[] = $post_id;
          // Mettre à jour le champ relationnel dans le post lié
          update_field('related_field_2', $existing_related_posts, $related_post_id);
        }
      }
    }
  }

  // Vérifier si le post appartient au second type de CPT ('cpt_slug_2')
  if ($post_type == 'custom_post_type_2') {
    // Récupérer les relations à synchroniser pour le second champ personnalisé
    $related_posts_2 = get_field('related_field_2', $post_id);

    if ($related_posts_2) {
      // Parcourir chaque relation pour les synchroniser dans l'autre sens
      foreach ($related_posts_2 as $related_post_id) {
        // Récupérer les relations existantes dans le premier champ du post lié
        $existing_related_posts = get_field('related_field_1', $related_post_id);
        if (!$existing_related_posts) {
          $existing_related_posts = array(); // Initialiser si vide
        }

        // Si le post actuel n'est pas déjà dans les relations, l'ajouter
        if (!in_array($post_id, $existing_related_posts)) {
          $existing_related_posts[] = $post_id;
          // Mettre à jour le champ relationnel dans le post lié
          update_field('related_field_1', $existing_related_posts, $related_post_id);
        }
      }
    }
  }
}

// Attacher la fonction à l'action 'acf/save_post' pour synchroniser après la sauvegarde d'un post
add_action('acf/save_post', 'sync_acf_relationship_fields', 20);

Authoriser les SVG dans les champs ACF

Placeholder image
/**
 * ACF SVG filter to allow raw SVG code.
 * 
 * https://www.advancedcustomfields.com/resources/html-escaping/
 * 
 */
add_filter( 'wp_kses_allowed_html', 'acf_add_allowed_svg_tag', 10, 2 );

function acf_add_allowed_svg_tag( $tags, $context ) {
    if ( $context === 'acf' ) {
      $tags['svg']  = array(
          'xmlns'				=> true,
          'width'				=> true,
          'height'				=> true,
          'preserveAspectRatio'	=> true,
          'fill'					=> true,
          'viewbox'			=> true,
          'role'				=> true,
          'aria-hidden'			=> true,
          'focusable'			=> true,
      );
      $tags['path'] = array(
          'd'    => true,
          'fill' => true,
      );
    }
    return $tags;
}

Selectionnez automatiquement une option de variation si elle est la seule disponible dans un produit Woocommerce

Placeholder image

Ce script permet de selectionner automatiquement une option de variation d’un produit dans woocommerce si elle est la seule disponible. Par exemple, si vous choisissez un t-shirt en S et que la seule couleur disponible pour cette taille est bleu, cette option sera automatiquement selectionnée.



add_action( 'wp_footer', 'auto_select_variation_option' );
function auto_select_variation_option() {
    if ( ! is_product() ) {
        return;
    }
    ?>
    <script type="text/javascript">
        jQuery(document).ready(function($){

            // Fonction pour sélectionner automatiquement l'attribut avec une seule option disponible
            function autoSelectSingleOption() {
                var changeTriggered = false; // Drapeau pour suivre si un changement a été déclenché

                $('.variations_form .variations select').each(function(){
                    if (changeTriggered) {
                        return false; // Sortir de la boucle si un changement a été déclenché
                    }

                    var select = $(this);
                    var selectedVal = select.val(); // Vérifier si une valeur est déjà sélectionnée
                    var options = select.find('option').not(':disabled'); // Obtenir les options disponibles

                    // Vérifier s'il n'y a qu'une seule option sélectionnable et aucune sélection faite
                    if (options.length === 2 && !selectedVal) { 
                        var optionToSelect = options.last().val(); // La seule option disponible

                        // Vérifier si cette option est déjà sélectionnée
                        if (select.val() !== optionToSelect) {
                            select.val(optionToSelect).trigger('change'); // Sélectionner et déclencher WooCommerce
                            changeTriggered = true; // Marquer qu'un changement a été déclenché
                        }
                    }
                });
            }

            // Lorsque la page est chargée et que la sélection change, on vérifie si une sélection automatique doit être faite
            $('.variations_form').on('woocommerce_variation_select_change', function() {
                if (!$('.variations_form').hasClass('processing')) { // Éviter de lancer si Ajax est déjà en cours
                    setTimeout(() => {
                      autoSelectSingleOption(); // Exécuter lors du changement de variation
                    }, 160);
                }
            });

        });
    </script>
    <?php
}

Ajouter un style pour l’editeur interne Gutenberg

Placeholder image

Pour designer les blocks dans l’admin aussi !

function mytheme_enqueue_block_editor_assets() {
    // Charger le fichier CSS personnalisé dans l'éditeur Gutenberg
    wp_enqueue_style(
        'mytheme-editor-styles', // Nom du handle
        get_theme_file_uri('/editor-style.css'), // Chemin vers le fichier CSS
        false, // Pas de dépendances
        '1.0', // Version du fichier
        'all' // Media
    );
}
add_action('enqueue_block_editor_assets', 'mytheme_enqueue_block_editor_assets');
// Custom style Editor only
function custom_gutenberg_editor_style() {
    echo '<style>
        .interface-complementary-area__fill,
        .interface-complementary-area__fill > div {
            width: 480px !important;
            min-width: 480px;
        }
    </style>';
}
add_action('admin_head', 'custom_gutenberg_editor_style');

Ajouter un style par défault à un bloc Gutenberg existant

Placeholder image
function mytheme_register_block_styles() {
    // Ajouter un style personnalisé "not" au bloc Groupe
    register_block_style(
        'core/group',
        array(
            'name'  => 'note',
            'label' => __('Note Style', 'mytheme'),
            'isDefault' => false, // Optionnel : false pour ne pas le définir comme style par défaut
        )
    );
}
add_action('init', 'mytheme_register_block_styles');
.wp-block-group.is-style-note {
    background-color: #f0f0f0;
    border: 2px dashed #ff0000;
    padding: 20px;
    color: #333;
}

Dates en français en PHP

Placeholder image

C’est juste compliqué, donc voilà la version courte.

Pour plus de formats : Formatting Dates and Times | ICU Documentation (unicode-org.github.io)

$date = new DateTime($time[0]['start']['date']);

// Créer le format de date avec le fuseau horaire français
$fmt = datefmt_create(
  'fr_FR',
  IntlDateFormatter::FULL, // Style complet (lundi 25 septembre 2023)
  IntlDateFormatter::FULL,
  'Europe/Paris', // Utilisation du fuseau horaire français
  IntlDateFormatter::GREGORIAN,
  'd MMMM yyyy' // Format : jour mois année (par exemple : 25 septembre 2023)
);

// Affichage de la date formatée
echo datefmt_format($fmt, $date);

Changer le nombre de produits affichés sur les pages Woocommerce

Placeholder image

Décoréller le nombre de posts à afficher par page pour avoir un nombre de produits par page sur Woocommerce.

add_filter( 'loop_shop_per_page', 'new_loop_shop_per_page', 20 );
function new_loop_shop_per_page( $cols ) {
  // $cols contains the current number of products per page based on the value stored on Options -> Reading
  // Return the number of products you wanna show per page.
  $cols = 9;

return $cols;
}

CPT : labels

Placeholder image

On utilise le générateur : Generate WordPress Post Type (generatewp.com)

Pour éviter à avoir à réécrire tous les labels en FR, voici la variable « args » avec les labels + notre domain (pour les trads) :

$labels = array(
  'name'                  => _x( 'FAQs', 'Post Type General Name', 'mahiiro' ),
  'singular_name'         => _x( 'FAQ', 'Post Type Singular Name', 'mahiiro' ),
  'menu_name'             => __( 'FAQs', 'mahiiro' ),
  'name_admin_bar'        => __( 'FAQs', 'mahiiro' ),
  'archives'              => __( 'Archives', 'mahiiro' ),
  'attributes'            => __( 'Attributs', 'mahiiro' ),
  'parent_item_colon'     => __( 'Parents', 'mahiiro' ),
  'all_items'             => __( 'Tous', 'mahiiro' ),
  'add_new_item'          => __( 'Ajouter', 'mahiiro' ),
  'add_new'               => __( 'Ajouter', 'mahiiro' ),
  'new_item'              => __( 'Nouveau', 'mahiiro' ),
  'edit_item'             => __( 'Editer', 'mahiiro' ),
  'update_item'           => __( 'Mettre à jour', 'mahiiro' ),
  'view_item'             => __( 'Voir', 'mahiiro' ),
  'view_items'            => __( 'Voir', 'mahiiro' ),
  'search_items'          => __( 'Chercher', 'mahiiro' ),
  'not_found'             => __( 'Non trouvé', 'mahiiro' ),
  'not_found_in_trash'    => __( 'Non trouvé dans la corbeille', 'mahiiro' ),
  'featured_image'        => __( 'Image à la une', 'mahiiro' ),
  'set_featured_image'    => __( 'Choisir l\'image à la UNE', 'mahiiro' ),
  'remove_featured_image' => __( 'Retirer l\'image à a une', 'mahiiro' ),
  'use_featured_image'    => __( 'Utiliser l\'image à la une', 'mahiiro' ),
  'insert_into_item'      => __( 'Insérer dans l\'élément', 'mahiiro' ),
  'uploaded_to_this_item' => __( 'Chargé dans l\'élément', 'mahiiro' ),
  'items_list'            => __( 'Liste d\'éléments', 'mahiiro' ),
  'items_list_navigation' => __( 'Items list navigation', 'mahiiro' ),
  'filter_items_list'     => __( 'Filter items list', 'mahiiro' ),
);

Custom taxonomie : labels

Placeholder image

On utilise le générateur : Generate WordPress Taxonomy (generatewp.com)

Pour éviter à avoir à réécrire tous les labels en FR, voici la variable « args » avec les labels + notre domain (pour les trads) :

$labels = array(
  'name'                       => _x( 'Catégories (faq)', 'Taxonomy General Name', 'mahiiro' ),
  'singular_name'              => _x( 'Catégorie (faq)', 'Taxonomy Singular Name', 'mahiiro' ),
  'menu_name'                  => __( 'Catégorie', 'mahiiro' ),
  'all_items'                  => __( 'Tous', 'mahiiro' ),
  'parent_item'                => __( 'Elément parent', 'mahiiro' ),
  'parent_item_colon'          => __( 'Elément parent:', 'mahiiro' ),
  'new_item_name'              => __( 'Nouveau', 'mahiiro' ),
  'add_new_item'               => __( 'Ajouter', 'mahiiro' ),
  'edit_item'                  => __( 'Editer', 'mahiiro' ),
  'update_item'                => __( 'Mettre à jour', 'mahiiro' ),
  'view_item'                  => __( 'Voir', 'mahiiro' ),
  'separate_items_with_commas' => __( 'Séparer par des virgules', 'mahiiro' ),
  'add_or_remove_items'        => __( 'Ajouter ou supprimer des éléments', 'mahiiro' ),
  'choose_from_most_used'      => __( 'Choisir le plus utilisé', 'mahiiro' ),
  'popular_items'              => __( 'Eléments populaires', 'mahiiro' ),
  'search_items'               => __( 'Chercher', 'mahiiro' ),
  'not_found'                  => __( 'Non trouvé', 'mahiiro' ),
  'no_terms'                   => __( 'Pas d\'éléments', 'mahiiro' ),
  'items_list'                 => __( 'Liste d\'éléments', 'mahiiro' ),
  'items_list_navigation'      => __( 'Items list navigation', 'mahiiro' ),
);