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/widgets/advanced-post-grid.php +346 -1233 1.0.0 → 1.3.18 View file →
@@ -1,1233 +1,346 @@
1 -<?php
2 -
3 -namespace UiCoreElements;
4 -
5 -use Elementor\Controls_Manager;
6 -use Elementor\Group_Control_Border;
7 -use Elementor\Group_Control_Box_Shadow;
8 -use Elementor\Group_Control_Typography;
9 -use Elementor\Group_Control_Background;
10 -use Elementor\Includes\Widgets\Traits\Button_Trait;
11 -use UiCoreElements\UiCoreWidget;
12 -
13 -use UiCoreElements\Utils\Pagination_Trait;
14 -use UiCoreElements\Utils\Post_Filters_Trait;
15 -use UiCoreElements\Utils\Meta_Trait;
16 -use UiCoreElements\Utils\Animation_Trait;
17 -use UiCoreElements\Utils\Grid_Trait;
18 -use UiCoreElements\Controls\Post_Filter;
19 -use UiCoreElements\Controls\Query;
20 -use UiCoreElements\Helper;
21 -use \Elementor\Plugin;
22 -
23 -
24 -defined('ABSPATH') || exit();
25 -
26 -/**
27 - * Scripts and Styles Class
28 - */
29 -class AdvancedPostGrid extends UiCoreWidget
30 -{
31 - use Button_Trait;
32 - use Meta_Trait;
33 - use Pagination_Trait;
34 - use Animation_Trait;
35 - use Grid_Trait;
36 - use Post_Filters_Trait;
37 -
38 - private $_query;
39 -
40 - public function get_name()
41 - {
42 - return 'uicore-advanced-post-grid';
43 - }
44 - public function get_categories()
45 - {
46 - return ['uicore'];
47 - }
48 - public function get_title()
49 - {
50 - return __('Advanced Post Grid', 'uicore-elements');
51 - }
52 - public function get_icon()
53 - {
54 - return 'eicon-gallery-grid ui-e-widget';
55 - }
56 - public function get_keywords()
57 - {
58 - return ['post', 'grid', 'blog', 'recent', 'news'];
59 - }
60 - public function get_styles()
61 - {
62 - return [
63 - 'advanced-post-grid',
64 - 'animation',
65 - 'entrance', // entrance basic style
66 - 'e-animations' => [ // entrance animations
67 - 'condition' => [
68 - 'animation_assets' => 'false'
69 - ],
70 - 'external' => true,
71 - ]
72 - ];
73 - }
74 - public function get_scripts()
75 - {
76 - return [
77 - 'advanced-post-grid',
78 - 'entrance' => [
79 - 'condition' => [
80 - 'animate_items' => 'ui-e-grid-animate'
81 - ],
82 - ],
83 - 'ajax-request' => [
84 - 'condition' => [
85 - 'pagination_type' => 'load_more'
86 - ]
87 - ]
88 - ];
89 - }
90 -
91 - private function filter_missing_taxonomies($settings)
92 - {
93 - $taxonomy_filter_args = [
94 - 'show_in_nav_menus' => true,
95 - ];
96 - if (!empty($settings['posts-filter_post_type'])) {
97 - $taxonomy_filter_args['object_type'] = [$settings['posts-filter_post_type']];
98 - }
99 -
100 - $taxonomies = get_taxonomies($taxonomy_filter_args, 'objects');
101 -
102 - foreach ($taxonomies as $taxonomy => $object) {
103 - $controll_id = 'posts-filter_' . $taxonomy . '_ids';
104 - \error_log($controll_id);
105 - \error_log(print_r($settings[$controll_id], true));
106 -
107 - if (!isset($settings[$controll_id]) || empty($settings[$controll_id])) {
108 - continue;
109 - }
110 -
111 - //if is set check if this id still exists
112 - $settings[$controll_id] = array_filter($settings[$controll_id], function ($term_id) use ($object) {
113 - return term_exists($term_id, $object->name);
114 - });
115 -
116 - if (empty($settings[$controll_id])) {
117 - $settings[$controll_id] = null;
118 - }
119 - }
120 -
121 - return $settings;
122 - }
123 -
124 - public function on_import($element)
125 - {
126 - $element['settings'] = $this->filter_missing_taxonomies($element['settings']);
127 - return $element;
128 - }
129 -
130 - public function get_query()
131 - {
132 - return $this->_query;
133 - }
134 - public function query_posts($posts_per_page, $type = null)
135 - {
136 - if (!Plugin::$instance->editor->is_edit_mode() && $this->get_settings('posts-filter_post_type') === 'current' && !isset($_GET['uicore-tb'])) {
137 - global $wp_query;
138 - $this->_query = $wp_query;
139 - } elseif ($this->get_settings('posts-filter_post_type') === 'related') {
140 - $this->_query = Helper::get_related('random', $posts_per_page);
141 - } else {
142 - $query_args = Query::get_query_args('posts-filter', $this->get_settings(), get_the_ID());
143 -
144 - if ($type === 'portfolio') {
145 - $query_args['orderby'] = 'menu_order date';
146 - }
147 -
148 - if ($type === 'current') {
149 - unset($query_args['posts_per_page']);
150 - }
151 -
152 - $this->_query = new \WP_Query($query_args);
153 - }
154 - }
155 - protected function register_controls()
156 - {
157 - // Query(curent/custom/related/manual)
158 -
159 - // /Pagination (filtering?)
160 - // /Aditional (no posts)
161 -
162 - $this->start_controls_section(
163 - 'section_layout',
164 - [
165 - 'label' => esc_html__('Grid', 'uicore-elements'),
166 - ]
167 - );
168 - $this->TRAIT_register_entrace_asset_helper(); // Animation asset condition
169 - $this->register_grid_layout_controls(false, [], true); // Grid Layouts with old masonry control
170 -
171 - $this->end_controls_section();
172 -
173 -
174 - $this->start_controls_section(
175 - 'section_item_content',
176 - [
177 - 'label' => esc_html__('Item', 'uicore-elements'),
178 - ]
179 - );
180 - $this->add_control(
181 - 'box_style',
182 - [
183 - 'label' => __('Item Style', 'uicore-elements'),
184 - 'type' => Controls_Manager::SELECT,
185 - 'default' => 'classic',
186 - 'options' => [
187 - 'classic' => __('Classic', 'uicore-elements'),
188 - 'split' => __('Split', 'uicore-elements'),
189 - 'overlay' => __('Overlay', 'uicore-elements'),
190 - ],
191 - 'prefix_class' => 'ui-e-apg-',
192 - ]
193 - );
194 - $this->add_control(
195 - 'image',
196 - [
197 - 'label' => __('Image', 'uicore-elements'),
198 - 'type' => Controls_Manager::SWITCHER,
199 - 'separator' => 'before',
200 - 'default' => 'yes'
201 - ]
202 - );
203 - $this->add_control(
204 - 'image_size_select',
205 - [
206 - 'label' => __('Image Size', 'uicore-elements'),
207 - 'type' => Controls_Manager::SELECT,
208 - 'default' => 'uicore-medium',
209 - 'options' => self::get_images_sizes(),
210 - 'condition' => [
211 - 'image' => 'yes',
212 - ]
213 - ]
214 - );
215 - // $this->add_control('cat_type',[
216 - // 'label' => __( 'Cat Type', 'uicore-elements' ),
217 - // 'type' => Controls_Manager::SELECT,
218 - // 'default' => 'category',
219 - // 'options' => [
220 - // 'category' => __( 'Category', 'uicore-elements' ),
221 - // 'custom' => __( 'Custom Taxonomy', 'uicore-elements' ),
222 - // ],
223 - // 'condition' => array(
224 - // 'category' => 'yes',
225 - // ),
226 - // ]
227 - // );
228 - // $this->add_control('cat_type_name',[
229 - // 'label' => __( 'Taxonomy', 'uicore-elements' ),
230 - // 'type' => Controls_Manager::TEXT,
231 - // 'placeholder' => __( 'my_custom_tax', 'uicore-elements' ),
232 - // 'condition' => array(
233 - // 'cat_type' => 'custom',
234 - // ),
235 - // ]
236 - // );
237 - $this->add_control(
238 - 'title',
239 - [
240 - 'label' => __('Title', 'uicore-elements'),
241 - 'type' => Controls_Manager::SWITCHER,
242 - 'separator' => 'before',
243 - 'default' => 'yes'
244 - ]
245 - );
246 - $this->add_control(
247 - 'excerpt',
248 - [
249 - 'label' => __('Excerpt', 'uicore-elements'),
250 - 'type' => Controls_Manager::SWITCHER,
251 - 'separator' => 'before',
252 - 'default' => 'yes'
253 - ]
254 - );
255 - $this->add_control(
256 - 'excerpt_trim',
257 - [
258 - 'label' => __('Excerpt Length (words)', 'uicore-elements'),
259 - 'type' => Controls_Manager::NUMBER,
260 - 'min' => 5,
261 - 'max' => 100,
262 - 'step' => 1,
263 - 'default' => 55,
264 - 'condition' => array(
265 - 'excerpt' => 'yes',
266 - ),
267 - ]
268 - );
269 - $this->add_control(
270 - 'show_button',
271 - [
272 - 'label' => __('Read More Button', 'uicore-elements'),
273 - 'type' => Controls_Manager::SWITCHER,
274 - 'separator' => 'before',
275 - 'default' => 'no'
276 - ]
277 - );
278 - $this->end_controls_section();
279 -
280 -
281 - $this->start_controls_section(
282 - 'section_button_content',
283 - [
284 - 'label' => esc_html__('Button', 'uicore-elements'),
285 - 'condition' => array(
286 - 'show_button' => 'yes',
287 - ),
288 - ]
289 - );
290 - $this->register_button_content_controls(['section_condition' => ['show_button' => 'yes'], 'button_default_text' => 'Read More']);
291 - $this->remove_control('button_type');
292 - $this->remove_control('link');
293 - $this->remove_control('button_css_id');
294 - $this->remove_control('size');
295 - $this->remove_control('align');
296 - $this->end_controls_section();
297 -
298 -
299 - $this->start_controls_section(
300 - 'section_extra_item_content',
301 - [
302 - 'label' => esc_html__('Meta', 'uicore-elements'),
303 - ]
304 - );
305 - $this->add_control(
306 - 'top_meta',
307 - [
308 - 'label' => esc_html__('Top Meta', 'uicore-elements'),
309 - 'type' => \Elementor\Controls_Manager::REPEATER,
310 - 'fields' => $this->get_meta_content_controls(),
311 - 'default' => [
312 - [
313 - 'type' => 'author'
314 - ],
315 - ],
316 - 'title_field' => '<span style="text-transform: capitalize">{{{ type }}}</span>',
317 - 'prevent_empty' => false,
318 - 'separator' => 'before'
319 - ]
320 - );
321 - $this->add_control(
322 - 'before_title_meta',
323 - [
324 - 'label' => esc_html__('Before Title Meta', 'uicore-elements'),
325 - 'type' => \Elementor\Controls_Manager::REPEATER,
326 - 'fields' => $this->get_meta_content_controls(),
327 - 'default' => [
328 - [
329 - 'type' => 'author'
330 - ],
331 - ],
332 - 'title_field' => '<span style="text-transform: capitalize">{{{ type }}}</span>',
333 - 'prevent_empty' => false,
334 - 'separator' => 'before',
335 - ]
336 - );
337 - $this->add_control(
338 - 'after_title_meta',
339 - [
340 - 'label' => esc_html__('After Title Meta', 'uicore-elements'),
341 - 'type' => \Elementor\Controls_Manager::REPEATER,
342 - 'fields' => $this->get_meta_content_controls(),
343 - 'default' => [
344 - [
345 - 'type' => 'author'
346 - ],
347 - ],
348 - 'title_field' => '<span style="text-transform: capitalize">{{{ type }}}</span>',
349 - 'prevent_empty' => false,
350 - 'separator' => 'before',
351 - ]
352 - );
353 - $this->add_control(
354 - 'bottom_meta',
355 - [
356 - 'label' => esc_html__('Bottom Meta', 'uicore-elements'),
357 - 'type' => \Elementor\Controls_Manager::REPEATER,
358 - 'fields' => $this->get_meta_content_controls(),
359 - 'default' => [
360 - [
361 - 'type' => 'author'
362 - ],
363 - ],
364 - 'title_field' => '<span style="text-transform: capitalize">{{{ type }}}</span>',
365 - 'prevent_empty' => false,
366 - 'separator' => 'before',
367 - ]
368 - );
369 - $this->end_controls_section();
370 -
371 -
372 - $this->start_controls_section(
373 - 'section_post_grid_def',
374 - [
375 - 'label' => esc_html__('Query', 'uicore-elements'),
376 - ]
377 - );
378 -
379 - $this->add_group_control(
380 - Post_Filter::get_type(),
381 - [
382 - 'name' => 'posts-filter',
383 - 'label' => esc_html__('Posts', 'uicore-elements'),
384 - 'description' => esc_html__('Current Query Settings > Reading', 'uicore-elements'),
385 - ]
386 - );
387 -
388 - $this->add_control('item_limit', [
389 - 'label' => esc_html__('Item Limit', 'uicore-elements'),
390 - 'type' => Controls_Manager::SLIDER,
391 - 'reder_type' => 'template',
392 - 'range' => [
393 - 'px' => [
394 - 'min' => -1,
395 - 'max' => 100,
396 - ],
397 - ],
398 - 'default' => [
399 - 'size' => 3,
400 - ],
401 - 'condition' => array(
402 - 'posts-filter_post_type!' => 'current',
403 - ),
404 - ]);
405 -
406 - $this->add_control('offset', [
407 - 'label' => esc_html__('Query Offset', 'uicore-elements'),
408 - 'type' => Controls_Manager::SLIDER,
409 - 'render_type' => 'template',
410 - 'range' => [
411 - 'px' => [
412 - 'min' => -1,
413 - 'max' => 10,
414 - ],
415 - ],
416 - 'default' => [
417 - 'size' => 0,
418 - ],
419 - 'condition' => [
420 - 'pagination_type' => 'numbers',
421 - ]
422 - ]);
423 -
424 - $this->add_control(
425 - 'offset_alert',
426 - [
427 - 'type' => Controls_Manager::ALERT,
428 - 'alert_type' => 'info',
429 - 'content' => esc_html__('Offset is disabled with Load More pagination.', 'uicore-elements'),
430 - 'condition' => [
431 - 'pagination_type!' => 'numbers',
432 - ]
433 - ]
434 - );
435 -
436 - $this->add_control('sticky', [
437 - 'label' => esc_html__('Sticky Posts', 'uicore-elements'),
438 - 'type' => \Elementor\Controls_Manager::SWITCHER,
439 - 'label_on' => esc_html__('Show', 'uicore-elements'),
440 - 'label_off' => esc_html__('Hide', 'uicore-elements'),
441 - 'description' => esc_html__('Sticky posts works only on the front-end.', 'uicore-elements'),
442 - 'return_value' => 1,
443 - 'default' => 0,
444 - 'condition' => array(
445 - 'pagination!' => 'yes',
446 - ),
447 - ]);
448 -
449 - $this->end_controls_section();
450 -
451 - $this->start_controls_section(
452 - 'section_filters',
453 - [
454 - 'label' => esc_html__('Filters', 'uicore-elements'),
455 - ]
456 - );
457 - $this->TRAIT_register_filter_controls();
458 - $this->end_controls_section();
459 -
460 - $this->start_controls_section(
461 - 'section_pagination',
462 - [
463 - 'label' => esc_html__('Pagination', 'uicore-elements'),
464 - ]
465 - );
466 - $this->TRAIT_register_pagination_controls();
467 - $this->end_controls_section();
468 -
469 - //STYLE
470 - $this->start_controls_section(
471 - 'section_style_item',
472 - [
473 - 'label' => __('Item Style', 'uicore-elements'),
474 - 'tab' => Controls_Manager::TAB_STYLE,
475 - ]
476 - );
477 - $this->add_control(
478 - 'item_radius',
479 - [
480 - 'label' => esc_html__('Border Radius', 'uicore-elements'),
481 - 'type' => Controls_Manager::DIMENSIONS,
482 - 'selectors' => [
483 - '{{WRAPPER}} ' => '--ui-e-border-radius: {{TOP}}px {{RIGHT}}px {{BOTTOM}}px {{LEFT}}px;'
484 - ],
485 - ]
486 - );
487 - $this->start_controls_tabs(
488 - 'item_border_shadow'
489 - );
490 -
491 - $this->start_controls_tab(
492 - 'item_bs_normal_tab',
493 - [
494 - 'label' => esc_html__('Normal', 'plugin-name'),
495 - ]
496 - );
497 - $this->add_group_control(
498 - Group_Control_Border::get_type(),
499 - [
500 - 'name' => 'item_border',
501 - 'selector' => '{{WRAPPER}} .ui-e-item article',
502 - 'separator' => 'before',
503 - ]
504 - );
505 - $this->add_group_control(
506 - Group_Control_Box_Shadow::get_type(),
507 - [
508 - 'name' => 'item_shadow',
509 - 'selector' => '{{WRAPPER}} .ui-e-item article',
510 - ]
511 - );
512 -
513 - $this->end_controls_tab();
514 - $this->start_controls_tab(
515 - 'item_bs_hover_tab',
516 - [
517 - 'label' => esc_html__('Hover', 'plugin-name'),
518 - ]
519 - );
520 - $this->add_group_control(
521 - Group_Control_Border::get_type(),
522 - [
523 - 'name' => 'item_border_hover',
524 - 'selector' => '{{WRAPPER}} .ui-e-item:hover article',
525 - 'separator' => 'before',
526 - ]
527 - );
528 - $this->add_group_control(
529 - Group_Control_Box_Shadow::get_type(),
530 - [
531 - 'name' => 'item_shadow_hover',
532 - 'selector' => '{{WRAPPER}} .ui-e-item:hover article',
533 - ]
534 - );
535 - $this->end_controls_tab();
536 - $this->end_controls_tabs();
537 -
538 - $this->end_controls_section();
539 -
540 -
541 - $this->start_controls_section(
542 - 'section_style_content',
543 - [
544 - 'label' => __('Content Style', 'uicore-elements'),
545 - 'tab' => Controls_Manager::TAB_STYLE,
546 - ]
547 - );
548 - $this->add_control(
549 - 'image_size',
550 - [
551 - 'label' => __('Image Height (%)', 'uicore-elements'),
552 - 'type' => Controls_Manager::NUMBER,
553 - 'min' => 1,
554 - 'max' => 500,
555 - 'step' => 1,
556 - 'default' => 57,
557 - 'condition' => array(
558 - 'masonry!' => 'ui-e-maso',
559 - ),
560 - 'selectors' => [
561 - '{{WRAPPER}} .ui-e-post-top' => '--ui-e-img-size: {{VALUE}}',
562 - ],
563 - ]
564 - );
565 - $this->add_control(
566 - 'image_overflow',
567 - [
568 - 'label' => __('Independent Border Radius and Shadow', 'uicore-elements'),
569 - 'type' => Controls_Manager::SWITCHER,
570 - 'default' => 'no',
571 - 'prefix_class' => 'ui-e-post-ovf-',
572 - 'condition' => array(
573 - 'box_style!' => 'overlay',
574 - ),
575 - ]
576 - );
577 - $this->add_control(
578 - 'image_radius',
579 - [
580 - 'label' => esc_html__('Border Radius', 'uicore-elements'),
581 - 'type' => Controls_Manager::DIMENSIONS,
582 - 'selectors' => [
583 - '{{WRAPPER}} .ui-e-post-top' => 'border-radius: {{TOP}}px {{RIGHT}}px {{BOTTOM}}px {{LEFT}}px;'
584 - ],
585 - 'condition' => array(
586 - 'image_overflow' => 'yes',
587 - ),
588 - ]
589 - );
590 - $this->add_group_control(
591 - Group_Control_Box_Shadow::get_type(),
592 - [
593 - 'name' => 'image_shadow',
594 - 'label' => esc_html__('Box Shadow', 'uicore-elements'),
595 - 'selector' => '{{WRAPPER}} .ui-e-post-top',
596 - 'condition' => array(
597 - 'image_overflow' => 'yes',
598 - ),
599 - ]
600 - );
601 - $this->add_responsive_control(
602 - 'content_align',
603 - [
604 - 'label' => esc_html__('Content Alignment', 'uicore-elements'),
605 - 'type' => Controls_Manager::CHOOSE,
606 - 'options' => [
607 - 'left' => [
608 - 'title' => esc_html__('Left', 'uicore-elements'),
609 - 'icon' => 'eicon-text-align-left',
610 - ],
611 - 'center' => [
612 - 'title' => esc_html__('Center', 'uicore-elements'),
613 - 'icon' => 'eicon-text-align-center',
614 - ],
615 - 'stretch' => [
616 - 'title' => esc_html__('Justified', 'uicore-elements'),
617 - 'icon' => 'eicon-text-align-justify',
618 - ],
619 - ],
620 - 'selectors' => [
621 - '{{WRAPPER}} .ui-e-post-content' => 'align-items: {{VALUE}}; text-align: {{VALUE}};',
622 - ],
623 - ]
624 - );
625 - $this->add_control(
626 - 'title_color',
627 - [
628 - 'label' => esc_html__('Title Color', 'uicore-elements'),
629 - 'type' => Controls_Manager::COLOR,
630 - 'default' => '',
631 - 'separator' => 'before',
632 - 'selectors' => [
633 - '{{WRAPPER}} .ui-e-post-title' => 'color: {{VALUE}};',
634 - ],
635 - ]
636 - );
637 - $this->add_control(
638 - 'title_hcolor',
639 - [
640 - 'label' => esc_html__('Title Hover Color', 'uicore-elements'),
641 - 'type' => Controls_Manager::COLOR,
642 - 'default' => '',
643 - 'selectors' => [
644 - '{{WRAPPER}} .ui-e-post-title:hover' => 'color: {{VALUE}};',
645 - ],
646 - ]
647 - );
648 - $this->add_group_control(
649 - Group_Control_Typography::get_type(),
650 - [
651 - 'name' => 'title_typography',
652 - 'label' => esc_html__('Title Typography', 'uicore-elements'),
653 - 'selector' => '{{WRAPPER}} .ui-e-post-title',
654 - ]
655 - );
656 - $this->add_control(
657 - 'title_gap',
658 - [
659 - 'label' => __('Title Top Space', 'uicore-elements'),
660 - 'type' => Controls_Manager::SLIDER,
661 - 'size_units' => ['em'],
662 - 'separator' => 'after',
663 - 'range' => [
664 - 'px' => [
665 - 'min' => 0,
666 - 'max' => 3,
667 - 'step' => 0.1,
668 - ],
669 - ],
670 - 'default' => [
671 - 'unit' => 'em',
672 - 'size' => 1.2,
673 - ],
674 - 'selectors' => [
675 - '{{WRAPPER}} .ui-e-post-title' => 'margin-top: {{SIZE}}em;',
676 - ],
677 - ]
678 - );
679 - $this->add_control(
680 - 'text_color',
681 - [
682 - 'label' => esc_html__('Excerpt Color', 'uicore-elements'),
683 - 'type' => Controls_Manager::COLOR,
684 - 'default' => '',
685 - 'selectors' => [
686 - '{{WRAPPER}} .ui-e-post-text' => 'color: {{VALUE}};',
687 - ],
688 - ]
689 - );
690 - $this->add_group_control(
691 - Group_Control_Typography::get_type(),
692 - [
693 - 'name' => 'text_typography',
694 - 'label' => esc_html__('Excerpt Typography', 'uicore-elements'),
695 - 'selector' => '{{WRAPPER}} .ui-e-post-text',
696 - ]
697 - );
698 - $this->add_control(
699 - 'text_gap',
700 - [
701 - 'label' => __('Excerpt Top Space', 'uicore-elements'),
702 - 'type' => Controls_Manager::SLIDER,
703 - 'size_units' => ['em'],
704 - 'separator' => 'after',
705 - 'range' => [
706 - 'px' => [
707 - 'min' => 0,
708 - 'max' => 3,
709 - 'step' => 0.1,
710 - ],
711 - ],
712 - 'default' => [
713 - 'unit' => 'em',
714 - 'size' => 0.8,
715 - ],
716 - 'selectors' => [
717 - '{{WRAPPER}} .ui-e-post-text' => 'margin-top: {{SIZE}}em;',
718 - ],
719 - ]
720 - );
721 - $this->add_responsive_control(
722 - 'content_padding',
723 - [
724 - 'label' => esc_html__('Content Padding', 'uicore-elements'),
725 - 'type' => Controls_Manager::DIMENSIONS,
726 - 'size_units' => ['px', 'em', '%'],
727 - 'selectors' => [
728 - '{{WRAPPER}} .ui-e-post-content' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};'
729 - ]
730 - ]
731 - );
732 - $this->add_control(
733 - 'content_gap',
734 - [
735 - 'label' => __('Content Space', 'uicore-elements'),
736 - 'type' => Controls_Manager::SLIDER,
737 - 'size_units' => ['em'],
738 - 'separator' => 'after',
739 - 'range' => [
740 - 'px' => [
741 - 'min' => 0,
742 - 'max' => 3,
743 - 'step' => 0.1,
744 - ],
745 - ],
746 - 'default' => [
747 - 'unit' => 'em',
748 - 'size' => 0,
749 - ],
750 - 'selectors' => [
751 - '{{WRAPPER}} ' => '--ui-e-content-space: {{SIZE}}em;',
752 - ],
753 - ]
754 - );
755 - $this->add_group_control(
756 - Group_Control_Background::get_type(),
757 - [
758 - 'name' => 'content_bg',
759 - 'selector' => '{{WRAPPER}} .ui-e-post-content',
760 - ]
761 - );
762 - $this->end_controls_section();
763 -
764 -
765 - $this->start_controls_section(
766 - 'section_button_style',
767 - [
768 - 'label' => esc_html__('Button Style', 'uicore-elements'),
769 - 'tab' => Controls_Manager::TAB_STYLE,
770 - 'condition' => array(
771 - 'show_button' => 'yes',
772 - ),
773 - ]
774 - );
775 - $this->register_button_style_controls(['section_condition' => ['show_button' => 'yes']]);
776 - $this->add_control(
777 - 'button_gap',
778 - [
779 - 'label' => __('Button Top Space', 'uicore-elements'),
780 - 'type' => Controls_Manager::SLIDER,
781 - 'size_units' => ['em'],
782 - 'range' => [
783 - 'px' => [
784 - 'min' => 0,
785 - 'max' => 3,
786 - 'step' => 0.1,
787 - ],
788 - ],
789 - 'default' => [
790 - 'unit' => 'em',
791 - 'size' => 0.8,
792 - ],
793 - 'selectors' => [
794 - '{{WRAPPER}} .elementor-button' => 'margin-top: {{SIZE}}em;',
795 - ],
796 - ]
797 - );
798 - $this->end_controls_section();
799 -
800 -
801 - $this->start_controls_section(
802 - 'section_style_extra_content',
803 - [
804 - 'label' => __('Meta Style', 'uicore-elements'),
805 - 'tab' => Controls_Manager::TAB_STYLE,
806 - ]
807 - );
808 - $this->start_controls_tabs('style_extra_tabs');
809 - $this->start_controls_tab(
810 - 'style_top_tab',
811 - [
812 - 'label' => esc_html__('Top', 'uicore-elements'),
813 - ]
814 - );
815 - $this->get_meta_style_controls('top');
816 - $this->end_controls_tab();
817 -
818 - $this->start_controls_tab(
819 - 'style_before_title_tab',
820 - [
821 - 'label' => esc_html__('Before Title', 'uicore-elements'),
822 - ]
823 - );
824 - $this->get_meta_style_controls('before_title');
825 - $this->end_controls_tab();
826 -
827 - $this->start_controls_tab(
828 - 'style_after_title_tab',
829 - [
830 - 'label' => esc_html__('After Title', 'uicore-elements'),
831 - ]
832 - );
833 - $this->get_meta_style_controls('after_title');
834 - $this->end_controls_tab();
835 -
836 - $this->start_controls_tab(
837 - 'style_bottom_tab',
838 - [
839 - 'label' => esc_html__('Bottom', 'uicore-elements'),
840 - ]
841 - );
842 - $this->get_meta_style_controls('bottom');
843 - $this->end_controls_tab();
844 -
845 - $this->end_controls_tabs();
846 - $this->end_controls_section();
847 -
848 - $this->TRAIT_register_filter_style_controls();
849 -
850 - $this->start_controls_section(
851 - 'section_style_pagination',
852 - [
853 - 'label' => __('Pagination Style', 'uicore-elements'),
854 - 'tab' => Controls_Manager::TAB_STYLE,
855 - 'condition' => [
856 - 'pagination' => 'yes',
857 - ],
858 - ]
859 - );
860 - $this->TRAIT_register_pagination_style_controls();
861 - $this->end_controls_section();
862 -
863 -
864 - $this->start_controls_section(
865 - 'section_style_animations',
866 - [
867 - 'label' => __('Animations', 'uicore-elements'),
868 - 'tab' => Controls_Manager::TAB_STYLE,
869 - ]
870 - );
871 - $this->TRAIT_register_entrance_animations_controls();
872 - $this->TRAIT_register_hover_animation_control(
873 - 'Item Hover Animation',
874 - [],
875 - ['underline'],
876 - 'anim_item'
877 - );
878 - $this->add_control(
879 - 'anim_image',
880 - [
881 - 'label' => __('Image Hover Animation', 'uicore-elements'),
882 - 'type' => Controls_Manager::SELECT,
883 - 'label_block' => true,
884 - 'default' => 'ui-e-img-anim-zoom',
885 - 'options' => [
886 - '' => __('None', 'uicore-elements'),
887 - 'ui-e-img-anim-zoom' => __('Zoom', 'uicore-elements'),
888 - ],
889 - 'prefix_class' => '',
890 - ]
891 - );
892 - $this->add_control(
893 - 'anim_meta',
894 - [
895 - 'label' => __('Meta Hover Animation', 'uicore-elements'),
896 - 'type' => Controls_Manager::SELECT,
897 - 'label_block' => true,
898 - 'default' => '',
899 - 'options' => [
900 - '' => __('None', 'uicore-elements'),
901 - 'ui-e-meta-anim-show' => __('Show', 'uicore-elements'),
902 - ],
903 - 'prefix_class' => '',
904 - ]
905 - );
906 - $this->add_control(
907 - 'important_note',
908 - [
909 - 'label' => esc_html__('Important Note', 'uicore-elements'),
910 - 'type' => \Elementor\Controls_Manager::RAW_HTML,
911 - 'raw' => '<div class="elementor-control-field-description" style="margin-top: -7px;">' . esc_html__('This works only for Below Title Meta.', 'uicore-elements') . '</div>',
912 - 'show_label' => false,
913 - 'condition' => array(
914 - 'box_style' => 'overlay',
915 - ),
916 - ]
917 - );
918 - $this->add_control(
919 - 'anim_title',
920 - [
921 - 'label' => __('Title Hover Animation', 'uicore-elements'),
922 - 'type' => Controls_Manager::SELECT,
923 - 'label_block' => true,
924 - 'default' => '',
925 - 'options' => [
926 - '' => __('None', 'uicore-elements'),
927 - 'ui-e-title-anim-underline' => __('Underline', 'uicore-elements'),
928 - ],
929 - 'prefix_class' => '',
930 - ]
931 - );
932 - $this->add_control(
933 - 'anim_content',
934 - [
935 - 'label' => __('Content Hover Animation', 'uicore-elements'),
936 - 'type' => Controls_Manager::SELECT,
937 - 'label_block' => true,
938 - 'default' => '',
939 - 'options' => [
940 - '' => __('None', 'uicore-elements'),
941 - 'ui-e-content-anim-show' => __('Show', 'uicore-elements'),
942 - ],
943 - 'prefix_class' => '',
944 - 'condition' => array(
945 - 'box_style' => 'overlay',
946 - ),
947 - ]
948 - );
949 - $this->add_control(
950 - 'anim_btn',
951 - [
952 - 'label' => __('Button Hover Animation', 'uicore-elements'),
953 - 'type' => Controls_Manager::SELECT,
954 - 'label_block' => true,
955 - 'default' => '',
956 - 'options' => [
957 - '' => __('None', 'uicore-elements'),
958 - 'ui-e-btn-anim-show' => __('Show', 'uicore-elements'),
959 - ],
960 - 'prefix_class' => '',
961 - 'condition' => [
962 - 'show_button' => 'yes',
963 - ],
964 - ]
965 - );
966 - $this->end_controls_section();
967 - }
968 - static function get_images_sizes()
969 - {
970 - $sizes = [];
971 - foreach (get_intermediate_image_sizes() as $size) {
972 - $sizes[$size] = $size;
973 - }
974 - return $sizes;
975 - }
976 - protected function get_post_image()
977 - {
978 -
979 - if ($this->get_settings_for_display('image') === 'yes') {
980 - $pic_id = get_post_thumbnail_id();
981 - if (!$pic_id)
982 - return;
983 - $size = $this->get_settings_for_display('image_size_select') ?? 'uicore-medium';
984 - ?>
985 - <a class="ui-e-post-img-wrapp" href="<?php echo esc_url(get_permalink()); ?>" title="<?php echo esc_attr__('View Post:', 'uicore-elements') . the_title_attribute(['echo' => false]); ?>">
986 - <?php if ($this->get_settings_for_display('masonry') === 'ui-e-maso') { ?>
987 - <?php the_post_thumbnail($size, ['class' => 'ui-e-post-img']); ?>
988 - <?php } else { ?>
989 - <div class="ui-e-post-img" style="background-image:url(<?php echo wp_get_attachment_image_url($pic_id, $size) ?>)"></div>
990 - <?php } ?>
991 - </a>
992 - <?php
993 - }
994 - }
995 -
996 - protected function get_post_title()
997 - {
998 - if ($this->get_settings_for_display('title') === 'yes')
999 - ?>
1000 - <a href="<?php echo esc_url( get_permalink() );?>" title="<?php echo esc_attr__('View Post:','uicore-elements') . esc_html(the_title_attribute(['echo'=>false])); ?>">
1001 - <h4 class="ui-e-post-title"><span><?php echo esc_html(get_the_title()); ?></span></h4>
1002 - </a>
1003 - <?php
1004 - }
1005 -
1006 - protected function get_post_meta($position)
1007 - {
1008 - $meta_list = $this->get_settings_for_display($position . '_meta');
1009 - if (!isset($meta_list[0]) || $meta_list[0]['type'] == '') {
1010 - return;
1011 - }
1012 - echo ($position == 'top') ? '<div class="ui-e-post-top-meta">' : '';
1013 - echo ($position == 'after_title') ? '<div class="ui-e-meta-wrapp">' : '';
1014 - echo '<div class="ui-e-post-meta ui-e-'.esc_attr($position).'">';
1015 - foreach ($meta_list as $meta) {
1016 - if($meta['type'] != 'none'){
1017 - echo '<div class="ui-e-meta-item">';
1018 - $this->display_meta($meta);
1019 - echo '</div>';
1020 -
1021 - if( next( $meta_list ) && $this->get_settings_for_display( $position.'_meta_separator' ) ) {
1022 - echo '<span class="ui-e-separator">'.esc_html($this->get_settings_for_display( $position.'_meta_separator' )).'</span>';
1023 - }
1024 - }
1025 - }
1026 - echo '</div>';
1027 - echo ($position == 'top' || $position == 'after_title') ? '</div>' : '';
1028 - }
1029 - function get_button()
1030 - {
1031 - $settings = $this->get_settings_for_display();
1032 -
1033 - $this->add_render_attribute('button', 'class', 'elementor-button-link');
1034 - $this->add_render_attribute('button', 'class', 'elementor-button');
1035 - $this->add_render_attribute('button', 'role', 'button');
1036 - $this->add_render_attribute('content-wrapper', 'class', 'elementor-button-content-wrapper');
1037 -
1038 - if (!empty($settings['button_css_id'])) {
1039 - $this->add_render_attribute('button', 'id', $settings['button_css_id']);
1040 - }
1041 -
1042 - if (!empty($settings['size'])) {
1043 - $this->add_render_attribute('button', 'class', 'elementor-size-' . $settings['size']);
1044 - }
1045 -
1046 - if (!empty($settings['hover_animation'])) {
1047 - $this->add_render_attribute('button', 'class', 'elementor-animation-' . $settings['hover_animation']);
1048 - }
1049 - $this->add_render_attribute([
1050 - 'icon-align' => [
1051 - 'class' => [
1052 - 'elementor-button-icon',
1053 - 'elementor-align-icon-' . $settings['icon_align'],
1054 - ],
1055 - ],
1056 - 'text' => [
1057 - 'class' => 'elementor-button-text',
1058 - ],
1059 - ]);
1060 -
1061 - $tbn_content = '<span ' . $this->get_render_attribute_string('content-wrapper') . '>';
1062 -
1063 - if (!empty($settings['icon']) || !empty($settings['selected_icon']['value'])) {
1064 - $tbn_content .= '<span ' . $this->get_render_attribute_string('icon-align') . '>';
1065 - \ob_start();
1066 - \Elementor\Icons_Manager::render_icon($settings['selected_icon'], ['aria-hidden' => 'true']);
1067 - $tbn_content .= \ob_get_clean();
1068 - $tbn_content .= '</span>';
1069 - }
1070 -
1071 - $tbn_content .= '<span ' . $this->get_render_attribute_string('text') . '>' . $this->get_settings_for_display('text') . '</span>';
1072 - $tbn_content .= '</span>';
1073 -
1074 - if ('product' === get_post_type()) {
1075 - // WooCommerce product
1076 - global $product;
1077 -
1078 - if ($product) {
1079 - // Display WooCommerce add to cart button
1080 - echo wp_kses_post(apply_filters(
1081 - 'woocommerce_loop_add_to_cart_link', // WPCS: XSS ok.
1082 - sprintf(
1083 - '<a href="%s" data-quantity="%s" %s>%s</a>',
1084 - esc_url($product->add_to_cart_url()),
1085 - esc_attr(1),
1086 - $this->get_render_attribute_string('button'),
1087 - $tbn_content
1088 - ),
1089 - $product
1090 - ));
1091 - }
1092 - } else {
1093 -
1094 - // Default button
1095 - ?>
1096 - <a href="<?php echo esc_url(get_permalink()); ?>" <?php $this->print_render_attribute_string('button'); ?>>
1097 - <?php echo wp_kses_post($tbn_content); ?>
1098 - </a>
1099 - <?php
1100 - }
1101 - }
1102 -
1103 - protected function render_item()
1104 - {
1105 - $excerpt_length = $this->get_settings_for_display('excerpt_trim');
1106 - $extra_post_classes = ['ui-e-post-item', 'ui-e-item', 'ui-e-animations-wrp'];
1107 -
1108 - if ($this->get_settings_for_display('animate_items') === 'ui-e-grid-animate') {
1109 - $extra_post_classes[] = 'elementor-invisible';
1110 - }
1111 - if ($this->get_settings_for_display('anim_item') !== '') {
1112 - $extra_post_classes[] = $this->get_settings_for_display('anim_item');
1113 - }
1114 - ?>
1115 - <div class="<?php echo esc_attr(implode(' ', $extra_post_classes)); ?>">
1116 - <article <?php post_class(); ?>>
1117 - <div class="ui-e-post-top">
1118 - <?php $this->get_post_image(); ?>
1119 - <?php $this->get_post_meta('top'); ?>
1120 - </div>
1121 - <div class="ui-e-post-content">
1122 - <?php $this->get_post_meta('before_title'); ?>
1123 - <?php
1124 - if ($this->get_settings_for_display('title') === 'yes')
1125 - $this->get_post_title();
1126 - ?>
1127 - <?php $this->get_post_meta('after_title'); ?>
1128 - <?php
1129 - if ($this->get_settings_for_display('excerpt'))
1130 - echo wp_kses_post('<div class="ui-e-post-text">' . wp_trim_words(get_the_excerpt(), $excerpt_length) . '</div>');
1131 - ?>
1132 - <?php $this->get_post_meta('bottom'); // button
1133 - ?>
1134 - <?php
1135 - if ($this->get_settings_for_display('show_button') === 'yes') {
1136 - $this->get_button();
1137 - }
1138 - ?>
1139 - </div>
1140 - </article>
1141 - </div>
1142 - <?php
1143 - }
1144 - function content_template()
1145 - {
1146 - }
1147 - /**
1148 - * Renders the widget content using AJAX.
1149 - *
1150 - * This method retrieves the query arguments and widget settings, sets up the query, and renders each post item.
1151 - * If no posts are found, it returns false. After rendering, it resets the query and returns the output.
1152 - *
1153 - * @return string|false The rendered widget content or false if no posts are found.
1154 - */
1155 - public function render_ajax()
1156 - {
1157 - // Get query args and widget settings
1158 - global $wp_query;
1159 - $default_query = $wp_query;
1160 - $settings = $this->get_settings();
1161 - $this->query_posts($settings['item_limit']['size'], $settings['posts-filter_post_type']);
1162 - $wp_query = $this->get_query();
1163 -
1164 - //return false if no post found
1165 - if (!$wp_query->have_posts()) {
1166 - return false;
1167 - }
1168 -
1169 - \ob_start();
1170 - while ($wp_query->have_posts()) {
1171 - $wp_query->the_post();
1172 - $this->render_item();
1173 - }
1174 - wp_reset_query();
1175 - $wp_query = $default_query;
1176 - return \ob_get_clean();
1177 - }
1178 -
1179 -
1180 - protected function render()
1181 - {
1182 -
1183 - // Get query args and widget settings
1184 - global $wp_query;
1185 - $default_query = $wp_query;
1186 - $settings = $this->get_settings();
1187 - $this->query_posts($settings['item_limit']['size'], $settings['posts-filter_post_type']);
1188 - $wp_query = $this->get_query();
1189 -
1190 - // Store widget settings in a transient
1191 - $ID = strval($this->get_ID());
1192 - set_transient('ui_elements_widgetdata_' . $ID, $settings, \MONTH_IN_SECONDS);
1193 -
1194 - // Get the quantity of items and creates a loop control
1195 - $items = $settings['item_limit']['size'];
1196 - $loops = 0;
1197 -
1198 -
1199 - $this->TRAIT_render_filters();
1200 -
1201 -
1202 - // No posts found
1203 - if (!$wp_query->have_posts()) {
1204 - echo '<p style="text-align:center">' . __('No posts found.', 'uicore-elements') . '</p>';
1205 - } else {
1206 -
1207 - ?>
1208 - <div class="ui-e-adv-grid">
1209 - <?php
1210 - while ($wp_query->have_posts()) {
1211 -
1212 - if ($settings['sticky'] && $items == $loops) {
1213 - break; // sticky posts disregards posts per page, so ending the loop if $items == $loop forces the query respects the users item limit
1214 - }
1215 -
1216 - $wp_query->the_post();
1217 - $this->render_item();
1218 -
1219 - $loops++;
1220 - }
1221 - ?>
1222 - </div>
1223 - <?php
1224 - $this->TRAIT_render_pagination();
1225 - }
1226 -
1227 -
1228 - //reset query
1229 - wp_reset_query();
1230 - $wp_query = $default_query;
1231 - }
1232 -}
1233 -\Elementor\Plugin::instance()->widgets_manager->register(new AdvancedPostGrid());
1 +<?php
2 +
3 +namespace UiCoreElements;
4 +
5 +use Elementor\Controls_Manager;
6 +use UiCoreElements\UiCoreWidget;
7 +use UiCoreElements\Utils\Pagination_Trait;
8 +use UiCoreElements\Utils\Animation_Trait;
9 +use UiCoreElements\Utils\Grid_Trait;
10 +use uicoreElements\Utils\Post_Trait;
11 +use uiCoreElements\Utils\Post_Filters_Trait;
12 +
13 +defined('ABSPATH') || exit();
14 +
15 +/**
16 + * Scripts and Styles Class
17 + *
18 + */
19 +class AdvancedPostGrid extends UiCoreWidget
20 +{
21 + use Pagination_Trait,
22 + Animation_Trait,
23 + Grid_Trait,
24 + Post_Filters_Trait,
25 + Post_Trait;
26 +
27 + private $_query;
28 +
29 + public function get_name()
30 + {
31 + return 'uicore-advanced-post-grid';
32 + }
33 + public function get_categories()
34 + {
35 + return ['uicore'];
36 + }
37 + public function get_title()
38 + {
39 + return __('Advanced Post Grid', 'uicore-elements');
40 + }
41 + public function get_icon()
42 + {
43 + return 'eicon-gallery-grid ui-e-widget';
44 + }
45 + public function get_keywords()
46 + {
47 + return ['post', 'grid', 'blog', 'recent', 'news'];
48 + }
49 + public function get_styles()
50 + {
51 + $styles = [
52 + 'advanced-post-grid',
53 + 'legacy-grid',
54 + 'post-meta',
55 + 'filters' => [
56 + 'condition' => [
57 + 'post_filtering' => 'yes',
58 + ],
59 + ],
60 + 'animation', // hover animations
61 + 'entrance', // entrance basic style
62 + ];
63 + if (!class_exists('\UiCore\Core') && !class_exists('\UiCoreAnimate\Base')) {
64 + $styles['e-animations'] = [ // entrance animations
65 + 'external' => true,
66 + ];
67 + }
68 + return $styles;
69 + }
70 +
71 + /**
72 + * Adds `woocommerce` classname so rating can inherit woo styles and
73 + * also follow theme option styles instead of plain text.
74 + */
75 + protected function add_render_attributes()
76 + {
77 + parent::add_render_attributes();
78 +
79 + if (class_exists('WooCommerce') && \is_woocommerce()) {
80 + return;
81 + }
82 +
83 + $this->add_render_attribute(
84 + '_wrapper',
85 + 'class',
86 + [
87 + 'woocommerce',
88 + $this->get_html_wrapper_class(),
89 + ]
90 + );
91 + }
92 + public function get_scripts()
93 + {
94 + return [
95 + 'masonry' => [
96 + 'condition' => [
97 + 'masonry' => 'ui-e-maso'
98 + ],
99 + ],
100 + 'entrance' => [
101 + 'condition' => [
102 + 'animate_items' => 'ui-e-grid-animate'
103 + ],
104 + ],
105 + 'ajax-request' => [
106 + 'condition' => [
107 + 'pagination_type' => 'load_more'
108 + ]
109 + ]
110 + ];
111 + }
112 + public function has_widget_inner_wrapper(): bool
113 + {
114 + // TODO: remove after Optmized Markup experiment is merged to the core
115 + return ! \Elementor\Plugin::$instance->experiments->is_feature_active('e_optimized_markup');
116 + }
117 +
118 + private function filter_missing_taxonomies($settings)
119 + {
120 + // Check if is an "Advanced Product.." widget, since this widget is extended by other(s)
121 + $slug = strpos($this->get_name(), 'product') !== false ?
122 + 'product-filter_post_type' :
123 + 'posts-filter_post_type';
124 +
125 + $taxonomy_filter_args = [
126 + 'show_in_nav_menus' => true,
127 + ];
128 + if (!empty($settings[$slug])) {
129 + $taxonomy_filter_args['object_type'] = [$settings[$slug]];
130 + }
131 +
132 + $taxonomies = get_taxonomies($taxonomy_filter_args, 'objects');
133 +
134 + foreach ($taxonomies as $taxonomy => $object) {
135 + $controll_id = 'posts-filter_' . $taxonomy . '_ids';
136 + //error_log($controll_id);
137 + //error_log(print_r($settings[$controll_id], true));
138 +
139 + if (!isset($settings[$controll_id]) || empty($settings[$controll_id])) {
140 + continue;
141 + }
142 +
143 + //if is set check if this id still exists
144 + $settings[$controll_id] = array_filter($settings[$controll_id], function ($term_id) use ($object) {
145 + return term_exists($term_id, $object->name);
146 + });
147 +
148 + if (empty($settings[$controll_id])) {
149 + $settings[$controll_id] = null;
150 + }
151 + }
152 +
153 + return $settings;
154 + }
155 + public function on_import($element)
156 + {
157 + $element['settings'] = $this->filter_missing_taxonomies($element['settings']);
158 + return $element;
159 + }
160 + function get_query()
161 + {
162 + return $this->_query;
163 + }
164 +
165 + protected function register_controls()
166 + {
167 + // Query(curent/custom/related/manual)
168 +
169 + // /Pagination (filtering?)
170 + // /Aditional (no posts)
171 +
172 + // Contents and Settings
173 + $this->start_controls_section(
174 + 'section_layout',
175 + [
176 + 'label' => esc_html__('Grid', 'uicore-elements'),
177 + ]
178 + );
179 + $this->TRAIT_register_grid_layout_controls();
180 + $this->end_controls_section();
181 +
182 + $this->TRAIT_register_post_item_controls();
183 + $this->TRAIT_register_post_button_controls();
184 + $this->TRAIT_register_post_meta_controls();
185 + $this->TRAIT_register_post_query_controls(true, $this->get_name());
186 + $this->TRAIT_register_filter_controls();
187 + $this->TRAIT_register_pagination_controls();
188 +
189 + // Styles
190 + $this->TRAIT_register_post_item_style_controls();
191 + $this->TRAIT_register_post_content_style_controls();
192 + $this->TRAIT_register_post_button_style_controls();
193 + $this->TRAIT_register_post_meta_style_controls();
194 + $this->TRAIT_register_filter_style_controls();
195 + $this->TRAIT_register_pagination_style_controls();
196 +
197 + $this->start_controls_section(
198 + 'section_style_animations',
199 + [
200 + 'label' => __('Animations', 'uicore-elements'),
201 + 'tab' => Controls_Manager::TAB_STYLE,
202 + ]
203 + );
204 + $this->TRAIT_register_entrance_animations_controls();
205 + $this->TRAIT_register_hover_animation_control(
206 + 'Item Hover Animation',
207 + [],
208 + ['underline'],
209 + 'anim_item'
210 + );
211 + $this->TRAIT_register_post_animation_controls();
212 + $this->end_controls_section();
213 +
214 + // Update masonry from component to a legacy version
215 + $this->update_control('masonry', [
216 + 'label' => __('Masonry', 'uicore-elements'),
217 + 'type' => Controls_Manager::SWITCHER,
218 + 'frontend_available' => true,
219 + 'default' => 'no',
220 + 'return_value' => 'ui-e-maso',
221 + 'render_type' => 'template',
222 + // reset values from component
223 + 'prefix_class' => '',
224 + 'condition' => [],
225 + 'selectors' => [],
226 + ]);
227 + }
228 +
229 + function content_template() {}
230 +
231 + /**
232 + * Renders the widget content using AJAX.
233 + *
234 + * This method retrieves the widget settings; set up the query, and renders each post item.
235 + * If no posts are found, it returns false. After rendering, it resets the query and returns the output.
236 + *
237 + * @param array|false $current_query The current query args, or false if the widget isn't set to use the current query.
238 + * @param int $pageID The ID of the page where the widget is located.
239 + *
240 + * @return string|false The rendered widget content or false if no posts are found.
241 + */
242 + public function render_ajax($current_query)
243 + {
244 + // Get settings and post type
245 + $settings = $this->get_settings();
246 + $loop = 0;
247 +
248 + $this->TRAIT_query_posts($settings, $current_query);
249 + $wp_query = $this->get_query();
250 +
251 + if (!$wp_query || !$wp_query->have_posts()) {
252 + $markup = '';
253 + }
254 +
255 + \ob_start();
256 + while ($wp_query->have_posts()) {
257 + $wp_query->the_post();
258 + $this->TRAIT_render_item($loop, false, true);
259 + $loop++;
260 + }
261 + $markup = \ob_get_clean();
262 +
263 + return [
264 + 'markup' => $markup,
265 + ];
266 + }
267 +
268 + protected function render()
269 + {
270 + // Get current post ID
271 + $post_id = get_the_ID();
272 +
273 + // Get query args, settings and post type slug
274 + global $wp_query;
275 + $default_query = $wp_query;
276 + $settings = $this->get_settings();
277 +
278 + // Build query
279 + $this->TRAIT_query_posts($settings, $wp_query->query);
280 + $wp_query = $this->get_query();
281 +
282 + // Store widget settings in a transient
283 + $ID = strval($this->get_ID());
284 + set_transient('ui_elements_widgetdata_' . $ID, $settings, \MONTH_IN_SECONDS);
285 +
286 + // Get the quantity of items and creates a loop control
287 + $items = $settings['item_limit']['size'];
288 + $loops = 0;
289 +
290 + // Set masonry class
291 + $masonry = $this->is_option('masonry', 'yes')
292 + ? 'ui-e-maso'
293 + : '';
294 +
295 + $this->TRAIT_render_filters($settings);
296 +
297 + // No posts found
298 + if (!$wp_query->have_posts()) {
299 + echo '<p style="text-align:center">' . esc_html__('No posts found.', 'uicore-elements') . '</p>';
300 + } else {
301 +
302 +?>
303 + <div class="ui-e-adv-grid <?php echo esc_attr($masonry); ?>">
304 + <?php
305 + while ($wp_query->have_posts()) {
306 +
307 + // sticky posts disregards posts per page, so ending the loop if $items == $loop forces the query respects the users item limit
308 + if ($settings['sticky'] && $items == $loops) {
309 + break;
310 + }
311 +
312 + $wp_query->the_post();
313 + $this->TRAIT_render_item($loops, false, true);
314 +
315 + $loops++;
316 + }
317 + ?>
318 + </div>
319 +<?php
320 +
321 + $this->TRAIT_render_pagination($settings, $post_id);
322 +
323 + if (
324 + $this->is_option('pagination', 'yes') &&
325 + $this->is_option('pagination_type', 'load_more') &&
326 + $this->is_option('posts-filter_post_type', 'current')
327 + ) {
328 +
329 + // Build the public query args the ajax request script passes to rest api
330 + $public_query = array();
331 + $public_query['query']['post_type'] = get_post_type();
332 + $public_query['query_vars'] = $wp_query->query_vars;
333 +
334 + echo '<script>';
335 + echo 'window.ui_total_pages_' . esc_html($ID) . ' = "none";'; // add none to avoid ajax errors for lack of value, but posts don't need it
336 + echo 'window.ui_query_' . esc_html($ID) . ' = ' . \json_encode($public_query) . ';';
337 + echo '</script>';
338 + }
339 + }
340 +
341 + //reset query
342 + wp_reset_query();
343 + $wp_query = $default_query;
344 + }
345 +}
346 +\Elementor\Plugin::instance()->widgets_manager->register(new AdvancedPostGrid());