start_controls_section( 'section_content', [ 'label' => esc_html__('Catégories', 'category-grid-widget'), 'tab' => \Elementor\Controls_Manager::TAB_CONTENT, ] ); // Contrôle : Sélection des catégories à afficher (multisélection). $options = []; $categories = get_categories(['hide_empty' => false]); foreach ($categories as $cat) { $options[$cat->term_id] = $cat->name; } $this->add_control( 'categories', [ 'label' => esc_html__('Catégories à afficher', 'category-grid-widget'), 'type' => \Elementor\Controls_Manager::SELECT2, 'multiple' => true, 'label_block' => true, 'options' => $options, 'description' => esc_html__('Sélectionnez les catégories d’articles à afficher.', 'category-grid-widget'), ] ); // Contrôle : Inclure les sous-catégories. $this->add_control( 'show_subcategories', [ 'label' => esc_html__('Afficher les sous-catégories', 'category-grid-widget'), 'type' => \Elementor\Controls_Manager::SWITCHER, 'label_on' => esc_html__('Oui', 'category-grid-widget'), 'label_off' => esc_html__('Non', 'category-grid-widget'), 'return_value' => 'yes', 'default' => 'yes', 'description' => esc_html__('Inclure aussi les sous-catégories des catégories sélectionnées.', 'category-grid-widget'), ] ); // ---------------------------------------------------------------------- // Contrôle : Ne montrer que les catégories avec image $this->add_control( 'hide_without_image', [ 'label' => esc_html__('Afficher uniquement catégories avec image', 'category-grid-widget'), 'type' => \Elementor\Controls_Manager::SWITCHER, 'label_on' => esc_html__('Oui', 'category-grid-widget'), 'label_off' => esc_html__('Non', 'category-grid-widget'), 'return_value' => 'yes', 'default' => 'no', 'description' => esc_html__('Si activé, les catégories sans image seront masquées.', 'category-grid-widget'), ] ); // Contrôle : Trier par (critère de tri des catégories). $this->add_control( 'order_by', [ 'label' => esc_html__('Trier par', 'category-grid-widget'), 'type' => \Elementor\Controls_Manager::SELECT, 'options' => [ 'name' => esc_html__('Nom (alphabétique)', 'category-grid-widget'), 'count' => esc_html__('Nombre d’articles', 'category-grid-widget'), 'id' => esc_html__('ID (date de création)', 'category-grid-widget'), ], 'default' => 'name', ] ); // Contrôle : Ordre croissant/décroissant. $this->add_control( 'order', [ 'label' => esc_html__('Ordre', 'category-grid-widget'), 'type' => \Elementor\Controls_Manager::SELECT, 'options' => [ 'ASC' => esc_html__('Croissant (A-Z / 0-9)', 'category-grid-widget'), 'DESC' => esc_html__('Décroissant (Z-A / 9-0)', 'category-grid-widget'), ], 'default' => 'ASC', ] ); $this->end_controls_section(); /* Section "Mise en page" pour les options d'affichage (colonnes, taille d'image) */ $this->start_controls_section( 'section_layout', [ 'label' => esc_html__('Mise en page', 'category-grid-widget'), 'tab' => \Elementor\Controls_Manager::TAB_CONTENT, ] ); // Contrôle : Nombre de colonnes de la grille. $this->add_control( 'columns', [ 'label' => esc_html__('Nombre de colonnes', 'category-grid-widget'), 'type' => \Elementor\Controls_Manager::SELECT, 'options' => [ 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', ], 'default' => 3, ] ); // Contrôle : Taille des images affichées. $this->add_control( 'image_size', [ 'label' => esc_html__('Taille des images', 'category-grid-widget'), 'type' => \Elementor\Controls_Manager::SELECT, 'options' => [ 'thumbnail' => esc_html__('Miniature (thumbnail)', 'category-grid-widget'), 'medium' => esc_html__('Moyen (medium)', 'category-grid-widget'), 'large' => esc_html__('Grand (large)', 'category-grid-widget'), 'full' => esc_html__('Plein (full)', 'category-grid-widget'), ], 'default' => 'medium', ] ); $this->end_controls_section(); } /** * Générer l'affichage du widget côté front-end. */ protected function render(): void { $settings = $this->get_settings_for_display(); // Récupérer les ID des catégories sélectionnées. $selected_ids = []; if (!empty($settings['categories'])) { // S'assurer d'avoir un tableau d'ID (entiers). $selected_ids = is_array($settings['categories']) ? $settings['categories'] : [$settings['categories']]; $selected_ids = array_map('intval', $selected_ids); } if (empty($selected_ids)) { // Aucune catégorie sélectionnée : ne rien afficher. return; } // Déterminer les catégories à afficher (inclure les sous-catégories si demandé). $category_ids_to_show = $selected_ids; if (!empty($settings['show_subcategories']) && $settings['show_subcategories'] === 'yes') { // Ajouter les sous-catégories de chaque catégorie sélectionnée. foreach ($selected_ids as $cat_id) { $child_ids = get_term_children($cat_id, 'category'); if (is_array($child_ids) && !empty($child_ids)) { $category_ids_to_show = array_merge($category_ids_to_show, $child_ids); } } // Éliminer les doublons d'ID au cas où. $category_ids_to_show = array_unique($category_ids_to_show); } // Préparer les args pour get_terms() – on ne précise PAS le tri si c'est par count $term_args = [ 'taxonomy' => 'category', 'include' => $category_ids_to_show, 'hide_empty' => false, ]; if ('count' !== $settings['order_by']) { // tri natif pour 'name' ou 'id' $term_args['orderby'] = $settings['order_by']; $term_args['order'] = $settings['order']; } // Récupérer les termes $raw_terms = get_terms($term_args); if (is_wp_error($raw_terms) || empty($raw_terms)) { return; } // Filtrer les termes sans image si demandé $terms = []; foreach ($raw_terms as $term) { $thumb_id = get_term_meta($term->term_id, 'thumbnail_id', true); $image_url = $thumb_id ? wp_get_attachment_image_url($thumb_id, $settings['image_size']) : ''; if ('yes' === $settings['hide_without_image'] && empty($image_url)) { continue; } // Stocker image_url temporaire pour éviter de recalculer $term->_image_url = $image_url; $terms[] = $term; } // Si tri par nombre d'articles, calculer et trier manuellement if ('count' === $settings['order_by']) { // Calcul du total d'articles (directs + descendants) pour chaque terme $counts = []; foreach ($terms as $term) { $total = (int) $term->count; $desc_ids = get_term_children($term->term_id, 'category'); if (is_array($desc_ids)) { foreach ($desc_ids as $desc_id) { $desc = get_term($desc_id, 'category'); if (!is_wp_error($desc)) { $total += (int) $desc->count; } } } $counts[$term->term_id] = $total; } // Tri selon l’ordre choisi usort($terms, function ($a, $b) use ($counts, $settings) { $ca = $counts[$a->term_id]; $cb = $counts[$b->term_id]; if ($ca === $cb) { return 0; } if ('ASC' === $settings['order']) { return ($ca < $cb) ? -1 : 1; } return ($ca > $cb) ? -1 : 1; }); } // Calcul de la classe grille $columns = (int) $settings['columns']; $grid_class = 'columns-' . $columns; // Rendu HTML echo '
'; foreach ($terms as $term) { $name = esc_html($term->name); $link = esc_url(get_term_link($term)); $image_url = esc_url($term->_image_url); echo '
'; echo ""; if ($image_url) { echo '
'; echo '' . $name . ''; echo '
'; } echo '
' . $name . '
'; echo '
'; echo '
'; } echo '
'; } }