PluginProbe ʕ •ᴥ•ʔ
FrontBlocks for Gutenberg/GeneratePress / 1.0.4
FrontBlocks for Gutenberg/GeneratePress v1.0.4
trunk 0.2.0 0.2.1 0.2.2 0.2.3 0.2.4 0.2.5 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.1.0 1.2.0 1.2.1 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 ci-artifacts
frontblocks / includes / Frontend / ProductCategories.php
frontblocks / includes / Frontend Last commit date
Animations.php 8 months ago Carousel.php 8 months ago Counter.php 8 months ago Gallery.php 8 months ago Headline.php 8 months ago InsertPost.php 8 months ago ProductCategories.php 8 months ago StickyColumn.php 8 months ago Testimonials.php 8 months ago
ProductCategories.php
263 lines
1 <?php
2 /**
3 * Product Categories module for FrontBlocks.
4 *
5 * @package FrontBlocks
6 * @author Alex Castellón <castellon@close.technology>
7 * @copyright 2025 Closemarketing
8 * @version 1.0
9 */
10
11 namespace FrontBlocks\Frontend;
12
13 use WP_Block_Type_Registry;
14
15 defined( 'ABSPATH' ) || exit;
16
17 /**
18 * ProductCategories class.
19 *
20 * @since 1.0.0
21 */
22 class ProductCategories {
23
24 /**
25 * Constructor.
26 */
27 public function __construct() {
28 add_action( 'init', array( $this, 'register_product_categories_block' ) );
29 add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_block_editor_assets' ) );
30 add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_frontend_styles' ) );
31 }
32
33 /**
34 * Enqueue frontend styles for the grid.
35 * Usa la constante FRBL_PLUGIN_URL para construir la URL pública correcta.
36 *
37 * @return void
38 */
39 public function enqueue_frontend_styles() {
40 wp_register_style(
41 'frontblocks-product-categories-grid-style',
42 FRBL_PLUGIN_URL . 'assets/product-categories/frontblocks-product-categories.css',
43 array(),
44 FRBL_VERSION
45 );
46
47 if ( is_admin() || has_block( 'frontblocks/product-categories' ) ) {
48 wp_enqueue_style( 'frontblocks-product-categories-grid-style' );
49 }
50 }
51
52 /**
53 * Enqueue block editor assets.
54 *
55 * @return void
56 */
57 public function enqueue_block_editor_assets() {
58 wp_enqueue_script(
59 'frontblocks-product-categories-option',
60 FRBL_PLUGIN_URL . 'assets/product-categories/frontblocks-product-categories.js',
61 array( 'wp-blocks', 'wp-element', 'wp-components', 'wp-data', 'wp-editor', 'wp-api-fetch', 'wp-i18n' ),
62 FRBL_VERSION,
63 true
64 );
65
66 wp_localize_script(
67 'frontblocks-product-categories-option',
68 'frblProductCategories',
69 array(
70 'nonce' => wp_create_nonce( 'wp_rest' ),
71 )
72 );
73 }
74
75 /**
76 * Register the Product Categories block.
77 *
78 * @return void
79 */
80 public function register_product_categories_block() {
81 if ( ! class_exists( 'WooCommerce' ) ) {
82 return;
83 }
84
85 $args = array(
86 'editor_script' => 'frontblocks-product-categories-option',
87 'render_callback' => array( $this, 'render_product_categories_block' ),
88 'attributes' => array(
89 'count' => array(
90 'type' => 'number',
91 'default' => 5,
92 ),
93 'orderby' => array(
94 'type' => 'string',
95 'default' => 'count',
96 ),
97 'order' => array(
98 'type' => 'string',
99 'default' => 'DESC',
100 ),
101 'hideEmpty' => array(
102 'type' => 'boolean',
103 'default' => false,
104 ),
105 'className' => array(
106 'type' => 'string',
107 'default' => '',
108 ),
109 'columns' => array(
110 'type' => 'number',
111 'default' => 2,
112 ),
113 'bgColor' => array(
114 'type' => 'string',
115 'default' => 'rgba(255, 255, 255, 0.5)',
116 ),
117 'borderColor' => array(
118 'type' => 'string',
119 'default' => '#dddddd',
120 ),
121 'borderWidth' => array(
122 'type' => 'number',
123 'default' => 1,
124 ),
125 'borderRadius' => array(
126 'type' => 'number',
127 'default' => 20,
128 ),
129 'textColor' => array(
130 'type' => 'string',
131 'default' => 'inherit',
132 ),
133 'hoverBgColor' => array(
134 'type' => 'string',
135 'default' => 'rgba(255, 255, 255, 0.7)',
136 ),
137 'hoverBorderColor' => array(
138 'type' => 'string',
139 'default' => '#555555',
140 ),
141 'hoverTextColor' => array(
142 'type' => 'string',
143 'default' => 'inherit',
144 ),
145 ),
146 );
147
148 if ( ! WP_Block_Type_Registry::get_instance()->is_registered( 'frontblocks/product-categories' ) ) {
149 register_block_type(
150 'frontblocks/product-categories',
151 $args
152 );
153 }
154 }
155
156 /**
157 * Render the Product Categories block on frontend.
158 *
159 * @param array $attributes Block attributes.
160 * @return string HTML output.
161 */
162 public function render_product_categories_block( $attributes ) {
163 if ( ! class_exists( 'WooCommerce' ) ) {
164 return '';
165 }
166
167 $count = absint( $attributes['count'] ?? 5 );
168 $orderby = sanitize_key( $attributes['orderby'] ?? 'count' );
169 $order = strtoupper( sanitize_key( $attributes['order'] ?? 'DESC' ) );
170 $hide_empty = $attributes['hideEmpty'] ?? false;
171 $columns = absint( $attributes['columns'] ?? 2 );
172
173 $bg_color = sanitize_text_field( $attributes['bgColor'] ?? 'rgba(255, 255, 255, 0.5)' );
174 $border_color = sanitize_text_field( $attributes['borderColor'] ?? '#dddddd' );
175 $border_width = absint( $attributes['borderWidth'] ?? 1 );
176 $border_radius = absint( $attributes['borderRadius'] ?? 20 );
177 $text_color = sanitize_text_field( $attributes['textColor'] ?? 'inherit' );
178 $hover_bg_color = sanitize_text_field( $attributes['hoverBgColor'] ?? 'rgba(255, 255, 255, 0.7)' );
179 $hover_border_color = sanitize_text_field( $attributes['hoverBorderColor'] ?? '#555555' );
180 $hover_text_color = sanitize_text_field( $attributes['hoverTextColor'] ?? 'inherit' );
181
182 /**
183 * Lógica para "Mostrar todas"
184 * Si el 'count' es 999 (el valor máximo en el editor),
185 * pasamos 'number' => 0 a get_terms para indicar que no hay límite.
186 */
187 $query_limit = ( 999 === $count ) ? 0 : $count;
188
189 $args = array(
190 'taxonomy' => 'product_cat',
191 'orderby' => $orderby,
192 'order' => $order,
193 'number' => $query_limit,
194 'hide_empty' => (bool) $hide_empty,
195 );
196 $categories = get_terms( $args );
197
198 if ( is_wp_error( $categories ) || empty( $categories ) ) {
199 if ( current_user_can( 'manage_options' ) ) {
200 $msg = is_wp_error( $categories ) ? $categories->get_error_message() : 'ATENCIÓN: No se encontraron categorías de producto.';
201 return '<div style="padding: 10px; border: 1px solid orange; background: #ffe;">' . $msg . '</div>';
202 }
203 return '';
204 }
205
206 $wrapper_class = 'frbl-product-categories-grid';
207 if ( ! empty( $attributes['className'] ) ) {
208 $wrapper_class .= ' ' . esc_attr( $attributes['className'] );
209 }
210
211 $style_vars = sprintf(
212 '--frbl-grid-columns: %d; --frbl-bg-color: %s; --frbl-border-color: %s; --frbl-border-width: %dpx; --frbl-text-color: %s; --frbl-hover-bg-color: %s; --frbl-hover-border-color: %s; --frbl-hover-text-color: %s; --frbl-border-radius: %dpx;',
213 $columns,
214 $bg_color,
215 $border_color,
216 $border_width,
217 $text_color,
218 $hover_bg_color,
219 $hover_border_color,
220 $hover_text_color,
221 $border_radius
222 );
223
224 ob_start();
225 ?>
226 <div class="<?php echo esc_attr( $wrapper_class ); ?>" style="<?php echo esc_attr( $style_vars ); ?>">
227 <?php
228 foreach ( $categories as $category ) :
229 $thumbnail_id = get_term_meta( $category->term_id, 'thumbnail_id', true );
230
231 if ( $thumbnail_id ) {
232 $image_url = wp_get_attachment_image_url( $thumbnail_id, 'woocommerce_thumbnail' );
233 } elseif ( function_exists( 'wc_placeholder_img_src' ) ) {
234 $image_url = wc_placeholder_img_src();
235 } else {
236 $image_url = 'https://placehold.co/600x400/eeeeee/333333?text=Product+Category';
237 }
238
239 $link = esc_url( get_term_link( $category, 'product_cat' ) );
240 ?>
241 <div class="frbl-category-item frbl-category-<?php echo esc_attr( $category->slug ); ?>">
242 <a href="<?php echo esc_url( $link ); ?>" class="frbl-category-link">
243 <div class="frbl-category-image-wrap">
244 <img
245 src="<?php echo esc_url( $image_url ); ?>"
246 alt="<?php echo esc_attr( $category->name ); ?>"
247 class="frbl-category-image"
248 />
249 </div>
250 <h3 class="frbl-category-name">
251 <?php echo esc_html( $category->name ); ?> (<?php echo esc_html( $category->count ); ?>)
252 </h3>
253 </a>
254 </div>
255 <?php endforeach; ?>
256 </div>
257 <?php
258 return ob_get_clean();
259 }
260 }
261
262 new ProductCategories();
263