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

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