PluginProbe
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder / 51.1.65
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder v51.1.65
51.1.83 51.1.82 51.1.81 51.1.79 51.1.78 51.1.77 51.1.76 51.1.74 51.1.75 51.1.65 51.1.64 51.1.63 trunk 51.1.14 51.1.2 51.1.35 51.1.36 51.1.37 51.1.38 51.1.39 51.1.44 51.1.45 51.1.46 51.1.47 51.1.49 All 37 releases
king-addons / includes / widgets / Quick_Post_Grid / Quick_Post_Grid.php

Quick_Post_Grid.php in King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder 51.1.65, at includes/widgets/Quick_Post_Grid/Quick_Post_Grid.php

1,171 lines 39.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Quick Post Grid Widget (Free)
4 *
5 * @package King_Addons
6 */
7
8 namespace King_Addons;
9
10 use Elementor\Controls_Manager;
11 use Elementor\Group_Control_Border;
12 use Elementor\Group_Control_Box_Shadow;
13 use Elementor\Group_Control_Image_Size;
14 use Elementor\Group_Control_Typography;
15 use Elementor\Utils;
16 use Elementor\Widget_Base;
17 use WP_Query;
18
19 if (!defined('ABSPATH')) {
20 exit;
21 }
22
23 /**
24 * Renders the Quick Post Grid widget.
25 */
26 class Quick_Post_Grid extends Widget_Base
27 {
28 public function get_name(): string
29 {
30 return 'king-addons-quick-post-grid';
31 }
32
33 public function get_title(): string
34 {
35 return esc_html__('Quick Post Grid', 'king-addons');
36 }
37
38 public function get_icon(): string
39 {
40 return 'king-addons-icon king-addons-simple-post-grid';
41 }
42
43 public function get_script_depends(): array
44 {
45 return [
46 KING_ADDONS_ASSETS_UNIQUE_KEY . '-quick-post-grid-script',
47 ];
48 }
49
50 public function get_style_depends(): array
51 {
52 return [
53 KING_ADDONS_ASSETS_UNIQUE_KEY . '-quick-post-grid-style',
54 ];
55 }
56
57 public function get_categories(): array
58 {
59 return ['king-addons'];
60 }
61
62 public function get_keywords(): array
63 {
64 return ['posts', 'grid', 'blog', 'king-addons'];
65 }
66
67 public function get_custom_help_url()
68 {
69 return 'mailto:bug@kingaddons.com?subject=Bug Report - King Addons&body=Please describe the issue';
70 }
71
72 public function register_controls(): void
73 {
74 $this->register_query_controls();
75 $this->register_layout_controls();
76 $this->register_style_card_controls();
77 $this->register_style_text_controls();
78 $this->register_style_meta_controls();
79 $this->register_style_button_controls();
80 $this->register_pro_notice_controls();
81 }
82
83 public function render(): void
84 {
85 $settings = $this->get_settings_for_display();
86 $this->render_output($settings);
87 }
88
89 public function render_output(array $settings): void
90 {
91 $query = $this->build_query($settings);
92 if (!$query->have_posts()) {
93 wp_reset_postdata();
94 return;
95 }
96
97 $wrapper_classes = $this->get_wrapper_classes($settings);
98 $wrapper_style = $this->get_wrapper_style($settings);
99 $card_linkable = ($settings['kng_card_linkable'] ?? '') === 'yes';
100
101 ?>
102 <div class="<?php echo esc_attr(implode(' ', $wrapper_classes)); ?>"<?php echo $wrapper_style; ?>>
103 <div class="king-addons-post-grid__grid">
104 <?php while ($query->have_posts()) : $query->the_post(); ?>
105 <?php $this->render_card($settings, $card_linkable); ?>
106 <?php endwhile; ?>
107 </div>
108 </div>
109 <?php
110 wp_reset_postdata();
111 }
112
113 protected function register_query_controls(): void
114 {
115 $this->start_controls_section(
116 'kng_query_section',
117 [
118 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Query', 'king-addons'),
119 'tab' => Controls_Manager::TAB_CONTENT,
120 ]
121 );
122
123 $this->add_control(
124 'kng_posts_per_page',
125 [
126 'label' => esc_html__('Posts Number', 'king-addons'),
127 'type' => Controls_Manager::NUMBER,
128 'min' => 1,
129 'max' => 6,
130 'step' => 1,
131 'default' => 6,
132 'description' => esc_html__('Free version is limited to 6 posts.', 'king-addons'),
133 ]
134 );
135
136 $this->add_control(
137 'kng_orderby',
138 [
139 'label' => esc_html__('Order By', 'king-addons'),
140 'type' => Controls_Manager::SELECT,
141 'default' => 'date',
142 'options' => [
143 'date' => esc_html__('Date', 'king-addons'),
144 'title' => esc_html__('Title', 'king-addons'),
145 'rand' => esc_html__('Random', 'king-addons'),
146 'menu_order' => esc_html__('Menu Order', 'king-addons'),
147 ],
148 ]
149 );
150
151 $this->add_control(
152 'kng_order',
153 [
154 'label' => esc_html__('Order', 'king-addons'),
155 'type' => Controls_Manager::SELECT,
156 'default' => 'DESC',
157 'options' => [
158 'DESC' => esc_html__('Descending', 'king-addons'),
159 'ASC' => esc_html__('Ascending', 'king-addons'),
160 ],
161 ]
162 );
163
164 $this->add_control_categories();
165
166 $this->add_control(
167 'kng_exclude_sticky',
168 [
169 'label' => esc_html__('Ignore Sticky Posts', 'king-addons'),
170 'type' => Controls_Manager::SWITCHER,
171 'return_value' => 'yes',
172 'default' => 'yes',
173 ]
174 );
175
176 $this->add_control(
177 'kng_show_image',
178 [
179 'label' => esc_html__('Show Featured Image', 'king-addons'),
180 'type' => Controls_Manager::SWITCHER,
181 'return_value' => 'yes',
182 'default' => 'yes',
183 ]
184 );
185
186 $this->add_group_control(
187 Group_Control_Image_Size::get_type(),
188 [
189 'name' => 'kng_image_size',
190 'default' => 'medium',
191 'condition' => [
192 'kng_show_image' => 'yes',
193 ],
194 ]
195 );
196
197 $this->add_control(
198 'kng_image_ratio',
199 [
200 'label' => esc_html__('Image Ratio', 'king-addons'),
201 'type' => Controls_Manager::SELECT,
202 'default' => 'original',
203 'options' => [
204 'original' => esc_html__('Original', 'king-addons'),
205 'square' => esc_html__('1:1', 'king-addons'),
206 '4-3' => esc_html__('4:3', 'king-addons'),
207 '3-2' => esc_html__('3:2', 'king-addons'),
208 '16-9' => esc_html__('16:9', 'king-addons'),
209 ],
210 'condition' => [
211 'kng_show_image' => 'yes',
212 ],
213 ]
214 );
215
216 $this->add_control(
217 'kng_image_fit',
218 [
219 'label' => esc_html__('Image Fit', 'king-addons'),
220 'type' => Controls_Manager::SELECT,
221 'default' => 'cover',
222 'options' => [
223 'cover' => esc_html__('Cover', 'king-addons'),
224 'contain' => esc_html__('Contain', 'king-addons'),
225 ],
226 'condition' => [
227 'kng_show_image' => 'yes',
228 ],
229 'selectors' => [
230 '{{WRAPPER}} .king-addons-post-grid' => '--kng-post-grid-image-fit: {{VALUE}};',
231 ],
232 ]
233 );
234
235 $this->add_responsive_control(
236 'kng_image_radius',
237 [
238 'label' => esc_html__('Image Border Radius', 'king-addons'),
239 'type' => Controls_Manager::SLIDER,
240 'size_units' => ['px', '%'],
241 'range' => [
242 'px' => ['min' => 0, 'max' => 60],
243 '%' => ['min' => 0, 'max' => 100],
244 ],
245 'condition' => [
246 'kng_show_image' => 'yes',
247 ],
248 'selectors' => [
249 '{{WRAPPER}} .king-addons-post-grid__media' => 'border-radius: {{SIZE}}{{UNIT}};',
250 ],
251 ]
252 );
253
254 $this->add_responsive_control(
255 'kng_image_spacing',
256 [
257 'label' => esc_html__('Image Bottom Spacing', 'king-addons'),
258 'type' => Controls_Manager::SLIDER,
259 'size_units' => ['px'],
260 'range' => [
261 'px' => ['min' => 0, 'max' => 80],
262 ],
263 'condition' => [
264 'kng_show_image' => 'yes',
265 ],
266 'selectors' => [
267 '{{WRAPPER}} .king-addons-post-grid__media' => 'margin-bottom: {{SIZE}}{{UNIT}};',
268 ],
269 ]
270 );
271
272 $this->add_control(
273 'kng_show_meta',
274 [
275 'label' => esc_html__('Show Meta', 'king-addons'),
276 'type' => Controls_Manager::SWITCHER,
277 'return_value' => 'yes',
278 'default' => 'yes',
279 ]
280 );
281
282 $this->add_control(
283 'kng_show_author',
284 [
285 'label' => esc_html__('Show Author', 'king-addons'),
286 'type' => Controls_Manager::SWITCHER,
287 'return_value' => 'yes',
288 'default' => 'yes',
289 'condition' => [
290 'kng_show_meta' => 'yes',
291 ],
292 ]
293 );
294
295 $this->add_control(
296 'kng_show_date',
297 [
298 'label' => esc_html__('Show Date', 'king-addons'),
299 'type' => Controls_Manager::SWITCHER,
300 'return_value' => 'yes',
301 'default' => 'yes',
302 'condition' => [
303 'kng_show_meta' => 'yes',
304 ],
305 ]
306 );
307
308 $this->add_control(
309 'kng_meta_separator',
310 [
311 'label' => esc_html__('Meta Separator', 'king-addons'),
312 'type' => Controls_Manager::TEXT,
313 'default' => '',
314 'condition' => [
315 'kng_show_meta' => 'yes',
316 ],
317 ]
318 );
319
320 $this->add_control(
321 'kng_show_excerpt',
322 [
323 'label' => esc_html__('Show Excerpt', 'king-addons'),
324 'type' => Controls_Manager::SWITCHER,
325 'return_value' => 'yes',
326 'default' => 'yes',
327 ]
328 );
329
330 $this->add_control(
331 'kng_excerpt_length',
332 [
333 'label' => esc_html__('Excerpt Length (words)', 'king-addons'),
334 'type' => Controls_Manager::NUMBER,
335 'min' => 5,
336 'max' => 80,
337 'step' => 1,
338 'default' => 18,
339 'condition' => [
340 'kng_show_excerpt' => 'yes',
341 ],
342 ]
343 );
344
345 $this->add_control(
346 'kng_show_read_more',
347 [
348 'label' => esc_html__('Show Read More', 'king-addons'),
349 'type' => Controls_Manager::SWITCHER,
350 'return_value' => 'yes',
351 'default' => 'yes',
352 ]
353 );
354
355 $this->add_control(
356 'kng_read_more_text',
357 [
358 'label' => esc_html__('Read More Text', 'king-addons'),
359 'type' => Controls_Manager::TEXT,
360 'default' => esc_html__('Read more', 'king-addons'),
361 'condition' => [
362 'kng_show_read_more' => 'yes',
363 ],
364 ]
365 );
366
367 $this->add_control(
368 'kng_card_linkable',
369 [
370 'label' => esc_html__('Make Card Clickable', 'king-addons'),
371 'type' => Controls_Manager::SWITCHER,
372 'label_on' => esc_html__('Yes', 'king-addons'),
373 'label_off' => esc_html__('No', 'king-addons'),
374 'return_value' => 'yes',
375 'default' => '',
376 'description' => esc_html__('Card click is disabled inside the Elementor editor to avoid interfering with editing.', 'king-addons'),
377 ]
378 );
379
380 $this->add_control(
381 'kng_card_link_new_tab',
382 [
383 'label' => esc_html__('Open Card in New Tab', 'king-addons'),
384 'type' => Controls_Manager::SWITCHER,
385 'return_value' => 'yes',
386 'default' => '',
387 'condition' => [
388 'kng_card_linkable' => 'yes',
389 ],
390 ]
391 );
392
393 $this->end_controls_section();
394 }
395
396 protected function add_control_categories(): void
397 {
398 $this->add_control(
399 'kng_categories',
400 [
401 'label' => sprintf(__('Categories %s', 'king-addons'), '<i class="eicon-pro-icon"></i>'),
402 'type' => Controls_Manager::TEXT,
403 'description' => esc_html__('Enter category slugs separated by commas.', 'king-addons'),
404 'placeholder' => esc_html__('news,features', 'king-addons'),
405 'classes' => 'king-addons-pro-control no-distance',
406 ]
407 );
408 }
409
410 protected function register_layout_controls(): void
411 {
412 $this->start_controls_section(
413 'kng_layout_section',
414 [
415 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Layout', 'king-addons'),
416 'tab' => Controls_Manager::TAB_CONTENT,
417 ]
418 );
419
420 $this->add_responsive_control(
421 'kng_columns',
422 [
423 'label' => esc_html__('Columns', 'king-addons'),
424 'type' => Controls_Manager::NUMBER,
425 'min' => 1,
426 'max' => 6,
427 'step' => 1,
428 'default' => 3,
429 'selectors' => [
430 '{{WRAPPER}} .king-addons-post-grid__grid' => 'grid-template-columns: repeat({{VALUE}}, minmax(0, 1fr));',
431 ],
432 ]
433 );
434
435 $this->add_responsive_control(
436 'kng_grid_gap',
437 [
438 'label' => esc_html__('Gap', 'king-addons'),
439 'type' => Controls_Manager::SLIDER,
440 'size_units' => ['px'],
441 'range' => [
442 'px' => [
443 'min' => 0,
444 'max' => 80,
445 ],
446 ],
447 'default' => [
448 'size' => 20,
449 'unit' => 'px',
450 ],
451 'selectors' => [
452 '{{WRAPPER}} .king-addons-post-grid__grid' => 'gap: {{SIZE}}{{UNIT}};',
453 ],
454 ]
455 );
456
457 $this->end_controls_section();
458 }
459
460 protected function register_style_card_controls(): void
461 {
462 $this->start_controls_section(
463 'kng_style_card_section',
464 [
465 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Card', 'king-addons'),
466 'tab' => Controls_Manager::TAB_STYLE,
467 ]
468 );
469
470 $this->add_control(
471 'kng_card_background',
472 [
473 'label' => esc_html__('Background', 'king-addons'),
474 'type' => Controls_Manager::COLOR,
475 'selectors' => [
476 '{{WRAPPER}} .king-addons-post-grid__card' => 'background-color: {{VALUE}};',
477 ],
478 ]
479 );
480
481 $this->add_control(
482 'kng_card_background_hover',
483 [
484 'label' => esc_html__('Background Hover', 'king-addons'),
485 'type' => Controls_Manager::COLOR,
486 'selectors' => [
487 '{{WRAPPER}} .king-addons-post-grid__card:hover' => 'background-color: {{VALUE}};',
488 ],
489 ]
490 );
491
492 $this->add_group_control(
493 Group_Control_Border::get_type(),
494 [
495 'name' => 'kng_card_border',
496 'selector' => '{{WRAPPER}} .king-addons-post-grid__card',
497 ]
498 );
499
500 $this->add_control(
501 'kng_card_border_color_hover',
502 [
503 'label' => esc_html__('Border Color Hover', 'king-addons'),
504 'type' => Controls_Manager::COLOR,
505 'selectors' => [
506 '{{WRAPPER}} .king-addons-post-grid__card:hover' => 'border-color: {{VALUE}};',
507 ],
508 ]
509 );
510
511 $this->add_control(
512 'kng_card_radius',
513 [
514 'label' => esc_html__('Border Radius', 'king-addons'),
515 'type' => Controls_Manager::SLIDER,
516 'size_units' => ['px', '%'],
517 'range' => [
518 'px' => ['min' => 0, 'max' => 60],
519 '%' => ['min' => 0, 'max' => 100],
520 ],
521 'selectors' => [
522 '{{WRAPPER}} .king-addons-post-grid__card' => 'border-radius: {{SIZE}}{{UNIT}};',
523 ],
524 ]
525 );
526
527 $this->add_group_control(
528 Group_Control_Box_Shadow::get_type(),
529 [
530 'name' => 'kng_card_shadow',
531 'selector' => '{{WRAPPER}} .king-addons-post-grid__card',
532 ]
533 );
534
535 $this->add_group_control(
536 Group_Control_Box_Shadow::get_type(),
537 [
538 'name' => 'kng_card_shadow_hover',
539 'selector' => '{{WRAPPER}} .king-addons-post-grid__card:hover',
540 ]
541 );
542
543 $this->add_control(
544 'kng_card_shadow_disable',
545 [
546 'label' => esc_html__('Disable Box Shadow', 'king-addons'),
547 'type' => Controls_Manager::SWITCHER,
548 'return_value' => 'yes',
549 'default' => '',
550 'selectors' => [
551 '{{WRAPPER}} .king-addons-post-grid__card' => 'box-shadow: none !important;',
552 ],
553 ]
554 );
555
556 $this->add_control(
557 'kng_card_shadow_hover_disable',
558 [
559 'label' => esc_html__('Disable Box Shadow on Hover', 'king-addons'),
560 'type' => Controls_Manager::SWITCHER,
561 'return_value' => 'yes',
562 'default' => '',
563 'selectors' => [
564 '{{WRAPPER}} .king-addons-post-grid__card:hover' => 'box-shadow: none !important;',
565 ],
566 ]
567 );
568
569 $this->add_responsive_control(
570 'kng_card_padding',
571 [
572 'label' => esc_html__('Card Padding', 'king-addons'),
573 'type' => Controls_Manager::DIMENSIONS,
574 'size_units' => ['px', '%', 'em'],
575 'selectors' => [
576 '{{WRAPPER}} .king-addons-post-grid__card' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
577 ],
578 ]
579 );
580
581 $this->end_controls_section();
582 }
583
584 protected function register_style_text_controls(): void
585 {
586 $this->start_controls_section(
587 'kng_style_text_section',
588 [
589 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Text', 'king-addons'),
590 'tab' => Controls_Manager::TAB_STYLE,
591 ]
592 );
593
594 $this->add_group_control(
595 Group_Control_Typography::get_type(),
596 [
597 'name' => 'kng_title_typography',
598 'selector' => '{{WRAPPER}} .king-addons-post-grid__title',
599 ]
600 );
601
602 $this->add_control(
603 'kng_title_color',
604 [
605 'label' => esc_html__('Title Color', 'king-addons'),
606 'type' => Controls_Manager::COLOR,
607 'selectors' => [
608 '{{WRAPPER}} .king-addons-post-grid__title a' => 'color: {{VALUE}};',
609 ],
610 ]
611 );
612
613 $this->add_responsive_control(
614 'kng_title_spacing',
615 [
616 'label' => esc_html__('Title Bottom Spacing', 'king-addons'),
617 'type' => Controls_Manager::SLIDER,
618 'size_units' => ['px'],
619 'range' => [
620 'px' => ['min' => 0, 'max' => 60],
621 ],
622 'selectors' => [
623 '{{WRAPPER}} .king-addons-post-grid__title' => 'margin-bottom: {{SIZE}}{{UNIT}};',
624 ],
625 ]
626 );
627
628 $this->add_group_control(
629 Group_Control_Typography::get_type(),
630 [
631 'name' => 'kng_excerpt_typography',
632 'selector' => '{{WRAPPER}} .king-addons-post-grid__excerpt',
633 ]
634 );
635
636 $this->add_control(
637 'kng_excerpt_color',
638 [
639 'label' => esc_html__('Excerpt Color', 'king-addons'),
640 'type' => Controls_Manager::COLOR,
641 'selectors' => [
642 '{{WRAPPER}} .king-addons-post-grid__excerpt' => 'color: {{VALUE}};',
643 ],
644 ]
645 );
646
647 $this->add_responsive_control(
648 'kng_excerpt_spacing',
649 [
650 'label' => esc_html__('Excerpt Bottom Spacing', 'king-addons'),
651 'type' => Controls_Manager::SLIDER,
652 'size_units' => ['px'],
653 'range' => [
654 'px' => ['min' => 0, 'max' => 80],
655 ],
656 'selectors' => [
657 '{{WRAPPER}} .king-addons-post-grid__excerpt' => 'margin-bottom: {{SIZE}}{{UNIT}};',
658 ],
659 ]
660 );
661
662 $this->add_control(
663 'kng_text_alignment',
664 [
665 'label' => esc_html__('Text Alignment', 'king-addons'),
666 'type' => Controls_Manager::CHOOSE,
667 'options' => [
668 'left' => [
669 'title' => esc_html__('Left', 'king-addons'),
670 'icon' => 'eicon-text-align-left',
671 ],
672 'center' => [
673 'title' => esc_html__('Center', 'king-addons'),
674 'icon' => 'eicon-text-align-center',
675 ],
676 'right' => [
677 'title' => esc_html__('Right', 'king-addons'),
678 'icon' => 'eicon-text-align-right',
679 ],
680 ],
681 'toggle' => false,
682 'default' => 'left',
683 'prefix_class' => 'king-addons-post-grid--text-align-',
684 ]
685 );
686
687 $this->end_controls_section();
688 }
689
690 protected function register_style_meta_controls(): void
691 {
692 $this->start_controls_section(
693 'kng_style_meta_section',
694 [
695 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Meta', 'king-addons'),
696 'tab' => Controls_Manager::TAB_STYLE,
697 'condition' => [
698 'kng_show_meta' => 'yes',
699 ],
700 ]
701 );
702
703 $this->add_group_control(
704 Group_Control_Typography::get_type(),
705 [
706 'name' => 'kng_meta_typography',
707 'selector' => '{{WRAPPER}} .king-addons-post-grid__meta',
708 ]
709 );
710
711 $this->add_control(
712 'kng_meta_color',
713 [
714 'label' => esc_html__('Meta Color', 'king-addons'),
715 'type' => Controls_Manager::COLOR,
716 'selectors' => [
717 '{{WRAPPER}} .king-addons-post-grid__meta' => 'color: {{VALUE}};',
718 ],
719 ]
720 );
721
722 $this->add_responsive_control(
723 'kng_meta_spacing',
724 [
725 'label' => esc_html__('Meta Bottom Spacing', 'king-addons'),
726 'type' => Controls_Manager::SLIDER,
727 'size_units' => ['px'],
728 'range' => [
729 'px' => ['min' => 0, 'max' => 60],
730 ],
731 'selectors' => [
732 '{{WRAPPER}} .king-addons-post-grid__meta' => 'margin-bottom: {{SIZE}}{{UNIT}};',
733 ],
734 ]
735 );
736
737 $this->end_controls_section();
738 }
739
740 protected function register_style_button_controls(): void
741 {
742 $this->start_controls_section(
743 'kng_style_button_section',
744 [
745 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Button', 'king-addons'),
746 'tab' => Controls_Manager::TAB_STYLE,
747 'condition' => [
748 'kng_show_read_more' => 'yes',
749 ],
750 ]
751 );
752
753 $this->add_control(
754 'kng_button_alignment',
755 [
756 'label' => esc_html__('Button Alignment', 'king-addons'),
757 'type' => Controls_Manager::CHOOSE,
758 'options' => [
759 'left' => [
760 'title' => esc_html__('Left', 'king-addons'),
761 'icon' => 'eicon-h-align-left',
762 ],
763 'center' => [
764 'title' => esc_html__('Center', 'king-addons'),
765 'icon' => 'eicon-h-align-center',
766 ],
767 'right' => [
768 'title' => esc_html__('Right', 'king-addons'),
769 'icon' => 'eicon-h-align-right',
770 ],
771 ],
772 'toggle' => false,
773 'default' => 'left',
774 'prefix_class' => 'king-addons-post-grid--button-align-',
775 ]
776 );
777
778 $this->add_control(
779 'kng_button_text_alignment',
780 [
781 'label' => esc_html__('Button Text Alignment', 'king-addons'),
782 'type' => Controls_Manager::CHOOSE,
783 'options' => [
784 'left' => [
785 'title' => esc_html__('Left', 'king-addons'),
786 'icon' => 'eicon-h-align-left',
787 ],
788 'center' => [
789 'title' => esc_html__('Center', 'king-addons'),
790 'icon' => 'eicon-h-align-center',
791 ],
792 'right' => [
793 'title' => esc_html__('Right', 'king-addons'),
794 'icon' => 'eicon-h-align-right',
795 ],
796 ],
797 'toggle' => false,
798 'default' => 'center',
799 'prefix_class' => 'king-addons-post-grid--button-text-align-',
800 ]
801 );
802
803 $this->add_control(
804 'kng_button_full_width',
805 [
806 'label' => esc_html__('Full Width', 'king-addons'),
807 'type' => Controls_Manager::SWITCHER,
808 'return_value' => 'yes',
809 'default' => '',
810 'selectors' => [
811 '{{WRAPPER}} .king-addons-post-grid__button' => 'width: 100%;',
812 ],
813 ]
814 );
815
816 $this->add_group_control(
817 Group_Control_Typography::get_type(),
818 [
819 'name' => 'kng_button_typography',
820 'selector' => '{{WRAPPER}} .king-addons-post-grid__button',
821 ]
822 );
823
824 $this->start_controls_tabs('kng_button_tabs');
825
826 $this->start_controls_tab(
827 'kng_button_tab_normal',
828 [
829 'label' => esc_html__('Normal', 'king-addons'),
830 ]
831 );
832
833 $this->add_control(
834 'kng_button_text_color',
835 [
836 'label' => esc_html__('Text Color', 'king-addons'),
837 'type' => Controls_Manager::COLOR,
838 'selectors' => [
839 '{{WRAPPER}} .king-addons-post-grid__button' => 'color: {{VALUE}};',
840 ],
841 ]
842 );
843
844 $this->add_control(
845 'kng_button_background',
846 [
847 'label' => esc_html__('Background', 'king-addons'),
848 'type' => Controls_Manager::COLOR,
849 'selectors' => [
850 '{{WRAPPER}} .king-addons-post-grid__button' => 'background-color: {{VALUE}};',
851 ],
852 ]
853 );
854
855 $this->add_group_control(
856 Group_Control_Border::get_type(),
857 [
858 'name' => 'kng_button_border',
859 'selector' => '{{WRAPPER}} .king-addons-post-grid__button',
860 ]
861 );
862
863 $this->add_group_control(
864 Group_Control_Box_Shadow::get_type(),
865 [
866 'name' => 'kng_button_shadow',
867 'selector' => '{{WRAPPER}} .king-addons-post-grid__button',
868 ]
869 );
870
871 $this->end_controls_tab();
872
873 $this->start_controls_tab(
874 'kng_button_tab_hover',
875 [
876 'label' => esc_html__('Hover', 'king-addons'),
877 ]
878 );
879
880 $this->add_control(
881 'kng_button_text_color_hover',
882 [
883 'label' => esc_html__('Text Color', 'king-addons'),
884 'type' => Controls_Manager::COLOR,
885 'selectors' => [
886 '{{WRAPPER}} .king-addons-post-grid__button:hover' => 'color: {{VALUE}};',
887 ],
888 ]
889 );
890
891 $this->add_control(
892 'kng_button_background_hover',
893 [
894 'label' => esc_html__('Background', 'king-addons'),
895 'type' => Controls_Manager::COLOR,
896 'selectors' => [
897 '{{WRAPPER}} .king-addons-post-grid__button:hover' => 'background-color: {{VALUE}};',
898 ],
899 ]
900 );
901
902 $this->add_control(
903 'kng_button_border_color_hover',
904 [
905 'label' => esc_html__('Border Color', 'king-addons'),
906 'type' => Controls_Manager::COLOR,
907 'selectors' => [
908 '{{WRAPPER}} .king-addons-post-grid__button:hover' => 'border-color: {{VALUE}};',
909 ],
910 ]
911 );
912
913 $this->add_group_control(
914 Group_Control_Box_Shadow::get_type(),
915 [
916 'name' => 'kng_button_shadow_hover',
917 'selector' => '{{WRAPPER}} .king-addons-post-grid__button:hover',
918 ]
919 );
920
921 $this->end_controls_tab();
922 $this->end_controls_tabs();
923
924 $this->add_responsive_control(
925 'kng_button_spacing',
926 [
927 'label' => esc_html__('Button Top Spacing', 'king-addons'),
928 'type' => Controls_Manager::SLIDER,
929 'size_units' => ['px'],
930 'range' => [
931 'px' => ['min' => 0, 'max' => 80],
932 ],
933 'selectors' => [
934 '{{WRAPPER}} .king-addons-post-grid__button' => 'margin-top: {{SIZE}}{{UNIT}};',
935 ],
936 'separator' => 'before',
937 ]
938 );
939
940 $this->add_responsive_control(
941 'kng_button_padding',
942 [
943 'label' => esc_html__('Padding', 'king-addons'),
944 'type' => Controls_Manager::DIMENSIONS,
945 'size_units' => ['px', '%', 'em'],
946 'selectors' => [
947 '{{WRAPPER}} .king-addons-post-grid__button' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
948 ],
949 'separator' => 'before',
950 ]
951 );
952
953 $this->add_control(
954 'kng_button_radius',
955 [
956 'label' => esc_html__('Border Radius', 'king-addons'),
957 'type' => Controls_Manager::SLIDER,
958 'size_units' => ['px', '%'],
959 'range' => [
960 'px' => ['min' => 0, 'max' => 80],
961 '%' => ['min' => 0, 'max' => 100],
962 ],
963 'selectors' => [
964 '{{WRAPPER}} .king-addons-post-grid__button' => 'border-radius: {{SIZE}}{{UNIT}};',
965 ],
966 ]
967 );
968
969 $this->add_control(
970 'kng_button_shadow_disable',
971 [
972 'label' => esc_html__('Disable Box Shadow', 'king-addons'),
973 'type' => Controls_Manager::SWITCHER,
974 'label_on' => esc_html__('Yes', 'king-addons'),
975 'label_off' => esc_html__('No', 'king-addons'),
976 'return_value' => 'yes',
977 'default' => '',
978 'selectors' => [
979 '{{WRAPPER}} .king-addons-post-grid__button' => 'box-shadow: none !important;',
980 ],
981 ]
982 );
983
984 $this->add_control(
985 'kng_button_shadow_hover_disable',
986 [
987 'label' => esc_html__('Disable Box Shadow on Hover', 'king-addons'),
988 'type' => Controls_Manager::SWITCHER,
989 'label_on' => esc_html__('Yes', 'king-addons'),
990 'label_off' => esc_html__('No', 'king-addons'),
991 'return_value' => 'yes',
992 'default' => '',
993 'selectors' => [
994 '{{WRAPPER}} .king-addons-post-grid__button:hover' => 'box-shadow: none !important;',
995 ],
996 ]
997 );
998
999 $this->end_controls_section();
1000 }
1001
1002 protected function build_query(array $settings): WP_Query
1003 {
1004 $per_page = !empty($settings['kng_posts_per_page']) ? (int) $settings['kng_posts_per_page'] : 6;
1005 if (!king_addons_freemius()->can_use_premium_code__premium_only()) {
1006 $per_page = min($per_page, 6);
1007 }
1008
1009 $order = strtoupper((string) ($settings['kng_order'] ?? 'DESC'));
1010 $order = in_array($order, ['ASC', 'DESC'], true) ? $order : 'DESC';
1011
1012 $allowed_orderby = ['date', 'title', 'rand', 'menu_order'];
1013 $orderby = (string) ($settings['kng_orderby'] ?? 'date');
1014 $orderby = in_array($orderby, $allowed_orderby, true) ? $orderby : 'date';
1015
1016 $args = [
1017 'post_type' => 'post',
1018 'posts_per_page' => $per_page,
1019 'order' => $order,
1020 'orderby' => $orderby,
1021 ];
1022
1023 if (!empty($settings['kng_categories']) && king_addons_freemius()->can_use_premium_code__premium_only()) {
1024 $slugs = array_filter(array_map('sanitize_title', array_map('trim', explode(',', (string) $settings['kng_categories']))));
1025 if (!empty($slugs)) {
1026 $args['category_name'] = implode(',', $slugs);
1027 }
1028 }
1029
1030 if (!empty($settings['kng_exclude_sticky'])) {
1031 $args['ignore_sticky_posts'] = true;
1032 }
1033
1034 return new WP_Query($args);
1035 }
1036
1037 protected function render_card(array $settings, bool $card_linkable): void
1038 {
1039 $show_image = $settings['kng_show_image'] === 'yes';
1040 $show_meta = ($settings['kng_show_meta'] ?? '') === 'yes';
1041 $show_author = ($settings['kng_show_author'] ?? 'yes') === 'yes';
1042 $show_date = ($settings['kng_show_date'] ?? 'yes') === 'yes';
1043 $show_excerpt = $settings['kng_show_excerpt'] === 'yes';
1044 $show_read_more = $settings['kng_show_read_more'] === 'yes';
1045
1046 $image_html = '';
1047 if ($show_image) {
1048 if (has_post_thumbnail()) {
1049 $image_html = wp_get_attachment_image(
1050 get_post_thumbnail_id(),
1051 $settings['kng_image_size_size'] ?? 'medium',
1052 false,
1053 ['alt' => esc_attr(get_the_title())]
1054 );
1055 }
1056 if (empty($image_html)) {
1057 $image_html = '<img src="' . esc_url(Utils::get_placeholder_image_src()) . '" alt="' . esc_attr(get_the_title()) . '"/>';
1058 }
1059 }
1060
1061 $excerpt_length = !empty($settings['kng_excerpt_length']) ? (int) $settings['kng_excerpt_length'] : 18;
1062 $excerpt_text = $show_excerpt ? wp_trim_words(get_the_excerpt(), $excerpt_length) : '';
1063
1064 $meta_parts = [];
1065 if ($show_meta) {
1066 if ($show_date) {
1067 $meta_parts[] = get_the_date();
1068 }
1069 if ($show_author) {
1070 $meta_parts[] = get_the_author();
1071 }
1072 }
1073
1074 $meta_separator = isset($settings['kng_meta_separator']) ? trim((string) $settings['kng_meta_separator']) : '';
1075 $meta_glue = $meta_separator === '' ? ' ' : ' ' . $meta_separator . ' ';
1076
1077 $card_attributes = [];
1078 if ($card_linkable) {
1079 $card_attributes[] = 'data-card-link="' . esc_url(get_permalink()) . '"';
1080 if (($settings['kng_card_link_new_tab'] ?? '') === 'yes') {
1081 $card_attributes[] = 'data-card-link-target="_blank"';
1082 }
1083 $card_attributes[] = 'tabindex="0"';
1084 $card_attributes[] = 'role="link"';
1085 $card_attributes[] = 'aria-label="' . esc_attr(sprintf(__('Open %s', 'king-addons'), get_the_title())) . '"';
1086 }
1087
1088 ?>
1089 <div class="king-addons-post-grid__item">
1090 <article class="king-addons-post-grid__card"<?php echo !empty($card_attributes) ? ' ' . implode(' ', $card_attributes) : ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
1091 <?php if (!empty($image_html)) : ?>
1092 <div class="king-addons-post-grid__media">
1093 <a href="<?php the_permalink(); ?>" class="king-addons-post-grid__media-link">
1094 <?php echo $image_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
1095 </a>
1096 </div>
1097 <?php endif; ?>
1098
1099 <div class="king-addons-post-grid__body">
1100 <h3 class="king-addons-post-grid__title">
1101 <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
1102 </h3>
1103
1104 <?php if (!empty($meta_parts)) : ?>
1105 <div class="king-addons-post-grid__meta">
1106 <?php echo esc_html(implode($meta_glue, $meta_parts)); ?>
1107 </div>
1108 <?php endif; ?>
1109
1110 <?php if (!empty($excerpt_text)) : ?>
1111 <div class="king-addons-post-grid__excerpt"><?php echo esc_html($excerpt_text); ?></div>
1112 <?php endif; ?>
1113
1114 <?php if ($show_read_more) : ?>
1115 <a class="king-addons-post-grid__button" href="<?php the_permalink(); ?>">
1116 <?php echo esc_html($settings['kng_read_more_text'] ?? esc_html__('Read more', 'king-addons')); ?>
1117 </a>
1118 <?php endif; ?>
1119 </div>
1120 </article>
1121 </div>
1122 <?php
1123 }
1124
1125 protected function get_wrapper_classes(array $settings): array
1126 {
1127 $classes = ['king-addons-post-grid'];
1128
1129 $image_ratio = $settings['kng_image_ratio'] ?? 'original';
1130 if ($image_ratio !== 'original') {
1131 $classes[] = 'king-addons-post-grid--image-ratio-' . sanitize_html_class((string) $image_ratio);
1132 }
1133
1134 $text_align = $settings['kng_text_alignment'] ?? 'left';
1135 $classes[] = 'king-addons-post-grid--text-align-' . sanitize_html_class((string) $text_align);
1136
1137 $button_align = $settings['kng_button_alignment'] ?? 'left';
1138 $classes[] = 'king-addons-post-grid--button-align-' . sanitize_html_class((string) $button_align);
1139
1140 $button_text_align = $settings['kng_button_text_alignment'] ?? 'center';
1141 $classes[] = 'king-addons-post-grid--button-text-align-' . sanitize_html_class((string) $button_text_align);
1142
1143 return array_filter($classes);
1144 }
1145
1146 protected function get_wrapper_style(array $settings): string
1147 {
1148 $style_parts = [];
1149 if (isset($settings['kng_grid_gap']['size'])) {
1150 $style_parts[] = '--kng-post-grid-gap:' . (float) $settings['kng_grid_gap']['size'] . $settings['kng_grid_gap']['unit'] . ';';
1151 }
1152
1153 if (!empty($style_parts)) {
1154 return ' style="' . esc_attr(implode(' ', $style_parts)) . '"';
1155 }
1156
1157 return '';
1158 }
1159
1160 protected function register_pro_notice_controls(): void
1161 {
1162 if (!king_addons_freemius()->can_use_premium_code__premium_only()) {
1163 Core::renderProFeaturesSection($this, '', Controls_Manager::RAW_HTML, 'quick-post-grid', [
1164 'Advanced query (categories) and higher post limits',
1165 'Hover animations and extended styling',
1166 'Navigation/pagination skins (if enabled in grid variant)',
1167 ]);
1168 }
1169 }
1170 }
1171