PluginProbe
UiCore Elements – Free widgets and templates for Elementor / 1.0.14
UiCore Elements – Free widgets and templates for Elementor v1.0.14
1.3.17 1.3.16 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 All 41 releases
uicore-elements / includes / utils / post-component.php

post-component.php in UiCore Elements – Free widgets and templates for Elementor 1.0.14, at includes/utils/post-component.php

1,232 lines 46.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace UiCoreElements\Utils;
3 use Elementor\Controls_Manager;
4 use Elementor\Icons_Manager;
5 use Elementor\Plugin;
6
7 use UiCoreElements\Helper;
8 use UiCoreElements\Controls\Query;
9 use UiCoreElements\Controls\Post_Filter;
10
11 use Elementor\Group_Control_Background;
12 use Elementor\Group_Control_Border;
13 use Elementor\Group_Control_Box_Shadow;
14 use Elementor\Group_Control_Typography;
15 use Elementor\Includes\Widgets\Traits\Button_Trait;
16 use UiCoreElements\Utils\Meta_Trait;
17
18 defined('ABSPATH') || exit();
19
20 /**
21 * Post Component
22 *
23 * @since 1.0.4
24 */
25
26 trait Post_Trait {
27
28 use Button_Trait,
29 Meta_Trait;
30
31 // Control Register Content functions
32 function TRAIT_register_post_item_controls($section = true)
33 {
34 if($section) {
35 $this->start_controls_section(
36 'section_item_content',
37 [
38 'label' => esc_html__('Item', 'uicore-elements'),
39 ]
40 );
41 }
42 $this->add_control(
43 'box_style',
44 [
45 'label' => __('Item Style', 'uicore-elements'),
46 'type' => Controls_Manager::SELECT,
47 'default' => 'classic',
48 'options' => [
49 'classic' => __('Classic', 'uicore-elements'),
50 'split' => __('Split', 'uicore-elements'),
51 'overlay' => __('Overlay', 'uicore-elements'),
52 ],
53 'render_type' => 'template',
54 'prefix_class' => 'ui-e-apg-',
55 ]
56 );
57 $this->add_control(
58 'image',
59 [
60 'label' => __('Image', 'uicore-elements'),
61 'type' => Controls_Manager::SWITCHER,
62 'separator' => 'before',
63 'default' => 'yes'
64 ]
65 );
66 $this->add_control(
67 'image_size_select',
68 [
69 'label' => __('Image Size', 'uicore-elements'),
70 'type' => Controls_Manager::SELECT,
71 'default' => 'uicore-medium',
72 'options' => Helper::get_images_sizes(),
73 'separator' => 'after',
74 'condition' => [
75 'image' => 'yes',
76 ]
77 ]
78 );
79 $this->add_control(
80 'title',
81 [
82 'label' => __('Title', 'uicore-elements'),
83 'type' => Controls_Manager::SWITCHER,
84 'default' => 'yes'
85 ]
86 );
87 $this->add_control(
88 'excerpt',
89 [
90 'label' => __('Excerpt', 'uicore-elements'),
91 'type' => Controls_Manager::SWITCHER,
92 'default' => 'yes'
93 ]
94 );
95 $this->add_control(
96 'excerpt_trim',
97 [
98 'label' => __('Excerpt Length (words)', 'uicore-elements'),
99 'type' => Controls_Manager::NUMBER,
100 'min' => 5,
101 'max' => 100,
102 'step' => 1,
103 'default' => 55,
104 'separator' => 'after',
105 'condition' => array(
106 'excerpt' => 'yes',
107 ),
108 ]
109 );
110 $this->add_control(
111 'show_button',
112 [
113 'label' => __('Read More Button', 'uicore-elements'),
114 'type' => Controls_Manager::SWITCHER,
115 'default' => 'no'
116 ]
117 );
118
119 if($section) {
120 $this->end_controls_section();
121 }
122 }
123 function TRAIT_register_post_button_controls($section = true)
124 {
125 if($section){
126 $this->start_controls_section(
127 'section_button_content',
128 [
129 'label' => esc_html__('Button', 'uicore-elements'),
130 'condition' => array(
131 'show_button' => 'yes',
132 ),
133 ]
134 );
135 }
136
137 $this->register_button_content_controls(
138 [
139 'section_condition' => [
140 'show_button' => 'yes'
141 ],
142 'button_default_text' => 'Read More'
143 ]
144 );
145 $this->remove_control('button_type');
146 $this->remove_control('link');
147 $this->remove_control('button_css_id');
148 $this->remove_control('size');
149 $this->remove_control('align');
150
151 if($section){
152 $this->end_controls_section();
153 }
154 }
155 /**
156 * Register Post Meta Controls.
157 *
158 * @param bool $section. Print section or not.
159 * @param bool $product_metas. If true, will only print options that relates with products.
160 */
161 function TRAIT_register_post_meta_controls($section = true, $product_metas = false)
162 {
163 if($section){
164 $this->start_controls_section(
165 'section_extra_item_content',
166 [
167 'label' => esc_html__('Meta', 'uicore-elements'),
168 ]
169 );
170 }
171
172 $this->add_control(
173 'top_meta',
174 [
175 'label' => esc_html__('Top Meta', 'uicore-elements'),
176 'type' => \Elementor\Controls_Manager::REPEATER,
177 'fields' => $this->get_meta_content_controls($product_metas),
178 'default' => [
179 [
180 'type' => $product_metas ? 'product sale' : 'category'
181 ],
182 ],
183 'title_field' => '<span style="text-transform: capitalize">{{{ type }}}</span>',
184 'prevent_empty' => false,
185 'separator' => 'before'
186 ]
187 );
188 $this->add_control(
189 'before_title_meta',
190 [
191 'label' => esc_html__('Before Title Meta', 'uicore-elements'),
192 'type' => \Elementor\Controls_Manager::REPEATER,
193 'fields' => $this->get_meta_content_controls($product_metas),
194 'default' => [
195 [
196 'type' => $product_metas ? 'none' : 'author'
197 ],
198 ],
199 'title_field' => '<span style="text-transform: capitalize">{{{ type }}}</span>',
200 'prevent_empty' => false,
201 'separator' => 'before',
202 ]
203 );
204 $this->add_control(
205 'after_title_meta',
206 [
207 'label' => esc_html__('After Title Meta', 'uicore-elements'),
208 'type' => \Elementor\Controls_Manager::REPEATER,
209 'fields' => $this->get_meta_content_controls($product_metas),
210 'default' => [
211 [
212 'type' => $product_metas ? 'product price' : 'date'
213 ],
214 ],
215 'title_field' => '<span style="text-transform: capitalize">{{{ type }}}</span>',
216 'prevent_empty' => false,
217 'separator' => 'before',
218 ]
219 );
220 $this->add_control(
221 'bottom_meta',
222 [
223 'label' => esc_html__('Bottom Meta', 'uicore-elements'),
224 'type' => \Elementor\Controls_Manager::REPEATER,
225 'fields' => $this->get_meta_content_controls($product_metas),
226 'default' => [
227 [
228 'type' => $product_metas ? 'none' : 'none'
229 ],
230 ],
231 'title_field' => '<span style="text-transform: capitalize">{{{ type }}}</span>',
232 'prevent_empty' => false,
233 'separator' => 'before',
234 ]
235 );
236 if($section){
237 $this->end_controls_section();
238 }
239 }
240 function TRAIT_register_post_query_controls($section = true)
241 {
242 if($section){
243 $this->start_controls_section(
244 'section_post_grid_def',
245 [
246 'label' => esc_html__('Query', 'uicore-elements'),
247 ]
248 );
249 }
250
251 $this->add_group_control(
252 Post_Filter::get_type(),
253 [
254 'name' => 'posts-filter',
255 'label' => esc_html__('Posts', 'uicore-elements'),
256 'description' => esc_html__('Current Query Settings > Reading', 'uicore-elements'),
257 ]
258 );
259 $this->add_control(
260 'item_limit',
261 [
262 'label' => esc_html__('Item Limit', 'uicore-elements'),
263 'type' => Controls_Manager::SLIDER,
264 'reder_type' => 'template',
265 'range' => [
266 'px' => [
267 'min' => -1,
268 'max' => 100,
269 ],
270 ],
271 'default' => [
272 'size' => 3,
273 ],
274 'condition' => array(
275 'posts-filter_post_type!' => 'current',
276 ),
277 ]
278 );
279
280 $this->add_control(
281 'offset',
282 [
283 'label' => esc_html__('Query Offset', 'uicore-elements'),
284 'type' => Controls_Manager::SLIDER,
285 'render_type' => 'template',
286 'range' => [
287 'px' => [
288 'min' => -1,
289 'max' => 10,
290 ],
291 ],
292 'default' => [
293 'size' => 0,
294 ],
295 'condition' => [
296 'pagination_type' => 'numbers',
297 ]
298 ]
299 );
300
301 $this->add_control(
302 'offset_alert',
303 [
304 'type' => Controls_Manager::ALERT,
305 'alert_type' => 'info',
306 'content' => esc_html__('Offset is disabled with Load More pagination.', 'uicore-elements'),
307 'condition' => [
308 'pagination_type!' => 'numbers',
309 ]
310 ]
311 );
312
313 $this->add_control(
314 'sticky',
315 [
316 'label' => esc_html__('Sticky Posts', 'uicore-elements'),
317 'type' => Controls_Manager::SWITCHER,
318 'label_on' => esc_html__('Show', 'uicore-elements'),
319 'label_off' => esc_html__('Hide', 'uicore-elements'),
320 'description' => esc_html__('Sticky posts works only on the front-end.', 'uicore-elements'),
321 'return_value' => 1,
322 'default' => 0,
323 'condition' => [
324 'pagination!' => 'yes',
325 ],
326 ]
327 );
328
329 if($section){
330 $this->end_controls_section();
331 }
332 }
333
334 // Control Register Styles functions
335 function TRAIT_register_post_item_style_controls($section = true, $active_tab = false)
336 {
337 if($section){
338 $this->start_controls_section(
339 'section_style_item',
340 [
341 'label' => __('Item Style', 'uicore-elements'),
342 'tab' => Controls_Manager::TAB_STYLE,
343 ]
344 );
345 }
346
347 $this->start_controls_tabs(
348 'item_border_shadow'
349 );
350
351 $this->start_controls_tab(
352 'item_bs_normal_tab',
353 [
354 'label' => esc_html__('Normal', 'plugin-name'),
355 ]
356 );
357 $this->add_group_control(
358 Group_Control_Border::get_type(),
359 [
360 'name' => 'item_border',
361 'selector' => '{{WRAPPER}} .ui-e-item article',
362 ]
363 );
364 $this->add_group_control(
365 Group_Control_Box_Shadow::get_type(),
366 [
367 'name' => 'item_shadow',
368 'selector' => '{{WRAPPER}} .ui-e-item article',
369 ]
370 );
371 $this->end_controls_tab();
372
373 $this->start_controls_tab(
374 'item_bs_hover_tab',
375 [
376 'label' => esc_html__('Hover', 'plugin-name'),
377 ]
378 );
379 $this->add_group_control(
380 Group_Control_Border::get_type(),
381 [
382 'name' => 'item_border_hover',
383 'selector' => '{{WRAPPER}} .ui-e-item:hover article',
384 ]
385 );
386 $this->add_group_control(
387 Group_Control_Box_Shadow::get_type(),
388 [
389 'name' => 'item_shadow_hover',
390 'selector' => '{{WRAPPER}} .ui-e-item:hover article',
391 ]
392 );
393 $this->end_controls_tab();
394
395 if($active_tab){
396 $this->start_controls_tab(
397 'item_bs_active_tab',
398 [
399 'label' => esc_html__('Active', 'plugin-name'),
400 ]
401 );
402 $this->add_group_control(
403 Group_Control_Border::get_type(),
404 [
405 'name' => 'item_border_active',
406 'selector' => '{{WRAPPER}} .ui-e-item.ui-e-active article',
407 ]
408 );
409 $this->add_group_control(
410 Group_Control_Box_Shadow::get_type(),
411 [
412 'name' => 'item_shadow_active',
413 'selector' => '{{WRAPPER}} .ui-e-item.ui-e-active article',
414 ]
415 );
416 $this->end_controls_tab();
417 }
418
419 $this->end_controls_tabs();
420
421 $this->add_control(
422 'item_radius',
423 [
424 'label' => esc_html__('Border Radius', 'uicore-elements'),
425 'type' => Controls_Manager::DIMENSIONS,
426 'separator' => 'before',
427 'selectors' => [
428 '{{WRAPPER}} ' => '--ui-e-border-radius: {{TOP}}px {{RIGHT}}px {{BOTTOM}}px {{LEFT}}px;'
429 ],
430 ]
431 );
432
433 if($section){
434 $this->end_controls_section();
435 }
436 }
437 function TRAIT_register_post_content_style_controls($section = true)
438 {
439 if($section){
440 $this->start_controls_section(
441 'section_style_content',
442 [
443 'label' => __('Content Style', 'uicore-elements'),
444 'tab' => Controls_Manager::TAB_STYLE,
445 ]
446 );
447 }
448 $this->add_control(
449 'image_size',
450 [
451 'label' => __('Image Height (%)', 'uicore-elements'),
452 'type' => Controls_Manager::NUMBER,
453 'min' => 1,
454 'max' => 500,
455 'step' => 1,
456 'default' => 57,
457 'selectors' => [
458 '{{WRAPPER}} .ui-e-post-top' => '--ui-e-img-size: {{VALUE}}',
459 ],
460 'condition' => [
461 'masonry!' => 'ui-e-maso',
462 ],
463 ]
464 );
465 $this->add_control(
466 'image_overflow',
467 [
468 'label' => __('Independent Border Radius and Shadow', 'uicore-elements'),
469 'type' => Controls_Manager::SWITCHER,
470 'default' => 'no',
471 'prefix_class' => 'ui-e-post-ovf-',
472 'condition' => array(
473 'box_style!' => 'overlay',
474 ),
475 ]
476 );
477 $this->add_control(
478 'image_radius',
479 [
480 'label' => esc_html__('Border Radius', 'uicore-elements'),
481 'type' => Controls_Manager::DIMENSIONS,
482 'selectors' => [
483 '{{WRAPPER}} .ui-e-post-top' => 'border-radius: {{TOP}}px {{RIGHT}}px {{BOTTOM}}px {{LEFT}}px;'
484 ],
485 'condition' => array(
486 'image_overflow' => 'yes',
487 ),
488 ]
489 );
490 $this->add_group_control(
491 Group_Control_Box_Shadow::get_type(),
492 [
493 'name' => 'image_shadow',
494 'label' => esc_html__('Box Shadow', 'uicore-elements'),
495 'selector' => '{{WRAPPER}} .ui-e-post-top',
496 'condition' => array(
497 'image_overflow' => 'yes',
498 ),
499 ]
500 );
501 $this->add_responsive_control(
502 'content_alignment',
503 [
504 'label' => esc_html__('Content Alignment', 'uicore-elements'),
505 'type' => Controls_Manager::CHOOSE,
506 'options' => [
507 'left' => [
508 'title' => esc_html__('Left', 'uicore-elements'),
509 'icon' => 'eicon-text-align-left',
510 ],
511 'center' => [
512 'title' => esc_html__('Center', 'uicore-elements'),
513 'icon' => 'eicon-text-align-center',
514 ],
515 'stretch' => [
516 'title' => esc_html__('Justified', 'uicore-elements'),
517 'icon' => 'eicon-text-align-justify',
518 ],
519 ],
520 'selectors' => [
521 '{{WRAPPER}} .ui-e-post-content' => 'align-items: {{VALUE}}; text-align: {{VALUE}};',
522 ],
523 ]
524 );
525 $this->add_control(
526 'title_color',
527 [
528 'label' => esc_html__('Title Color', 'uicore-elements'),
529 'type' => Controls_Manager::COLOR,
530 'default' => '',
531 'separator' => 'before',
532 'selectors' => [
533 '{{WRAPPER}} .ui-e-post-title' => 'color: {{VALUE}};',
534 ],
535 ]
536 );
537 $this->add_control(
538 'title_hcolor',
539 [
540 'label' => esc_html__('Title Hover Color', 'uicore-elements'),
541 'type' => Controls_Manager::COLOR,
542 'default' => '',
543 'selectors' => [
544 '{{WRAPPER}} .ui-e-post-title:hover' => 'color: {{VALUE}};',
545 ],
546 ]
547 );
548 $this->add_group_control(
549 Group_Control_Typography::get_type(),
550 [
551 'name' => 'title_typography',
552 'label' => esc_html__('Title Typography', 'uicore-elements'),
553 'selector' => '{{WRAPPER}} .ui-e-post-title',
554 ]
555 );
556 $this->add_control(
557 'title_gap',
558 [
559 'label' => __('Title Top Space', 'uicore-elements'),
560 'type' => Controls_Manager::SLIDER,
561 'size_units' => ['em'],
562 'separator' => 'after',
563 'range' => [
564 'px' => [
565 'min' => 0,
566 'max' => 3,
567 'step' => 0.1,
568 ],
569 ],
570 'default' => [
571 'unit' => 'em',
572 'size' => 1.2,
573 ],
574 'selectors' => [
575 '{{WRAPPER}} .ui-e-post-title' => 'margin-top: {{SIZE}}em;',
576 ],
577 ]
578 );
579 $this->add_control(
580 'text_color',
581 [
582 'label' => esc_html__('Excerpt Color', 'uicore-elements'),
583 'type' => Controls_Manager::COLOR,
584 'default' => '',
585 'selectors' => [
586 '{{WRAPPER}} .ui-e-post-text' => 'color: {{VALUE}};',
587 ],
588 ]
589 );
590 $this->add_group_control(
591 Group_Control_Typography::get_type(),
592 [
593 'name' => 'text_typography',
594 'label' => esc_html__('Excerpt Typography', 'uicore-elements'),
595 'selector' => '{{WRAPPER}} .ui-e-post-text',
596 ]
597 );
598 $this->add_control(
599 'text_gap',
600 [
601 'label' => __('Excerpt Top Space', 'uicore-elements'),
602 'type' => Controls_Manager::SLIDER,
603 'size_units' => ['em'],
604 'separator' => 'after',
605 'range' => [
606 'px' => [
607 'min' => 0,
608 'max' => 3,
609 'step' => 0.1,
610 ],
611 ],
612 'default' => [
613 'unit' => 'em',
614 'size' => 0.8,
615 ],
616 'selectors' => [
617 '{{WRAPPER}} .ui-e-post-text' => 'margin-top: {{SIZE}}em;',
618 ],
619 ]
620 );
621 $this->add_responsive_control(
622 'content_padding',
623 [
624 'label' => esc_html__('Content Padding', 'uicore-elements'),
625 'type' => Controls_Manager::DIMENSIONS,
626 'size_units' => ['px', 'em', '%'],
627 'selectors' => [
628 '{{WRAPPER}} .ui-e-post-content' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};'
629 ]
630 ]
631 );
632 $this->add_control(
633 'content_gap',
634 [
635 'label' => __('Content Space', 'uicore-elements'),
636 'type' => Controls_Manager::SLIDER,
637 'size_units' => ['em'],
638 'separator' => 'after',
639 'range' => [
640 'px' => [
641 'min' => 0,
642 'max' => 3,
643 'step' => 0.1,
644 ],
645 ],
646 'default' => [
647 'unit' => 'em',
648 'size' => 0,
649 ],
650 'selectors' => [
651 '{{WRAPPER}} ' => '--ui-e-content-space: {{SIZE}}em;',
652 ],
653 ]
654 );
655 $this->add_group_control(
656 Group_Control_Background::get_type(),
657 [
658 'name' => 'content_bg',
659 'selector' => '{{WRAPPER}} .ui-e-post-content',
660 ]
661 );
662
663 if($section){
664 $this->end_controls_section();
665 }
666 }
667 function TRAIT_register_post_button_style_controls($section = true)
668 {
669 if($section){
670 $this->start_controls_section(
671 'section_button_style',
672 [
673 'label' => esc_html__('Button Style', 'uicore-elements'),
674 'tab' => Controls_Manager::TAB_STYLE,
675 'condition' => array(
676 'show_button' => 'yes',
677 ),
678 ]
679 );
680 }
681 $this->add_responsive_control(
682 'button_align',
683 [
684 'label' => esc_html__( 'Alignment', 'elementor' ),
685 'type' => Controls_Manager::CHOOSE,
686 'options' => [
687 'start' => [
688 'title' => esc_html__( 'Left', 'elementor' ),
689 'icon' => 'eicon-text-align-left',
690 ],
691 'center' => [
692 'title' => esc_html__( 'Center', 'elementor' ),
693 'icon' => 'eicon-text-align-center',
694 ],
695 'end' => [
696 'title' => esc_html__( 'Right', 'elementor' ),
697 'icon' => 'eicon-text-align-right',
698 ],
699 'normal' => [
700 'title' => esc_html__( 'Justified', 'elementor' ),
701 'icon' => 'eicon-text-align-justify',
702 ],
703 ],
704 'default' => 'start',
705 'selectors' => [
706 '{{WRAPPER}} .ui-e-readmore' => 'align-self: {{VALUE}};',
707 ],
708
709 ]
710 );
711 $this->register_button_style_controls(
712 [
713 'section_condition' => [
714 'show_button' => 'yes'
715 ]
716 ]
717 );
718 // Remove button alignment from Elementor button traits because (seens to be a bug), updating Selector CSS with update_control(), don't work as expected with responsiveness
719 $this->remove_responsive_control('align');
720
721 $this->TRAIT_register_post_specific_controls('button_gap');
722
723 if($section) {
724 $this->end_controls_section();
725 }
726 }
727 function TRAIT_register_post_meta_style_controls($section = true)
728 {
729 if($section) {
730 $this->start_controls_section(
731 'section_style_extra_content',
732 [
733 'label' => __('Meta Style', 'uicore-elements'),
734 'tab' => Controls_Manager::TAB_STYLE,
735 ]
736 );
737 }
738 $this->start_controls_tabs('style_extra_tabs');
739 $this->start_controls_tab(
740 'style_top_tab',
741 [
742 'label' => esc_html__('Top', 'uicore-elements'),
743 ]
744 );
745 $this->get_meta_style_controls('top');
746 $this->end_controls_tab();
747
748 $this->start_controls_tab(
749 'style_before_title_tab',
750 [
751 'label' => esc_html__('Before Title', 'uicore-elements'),
752 ]
753 );
754 $this->get_meta_style_controls('before_title');
755 $this->end_controls_tab();
756
757 $this->start_controls_tab(
758 'style_after_title_tab',
759 [
760 'label' => esc_html__('After Title', 'uicore-elements'),
761 ]
762 );
763 $this->get_meta_style_controls('after_title');
764 $this->end_controls_tab();
765
766 $this->start_controls_tab(
767 'style_bottom_tab',
768 [
769 'label' => esc_html__('Bottom', 'uicore-elements'),
770 ]
771 );
772 $this->get_meta_style_controls('bottom');
773 $this->end_controls_tab();
774 $this->end_controls_tabs();
775
776 if($section) {
777 $this->end_controls_section();
778 }
779 }
780 function TRAIT_register_post_animation_controls()
781 {
782 $this->add_control(
783 'anim_image',
784 [
785 'label' => __('Image Hover Animation', 'uicore-elements'),
786 'type' => Controls_Manager::SELECT,
787 'label_block' => true,
788 'default' => 'ui-e-img-anim-zoom',
789 'options' => [
790 '' => __('None', 'uicore-elements'),
791 'ui-e-img-anim-zoom' => __('Zoom', 'uicore-elements'),
792 ],
793 'prefix_class' => '',
794 ]
795 );
796 $this->add_control(
797 'anim_meta',
798 [
799 'label' => __('Meta Hover Animation', 'uicore-elements'),
800 'type' => Controls_Manager::SELECT,
801 'label_block' => true,
802 'default' => '',
803 'options' => [
804 '' => __('None', 'uicore-elements'),
805 'ui-e-meta-anim-show' => __('Show', 'uicore-elements'),
806 ],
807 'prefix_class' => '',
808 ]
809 );
810 $this->add_control(
811 'important_note',
812 [
813 'label' => esc_html__('Important Note', 'uicore-elements'),
814 'type' => \Elementor\Controls_Manager::RAW_HTML,
815 'raw' => '<div class="elementor-control-field-description" style="margin-top: -7px;">' . esc_html__('This works only for Below Title Meta.', 'uicore-elements') . '</div>',
816 'show_label' => false,
817 'condition' => array(
818 'box_style' => 'overlay',
819 ),
820 ]
821 );
822 $this->add_control(
823 'anim_title',
824 [
825 'label' => __('Title Hover Animation', 'uicore-elements'),
826 'type' => Controls_Manager::SELECT,
827 'label_block' => true,
828 'default' => '',
829 'options' => [
830 '' => __('None', 'uicore-elements'),
831 'ui-e-title-anim-underline' => __('Underline', 'uicore-elements'),
832 ],
833 'prefix_class' => '',
834 ]
835 );
836 $this->add_control(
837 'anim_content',
838 [
839 'label' => __('Content Hover Animation', 'uicore-elements'),
840 'type' => Controls_Manager::SELECT,
841 'label_block' => true,
842 'default' => '',
843 'options' => [
844 '' => __('None', 'uicore-elements'),
845 'ui-e-content-anim-show' => __('Show', 'uicore-elements'),
846 ],
847 'prefix_class' => '',
848 'condition' => array(
849 'box_style' => 'overlay',
850 ),
851 ]
852 );
853 $this->add_control(
854 'anim_btn',
855 [
856 'label' => __('Button Hover Animation', 'uicore-elements'),
857 'type' => Controls_Manager::SELECT,
858 'label_block' => true,
859 'default' => '',
860 'options' => [
861 '' => __('None', 'uicore-elements'),
862 'ui-e-btn-anim-show' => __('Show', 'uicore-elements'),
863 ],
864 'prefix_class' => '',
865 'condition' => [
866 'show_button' => 'yes',
867 ],
868 ]
869 );
870 }
871 /**
872 * Registers specific controls that can't be registered in blocks because of diferent use by different widgets or some other reason.
873 * TODO: update to the use injection control, a better approach.
874 *
875 * @param string $control The control to register.
876 * @return void
877 */
878 function TRAIT_register_post_specific_controls($control)
879 {
880 switch ($control) {
881 case 'button_gap':
882 $this->add_control(
883 'button_gap',
884 [
885 'label' => __('Button Top Space', 'uicore-elements'),
886 'type' => Controls_Manager::SLIDER,
887 'size_units' => ['em'],
888 'range' => [
889 'px' => [
890 'min' => 0,
891 'max' => 3,
892 'step' => 0.1,
893 ],
894 ],
895 'default' => [
896 'unit' => 'em',
897 'size' => 0.8,
898 ],
899 'selectors' => [
900 '{{WRAPPER}} .elementor-button' => 'margin-top: {{SIZE}}em;',
901 ],
902 ]
903 );
904 break;
905 }
906 }
907
908 /**
909 * Returns the proper query args for a given post type.
910 *
911 * @param array $settings Elementor controls settings.
912 * @param object $default_query The default query object. Used to tell if is a frontend or rest api request.
913 *
914 * @return void Don't return anything, but sets the query object to $_query variable that can be accessed by the widget.
915 */
916 function TRAIT_query_posts($settings, $default_query)
917 {
918 $post_type = $settings['posts-filter_post_type'];
919
920 if ( $post_type === 'related' ) {
921 $this->_query = Helper::get_related('random', $settings['item_limit']['size']);
922
923 } else {
924 $query_args = Query::get_query_args('posts-filter', $settings);
925
926 if ($post_type === 'current') {
927 $query_args = $default_query;
928
929 // Post type fallback for APG
930 if( isset($default_query['post_type']) || isset($default_query['query']['post_type']) ){
931 $post_type = $default_query['post_type'] ?? $default_query['query']['post_type'];
932 } else {
933 $post_type = 'post';
934 }
935
936 // Set pagination
937 $query_args['paged'] = Query::get_queried_page($settings);
938
939 // Set tax filters for filter component, if enabled
940 $queried_filters = Query::get_queried_filters($settings, get_post_type(), 'posts-filter');
941 $query_args['tax_query'] = empty($queried_filters['tax_query']) ? [] : $queried_filters['tax_query'];
942 }
943
944 if ($post_type === 'portfolio') {
945 $query_args['orderby'] = 'menu_order date';
946 }
947
948 $this->_query = new \WP_Query($query_args);
949 }
950 }
951
952 /**
953 * Match each meta icon size (if SVG) with the correspondent font size set by the user.
954 *
955 * @param array $settings Elementor controls settings.
956 *
957 * @return void
958 */
959 function TRAIT_set_meta_font_size_to_svg($settings)
960 {
961 // Required specifically for SVG icons
962 if( \Elementor\Plugin::$instance->experiments->is_feature_active('e_font_icon_svg') == false ){
963 return;
964 }
965
966 // Get all available metas
967 $metas = ['top_meta', 'before_title_meta', 'after_title_meta', 'bottom_meta'];
968 $metas_css = '';
969 $default_size = '16px';
970
971 // Creates a variable for each meta font-size and set a font-size, falling back to default size as last resource.
972 foreach ($metas as $meta) {
973
974 // Check if current meta has a font-size set.
975 ${$meta . '_size'} = isset( $settings[$meta . '_typography_font_size'] ) ? $settings[$meta . '_typography_font_size'] : $default_size;
976
977 // Check if the font-size value is not empty (user might customize other infos but not the font-size)
978 ${$meta . '_size'} = !empty( ${$meta .'_size'}['size'] )
979 ? ${$meta .'_size'}['size'] . ${$meta .'_size'}['unit']
980 : $default_size;
981
982 // Creates the css variable
983 $metas_css .= '--' . $meta . '-font-size: ' . esc_html(${$meta . '_size'}) . ';';
984 }
985
986 // print it on the main widget wrapper
987 $this->add_render_attribute(
988 '_wrapper',
989 'style',
990 $metas_css
991 );
992 }
993
994 // Render functions
995 function get_post_image()
996 {
997 if ($this->get_settings_for_display('image') !== 'yes') {
998 return;
999 }
1000
1001 $pic_id = get_post_thumbnail_id();
1002 if (!$pic_id)
1003 return;
1004 $size = $this->get_settings_for_display('image_size_select') ?? 'uicore-medium';
1005 ?>
1006 <a class="ui-e-post-img-wrapp"
1007 href="<?php echo esc_url(get_permalink()); ?>"
1008 title="<?php echo esc_attr__('View Post:', 'uicore-elements') . the_title_attribute(['echo' => false]); ?>">
1009
1010 <?php if ($this->get_settings_for_display('masonry') === 'ui-e-maso') { ?>
1011 <?php the_post_thumbnail($size, ['class' => 'ui-e-post-img']); ?>
1012 <?php } else { ?>
1013 <div class="ui-e-post-img" style="background-image:url(<?php echo wp_get_attachment_image_url($pic_id, $size) ?>)"></div>
1014 <?php } ?>
1015 </a>
1016 <?php
1017
1018 }
1019 function get_post_title()
1020 {
1021 if ($this->get_settings_for_display('title') !== 'yes') {
1022 return;
1023 }
1024 ?>
1025 <a href="<?php echo esc_url( get_permalink() );?>" title="<?php echo esc_attr__('View Post:','uicore-elements') . esc_html(the_title_attribute(['echo'=>false])); ?>">
1026 <h4 class="ui-e-post-title"><span><?php echo esc_html(get_the_title()); ?></span></h4>
1027 </a>
1028 <?php
1029 }
1030 function get_post_meta($position)
1031 {
1032 $meta_list = $this->get_settings_for_display($position . '_meta');
1033 if (!isset($meta_list[0]) || $meta_list[0]['type'] == '') {
1034 return;
1035 }
1036 echo ($position == 'top') ? '<div class="ui-e-post-top-meta">' : '';
1037 echo ($position == 'after_title') ? '<div class="ui-e-meta-wrapp">' : '';
1038 echo '<div class="ui-e-post-meta ui-e-'.esc_attr($position).'">';
1039 foreach ($meta_list as $meta) {
1040 if($meta['type'] != 'none'){
1041 $this->display_meta($meta);
1042
1043 if( next( $meta_list ) && $this->get_settings_for_display( $position.'_meta_separator' ) ) {
1044 echo '<span class="ui-e-separator">'.esc_html($this->get_settings_for_display( $position.'_meta_separator' )).'</span>';
1045 }
1046 }
1047 }
1048 echo '</div>';
1049 echo ($position == 'top' || $position == 'after_title') ? '</div>' : '';
1050 }
1051 /**
1052 * Render the post read more button.
1053 *
1054 * @param bool $is_product. If true, will render an add to cart button.
1055 *
1056 * @return void
1057 */
1058 function TRAIT_get_button($is_product = false)
1059 {
1060 $settings = $this->get_settings_for_display();
1061
1062 if( $is_product ){
1063 global $product;
1064
1065 // Get default add to cart text as fallback
1066 $settings['text'] = empty($settings['text']) ? $product->add_to_cart_text() : $settings['text'];
1067 }
1068
1069 $this->add_render_attribute('button', [
1070 'class' => ['elementor-button-link', 'elementor-button', 'ui-e-readmore'],
1071 'role' => 'button',
1072 ]);
1073 $this->add_render_attribute('content-wrapper', 'class', 'elementor-button-content-wrapper');
1074
1075 if (!empty($settings['button_css_id'])) {
1076 $this->add_render_attribute('button', 'id', $settings['button_css_id']);
1077 }
1078
1079 if (!empty($settings['size'])) {
1080 $this->add_render_attribute('button', 'class', 'elementor-size-' . $settings['size']);
1081 }
1082
1083 if (!empty($settings['hover_animation'])) {
1084 $this->add_render_attribute('button', 'class', 'elementor-animation-' . $settings['hover_animation']);
1085 }
1086
1087 $btn_classes = isset($settings['icon_align'])
1088 ? ['elementor-button-icon', 'elementor-align-icon-' . $settings['icon_align'] ]
1089 : 'elementor-button-icon';
1090
1091 $this->add_render_attribute([
1092 'icon-align' => [
1093 'class' => $btn_classes
1094 ],
1095 'text' => [
1096 'class' => 'elementor-button-text',
1097 ],
1098 ]);
1099
1100 if( isset($settings['icon_align']) ){
1101 $this->add_render_attribute('content-wrapper', 'class', 'elementor-button-content');
1102 }
1103
1104 $tbn_content = '<span ' . $this->get_render_attribute_string('content-wrapper') . '>';
1105
1106 if (!empty($settings['icon']) || !empty($settings['selected_icon']['value'])) {
1107 $tbn_content .= '<span ' . $this->get_render_attribute_string('icon-align') . '>';
1108 \ob_start();
1109 Icons_Manager::render_icon($settings['selected_icon'], ['aria-hidden' => 'true']);
1110 $tbn_content .= \ob_get_clean();
1111 $tbn_content .= '</span>';
1112 }
1113
1114 $tbn_content .= '<span ' . $this->get_render_attribute_string('text') . '>';
1115 $tbn_content .= $settings['text'];
1116 $tbn_content .= '</span> </span>';
1117
1118 // WooCommerce add to cart button
1119 if ($is_product) {
1120 if ($product) {
1121 echo Helper::esc_svg(apply_filters(
1122 'woocommerce_loop_add_to_cart_link', // WPCS: XSS ok.
1123 sprintf(
1124 '<a href="%s" data-quantity="%s" %s>%s</a>',
1125 esc_url($product->add_to_cart_url()),
1126 esc_attr(1),
1127 $this->get_render_attribute_string('button'),
1128 $tbn_content
1129 ),
1130 $product
1131 ));
1132 }
1133
1134 // Default button
1135 } else {
1136 ?>
1137 <a href="<?php echo esc_url(get_permalink()); ?>" <?php $this->print_render_attribute_string('button'); ?>>
1138 <?php echo Helper::esc_svg( $tbn_content ); ?>
1139 </a>
1140 <?php
1141 }
1142 }
1143 /**
1144 * Renders a post item with various settings and options.
1145 * Important: any changes here should also be considered to `TRAIT_render_product()` from Product Component.
1146 *
1147 * @param bool $carousel Indicates if the item needs carousel classnames.
1148 * @param bool $legacy Indicates if the item is using legacy classnames.
1149 *
1150 * @return void
1151 */
1152 function TRAIT_render_item($carousel = false, $legacy = false)
1153 {
1154 $settings = $this->get_settings_for_display();
1155 $excerpt_length = $settings['excerpt_trim'];
1156
1157 // Classnames but checking if we the widget is APG (legacy version)
1158 $item_classes = $legacy ? ['ui-e-post-item', 'ui-e-item'] : ['ui-e-item'] ; // Single item lower wrap class receptor
1159 $hover_item_class = $legacy ? 'anim_item' : 'item_hover_animation'; // item hover animation class
1160
1161 // If widget is not carousel type, we set animations classes directly on item selector
1162 if(!$carousel) {
1163 $item_classes[] = 'ui-e-animations-wrp';
1164 $item_classes[] = $settings['animate_items'] === 'ui-e-grid-animate' ? 'elementor-invisible' : '';
1165 $item_classes[] = $settings[$hover_item_class] !== '' ? $settings[$hover_item_class] : '';
1166
1167 } else {
1168 // Get entrance and item hover animation classes
1169 $entrance = (isset($settings['animate_items']) && $settings['animate_items'] == 'ui-e-grid-animate') ? 'elementor-invisible' : '';
1170 $hover = isset($settings[$hover_item_class]) ? $settings[$hover_item_class] : '';
1171 $animations = sprintf('%s %s', $entrance, $hover);
1172
1173 // Check if entrance or hover animation are set
1174 $has_animation = !empty($entrance) || !empty($hover)
1175
1176 // Prints extra wrappers required by the carousel script
1177 ?>
1178 <div class="ui-e-wrp swiper-slide">
1179 <?php if($has_animation) : ?>
1180 <div class="ui-e-animations-wrp <?php echo esc_attr($animations);?>">
1181 <?php endif; ?>
1182
1183 <?php } ?>
1184
1185 <div class="<?php echo esc_attr( implode(' ', $item_classes));?>">
1186 <article <?php post_class(); ?>>
1187 <div class="ui-e-post-top">
1188 <?php $this->get_post_image(); ?>
1189 <?php $this->get_post_meta('top'); ?>
1190 </div>
1191 <div class="ui-e-post-content">
1192 <?php $this->get_post_meta('before_title'); ?>
1193 <?php
1194 if ($this->get_settings_for_display('title') === 'yes')
1195 $this->get_post_title();
1196 ?>
1197 <?php $this->get_post_meta('after_title'); ?>
1198 <?php
1199 if ($this->get_settings_for_display('excerpt'))
1200 echo wp_kses_post('<div class="ui-e-post-text">' . wp_trim_words(get_the_excerpt(), $excerpt_length) . '</div>');
1201 ?>
1202 <?php $this->get_post_meta('bottom'); // button
1203 ?>
1204 <?php
1205 if ( $this->get_settings_for_display('show_button') === 'yes' ) {
1206 // Add match height spacing element if carousel. May look intrusive, but is the simplest method compared
1207 // to absolute positioning or catching last content element to apply margin.
1208 if($carousel && $settings['match_height'] === 'yes'){
1209 ?>
1210 <span class="ui-e-match-height"></span>
1211 <?php
1212 }
1213
1214 if( !isset($settings['button_position']) || empty($settings['button_position']) ) {
1215 $this->TRAIT_get_button();
1216 }
1217 }
1218 ?>
1219 </div>
1220 </article>
1221 </div>
1222
1223 <?php if($carousel) { ?>
1224 </div>
1225 <?php if($has_animation) : ?>
1226 </div>
1227 <?php endif; ?>
1228
1229 <?php }
1230 }
1231 }
1232