feat: enhanced sorting by post number

This commit is contained in:
MrRaph_
2025-05-23 10:56:26 +00:00
parent fd2367ebcd
commit b19dcfc0c7
3 changed files with 145 additions and 110 deletions

View File

@@ -57,7 +57,7 @@
text-align: center; text-align: center;
color: #ffffff; color: #ffffff;
/* background: rgba(0, 0, 0, 0.4); */ /* background: rgba(0, 0, 0, 0.4); */
border-radius: 4px; /* border-radius: 4px; */
transition: background .3s ease; transition: background .3s ease;
} }

View File

@@ -2,7 +2,7 @@
/** /**
* Plugin Name: Elementor Category Grid Widget * Plugin Name: Elementor Category Grid Widget
* Description: Custom Elementor widget to display a grid of post categories with images. * Description: Custom Elementor widget to display a grid of post categories with images.
* Version: 1.1.0 * Version: 1.2.0
* Author: MrRaph_ * Author: MrRaph_
* Text Domain: category-grid-widget * Text Domain: category-grid-widget
* Requires Plugins: elementor * Requires Plugins: elementor
@@ -36,7 +36,7 @@ function ccgw_enqueue_media_uploader( $hook_suffix ) {
'ccgw-category-image', 'ccgw-category-image',
plugin_dir_url( __FILE__ ) . 'admin/js/category-image.js', plugin_dir_url( __FILE__ ) . 'admin/js/category-image.js',
[ 'jquery' ], [ 'jquery' ],
'1.0', '1.2.0',
true true
); );
@@ -172,7 +172,7 @@ function ccgw_enqueue_front_styles() {
'ccgw-category-grid-style', 'ccgw-category-grid-style',
plugin_dir_url( __FILE__ ) . 'css/style.css', plugin_dir_url( __FILE__ ) . 'css/style.css',
[], [],
'1.0.0' '1.2.0'
); );
} }
} }

View File

@@ -9,14 +9,16 @@ if ( ! defined( 'ABSPATH' ) ) {
* Widget Elementor personnalisé qui affiche une grille de catégories d'articles. * Widget Elementor personnalisé qui affiche une grille de catégories d'articles.
* Chaque catégorie est affichée sous forme de carte avec son nom, son image et un lien vers son archive. * Chaque catégorie est affichée sous forme de carte avec son nom, son image et un lien vers son archive.
*/ */
class Elementor_Category_Grid_Widget extends \Elementor\Widget_Base { class Elementor_Category_Grid_Widget extends \Elementor\Widget_Base
{
/** /**
* Identifiant unique du widget. * Identifiant unique du widget.
* *
* @return string Slug du widget. * @return string Slug du widget.
*/ */
public function get_name(): string { public function get_name(): string
{
return 'category-grid'; return 'category-grid';
} }
@@ -25,7 +27,8 @@ class Elementor_Category_Grid_Widget extends \Elementor\Widget_Base {
* *
* @return string Titre du widget. * @return string Titre du widget.
*/ */
public function get_title(): string { public function get_title(): string
{
return esc_html__('Grille de Catégories', 'category-grid-widget'); return esc_html__('Grille de Catégories', 'category-grid-widget');
} }
@@ -34,7 +37,8 @@ class Elementor_Category_Grid_Widget extends \Elementor\Widget_Base {
* *
* @return string Classe de l'icône du widget. * @return string Classe de l'icône du widget.
*/ */
public function get_icon(): string { public function get_icon(): string
{
return 'eicon-posts-grid'; return 'eicon-posts-grid';
} }
@@ -43,7 +47,8 @@ class Elementor_Category_Grid_Widget extends \Elementor\Widget_Base {
* *
* @return array Catégories du panneau Elementor. * @return array Catégories du panneau Elementor.
*/ */
public function get_categories(): array { public function get_categories(): array
{
return ['general']; return ['general'];
} }
@@ -52,14 +57,16 @@ class Elementor_Category_Grid_Widget extends \Elementor\Widget_Base {
* *
* @return array Mots-clés du widget. * @return array Mots-clés du widget.
*/ */
public function get_keywords(): array { public function get_keywords(): array
{
return ['category', 'catégorie', 'grid', 'grille']; return ['category', 'catégorie', 'grid', 'grille'];
} }
/** /**
* Enregistrer les contrôles du widget (champs configurables dans Elementor). * Enregistrer les contrôles du widget (champs configurables dans Elementor).
*/ */
protected function register_controls(): void { protected function register_controls(): void
{
/* Section "Contenu" pour le choix des catégories et options de requête */ /* Section "Contenu" pour le choix des catégories et options de requête */
$this->start_controls_section( $this->start_controls_section(
'section_content', 'section_content',
@@ -196,7 +203,8 @@ class Elementor_Category_Grid_Widget extends \Elementor\Widget_Base {
/** /**
* Générer l'affichage du widget côté front-end. * 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(); $settings = $this->get_settings_for_display();
// Récupérer les ID des catégories sélectionnées. // Récupérer les ID des catégories sélectionnées.
@@ -225,68 +233,95 @@ class Elementor_Category_Grid_Widget extends \Elementor\Widget_Base {
$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 = [ $term_args = [
'taxonomy' => 'category', 'taxonomy' => 'category',
'include' => $category_ids_to_show, 'include' => $category_ids_to_show,
'hide_empty' => false, 'hide_empty' => false,
]; ];
// Appliquer les options de tri. if ('count' !== $settings['order_by']) {
if ( ! empty( $settings['order_by'] ) ) { // tri natif pour 'name' ou 'id'
$term_args['orderby'] = $settings['order_by']; $term_args['orderby'] = $settings['order_by'];
}
if ( ! empty( $settings['order'] ) ) {
$term_args['order'] = $settings['order']; $term_args['order'] = $settings['order'];
} }
// Obtenir les termes de catégories à afficher. // Récupérer les termes
$categories = get_terms( $term_args ); $raw_terms = get_terms($term_args);
if ( is_wp_error( $categories ) || empty( $categories ) ) { if (is_wp_error($raw_terms) || empty($raw_terms)) {
return; return;
} }
// Calculer la classe CSS pour le nombre de colonnes (pour usage dans le CSS). // Filtrer les termes sans image si demandé
$columns = ! empty( $settings['columns'] ) ? (int) $settings['columns'] : 3; $terms = [];
$grid_class = 'columns-' . $columns; 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 '<div class="elementor-category-grid ' . esc_attr( $grid_class ) . '">';
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; 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 lordre 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 '<div class="elementor-category-grid ' . esc_attr($grid_class) . '">';
foreach ($terms as $term) {
$name = esc_html($term->name);
$link = esc_url(get_term_link($term));
$image_url = esc_url($term->_image_url);
echo '<div class="category-card">'; echo '<div class="category-card">';
// Rendre la carte cliquable vers l'archive de la catégorie. echo "<a href=\"{$link}\">";
echo '<a href="' . esc_url( $term_link ) . '">';
// Image de la catégorie (si disponible).
if ($image_url) { if ($image_url) {
echo '<div class="category-card-image">'; echo '<div class="category-card-image">';
echo '<img src="' . esc_url( $image_url ) . '" alt="' . esc_attr( $term_name ) . '" />'; echo '<img src="' . $image_url . '" alt="' . $name . '">';
echo '</div>'; echo '</div>';
} }
// Nom de la catégorie. echo '<div class="category-card-name">' . $name . '</div>';
echo '<div class="category-card-name">' . esc_html( $term_name ) . '</div>';
echo '</a>'; echo '</a>';
echo '</div>'; // .category-card echo '</div>';
}
echo '</div>';
} }
echo '</div>'; // .elementor-category-grid
// Astuce : ajouter du CSS (feuille de style ou balise <style>) pour styliser la grille.
// Par exemple, .elementor-category-grid.columns-3 .category-card { width: 33.33%; float: left; } pour disposer 3 colonnes.
}
} }