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 -297 1.0.12 → 1.3.18 View file →
@@ -1,297 +1,346 @@
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 - 'animation', // hover animations
54 - 'entrance', // entrance basic style
55 - ];
56 - if(!class_exists('\UiCore\Core') && !class_exists('\UiCoreAnimate\Base')){
57 - $styles['e-animations'] = [ // entrance animations
58 - 'external' => true,
59 - ];
60 - }
61 - return $styles;
62 - }
63 - public function get_scripts()
64 - {
65 - return [
66 - 'masonry' => [
67 - 'condition' => [
68 - 'masonry' => 'ui-e-maso'
69 - ],
70 - ],
71 - 'entrance' => [
72 - 'condition' => [
73 - 'animate_items' => 'ui-e-grid-animate'
74 - ],
75 - ],
76 - 'ajax-request' => [
77 - 'condition' => [
78 - 'pagination_type' => 'load_more'
79 - ]
80 - ]
81 - ];
82 - }
83 -
84 - private function filter_missing_taxonomies($settings)
85 - {
86 - // Check if is an "Advanced Product.." widget, since this widget is extended by other(s)
87 - $slug = strpos($this->get_name(), 'product') !== false ?
88 - 'product-filter_post_type' :
89 - 'posts-filter_post_type';
90 -
91 - $taxonomy_filter_args = [
92 - 'show_in_nav_menus' => true,
93 - ];
94 - if ( !empty($settings[$slug]) ) {
95 - $taxonomy_filter_args['object_type'] = [$settings[$slug]];
96 - }
97 -
98 - $taxonomies = get_taxonomies($taxonomy_filter_args, 'objects');
99 -
100 - foreach ($taxonomies as $taxonomy => $object) {
101 - $controll_id = 'posts-filter_' . $taxonomy . '_ids';
102 - \error_log($controll_id);
103 - \error_log(print_r($settings[$controll_id], true));
104 -
105 - if (!isset($settings[$controll_id]) || empty($settings[$controll_id])) {
106 - continue;
107 - }
108 -
109 - //if is set check if this id still exists
110 - $settings[$controll_id] = array_filter($settings[$controll_id], function ($term_id) use ($object) {
111 - return term_exists($term_id, $object->name);
112 - });
113 -
114 - if (empty($settings[$controll_id])) {
115 - $settings[$controll_id] = null;
116 - }
117 - }
118 -
119 - return $settings;
120 - }
121 - public function on_import($element)
122 - {
123 - $element['settings'] = $this->filter_missing_taxonomies($element['settings']);
124 - return $element;
125 - }
126 - function get_query()
127 - {
128 - return $this->_query;
129 - }
130 -
131 - protected function register_controls()
132 - {
133 - // Query(curent/custom/related/manual)
134 -
135 - // /Pagination (filtering?)
136 - // /Aditional (no posts)
137 -
138 - // Contents and Settings
139 - $this->start_controls_section(
140 - 'section_layout',
141 - [
142 - 'label' => esc_html__('Grid', 'uicore-elements'),
143 - ]
144 - );
145 - $this->TRAIT_register_grid_layout_controls();
146 - $this->end_controls_section();
147 -
148 - $this->TRAIT_register_post_item_controls();
149 - $this->TRAIT_register_post_button_controls();
150 - $this->TRAIT_register_post_meta_controls();
151 - $this->TRAIT_register_post_query_controls(true, $this->get_name());
152 - $this->TRAIT_register_filter_controls();
153 - $this->TRAIT_register_pagination_controls();
154 -
155 - // Styles
156 - $this->TRAIT_register_post_item_style_controls();
157 - $this->TRAIT_register_post_content_style_controls();
158 - $this->TRAIT_register_post_button_style_controls();
159 - $this->TRAIT_register_post_meta_style_controls();
160 - $this->TRAIT_register_filter_style_controls();
161 - $this->TRAIT_register_pagination_style_controls();
162 -
163 - $this->start_controls_section(
164 - 'section_style_animations',
165 - [
166 - 'label' => __('Animations', 'uicore-elements'),
167 - 'tab' => Controls_Manager::TAB_STYLE,
168 - ]
169 - );
170 - $this->TRAIT_register_entrance_animations_controls();
171 - $this->TRAIT_register_hover_animation_control(
172 - 'Item Hover Animation',
173 - [],
174 - ['underline'],
175 - 'anim_item'
176 - );
177 - $this->TRAIT_register_post_animation_controls();
178 - $this->end_controls_section();
179 -
180 - // Update masonry from component to a legacy version
181 - $this->update_control('masonry', [
182 - 'label' => __( 'Masonry', 'uicore-elements' ),
183 - 'type' => Controls_Manager::SWITCHER,
184 - 'frontend_available' => true,
185 - 'default' => 'no',
186 - 'return_value' => 'ui-e-maso',
187 - 'render_type' => 'template',
188 - // reset values from component
189 - 'prefix_class' => '',
190 - 'condition' => [],
191 - 'selectors' => [],
192 - ]);
193 - }
194 -
195 - function content_template()
196 - {
197 - }
198 -
199 - /**
200 - * Renders the widget content using AJAX.
201 - *
202 - * This method retrieves the widget settings; set up the query, and renders each post item.
203 - * If no posts are found, it returns false. After rendering, it resets the query and returns the output.
204 - *
205 - * @param array|false $current_query The current query args, or false if the widget isn't set to use the current query.
206 - *
207 - * @return string|false The rendered widget content or false if no posts are found.
208 - */
209 - public function render_ajax($current_query)
210 - {
211 -
212 - // Get settings and post type
213 - $settings = $this->get_settings();
214 -
215 - $this->TRAIT_query_posts( $settings, $current_query );
216 - $wp_query = $this->get_query();
217 -
218 - if (!$wp_query->have_posts()) {
219 - return false;
220 - }
221 -
222 - \ob_start();
223 - while ($wp_query->have_posts()) {
224 - $wp_query->the_post();
225 - $this->TRAIT_render_item(false, true);
226 - }
227 - $markup = \ob_get_clean();
228 -
229 - return [
230 - 'markup' => $markup,
231 - ];
232 - }
233 -
234 - protected function render()
235 - {
236 - // Get query args, settings and post type slug
237 - global $wp_query;
238 - $default_query = $wp_query;
239 - $settings = $this->get_settings();
240 -
241 - // Build query
242 - $this->TRAIT_query_posts( $settings, $wp_query->query );
243 - $wp_query = $this->get_query();
244 -
245 - $this->TRAIT_set_meta_font_size_to_svg($settings); // SVG icon experiment font-size adjustment
246 -
247 - // Store widget settings in a transient
248 - $ID = strval($this->get_ID());
249 - set_transient('ui_elements_widgetdata_' . $ID, $settings, \MONTH_IN_SECONDS);
250 -
251 - // Get the quantity of items and creates a loop control
252 - $items = $settings['item_limit']['size'];
253 - $loops = 0;
254 -
255 - $this->TRAIT_render_filters($settings);
256 -
257 - // No posts found
258 - if (!$wp_query->have_posts()) {
259 - echo '<p style="text-align:center">' . __('No posts found.', 'uicore-elements') . '</p>';
260 - } else {
261 -
262 - ?>
263 - <div class="ui-e-adv-grid">
264 - <?php
265 - while ($wp_query->have_posts()) {
266 -
267 - // sticky posts disregards posts per page, so ending the loop if $items == $loop forces the query respects the users item limit
268 - if ($settings['sticky'] && $items == $loops) {
269 - break;
270 - }
271 -
272 - $wp_query->the_post();
273 - $this->TRAIT_render_item(false, true);
274 -
275 - $loops++;
276 - }
277 - ?>
278 - </div>
279 - <?php
280 -
281 - $this->TRAIT_render_pagination($settings);
282 -
283 - if( $settings['pagination'] == 'yes' && $settings['pagination_type'] == 'load_more' && $settings['posts-filter_post_type'] == 'current' ) {
284 -
285 - echo '<script>';
286 - 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
287 - echo 'window.ui_query_' . esc_html($ID) . ' = ' . \json_encode($wp_query) . ';';
288 - echo '</script>';
289 - }
290 - }
291 -
292 - //reset query
293 - wp_reset_query();
294 - $wp_query = $default_query;
295 - }
296 -}
297 -\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());