PluginProbe
UiCore Elements – Free widgets and templates for Elementor / 1.3.17
UiCore Elements – Free widgets and templates for Elementor v1.3.17
1.3.17 1.3.16 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 All 41 releases
uicore-elements / includes / widgets / advanced-post-grid.php

advanced-post-grid.php in UiCore Elements – Free widgets and templates for Elementor 1.3.17, at includes/widgets/advanced-post-grid.php

347 lines 10.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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());
347