PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.87
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.87
51.1.87 51.1.86 51.1.84 51.1.85 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 All 41 releases
king-addons / includes / widgets / Quick_Post_Grid / Quick_Post_Grid.php

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

1,173 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:[email protected]?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 'tablet_default' => 2,
430 'mobile_default' => 1,
431 'selectors' => [
432 '{{WRAPPER}} .king-addons-post-grid__grid' => 'grid-template-columns: repeat({{VALUE}}, minmax(0, 1fr));',
433 ],
434 ]
435 );
436
437 $this->add_responsive_control(
438 'kng_grid_gap',
439 [
440 'label' => esc_html__('Gap', 'king-addons'),
441 'type' => Controls_Manager::SLIDER,
442 'size_units' => ['px'],
443 'range' => [
444 'px' => [
445 'min' => 0,
446 'max' => 80,
447 ],
448 ],
449 'default' => [
450 'size' => 20,
451 'unit' => 'px',
452 ],
453 'selectors' => [
454 '{{WRAPPER}} .king-addons-post-grid__grid' => 'gap: {{SIZE}}{{UNIT}};',
455 ],
456 ]
457 );
458
459 $this->end_controls_section();
460 }
461
462 protected function register_style_card_controls(): void
463 {
464 $this->start_controls_section(
465 'kng_style_card_section',
466 [
467 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Card', 'king-addons'),
468 'tab' => Controls_Manager::TAB_STYLE,
469 ]
470 );
471
472 $this->add_control(
473 'kng_card_background',
474 [
475 'label' => esc_html__('Background', 'king-addons'),
476 'type' => Controls_Manager::COLOR,
477 'selectors' => [
478 '{{WRAPPER}} .king-addons-post-grid__card' => 'background-color: {{VALUE}};',
479 ],
480 ]
481 );
482
483 $this->add_control(
484 'kng_card_background_hover',
485 [
486 'label' => esc_html__('Background Hover', 'king-addons'),
487 'type' => Controls_Manager::COLOR,
488 'selectors' => [
489 '{{WRAPPER}} .king-addons-post-grid__card:hover' => 'background-color: {{VALUE}};',
490 ],
491 ]
492 );
493
494 $this->add_group_control(
495 Group_Control_Border::get_type(),
496 [
497 'name' => 'kng_card_border',
498 'selector' => '{{WRAPPER}} .king-addons-post-grid__card',
499 ]
500 );
501
502 $this->add_control(
503 'kng_card_border_color_hover',
504 [
505 'label' => esc_html__('Border Color Hover', 'king-addons'),
506 'type' => Controls_Manager::COLOR,
507 'selectors' => [
508 '{{WRAPPER}} .king-addons-post-grid__card:hover' => 'border-color: {{VALUE}};',
509 ],
510 ]
511 );
512
513 $this->add_control(
514 'kng_card_radius',
515 [
516 'label' => esc_html__('Border Radius', 'king-addons'),
517 'type' => Controls_Manager::SLIDER,
518 'size_units' => ['px', '%'],
519 'range' => [
520 'px' => ['min' => 0, 'max' => 60],
521 '%' => ['min' => 0, 'max' => 100],
522 ],
523 'selectors' => [
524 '{{WRAPPER}} .king-addons-post-grid__card' => 'border-radius: {{SIZE}}{{UNIT}};',
525 ],
526 ]
527 );
528
529 $this->add_group_control(
530 Group_Control_Box_Shadow::get_type(),
531 [
532 'name' => 'kng_card_shadow',
533 'selector' => '{{WRAPPER}} .king-addons-post-grid__card',
534 ]
535 );
536
537 $this->add_group_control(
538 Group_Control_Box_Shadow::get_type(),
539 [
540 'name' => 'kng_card_shadow_hover',
541 'selector' => '{{WRAPPER}} .king-addons-post-grid__card:hover',
542 ]
543 );
544
545 $this->add_control(
546 'kng_card_shadow_disable',
547 [
548 'label' => esc_html__('Disable Box Shadow', 'king-addons'),
549 'type' => Controls_Manager::SWITCHER,
550 'return_value' => 'yes',
551 'default' => '',
552 'selectors' => [
553 '{{WRAPPER}} .king-addons-post-grid__card' => 'box-shadow: none !important;',
554 ],
555 ]
556 );
557
558 $this->add_control(
559 'kng_card_shadow_hover_disable',
560 [
561 'label' => esc_html__('Disable Box Shadow on Hover', 'king-addons'),
562 'type' => Controls_Manager::SWITCHER,
563 'return_value' => 'yes',
564 'default' => '',
565 'selectors' => [
566 '{{WRAPPER}} .king-addons-post-grid__card:hover' => 'box-shadow: none !important;',
567 ],
568 ]
569 );
570
571 $this->add_responsive_control(
572 'kng_card_padding',
573 [
574 'label' => esc_html__('Card Padding', 'king-addons'),
575 'type' => Controls_Manager::DIMENSIONS,
576 'size_units' => ['px', '%', 'em'],
577 'selectors' => [
578 '{{WRAPPER}} .king-addons-post-grid__card' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
579 ],
580 ]
581 );
582
583 $this->end_controls_section();
584 }
585
586 protected function register_style_text_controls(): void
587 {
588 $this->start_controls_section(
589 'kng_style_text_section',
590 [
591 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Text', 'king-addons'),
592 'tab' => Controls_Manager::TAB_STYLE,
593 ]
594 );
595
596 $this->add_group_control(
597 Group_Control_Typography::get_type(),
598 [
599 'name' => 'kng_title_typography',
600 'selector' => '{{WRAPPER}} .king-addons-post-grid__title',
601 ]
602 );
603
604 $this->add_control(
605 'kng_title_color',
606 [
607 'label' => esc_html__('Title Color', 'king-addons'),
608 'type' => Controls_Manager::COLOR,
609 'selectors' => [
610 '{{WRAPPER}} .king-addons-post-grid__title a' => 'color: {{VALUE}};',
611 ],
612 ]
613 );
614
615 $this->add_responsive_control(
616 'kng_title_spacing',
617 [
618 'label' => esc_html__('Title Bottom Spacing', 'king-addons'),
619 'type' => Controls_Manager::SLIDER,
620 'size_units' => ['px'],
621 'range' => [
622 'px' => ['min' => 0, 'max' => 60],
623 ],
624 'selectors' => [
625 '{{WRAPPER}} .king-addons-post-grid__title' => 'margin-bottom: {{SIZE}}{{UNIT}};',
626 ],
627 ]
628 );
629
630 $this->add_group_control(
631 Group_Control_Typography::get_type(),
632 [
633 'name' => 'kng_excerpt_typography',
634 'selector' => '{{WRAPPER}} .king-addons-post-grid__excerpt',
635 ]
636 );
637
638 $this->add_control(
639 'kng_excerpt_color',
640 [
641 'label' => esc_html__('Excerpt Color', 'king-addons'),
642 'type' => Controls_Manager::COLOR,
643 'selectors' => [
644 '{{WRAPPER}} .king-addons-post-grid__excerpt' => 'color: {{VALUE}};',
645 ],
646 ]
647 );
648
649 $this->add_responsive_control(
650 'kng_excerpt_spacing',
651 [
652 'label' => esc_html__('Excerpt Bottom Spacing', 'king-addons'),
653 'type' => Controls_Manager::SLIDER,
654 'size_units' => ['px'],
655 'range' => [
656 'px' => ['min' => 0, 'max' => 80],
657 ],
658 'selectors' => [
659 '{{WRAPPER}} .king-addons-post-grid__excerpt' => 'margin-bottom: {{SIZE}}{{UNIT}};',
660 ],
661 ]
662 );
663
664 $this->add_control(
665 'kng_text_alignment',
666 [
667 'label' => esc_html__('Text Alignment', 'king-addons'),
668 'type' => Controls_Manager::CHOOSE,
669 'options' => [
670 'left' => [
671 'title' => esc_html__('Left', 'king-addons'),
672 'icon' => 'eicon-text-align-left',
673 ],
674 'center' => [
675 'title' => esc_html__('Center', 'king-addons'),
676 'icon' => 'eicon-text-align-center',
677 ],
678 'right' => [
679 'title' => esc_html__('Right', 'king-addons'),
680 'icon' => 'eicon-text-align-right',
681 ],
682 ],
683 'toggle' => false,
684 'default' => 'left',
685 'prefix_class' => 'king-addons-post-grid--text-align-',
686 ]
687 );
688
689 $this->end_controls_section();
690 }
691
692 protected function register_style_meta_controls(): void
693 {
694 $this->start_controls_section(
695 'kng_style_meta_section',
696 [
697 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Meta', 'king-addons'),
698 'tab' => Controls_Manager::TAB_STYLE,
699 'condition' => [
700 'kng_show_meta' => 'yes',
701 ],
702 ]
703 );
704
705 $this->add_group_control(
706 Group_Control_Typography::get_type(),
707 [
708 'name' => 'kng_meta_typography',
709 'selector' => '{{WRAPPER}} .king-addons-post-grid__meta',
710 ]
711 );
712
713 $this->add_control(
714 'kng_meta_color',
715 [
716 'label' => esc_html__('Meta Color', 'king-addons'),
717 'type' => Controls_Manager::COLOR,
718 'selectors' => [
719 '{{WRAPPER}} .king-addons-post-grid__meta' => 'color: {{VALUE}};',
720 ],
721 ]
722 );
723
724 $this->add_responsive_control(
725 'kng_meta_spacing',
726 [
727 'label' => esc_html__('Meta Bottom Spacing', 'king-addons'),
728 'type' => Controls_Manager::SLIDER,
729 'size_units' => ['px'],
730 'range' => [
731 'px' => ['min' => 0, 'max' => 60],
732 ],
733 'selectors' => [
734 '{{WRAPPER}} .king-addons-post-grid__meta' => 'margin-bottom: {{SIZE}}{{UNIT}};',
735 ],
736 ]
737 );
738
739 $this->end_controls_section();
740 }
741
742 protected function register_style_button_controls(): void
743 {
744 $this->start_controls_section(
745 'kng_style_button_section',
746 [
747 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Button', 'king-addons'),
748 'tab' => Controls_Manager::TAB_STYLE,
749 'condition' => [
750 'kng_show_read_more' => 'yes',
751 ],
752 ]
753 );
754
755 $this->add_control(
756 'kng_button_alignment',
757 [
758 'label' => esc_html__('Button Alignment', 'king-addons'),
759 'type' => Controls_Manager::CHOOSE,
760 'options' => [
761 'left' => [
762 'title' => esc_html__('Left', 'king-addons'),
763 'icon' => 'eicon-h-align-left',
764 ],
765 'center' => [
766 'title' => esc_html__('Center', 'king-addons'),
767 'icon' => 'eicon-h-align-center',
768 ],
769 'right' => [
770 'title' => esc_html__('Right', 'king-addons'),
771 'icon' => 'eicon-h-align-right',
772 ],
773 ],
774 'toggle' => false,
775 'default' => 'left',
776 'prefix_class' => 'king-addons-post-grid--button-align-',
777 ]
778 );
779
780 $this->add_control(
781 'kng_button_text_alignment',
782 [
783 'label' => esc_html__('Button Text Alignment', 'king-addons'),
784 'type' => Controls_Manager::CHOOSE,
785 'options' => [
786 'left' => [
787 'title' => esc_html__('Left', 'king-addons'),
788 'icon' => 'eicon-h-align-left',
789 ],
790 'center' => [
791 'title' => esc_html__('Center', 'king-addons'),
792 'icon' => 'eicon-h-align-center',
793 ],
794 'right' => [
795 'title' => esc_html__('Right', 'king-addons'),
796 'icon' => 'eicon-h-align-right',
797 ],
798 ],
799 'toggle' => false,
800 'default' => 'center',
801 'prefix_class' => 'king-addons-post-grid--button-text-align-',
802 ]
803 );
804
805 $this->add_control(
806 'kng_button_full_width',
807 [
808 'label' => esc_html__('Full Width', 'king-addons'),
809 'type' => Controls_Manager::SWITCHER,
810 'return_value' => 'yes',
811 'default' => '',
812 'selectors' => [
813 '{{WRAPPER}} .king-addons-post-grid__button' => 'width: 100%;',
814 ],
815 ]
816 );
817
818 $this->add_group_control(
819 Group_Control_Typography::get_type(),
820 [
821 'name' => 'kng_button_typography',
822 'selector' => '{{WRAPPER}} .king-addons-post-grid__button',
823 ]
824 );
825
826 $this->start_controls_tabs('kng_button_tabs');
827
828 $this->start_controls_tab(
829 'kng_button_tab_normal',
830 [
831 'label' => esc_html__('Normal', 'king-addons'),
832 ]
833 );
834
835 $this->add_control(
836 'kng_button_text_color',
837 [
838 'label' => esc_html__('Text Color', 'king-addons'),
839 'type' => Controls_Manager::COLOR,
840 'selectors' => [
841 '{{WRAPPER}} .king-addons-post-grid__button' => 'color: {{VALUE}};',
842 ],
843 ]
844 );
845
846 $this->add_control(
847 'kng_button_background',
848 [
849 'label' => esc_html__('Background', 'king-addons'),
850 'type' => Controls_Manager::COLOR,
851 'selectors' => [
852 '{{WRAPPER}} .king-addons-post-grid__button' => 'background-color: {{VALUE}};',
853 ],
854 ]
855 );
856
857 $this->add_group_control(
858 Group_Control_Border::get_type(),
859 [
860 'name' => 'kng_button_border',
861 'selector' => '{{WRAPPER}} .king-addons-post-grid__button',
862 ]
863 );
864
865 $this->add_group_control(
866 Group_Control_Box_Shadow::get_type(),
867 [
868 'name' => 'kng_button_shadow',
869 'selector' => '{{WRAPPER}} .king-addons-post-grid__button',
870 ]
871 );
872
873 $this->end_controls_tab();
874
875 $this->start_controls_tab(
876 'kng_button_tab_hover',
877 [
878 'label' => esc_html__('Hover', 'king-addons'),
879 ]
880 );
881
882 $this->add_control(
883 'kng_button_text_color_hover',
884 [
885 'label' => esc_html__('Text Color', 'king-addons'),
886 'type' => Controls_Manager::COLOR,
887 'selectors' => [
888 '{{WRAPPER}} .king-addons-post-grid__button:hover' => 'color: {{VALUE}};',
889 ],
890 ]
891 );
892
893 $this->add_control(
894 'kng_button_background_hover',
895 [
896 'label' => esc_html__('Background', 'king-addons'),
897 'type' => Controls_Manager::COLOR,
898 'selectors' => [
899 '{{WRAPPER}} .king-addons-post-grid__button:hover' => 'background-color: {{VALUE}};',
900 ],
901 ]
902 );
903
904 $this->add_control(
905 'kng_button_border_color_hover',
906 [
907 'label' => esc_html__('Border Color', 'king-addons'),
908 'type' => Controls_Manager::COLOR,
909 'selectors' => [
910 '{{WRAPPER}} .king-addons-post-grid__button:hover' => 'border-color: {{VALUE}};',
911 ],
912 ]
913 );
914
915 $this->add_group_control(
916 Group_Control_Box_Shadow::get_type(),
917 [
918 'name' => 'kng_button_shadow_hover',
919 'selector' => '{{WRAPPER}} .king-addons-post-grid__button:hover',
920 ]
921 );
922
923 $this->end_controls_tab();
924 $this->end_controls_tabs();
925
926 $this->add_responsive_control(
927 'kng_button_spacing',
928 [
929 'label' => esc_html__('Button Top Spacing', 'king-addons'),
930 'type' => Controls_Manager::SLIDER,
931 'size_units' => ['px'],
932 'range' => [
933 'px' => ['min' => 0, 'max' => 80],
934 ],
935 'selectors' => [
936 '{{WRAPPER}} .king-addons-post-grid__button' => 'margin-top: {{SIZE}}{{UNIT}};',
937 ],
938 'separator' => 'before',
939 ]
940 );
941
942 $this->add_responsive_control(
943 'kng_button_padding',
944 [
945 'label' => esc_html__('Padding', 'king-addons'),
946 'type' => Controls_Manager::DIMENSIONS,
947 'size_units' => ['px', '%', 'em'],
948 'selectors' => [
949 '{{WRAPPER}} .king-addons-post-grid__button' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
950 ],
951 'separator' => 'before',
952 ]
953 );
954
955 $this->add_control(
956 'kng_button_radius',
957 [
958 'label' => esc_html__('Border Radius', 'king-addons'),
959 'type' => Controls_Manager::SLIDER,
960 'size_units' => ['px', '%'],
961 'range' => [
962 'px' => ['min' => 0, 'max' => 80],
963 '%' => ['min' => 0, 'max' => 100],
964 ],
965 'selectors' => [
966 '{{WRAPPER}} .king-addons-post-grid__button' => 'border-radius: {{SIZE}}{{UNIT}};',
967 ],
968 ]
969 );
970
971 $this->add_control(
972 'kng_button_shadow_disable',
973 [
974 'label' => esc_html__('Disable Box Shadow', 'king-addons'),
975 'type' => Controls_Manager::SWITCHER,
976 'label_on' => esc_html__('Yes', 'king-addons'),
977 'label_off' => esc_html__('No', 'king-addons'),
978 'return_value' => 'yes',
979 'default' => '',
980 'selectors' => [
981 '{{WRAPPER}} .king-addons-post-grid__button' => 'box-shadow: none !important;',
982 ],
983 ]
984 );
985
986 $this->add_control(
987 'kng_button_shadow_hover_disable',
988 [
989 'label' => esc_html__('Disable Box Shadow on Hover', 'king-addons'),
990 'type' => Controls_Manager::SWITCHER,
991 'label_on' => esc_html__('Yes', 'king-addons'),
992 'label_off' => esc_html__('No', 'king-addons'),
993 'return_value' => 'yes',
994 'default' => '',
995 'selectors' => [
996 '{{WRAPPER}} .king-addons-post-grid__button:hover' => 'box-shadow: none !important;',
997 ],
998 ]
999 );
1000
1001 $this->end_controls_section();
1002 }
1003
1004 protected function build_query(array $settings): WP_Query
1005 {
1006 $per_page = !empty($settings['kng_posts_per_page']) ? (int) $settings['kng_posts_per_page'] : 6;
1007 if (!king_addons_freemius()->can_use_premium_code__premium_only()) {
1008 $per_page = min($per_page, 6);
1009 }
1010
1011 $order = strtoupper((string) ($settings['kng_order'] ?? 'DESC'));
1012 $order = in_array($order, ['ASC', 'DESC'], true) ? $order : 'DESC';
1013
1014 $allowed_orderby = ['date', 'title', 'rand', 'menu_order'];
1015 $orderby = (string) ($settings['kng_orderby'] ?? 'date');
1016 $orderby = in_array($orderby, $allowed_orderby, true) ? $orderby : 'date';
1017
1018 $args = [
1019 'post_type' => 'post',
1020 'posts_per_page' => $per_page,
1021 'order' => $order,
1022 'orderby' => $orderby,
1023 ];
1024
1025 if (!empty($settings['kng_categories']) && king_addons_freemius()->can_use_premium_code__premium_only()) {
1026 $slugs = array_filter(array_map('sanitize_title', array_map('trim', explode(',', (string) $settings['kng_categories']))));
1027 if (!empty($slugs)) {
1028 $args['category_name'] = implode(',', $slugs);
1029 }
1030 }
1031
1032 if (!empty($settings['kng_exclude_sticky'])) {
1033 $args['ignore_sticky_posts'] = true;
1034 }
1035
1036 return new WP_Query($args);
1037 }
1038
1039 protected function render_card(array $settings, bool $card_linkable): void
1040 {
1041 $show_image = $settings['kng_show_image'] === 'yes';
1042 $show_meta = ($settings['kng_show_meta'] ?? '') === 'yes';
1043 $show_author = ($settings['kng_show_author'] ?? 'yes') === 'yes';
1044 $show_date = ($settings['kng_show_date'] ?? 'yes') === 'yes';
1045 $show_excerpt = $settings['kng_show_excerpt'] === 'yes';
1046 $show_read_more = $settings['kng_show_read_more'] === 'yes';
1047
1048 $image_html = '';
1049 if ($show_image) {
1050 if (has_post_thumbnail()) {
1051 $image_html = wp_get_attachment_image(
1052 get_post_thumbnail_id(),
1053 $settings['kng_image_size_size'] ?? 'medium',
1054 false,
1055 ['alt' => esc_attr(get_the_title())]
1056 );
1057 }
1058 if (empty($image_html)) {
1059 $image_html = '<img src="' . esc_url(Utils::get_placeholder_image_src()) . '" alt="' . esc_attr(get_the_title()) . '"/>';
1060 }
1061 }
1062
1063 $excerpt_length = !empty($settings['kng_excerpt_length']) ? (int) $settings['kng_excerpt_length'] : 18;
1064 $excerpt_text = $show_excerpt ? wp_trim_words(get_the_excerpt(), $excerpt_length) : '';
1065
1066 $meta_parts = [];
1067 if ($show_meta) {
1068 if ($show_date) {
1069 $meta_parts[] = get_the_date();
1070 }
1071 if ($show_author) {
1072 $meta_parts[] = get_the_author();
1073 }
1074 }
1075
1076 $meta_separator = isset($settings['kng_meta_separator']) ? trim((string) $settings['kng_meta_separator']) : '•';
1077 $meta_glue = $meta_separator === '' ? ' ' : ' ' . $meta_separator . ' ';
1078
1079 $card_attributes = [];
1080 if ($card_linkable) {
1081 $card_attributes[] = 'data-card-link="' . esc_url(get_permalink()) . '"';
1082 if (($settings['kng_card_link_new_tab'] ?? '') === 'yes') {
1083 $card_attributes[] = 'data-card-link-target="_blank"';
1084 }
1085 $card_attributes[] = 'tabindex="0"';
1086 $card_attributes[] = 'role="link"';
1087 $card_attributes[] = 'aria-label="' . esc_attr(sprintf(__('Open %s', 'king-addons'), get_the_title())) . '"';
1088 }
1089
1090 ?>
1091 <div class="king-addons-post-grid__item">
1092 <article class="king-addons-post-grid__card"<?php echo !empty($card_attributes) ? ' ' . implode(' ', $card_attributes) : ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
1093 <?php if (!empty($image_html)) : ?>
1094 <div class="king-addons-post-grid__media">
1095 <a href="<?php the_permalink(); ?>" class="king-addons-post-grid__media-link">
1096 <?php echo $image_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
1097 </a>
1098 </div>
1099 <?php endif; ?>
1100
1101 <div class="king-addons-post-grid__body">
1102 <h3 class="king-addons-post-grid__title">
1103 <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
1104 </h3>
1105
1106 <?php if (!empty($meta_parts)) : ?>
1107 <div class="king-addons-post-grid__meta">
1108 <?php echo esc_html(implode($meta_glue, $meta_parts)); ?>
1109 </div>
1110 <?php endif; ?>
1111
1112 <?php if (!empty($excerpt_text)) : ?>
1113 <div class="king-addons-post-grid__excerpt"><?php echo esc_html($excerpt_text); ?></div>
1114 <?php endif; ?>
1115
1116 <?php if ($show_read_more) : ?>
1117 <a class="king-addons-post-grid__button" href="<?php the_permalink(); ?>">
1118 <?php echo esc_html($settings['kng_read_more_text'] ?? esc_html__('Read more', 'king-addons')); ?>
1119 </a>
1120 <?php endif; ?>
1121 </div>
1122 </article>
1123 </div>
1124 <?php
1125 }
1126
1127 protected function get_wrapper_classes(array $settings): array
1128 {
1129 $classes = ['king-addons-post-grid'];
1130
1131 $image_ratio = $settings['kng_image_ratio'] ?? 'original';
1132 if ($image_ratio !== 'original') {
1133 $classes[] = 'king-addons-post-grid--image-ratio-' . sanitize_html_class((string) $image_ratio);
1134 }
1135
1136 $text_align = $settings['kng_text_alignment'] ?? 'left';
1137 $classes[] = 'king-addons-post-grid--text-align-' . sanitize_html_class((string) $text_align);
1138
1139 $button_align = $settings['kng_button_alignment'] ?? 'left';
1140 $classes[] = 'king-addons-post-grid--button-align-' . sanitize_html_class((string) $button_align);
1141
1142 $button_text_align = $settings['kng_button_text_alignment'] ?? 'center';
1143 $classes[] = 'king-addons-post-grid--button-text-align-' . sanitize_html_class((string) $button_text_align);
1144
1145 return array_filter($classes);
1146 }
1147
1148 protected function get_wrapper_style(array $settings): string
1149 {
1150 $style_parts = [];
1151 if (isset($settings['kng_grid_gap']['size'])) {
1152 $style_parts[] = '--kng-post-grid-gap:' . (float) $settings['kng_grid_gap']['size'] . $settings['kng_grid_gap']['unit'] . ';';
1153 }
1154
1155 if (!empty($style_parts)) {
1156 return ' style="' . esc_attr(implode(' ', $style_parts)) . '"';
1157 }
1158
1159 return '';
1160 }
1161
1162 protected function register_pro_notice_controls(): void
1163 {
1164 if (!king_addons_freemius()->can_use_premium_code__premium_only()) {
1165 Core::renderProFeaturesSection($this, '', Controls_Manager::RAW_HTML, 'quick-post-grid', [
1166 'Advanced query (categories) and higher post limits',
1167 'Hover animations and extended styling',
1168 'Navigation/pagination skins (if enabled in grid variant)',
1169 ]);
1170 }
1171 }
1172 }
1173