PluginProbe
UiCore Elements – Free widgets and templates for Elementor / 1.0.15
UiCore Elements – Free widgets and templates for Elementor v1.0.15
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.15, at includes/utils/post-component.php

1,239 lines 46.6 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
928 // Makes sure widget will render some posts at editor screen
929 if( $this->is_edit_mode() ){
930 $query_args['post_type'] = 'post';
931
932 } else {
933 $query_args = $default_query;
934
935 // Post type fallback for APG
936 if( isset($default_query['post_type']) || isset($default_query['query']['post_type']) ){
937 $post_type = $default_query['post_type'] ?? $default_query['query']['post_type'];
938 } else {
939 $post_type = 'post';
940 }
941
942 // Set pagination
943 $query_args['paged'] = Query::get_queried_page($settings);
944
945 // Set tax filters for filter component, if enabled
946 $queried_filters = Query::get_queried_filters($settings, get_post_type(), 'posts-filter');
947 $query_args['tax_query'] = empty($queried_filters['tax_query']) ? [] : $queried_filters['tax_query'];
948 }
949 }
950
951 if ($post_type === 'portfolio') {
952 $query_args['orderby'] = 'menu_order date';
953 }
954
955 $this->_query = new \WP_Query($query_args);
956 }
957 }
958
959 /**
960 * Match each meta icon size (if SVG) with the correspondent font size set by the user.
961 *
962 * @param array $settings Elementor controls settings.
963 *
964 * @return void
965 */
966 function TRAIT_set_meta_font_size_to_svg($settings)
967 {
968 // Required specifically for SVG icons
969 if( \Elementor\Plugin::$instance->experiments->is_feature_active('e_font_icon_svg') == false ){
970 return;
971 }
972
973 // Get all available metas
974 $metas = ['top_meta', 'before_title_meta', 'after_title_meta', 'bottom_meta'];
975 $metas_css = '';
976 $default_size = '16px';
977
978 // Creates a variable for each meta font-size and set a font-size, falling back to default size as last resource.
979 foreach ($metas as $meta) {
980
981 // Check if current meta has a font-size set.
982 ${$meta . '_size'} = isset( $settings[$meta . '_typography_font_size'] ) ? $settings[$meta . '_typography_font_size'] : $default_size;
983
984 // Check if the font-size value is not empty (user might customize other infos but not the font-size)
985 ${$meta . '_size'} = !empty( ${$meta .'_size'}['size'] )
986 ? ${$meta .'_size'}['size'] . ${$meta .'_size'}['unit']
987 : $default_size;
988
989 // Creates the css variable
990 $metas_css .= '--' . $meta . '-font-size: ' . esc_html(${$meta . '_size'}) . ';';
991 }
992
993 // print it on the main widget wrapper
994 $this->add_render_attribute(
995 '_wrapper',
996 'style',
997 $metas_css
998 );
999 }
1000
1001 // Render functions
1002 function get_post_image()
1003 {
1004 if ($this->get_settings_for_display('image') !== 'yes') {
1005 return;
1006 }
1007
1008 $pic_id = get_post_thumbnail_id();
1009 if (!$pic_id)
1010 return;
1011 $size = $this->get_settings_for_display('image_size_select') ?? 'uicore-medium';
1012 ?>
1013 <a class="ui-e-post-img-wrapp"
1014 href="<?php echo esc_url(get_permalink()); ?>"
1015 title="<?php echo esc_attr__('View Post:', 'uicore-elements') . the_title_attribute(['echo' => false]); ?>">
1016
1017 <?php if ($this->get_settings_for_display('masonry') === 'ui-e-maso') { ?>
1018 <?php the_post_thumbnail($size, ['class' => 'ui-e-post-img']); ?>
1019 <?php } else { ?>
1020 <div class="ui-e-post-img" style="background-image:url(<?php echo wp_get_attachment_image_url($pic_id, $size) ?>)"></div>
1021 <?php } ?>
1022 </a>
1023 <?php
1024
1025 }
1026 function get_post_title()
1027 {
1028 if ($this->get_settings_for_display('title') !== 'yes') {
1029 return;
1030 }
1031 ?>
1032 <a href="<?php echo esc_url( get_permalink() );?>" title="<?php echo esc_attr__('View Post:','uicore-elements') . esc_html(the_title_attribute(['echo'=>false])); ?>">
1033 <h4 class="ui-e-post-title"><span><?php echo esc_html(get_the_title()); ?></span></h4>
1034 </a>
1035 <?php
1036 }
1037 function get_post_meta($position)
1038 {
1039 $meta_list = $this->get_settings_for_display($position . '_meta');
1040 if (!isset($meta_list[0]) || $meta_list[0]['type'] == '') {
1041 return;
1042 }
1043 echo ($position == 'top') ? '<div class="ui-e-post-top-meta">' : '';
1044 echo ($position == 'after_title') ? '<div class="ui-e-meta-wrapp">' : '';
1045 echo '<div class="ui-e-post-meta ui-e-'.esc_attr($position).'">';
1046 foreach ($meta_list as $meta) {
1047 if($meta['type'] != 'none'){
1048 $this->display_meta($meta);
1049
1050 if( next( $meta_list ) && $this->get_settings_for_display( $position.'_meta_separator' ) ) {
1051 echo '<span class="ui-e-separator">'.esc_html($this->get_settings_for_display( $position.'_meta_separator' )).'</span>';
1052 }
1053 }
1054 }
1055 echo '</div>';
1056 echo ($position == 'top' || $position == 'after_title') ? '</div>' : '';
1057 }
1058 /**
1059 * Render the post read more button.
1060 *
1061 * @param bool $is_product. If true, will render an add to cart button.
1062 *
1063 * @return void
1064 */
1065 function TRAIT_get_button($is_product = false)
1066 {
1067 $settings = $this->get_settings_for_display();
1068
1069 if( $is_product ){
1070 global $product;
1071
1072 // Get default add to cart text as fallback
1073 $settings['text'] = empty($settings['text']) ? $product->add_to_cart_text() : $settings['text'];
1074 }
1075
1076 $this->add_render_attribute('button', [
1077 'class' => ['elementor-button-link', 'elementor-button', 'ui-e-readmore'],
1078 'role' => 'button',
1079 ]);
1080 $this->add_render_attribute('content-wrapper', 'class', 'elementor-button-content-wrapper');
1081
1082 if (!empty($settings['button_css_id'])) {
1083 $this->add_render_attribute('button', 'id', $settings['button_css_id']);
1084 }
1085
1086 if (!empty($settings['size'])) {
1087 $this->add_render_attribute('button', 'class', 'elementor-size-' . $settings['size']);
1088 }
1089
1090 if (!empty($settings['hover_animation'])) {
1091 $this->add_render_attribute('button', 'class', 'elementor-animation-' . $settings['hover_animation']);
1092 }
1093
1094 $btn_classes = isset($settings['icon_align'])
1095 ? ['elementor-button-icon', 'elementor-align-icon-' . $settings['icon_align'] ]
1096 : 'elementor-button-icon';
1097
1098 $this->add_render_attribute([
1099 'icon-align' => [
1100 'class' => $btn_classes
1101 ],
1102 'text' => [
1103 'class' => 'elementor-button-text',
1104 ],
1105 ]);
1106
1107 if( isset($settings['icon_align']) ){
1108 $this->add_render_attribute('content-wrapper', 'class', 'elementor-button-content');
1109 }
1110
1111 $tbn_content = '<span ' . $this->get_render_attribute_string('content-wrapper') . '>';
1112
1113 if (!empty($settings['icon']) || !empty($settings['selected_icon']['value'])) {
1114 $tbn_content .= '<span ' . $this->get_render_attribute_string('icon-align') . '>';
1115 \ob_start();
1116 Icons_Manager::render_icon($settings['selected_icon'], ['aria-hidden' => 'true']);
1117 $tbn_content .= \ob_get_clean();
1118 $tbn_content .= '</span>';
1119 }
1120
1121 $tbn_content .= '<span ' . $this->get_render_attribute_string('text') . '>';
1122 $tbn_content .= $settings['text'];
1123 $tbn_content .= '</span> </span>';
1124
1125 // WooCommerce add to cart button
1126 if ($is_product) {
1127 if ($product) {
1128 echo Helper::esc_svg(apply_filters(
1129 'woocommerce_loop_add_to_cart_link', // WPCS: XSS ok.
1130 sprintf(
1131 '<a href="%s" data-quantity="%s" %s>%s</a>',
1132 esc_url($product->add_to_cart_url()),
1133 esc_attr(1),
1134 $this->get_render_attribute_string('button'),
1135 $tbn_content
1136 ),
1137 $product
1138 ));
1139 }
1140
1141 // Default button
1142 } else {
1143 ?>
1144 <a href="<?php echo esc_url(get_permalink()); ?>" <?php $this->print_render_attribute_string('button'); ?>>
1145 <?php echo Helper::esc_svg( $tbn_content ); ?>
1146 </a>
1147 <?php
1148 }
1149 }
1150 /**
1151 * Renders a post item with various settings and options.
1152 * Important: any changes here should also be considered to `TRAIT_render_product()` from Product Component.
1153 *
1154 * @param bool $carousel Indicates if the item needs carousel classnames.
1155 * @param bool $legacy Indicates if the item is using legacy classnames.
1156 *
1157 * @return void
1158 */
1159 function TRAIT_render_item($carousel = false, $legacy = false)
1160 {
1161 $settings = $this->get_settings_for_display();
1162 $excerpt_length = $settings['excerpt_trim'];
1163
1164 // Classnames but checking if we the widget is APG (legacy version)
1165 $item_classes = $legacy ? ['ui-e-post-item', 'ui-e-item'] : ['ui-e-item'] ; // Single item lower wrap class receptor
1166 $hover_item_class = $legacy ? 'anim_item' : 'item_hover_animation'; // item hover animation class
1167
1168 // If widget is not carousel type, we set animations classes directly on item selector
1169 if(!$carousel) {
1170 $item_classes[] = 'ui-e-animations-wrp';
1171 $item_classes[] = $settings['animate_items'] === 'ui-e-grid-animate' ? 'elementor-invisible' : '';
1172 $item_classes[] = $settings[$hover_item_class] !== '' ? $settings[$hover_item_class] : '';
1173
1174 } else {
1175 // Get entrance and item hover animation classes
1176 $entrance = (isset($settings['animate_items']) && $settings['animate_items'] == 'ui-e-grid-animate') ? 'elementor-invisible' : '';
1177 $hover = isset($settings[$hover_item_class]) ? $settings[$hover_item_class] : '';
1178 $animations = sprintf('%s %s', $entrance, $hover);
1179
1180 // Check if entrance or hover animation are set
1181 $has_animation = !empty($entrance) || !empty($hover)
1182
1183 // Prints extra wrappers required by the carousel script
1184 ?>
1185 <div class="ui-e-wrp swiper-slide">
1186 <?php if($has_animation) : ?>
1187 <div class="ui-e-animations-wrp <?php echo esc_attr($animations);?>">
1188 <?php endif; ?>
1189
1190 <?php } ?>
1191
1192 <div class="<?php echo esc_attr( implode(' ', $item_classes));?>">
1193 <article <?php post_class(); ?>>
1194 <div class="ui-e-post-top">
1195 <?php $this->get_post_image(); ?>
1196 <?php $this->get_post_meta('top'); ?>
1197 </div>
1198 <div class="ui-e-post-content">
1199 <?php $this->get_post_meta('before_title'); ?>
1200 <?php
1201 if ($this->get_settings_for_display('title') === 'yes')
1202 $this->get_post_title();
1203 ?>
1204 <?php $this->get_post_meta('after_title'); ?>
1205 <?php
1206 if ($this->get_settings_for_display('excerpt'))
1207 echo wp_kses_post('<div class="ui-e-post-text">' . wp_trim_words(get_the_excerpt(), $excerpt_length) . '</div>');
1208 ?>
1209 <?php $this->get_post_meta('bottom'); // button
1210 ?>
1211 <?php
1212 if ( $this->get_settings_for_display('show_button') === 'yes' ) {
1213 // Add match height spacing element if carousel. May look intrusive, but is the simplest method compared
1214 // to absolute positioning or catching last content element to apply margin.
1215 if($carousel && $settings['match_height'] === 'yes'){
1216 ?>
1217 <span class="ui-e-match-height"></span>
1218 <?php
1219 }
1220
1221 if( !isset($settings['button_position']) || empty($settings['button_position']) ) {
1222 $this->TRAIT_get_button();
1223 }
1224 }
1225 ?>
1226 </div>
1227 </article>
1228 </div>
1229
1230 <?php if($carousel) { ?>
1231 </div>
1232 <?php if($has_animation) : ?>
1233 </div>
1234 <?php endif; ?>
1235
1236 <?php }
1237 }
1238 }
1239