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

1,279 lines 48.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', 'uicore-elements'),
355 ]
356 );
357 $this->add_group_control(
358 Group_Control_Background::get_type(),
359 [
360 'name' => 'content_bg',
361 'types' => [ 'classic', 'gradient' ],
362 'selector' => '{{WRAPPER}} .ui-e-item article',
363 ]
364 );
365 $this->add_group_control(
366 Group_Control_Border::get_type(),
367 [
368 'name' => 'item_border',
369 'selector' => '{{WRAPPER}} .ui-e-item article',
370 ]
371 );
372 $this->add_group_control(
373 Group_Control_Box_Shadow::get_type(),
374 [
375 'name' => 'item_shadow',
376 'selector' => '{{WRAPPER}} .ui-e-item article',
377 ]
378 );
379 $this->end_controls_tab();
380
381 $this->start_controls_tab(
382 'item_bs_hover_tab',
383 [
384 'label' => esc_html__('Hover', 'uicore-elements'),
385 ]
386 );
387 $this->add_group_control(
388 Group_Control_Background::get_type(),
389 [
390 'name' => 'content_bg_hover',
391 'types' => [ 'classic', 'gradient' ],
392 'selector' => '{{WRAPPER}} .ui-e-item article',
393 ]
394 );
395 $this->add_group_control(
396 Group_Control_Border::get_type(),
397 [
398 'name' => 'item_border_hover',
399 'selector' => '{{WRAPPER}} .ui-e-item:hover article',
400 ]
401 );
402 $this->add_group_control(
403 Group_Control_Box_Shadow::get_type(),
404 [
405 'name' => 'item_shadow_hover',
406 'selector' => '{{WRAPPER}} .ui-e-item:hover article',
407 ]
408 );
409 $this->end_controls_tab();
410
411 if($active_tab){
412 $this->start_controls_tab(
413 'item_bs_active_tab',
414 [
415 'label' => esc_html__('Active', 'uicore-elements'),
416 ]
417 );
418 $this->add_group_control(
419 Group_Control_Border::get_type(),
420 [
421 'name' => 'item_border_active',
422 'selector' => '{{WRAPPER}} .ui-e-item.ui-e-active article',
423 ]
424 );
425 $this->add_group_control(
426 Group_Control_Box_Shadow::get_type(),
427 [
428 'name' => 'item_shadow_active',
429 'selector' => '{{WRAPPER}} .ui-e-item.ui-e-active article',
430 ]
431 );
432 $this->end_controls_tab();
433 }
434
435 $this->end_controls_tabs();
436
437 $this->add_control(
438 'item_padding',
439 [
440 'label' => esc_html__('Padding', 'uicore-elements'),
441 'type' => Controls_Manager::DIMENSIONS,
442 'size_units' => ['px', 'em', 'rem', '%'],
443 'separator' => 'before',
444 'selectors' => [
445 '{{WRAPPER}} .ui-e-item article' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};'
446 ],
447 'condition' => array(
448 'box_style!' => 'overlay',
449 ),
450 ]
451
452 );
453 $this->add_control(
454 'item_radius',
455 [
456 'label' => esc_html__('Border Radius', 'uicore-elements'),
457 'type' => Controls_Manager::DIMENSIONS,
458 'selectors' => [
459 '{{WRAPPER}} ' => '--ui-e-border-radius: {{TOP}}px {{RIGHT}}px {{BOTTOM}}px {{LEFT}}px;'
460 ],
461 ]
462 );
463
464 if($section){
465 $this->end_controls_section();
466 }
467 }
468 function TRAIT_register_post_content_style_controls($section = true)
469 {
470 if($section){
471 $this->start_controls_section(
472 'section_style_content',
473 [
474 'label' => __('Content Style', 'uicore-elements'),
475 'tab' => Controls_Manager::TAB_STYLE,
476 ]
477 );
478 }
479 $this->add_control(
480 'image_size',
481 [
482 'label' => __('Image Height (%)', 'uicore-elements'),
483 'type' => Controls_Manager::NUMBER,
484 'min' => 1,
485 'max' => 500,
486 'step' => 1,
487 'default' => 57,
488 'selectors' => [
489 '{{WRAPPER}} .ui-e-post-top' => '--ui-e-img-size: {{VALUE}}',
490 ],
491 'condition' => [
492 'masonry!' => 'ui-e-maso',
493 ],
494 ]
495 );
496 $this->add_control(
497 'image_radius',
498 [
499 'label' => esc_html__('Border Radius', 'uicore-elements'),
500 'type' => Controls_Manager::DIMENSIONS,
501 'size_units' => ['px', 'em', '%'],
502 'selectors' => [
503 '{{WRAPPER}} .ui-e-post-top' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}px {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};'
504 ],
505 'condition' => array(
506 'box_style!' => 'overlay',
507 ),
508 ]
509 );
510 $this->add_group_control(
511 Group_Control_Box_Shadow::get_type(),
512 [
513 'name' => 'image_shadow',
514 'label' => esc_html__('Box Shadow', 'uicore-elements'),
515 'selector' => '{{WRAPPER}} .ui-e-post-top',
516 'condition' => array(
517 'box_style!' => 'overlay',
518 ),
519 ]
520 );
521 $this->add_responsive_control(
522 'content_alignment',
523 [
524 'label' => esc_html__('Content Alignment', 'uicore-elements'),
525 'type' => Controls_Manager::CHOOSE,
526 'options' => [
527 'left' => [
528 'title' => esc_html__('Left', 'uicore-elements'),
529 'icon' => 'eicon-text-align-left',
530 ],
531 'center' => [
532 'title' => esc_html__('Center', 'uicore-elements'),
533 'icon' => 'eicon-text-align-center',
534 ],
535 'stretch' => [
536 'title' => esc_html__('Justified', 'uicore-elements'),
537 'icon' => 'eicon-text-align-justify',
538 ],
539 ],
540 'selectors' => [
541 '{{WRAPPER}} .ui-e-post-content' => 'align-items: {{VALUE}}; text-align: {{VALUE}};',
542 ],
543 ]
544 );
545 $this->add_control(
546 'title_color',
547 [
548 'label' => esc_html__('Title Color', 'uicore-elements'),
549 'type' => Controls_Manager::COLOR,
550 'default' => '',
551 'separator' => 'before',
552 'selectors' => [
553 '{{WRAPPER}} .ui-e-post-title' => 'color: {{VALUE}};',
554 ],
555 ]
556 );
557 $this->add_control(
558 'title_hcolor',
559 [
560 'label' => esc_html__('Title Hover Color', 'uicore-elements'),
561 'type' => Controls_Manager::COLOR,
562 'default' => '',
563 'selectors' => [
564 '{{WRAPPER}} .ui-e-post-title:hover' => 'color: {{VALUE}};',
565 ],
566 ]
567 );
568 $this->add_group_control(
569 Group_Control_Typography::get_type(),
570 [
571 'name' => 'title_typography',
572 'label' => esc_html__('Title Typography', 'uicore-elements'),
573 'selector' => '{{WRAPPER}} .ui-e-post-title',
574 ]
575 );
576 $this->add_control(
577 'title_gap',
578 [
579 'label' => __('Title Top Space', 'uicore-elements'),
580 'type' => Controls_Manager::SLIDER,
581 'size_units' => ['em'],
582 'separator' => 'after',
583 'range' => [
584 'px' => [
585 'min' => 0,
586 'max' => 3,
587 'step' => 0.1,
588 ],
589 ],
590 'default' => [
591 'unit' => 'em',
592 'size' => 1.2,
593 ],
594 'selectors' => [
595 '{{WRAPPER}} .ui-e-post-title' => 'margin-top: {{SIZE}}em;',
596 ],
597 ]
598 );
599 $this->add_control(
600 'text_color',
601 [
602 'label' => esc_html__('Excerpt Color', 'uicore-elements'),
603 'type' => Controls_Manager::COLOR,
604 'default' => '',
605 'selectors' => [
606 '{{WRAPPER}} .ui-e-post-text' => 'color: {{VALUE}};',
607 ],
608 ]
609 );
610 $this->add_group_control(
611 Group_Control_Typography::get_type(),
612 [
613 'name' => 'text_typography',
614 'label' => esc_html__('Excerpt Typography', 'uicore-elements'),
615 'selector' => '{{WRAPPER}} .ui-e-post-text',
616 ]
617 );
618 $this->add_control(
619 'text_gap',
620 [
621 'label' => __('Excerpt Top Space', 'uicore-elements'),
622 'type' => Controls_Manager::SLIDER,
623 'size_units' => ['em'],
624 'separator' => 'after',
625 'range' => [
626 'px' => [
627 'min' => 0,
628 'max' => 3,
629 'step' => 0.1,
630 ],
631 ],
632 'default' => [
633 'unit' => 'em',
634 'size' => 0.8,
635 ],
636 'selectors' => [
637 '{{WRAPPER}} .ui-e-post-text' => 'margin-top: {{SIZE}}em;',
638 ],
639 ]
640 );
641 $this->add_group_control(
642 Group_Control_Background::get_type(),
643 [
644 'name' => 'content_background',
645 'selector' => '{{WRAPPER}} .ui-e-post-content',
646 ]
647 );
648 $this->add_responsive_control(
649 'content_padding',
650 [
651 'label' => esc_html__('Content Padding', 'uicore-elements'),
652 'type' => Controls_Manager::DIMENSIONS,
653 'size_units' => ['px', 'em', '%'],
654 'selectors' => [
655 '{{WRAPPER}} .ui-e-post-content' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};'
656 ]
657 ]
658 );
659 $this->add_control(
660 'content_radius',
661 [
662 'label' => esc_html__('Content Border Radius', 'uicore-elements'),
663 'type' => Controls_Manager::DIMENSIONS,
664 'selectors' => [
665 '{{WRAPPER}} .ui-e-post-content' => 'border-radius: {{TOP}}px {{RIGHT}}px {{BOTTOM}}px {{LEFT}}px;'
666 ],
667 'condition' => array(
668 'box_style!' => 'overlay',
669 ),
670 ]
671 );
672 $this->add_control(
673 'content_gap',
674 [
675 'label' => __('Content Space', 'uicore-elements'),
676 'type' => Controls_Manager::SLIDER,
677 'size_units' => ['em'],
678 'separator' => 'after',
679 'range' => [
680 'px' => [
681 'min' => 0,
682 'max' => 3,
683 'step' => 0.1,
684 ],
685 ],
686 'default' => [
687 'unit' => 'em',
688 'size' => 0,
689 ],
690 'selectors' => [
691 '{{WRAPPER}} ' => '--ui-e-content-space: {{SIZE}}em;',
692 ],
693 'condition' => array(
694 'box_style!' => 'overlay',
695 ),
696 ]
697 );
698
699 if($section){
700 $this->end_controls_section();
701 }
702 }
703 function TRAIT_register_post_button_style_controls($section = true)
704 {
705 if($section){
706 $this->start_controls_section(
707 'section_button_style',
708 [
709 'label' => esc_html__('Button Style', 'uicore-elements'),
710 'tab' => Controls_Manager::TAB_STYLE,
711 'condition' => array(
712 'show_button' => 'yes',
713 ),
714 ]
715 );
716 }
717 $this->add_responsive_control(
718 'button_align',
719 [
720 'label' => esc_html__( 'Alignment', 'uicore-elements' ),
721 'type' => Controls_Manager::CHOOSE,
722 'options' => [
723 'start' => [
724 'title' => esc_html__( 'Left', 'uicore-elements' ),
725 'icon' => 'eicon-text-align-left',
726 ],
727 'center' => [
728 'title' => esc_html__( 'Center', 'uicore-elements' ),
729 'icon' => 'eicon-text-align-center',
730 ],
731 'end' => [
732 'title' => esc_html__( 'Right', 'uicore-elements' ),
733 'icon' => 'eicon-text-align-right',
734 ],
735 'normal' => [
736 'title' => esc_html__( 'Justified', 'uicore-elements' ),
737 'icon' => 'eicon-text-align-justify',
738 ],
739 ],
740 'default' => 'start',
741 'selectors' => [
742 '{{WRAPPER}} .ui-e-readmore' => 'align-self: {{VALUE}};',
743 ],
744
745 ]
746 );
747 $this->register_button_style_controls(
748 [
749 'section_condition' => [
750 'show_button' => 'yes'
751 ]
752 ]
753 );
754 // 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
755 $this->remove_responsive_control('align');
756
757 $this->TRAIT_register_post_specific_controls('button_gap');
758
759 if($section) {
760 $this->end_controls_section();
761 }
762 }
763 function TRAIT_register_post_meta_style_controls($section = true)
764 {
765 if($section) {
766 $this->start_controls_section(
767 'section_style_extra_content',
768 [
769 'label' => __('Meta Style', 'uicore-elements'),
770 'tab' => Controls_Manager::TAB_STYLE,
771 ]
772 );
773 }
774 $this->start_controls_tabs('style_extra_tabs');
775 $this->start_controls_tab(
776 'style_top_tab',
777 [
778 'label' => esc_html__('Top', 'uicore-elements'),
779 ]
780 );
781 $this->get_meta_style_controls('top');
782 $this->end_controls_tab();
783
784 $this->start_controls_tab(
785 'style_before_title_tab',
786 [
787 'label' => esc_html__('Before Title', 'uicore-elements'),
788 ]
789 );
790 $this->get_meta_style_controls('before_title');
791 $this->end_controls_tab();
792
793 $this->start_controls_tab(
794 'style_after_title_tab',
795 [
796 'label' => esc_html__('After Title', 'uicore-elements'),
797 ]
798 );
799 $this->get_meta_style_controls('after_title');
800 $this->end_controls_tab();
801
802 $this->start_controls_tab(
803 'style_bottom_tab',
804 [
805 'label' => esc_html__('Bottom', 'uicore-elements'),
806 ]
807 );
808 $this->get_meta_style_controls('bottom');
809 $this->end_controls_tab();
810 $this->end_controls_tabs();
811
812 if($section) {
813 $this->end_controls_section();
814 }
815 }
816 function TRAIT_register_post_animation_controls()
817 {
818 $this->add_control(
819 'anim_image',
820 [
821 'label' => __('Image Hover Animation', 'uicore-elements'),
822 'type' => Controls_Manager::SELECT,
823 'label_block' => true,
824 'default' => 'ui-e-img-anim-zoom',
825 'options' => [
826 '' => __('None', 'uicore-elements'),
827 'ui-e-img-anim-zoom' => __('Zoom', 'uicore-elements'),
828 ],
829 'prefix_class' => '',
830 ]
831 );
832 $this->add_control(
833 'anim_meta',
834 [
835 'label' => __('Meta Hover Animation', 'uicore-elements'),
836 'type' => Controls_Manager::SELECT,
837 'label_block' => true,
838 'default' => '',
839 'options' => [
840 '' => __('None', 'uicore-elements'),
841 'ui-e-meta-anim-show' => __('Show', 'uicore-elements'),
842 ],
843 'prefix_class' => '',
844 ]
845 );
846 $this->add_control(
847 'important_note',
848 [
849 'label' => esc_html__('Important Note', 'uicore-elements'),
850 'type' => \Elementor\Controls_Manager::RAW_HTML,
851 'raw' => '<div class="elementor-control-field-description" style="margin-top: -7px;">' . esc_html__('This works only for Below Title Meta.', 'uicore-elements') . '</div>',
852 'show_label' => false,
853 'condition' => array(
854 'box_style' => 'overlay',
855 ),
856 ]
857 );
858 $this->add_control(
859 'anim_title',
860 [
861 'label' => __('Title Hover Animation', 'uicore-elements'),
862 'type' => Controls_Manager::SELECT,
863 'label_block' => true,
864 'default' => '',
865 'options' => [
866 '' => __('None', 'uicore-elements'),
867 'ui-e-title-anim-underline' => __('Underline', 'uicore-elements'),
868 ],
869 'prefix_class' => '',
870 ]
871 );
872 $this->add_control(
873 'anim_content',
874 [
875 'label' => __('Content Hover Animation', 'uicore-elements'),
876 'type' => Controls_Manager::SELECT,
877 'label_block' => true,
878 'default' => '',
879 'options' => [
880 '' => __('None', 'uicore-elements'),
881 'ui-e-content-anim-show' => __('Show', 'uicore-elements'),
882 ],
883 'prefix_class' => '',
884 'condition' => array(
885 'box_style' => 'overlay',
886 ),
887 ]
888 );
889 $this->add_control(
890 'anim_btn',
891 [
892 'label' => __('Button Hover Animation', 'uicore-elements'),
893 'type' => Controls_Manager::SELECT,
894 'label_block' => true,
895 'default' => '',
896 'options' => [
897 '' => __('None', 'uicore-elements'),
898 'ui-e-btn-anim-show' => __('Show', 'uicore-elements'),
899 ],
900 'prefix_class' => '',
901 'condition' => [
902 'show_button' => 'yes',
903 ],
904 ]
905 );
906 }
907 /**
908 * Registers specific controls that can't be registered in blocks because of diferent use by different widgets or some other reason.
909 * TODO: update to the use injection control, a better approach.
910 *
911 * @param string $control The control to register.
912 * @return void
913 */
914 function TRAIT_register_post_specific_controls($control)
915 {
916 switch ($control) {
917 case 'button_gap':
918 $this->add_control(
919 'button_gap',
920 [
921 'label' => __('Button Top Space', 'uicore-elements'),
922 'type' => Controls_Manager::SLIDER,
923 'size_units' => ['em'],
924 'range' => [
925 'px' => [
926 'min' => 0,
927 'max' => 3,
928 'step' => 0.1,
929 ],
930 ],
931 'default' => [
932 'unit' => 'em',
933 'size' => 0.8,
934 ],
935 'selectors' => [
936 '{{WRAPPER}} .elementor-button' => 'margin-top: {{SIZE}}em;',
937 ],
938 ]
939 );
940 break;
941 }
942 }
943
944 /**
945 * Returns the proper query args for a given post type.
946 *
947 * @param array $settings Elementor controls settings.
948 * @param object $default_query The default query object. Used to tell if is a frontend or rest api request.
949 *
950 * @return void Don't return anything, but sets the query object to $_query variable that can be accessed by the widget.
951 */
952 function TRAIT_query_posts($settings, $default_query)
953 {
954 $post_type = $settings['posts-filter_post_type'];
955
956 if ( $post_type === 'related' ) {
957 $this->_query = Helper::get_related('random', $settings['item_limit']['size']);
958
959 } else {
960 $query_args = Query::get_query_args('posts-filter', $settings);
961
962 if ($post_type === 'current') {
963
964 // Makes sure widget will render some posts at editor screen
965 if( $this->is_edit_mode() ){
966 $query_args['post_type'] = 'post';
967
968 } else {
969 $query_args = $default_query;
970
971 // Post type fallback for APG
972 if( isset($default_query['post_type']) || isset($default_query['query']['post_type']) ){
973 $post_type = $default_query['post_type'] ?? $default_query['query']['post_type'];
974 } else {
975 $post_type = 'post';
976 }
977
978 // Set pagination
979 $query_args['paged'] = Query::get_queried_page($settings);
980
981 // Set tax filters for filter component, if enabled
982 $queried_filters = Query::get_queried_filters($settings, get_post_type(), 'posts-filter');
983 $query_args['tax_query'] = empty($queried_filters['tax_query']) ? [] : $queried_filters['tax_query'];
984 }
985 }
986
987 if ($post_type === 'portfolio') {
988 $query_args['orderby'] = 'menu_order date';
989 }
990
991 $this->_query = new \WP_Query($query_args);
992 }
993 }
994
995 /**
996 * Match each meta icon size (if SVG) with the correspondent font size set by the user.
997 *
998 * @param array $settings Elementor controls settings.
999 *
1000 * @return void
1001 */
1002 function TRAIT_set_meta_font_size_to_svg($settings)
1003 {
1004 // Required specifically for SVG icons
1005 if( \Elementor\Plugin::$instance->experiments->is_feature_active('e_font_icon_svg') == false ){
1006 return;
1007 }
1008
1009 // Get all available metas
1010 $metas = ['top_meta', 'before_title_meta', 'after_title_meta', 'bottom_meta'];
1011 $metas_css = '';
1012 $default_size = '16px';
1013
1014 // Creates a variable for each meta font-size and set a font-size, falling back to default size as last resource.
1015 foreach ($metas as $meta) {
1016
1017 // Check if current meta has a font-size set.
1018 ${$meta . '_size'} = isset( $settings[$meta . '_typography_font_size'] ) ? $settings[$meta . '_typography_font_size'] : $default_size;
1019
1020 // Check if the font-size value is not empty (user might customize other infos but not the font-size)
1021 ${$meta . '_size'} = !empty( ${$meta .'_size'}['size'] )
1022 ? ${$meta .'_size'}['size'] . ${$meta .'_size'}['unit']
1023 : $default_size;
1024
1025 // Creates the css variable
1026 $metas_css .= '--' . $meta . '-font-size: ' . esc_html(${$meta . '_size'}) . ';';
1027 }
1028
1029 // print it on the main widget wrapper
1030 $this->add_render_attribute(
1031 '_wrapper',
1032 'style',
1033 $metas_css
1034 );
1035 }
1036
1037 // Render functions
1038 function get_post_image()
1039 {
1040 if ($this->get_settings_for_display('image') !== 'yes') {
1041 return;
1042 }
1043
1044 $pic_id = get_post_thumbnail_id();
1045 if (!$pic_id)
1046 return;
1047 $size = $this->get_settings_for_display('image_size_select') ?? 'uicore-medium';
1048 ?>
1049 <a class="ui-e-post-img-wrapp"
1050 href="<?php echo esc_url(get_permalink()); ?>"
1051 title="<?php echo esc_attr__('View Post:', 'uicore-elements') . the_title_attribute(['echo' => false]); ?>">
1052
1053 <?php if ($this->get_settings_for_display('masonry') === 'ui-e-maso') { ?>
1054 <?php the_post_thumbnail($size, ['class' => 'ui-e-post-img']); ?>
1055 <?php } else { ?>
1056 <div class="ui-e-post-img" style="background-image:url(<?php echo esc_url( wp_get_attachment_image_url($pic_id, $size)); ?>)"></div>
1057 <?php } ?>
1058 </a>
1059 <?php
1060
1061 }
1062 function get_post_title()
1063 {
1064 if ($this->get_settings_for_display('title') !== 'yes') {
1065 return;
1066 }
1067 ?>
1068 <a href="<?php echo esc_url( get_permalink() );?>" title="<?php echo esc_attr__('View Post:','uicore-elements') . esc_html(the_title_attribute(['echo'=>false])); ?>">
1069 <h4 class="ui-e-post-title"><span><?php echo esc_html(get_the_title()); ?></span></h4>
1070 </a>
1071 <?php
1072 }
1073 function get_post_meta($position)
1074 {
1075 $meta_list = $this->get_settings_for_display($position . '_meta');
1076 if (!isset($meta_list[0]) || $meta_list[0]['type'] == '') {
1077 return;
1078 }
1079 echo ($position == 'top') ? '<div class="ui-e-post-top-meta">' : '';
1080 echo ($position == 'after_title') ? '<div class="ui-e-meta-wrapp">' : '';
1081 echo '<div class="ui-e-post-meta ui-e-'.esc_attr($position).'">';
1082 foreach ($meta_list as $meta) {
1083 if($meta['type'] != 'none'){
1084 $this->display_meta($meta);
1085
1086 if( next( $meta_list ) && $this->get_settings_for_display( $position.'_meta_separator' ) ) {
1087 echo '<span class="ui-e-separator">'.esc_html($this->get_settings_for_display( $position.'_meta_separator' )).'</span>';
1088 }
1089 }
1090 }
1091 echo '</div>';
1092 echo ($position == 'top' || $position == 'after_title') ? '</div>' : '';
1093 }
1094 /**
1095 * Render the post read more button.
1096 *
1097 * @param bool $is_product. If true, will render an add to cart button.
1098 *
1099 * @return void
1100 */
1101 function TRAIT_get_button($is_product = false)
1102 {
1103 $settings = $this->get_settings_for_display();
1104
1105 if( $is_product ){
1106 global $product;
1107
1108 // Get default add to cart text as fallback
1109 $settings['text'] = empty($settings['text']) ? $product->add_to_cart_text() : $settings['text'];
1110 }
1111
1112 $this->add_render_attribute('button', [
1113 'class' => ['elementor-button-link', 'elementor-button', 'ui-e-readmore'],
1114 'role' => 'button',
1115 ]);
1116 $this->add_render_attribute('content-wrapper', 'class', 'elementor-button-content-wrapper');
1117
1118 if (!empty($settings['button_css_id'])) {
1119 $this->add_render_attribute('button', 'id', $settings['button_css_id']);
1120 }
1121
1122 if (!empty($settings['size'])) {
1123 $this->add_render_attribute('button', 'class', 'elementor-size-' . $settings['size']);
1124 }
1125
1126 if (!empty($settings['hover_animation'])) {
1127 $this->add_render_attribute('button', 'class', 'elementor-animation-' . $settings['hover_animation']);
1128 }
1129
1130 $btn_classes = isset($settings['icon_align'])
1131 ? ['elementor-button-icon', 'elementor-align-icon-' . $settings['icon_align'] ]
1132 : 'elementor-button-icon';
1133
1134 $this->add_render_attribute([
1135 'icon-align' => [
1136 'class' => $btn_classes
1137 ],
1138 'text' => [
1139 'class' => 'elementor-button-text',
1140 ],
1141 ]);
1142
1143 if( isset($settings['icon_align']) ){
1144 $this->add_render_attribute('content-wrapper', 'class', 'elementor-button-content');
1145 }
1146
1147 $tbn_content = '<span ' . $this->get_render_attribute_string('content-wrapper') . '>';
1148
1149 if (!empty($settings['icon']) || !empty($settings['selected_icon']['value'])) {
1150 $tbn_content .= '<span ' . $this->get_render_attribute_string('icon-align') . '>';
1151 \ob_start();
1152 Icons_Manager::render_icon($settings['selected_icon'], ['aria-hidden' => 'true']);
1153 $tbn_content .= \ob_get_clean();
1154 $tbn_content .= '</span>';
1155 }
1156
1157 $tbn_content .= '<span ' . $this->get_render_attribute_string('text') . '>';
1158 $tbn_content .= $settings['text'];
1159 $tbn_content .= '</span> </span>';
1160
1161 // WooCommerce add to cart button
1162 if ($is_product) {
1163 if ($product) {
1164 //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1165 echo Helper::esc_svg(apply_filters(
1166 'woocommerce_loop_add_to_cart_link', // WPCS: XSS ok.
1167 sprintf(
1168 '<a href="%1$s" data-quantity="1" %2$s> %3$s </a>',
1169 esc_url($product->add_to_cart_url()),
1170 //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1171 $this->get_render_attribute_string('button'),
1172 wp_kses_post($tbn_content)
1173 ),
1174 wp_kses_post($product)
1175 ));
1176 }
1177
1178 // Default button
1179 } else {
1180 ?>
1181 <a href="<?php echo esc_url(get_permalink()); ?>" <?php $this->print_render_attribute_string('button'); ?>>
1182 <?php
1183 //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1184 echo Helper::esc_svg( $tbn_content );
1185 ?>
1186 </a>
1187 <?php
1188 }
1189 }
1190 /**
1191 * Renders a post item with various settings and options.
1192 * Important: any changes here should also be considered to `TRAIT_render_product()` from Product Component.
1193 *
1194 * @param bool $carousel Indicates if the item needs carousel classnames.
1195 * @param bool $legacy Indicates if the item is using legacy classnames.
1196 *
1197 * @return void
1198 */
1199 function TRAIT_render_item($carousel = false, $legacy = false)
1200 {
1201 $settings = $this->get_settings_for_display();
1202 $excerpt_length = $settings['excerpt_trim'];
1203
1204 // Classnames but checking if we the widget is APG (legacy version)
1205 $item_classes = $legacy ? ['ui-e-post-item', 'ui-e-item'] : ['ui-e-item'] ; // Single item lower wrap class receptor
1206 $hover_item_class = $legacy ? 'anim_item' : 'item_hover_animation'; // item hover animation class
1207
1208 // If widget is not carousel type, we set animations classes directly on item selector
1209 if(!$carousel) {
1210 $item_classes[] = 'ui-e-animations-wrp';
1211 $item_classes[] = $settings['animate_items'] === 'ui-e-grid-animate' ? 'elementor-invisible' : '';
1212 $item_classes[] = $settings[$hover_item_class] !== '' ? $settings[$hover_item_class] : '';
1213
1214 } else {
1215 // Get entrance and item hover animation classes
1216 $entrance = (isset($settings['animate_items']) && $settings['animate_items'] == 'ui-e-grid-animate') ? 'elementor-invisible' : '';
1217 $hover = isset($settings[$hover_item_class]) ? $settings[$hover_item_class] : '';
1218 $animations = sprintf('%s %s', $entrance, $hover);
1219
1220 // Check if entrance or hover animation are set
1221 $has_animation = !empty($entrance) || !empty($hover)
1222
1223 // Prints extra wrappers required by the carousel script
1224 ?>
1225 <div class="ui-e-wrp swiper-slide">
1226 <?php if($has_animation) : ?>
1227 <div class="ui-e-animations-wrp <?php echo esc_attr($animations);?>">
1228 <?php endif; ?>
1229
1230 <?php } ?>
1231
1232 <div class="<?php echo esc_attr( implode(' ', $item_classes));?>">
1233 <article <?php post_class(); ?>>
1234 <div class="ui-e-post-top">
1235 <?php $this->get_post_image(); ?>
1236 <?php $this->get_post_meta('top'); ?>
1237 </div>
1238 <div class="ui-e-post-content">
1239 <?php $this->get_post_meta('before_title'); ?>
1240 <?php
1241 if ($this->get_settings_for_display('title') === 'yes')
1242 $this->get_post_title();
1243 ?>
1244 <?php $this->get_post_meta('after_title'); ?>
1245 <?php
1246 if ($this->get_settings_for_display('excerpt'))
1247 echo wp_kses_post('<div class="ui-e-post-text">' . wp_trim_words(get_the_excerpt(), $excerpt_length) . '</div>');
1248 ?>
1249 <?php $this->get_post_meta('bottom'); // button
1250 ?>
1251 <?php
1252 if ( $this->get_settings_for_display('show_button') === 'yes' ) {
1253 // Add match height spacing element if carousel. May look intrusive, but is the simplest method compared
1254 // to absolute positioning or catching last content element to apply margin.
1255 if($carousel && $settings['match_height'] === 'yes'){
1256 ?>
1257 <span class="ui-e-match-height"></span>
1258 <?php
1259 }
1260
1261 if( !isset($settings['button_position']) || empty($settings['button_position']) ) {
1262 $this->TRAIT_get_button();
1263 }
1264 }
1265 ?>
1266 </div>
1267 </article>
1268 </div>
1269
1270 <?php if($carousel) { ?>
1271 </div>
1272 <?php if($has_animation) : ?>
1273 </div>
1274 <?php endif; ?>
1275
1276 <?php }
1277 }
1278 }
1279