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