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

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