diff --git a/css/style.css b/css/style.css index 2f7fb0e..75aaef4 100644 --- a/css/style.css +++ b/css/style.css @@ -57,7 +57,7 @@ text-align: center; color: #ffffff; /* background: rgba(0, 0, 0, 0.4); */ - border-radius: 4px; + /* border-radius: 4px; */ transition: background .3s ease; } diff --git a/elementor-category-grid-widget.php b/elementor-category-grid-widget.php index b77cf1e..86a96ea 100644 --- a/elementor-category-grid-widget.php +++ b/elementor-category-grid-widget.php @@ -2,7 +2,7 @@ /** * Plugin Name: Elementor Category Grid Widget * Description: Custom Elementor widget to display a grid of post categories with images. - * Version: 1.1.0 + * Version: 1.2.0 * Author: MrRaph_ * Text Domain: category-grid-widget * Requires Plugins: elementor @@ -36,7 +36,7 @@ function ccgw_enqueue_media_uploader( $hook_suffix ) { 'ccgw-category-image', plugin_dir_url( __FILE__ ) . 'admin/js/category-image.js', [ 'jquery' ], - '1.0', + '1.2.0', true ); @@ -172,7 +172,7 @@ function ccgw_enqueue_front_styles() { 'ccgw-category-grid-style', plugin_dir_url( __FILE__ ) . 'css/style.css', [], - '1.0.0' + '1.2.0' ); } } diff --git a/widgets/category-grid-widget.php b/widgets/category-grid-widget.php index df5326c..16679d0 100644 --- a/widgets/category-grid-widget.php +++ b/widgets/category-grid-widget.php @@ -1,5 +1,5 @@ start_controls_section( 'section_content', [ - 'label' => esc_html__( 'Catégories', 'category-grid-widget' ), - 'tab' => \Elementor\Controls_Manager::TAB_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; + $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' => 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' ), + 'options' => $options, + 'description' => esc_html__('Sélectionnez les catégories d’articles à afficher.', 'category-grid-widget'), ] ); @@ -91,13 +98,13 @@ class Elementor_Category_Grid_Widget extends \Elementor\Widget_Base { $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' ), + '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' ), + 'default' => 'yes', + 'description' => esc_html__('Inclure aussi les sous-catégories des catégories sélectionnées.', 'category-grid-widget'), ] ); @@ -106,13 +113,13 @@ class Elementor_Category_Grid_Widget extends \Elementor\Widget_Base { $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' ), + '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' ), + 'default' => 'no', + 'description' => esc_html__('Si activé, les catégories sans image seront masquées.', 'category-grid-widget'), ] ); @@ -120,12 +127,12 @@ class Elementor_Category_Grid_Widget extends \Elementor\Widget_Base { $this->add_control( 'order_by', [ - 'label' => esc_html__( 'Trier par', 'category-grid-widget' ), - 'type' => \Elementor\Controls_Manager::SELECT, + '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' ), + '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', ] @@ -135,11 +142,11 @@ class Elementor_Category_Grid_Widget extends \Elementor\Widget_Base { $this->add_control( 'order', [ - 'label' => esc_html__( 'Ordre', 'category-grid-widget' ), - 'type' => \Elementor\Controls_Manager::SELECT, + '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' ), + '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', ] @@ -151,8 +158,8 @@ class Elementor_Category_Grid_Widget extends \Elementor\Widget_Base { $this->start_controls_section( 'section_layout', [ - 'label' => esc_html__( 'Mise en page', 'category-grid-widget' ), - 'tab' => \Elementor\Controls_Manager::TAB_CONTENT, + 'label' => esc_html__('Mise en page', 'category-grid-widget'), + 'tab' => \Elementor\Controls_Manager::TAB_CONTENT, ] ); @@ -160,8 +167,8 @@ class Elementor_Category_Grid_Widget extends \Elementor\Widget_Base { $this->add_control( 'columns', [ - 'label' => esc_html__( 'Nombre de colonnes', 'category-grid-widget' ), - 'type' => \Elementor\Controls_Manager::SELECT, + 'label' => esc_html__('Nombre de colonnes', 'category-grid-widget'), + 'type' => \Elementor\Controls_Manager::SELECT, 'options' => [ 1 => '1', 2 => '2', @@ -178,13 +185,13 @@ class Elementor_Category_Grid_Widget extends \Elementor\Widget_Base { $this->add_control( 'image_size', [ - 'label' => esc_html__( 'Taille des images', 'category-grid-widget' ), - 'type' => \Elementor\Controls_Manager::SELECT, + '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' ), + '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', ] @@ -196,97 +203,125 @@ class Elementor_Category_Grid_Widget extends \Elementor\Widget_Base { /** * Générer l'affichage du widget côté front-end. */ - protected function render(): void { + 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'] ) ) { + 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 ); + $selected_ids = is_array($settings['categories']) ? $settings['categories'] : [$settings['categories']]; + $selected_ids = array_map('intval', $selected_ids); } - if ( empty( $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' ) { + 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 ); + 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 ); + $category_ids_to_show = array_unique($category_ids_to_show); } - // Préparer les arguments de requête pour récupérer les termes. + // 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, + 'taxonomy' => 'category', + 'include' => $category_ids_to_show, 'hide_empty' => false, ]; - // Appliquer les options de tri. - if ( ! empty( $settings['order_by'] ) ) { + if ('count' !== $settings['order_by']) { + // tri natif pour 'name' ou 'id' $term_args['orderby'] = $settings['order_by']; - } - if ( ! empty( $settings['order'] ) ) { $term_args['order'] = $settings['order']; } - // Obtenir les termes de catégories à afficher. - $categories = get_terms( $term_args ); - if ( is_wp_error( $categories ) || empty( $categories ) ) { + // Récupérer les termes + $raw_terms = get_terms($term_args); + if (is_wp_error($raw_terms) || empty($raw_terms)) { return; } - // Calculer la classe CSS pour le nombre de colonnes (pour usage dans le CSS). - $columns = ! empty( $settings['columns'] ) ? (int) $settings['columns'] : 3; - $grid_class = 'columns-' . $columns; + // 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']) + : ''; - // Début du markup HTML de la grille. - echo '
'; - foreach ( $categories as $term ) { - $term_name = $term->name; - $term_link = get_term_link( $term ); - if ( is_wp_error( $term_link ) ) { - continue; // Ignorer si le lien d'archive pose un problème. - } - // Récupérer l'image de la catégorie via sa méta 'thumbnail_id' (image mise en avant de la catégorie). - $image_url = ''; - $thumbnail_id = get_term_meta( $term->term_id, 'thumbnail_id', true ); - if ( $thumbnail_id ) { - $size = ! empty( $settings['image_size'] ) ? $settings['image_size'] : 'medium'; - $image_url = wp_get_attachment_image_url( $thumbnail_id, $size ); - } - - // *** Nouveau filtre *** - if ( 'yes' === $settings['hide_without_image'] && empty( $image_url ) ) { + 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 ''; // .category-card + echo '
'; } - echo '
'; // .elementor-category-grid - - // Astuce : ajouter du CSS (feuille de style ou balise