PluginProbe
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder / 51.1.49
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder v51.1.49
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.49, at includes/widgets/Quick_Post_Grid/Quick_Post_Grid.php

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