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
← All changes | includes/class-helper.php +328 -89 1.0.41.3.17 View file →
@@ -1,7 +1,10 @@
1 1 <?php
2 +
2 3 namespace UiCoreElements;
3 4
5 +use Elementor\Plugin;
6 +
4 7 defined('ABSPATH') || exit();
5 8 /**
6 9 * UiCore Utils Functions
7 10 */
@@ -12,24 +15,41 @@
12 15 {
13 16 return '<span class="uicore-meta-separator"></span>';
14 17 }
15 18
16 - public static function get_taxonomies($custom = true)
19 + public static function get_taxonomies($custom = true, $only_products = false)
17 20 {
18 - $taxonomies = get_taxonomies(['public' => true], 'objects');
19 - $exclusions = ['nav_menu', 'link_category', 'post_format']; // Exclude these taxonomies from the list
20 21
21 - $taxonomies = array_filter($taxonomies, function ($taxonomy) use ($exclusions) {
22 - return !in_array($taxonomy->name, $exclusions);
23 - });
22 + // Woo only taxonomies
23 + if ($only_products) {
24 + $taxonomies = [
25 + 'product_cat' => 'Product Categories',
26 + 'product_tag' => 'Product Tags'
27 + ];
24 28
25 - $taxonomies = array_map(function ($taxonomy) {
26 - if('portfolio_category' === $taxonomy->name){
27 - return 'Portfolio Category';
29 + $attributes = wc_get_attribute_taxonomies();
30 + foreach ($attributes as $att) {
31 + $taxonomies['pa_' . $att->attribute_name] = $att->attribute_label;
28 32 }
29 - return $taxonomy->label;
30 - }, $taxonomies);
31 33
34 + // All taxonomies
35 + } else {
36 +
37 + $taxonomies = get_taxonomies(['public' => true], 'objects');
38 + $exclusions = ['nav_menu', 'link_category', 'post_format']; // Exclude these taxonomies from the list
39 +
40 + $taxonomies = array_filter($taxonomies, function ($taxonomy) use ($exclusions) {
41 + return !in_array($taxonomy->name, $exclusions);
42 + });
43 +
44 + $taxonomies = array_map(function ($taxonomy) {
45 + if ('portfolio_category' === $taxonomy->name) {
46 + return 'Portfolio Category';
47 + }
48 + return $taxonomy->label;
49 + }, $taxonomies);
50 + }
51 +
32 52 if ($custom) {
33 53 $taxonomies = array_merge(['custom' => __('Custom Meta', 'uicore-elements')], $taxonomies);
34 54 }
35 55
@@ -38,15 +58,15 @@
38 58
39 59 static function get_taxonomy($name)
40 60 {
41 61 global $post;
62 + $categories = get_the_terms($post->ID, $name);
42 63
43 - $categories = get_the_terms( $post->ID, $name );
44 - if ( ! $categories || is_wp_error( $categories ) ) {
64 + if (! $categories || is_wp_error($categories)) {
45 65 return false;
46 66 }
47 67
48 - $categories = array_values( $categories );
68 + $categories = array_values($categories);
49 69 foreach ($categories as $t) {
50 70 $term_name[] =
51 71 '<a href="' . get_term_link($t) . '" title="View ' . \esc_attr($t->name) . ' posts">' . esc_html($t->name) . '</a>';
52 72 }
@@ -54,101 +74,151 @@
54 74
55 75 return $category;
56 76 }
57 77
78 + static function get_custom_meta($name, $product_id = null)
79 + {
80 + if (isset($product_id)) {
81 + $product = wc_get_product($product_id);
82 + $meta = $product->get_meta($name);
83 + } else {
84 + global $post;
85 + $meta = get_post_meta($post->ID, $name, true);
86 + }
87 +
88 + // If is an array means meta is not valid since we are expecting a single value string
89 + if (! $meta || is_array($meta)) {
90 + return false;
91 + }
92 +
93 + return $meta;
94 + }
95 +
58 96 static function get_reading_time()
59 97 {
60 98 global $post;
61 - // get the content
99 +
62 100 $the_content = $post->post_content;
63 - // count the number of words
64 - $words = str_word_count( wp_strip_all_tags( $the_content ) );
65 - // rounding off and deviding per 200 words per minute
66 - $minute = floor( $words / 200 );
101 + $words = str_word_count(wp_strip_all_tags($the_content)); // count the number of words
102 + $minute = floor($words / 200); // rounding off and deviding per 200 words per minute
67 103
68 - // calculate the amount of time needed to read
69 104 return $minute;
70 105 }
71 106
72 - static function register_widget_style($name,$deps=[],$external=false)
107 + static function get_site_domain()
73 108 {
74 - $handle = (!$external ? 'ui-e-' : '' ). $name;
75 - wp_register_style($handle, UICORE_ELEMENTS_ASSETS . '/css/elements/'.$name.'.css',$deps,UICORE_ELEMENTS_VERSION);
109 + return str_ireplace('www.', '', parse_url(home_url(), PHP_URL_HOST));
110 + }
111 +
112 + /**
113 + * Returns the Uicore Elements settings page URL. You may pass a message so it'll be wrapped under a <a> tag.
114 + *
115 + * @param string $message Optional. A clickable message to be displayed that'll redirect, in a new tab, to settings page.
116 + *
117 + * @return string Uicore Elements settings page URL or an <a> tag HTML with the url and the passed message.
118 + */
119 + static function get_admin_settings_url(string $message = '')
120 + {
121 + $url = admin_url('options-general.php?page=uicore-elements');
122 + return !empty($message)
123 + ? '<a href="' . esc_url($url) . '" target="_blank">' . esc_html($message) . '</a>'
124 + : $url;
125 + }
126 +
127 + static function register_widget_style($name, $deps = [], $external = false)
128 + {
129 + $handle = (!$external ? 'ui-e-' : '') . $name;
130 + wp_register_style($handle, UICORE_ELEMENTS_ASSETS . '/css/elements/' . $name . '.css', $deps, UICORE_ELEMENTS_VERSION);
76 131 return $handle;
77 132 }
78 - static function register_widget_script($name,$deps=[],$external=false)
133 + static function register_widget_script($name, $deps = [], $external = false)
79 134 {
80 - $handle = (!$external ? 'ui-e-' : '' ). $name;
81 - wp_register_script($handle, UICORE_ELEMENTS_ASSETS . '/js/elements/'.$name.'.js',$deps,UICORE_ELEMENTS_VERSION,true);
135 + $handle = (!$external ? 'ui-e-' : '') . $name;
136 + //if name contains / then we need to set a custom path
137 + if (strpos($name, '/') !== false) {
138 + $path = '';
139 + } else {
140 + $path = 'elements/';
141 + }
142 + wp_register_script($handle, UICORE_ELEMENTS_ASSETS . '/js/' . $path . $name . '.js', $deps, UICORE_ELEMENTS_VERSION, true);
82 143 return $handle;
83 144 }
84 145
85 -
86 - public static function get_related($filter, $number)
146 + /**
147 + * Build the related posts query in REST API context.
148 + *
149 + * @param int $page_number The current page number for pagination.
150 + * @param int $per_page The number of posts to retrieve per page.
151 + * @param string/int $pageID The current post/page ID.
152 + *
153 + * @return \WP_Query Returns a WP_Query object.
154 + */
155 + public static function get_related_ajax(int $page_number, int $per_page, $pageID)
87 156 {
88 - global $post;
157 + $args = [
158 + 'post__not_in' => [$pageID],
159 + 'posts_per_page' => $per_page,
160 + 'paged' => $page_number,
161 + ];
89 162
90 - $args = [];
163 + $categories = get_the_category($pageID);
164 + $tags = wp_get_post_tags($pageID);
91 165
92 - if ($filter == 'category') {
93 - $categories = get_the_category($post->ID);
166 + $tax_query = [];
94 167
95 - if ($categories) {
96 - $category_ids = [];
97 - foreach ($categories as $individual_category) {
98 - $category_ids[] = $individual_category->term_id;
99 - }
168 + if ($categories) {
169 + $category_ids = array_map(fn($cat) => $cat->term_id, $categories);
170 + $tax_query[] = [
171 + 'taxonomy' => 'category',
172 + 'field' => 'term_id',
173 + 'terms' => $category_ids,
174 + 'operator' => 'IN',
175 + ];
176 + }
100 177
101 - $args = [
102 - 'category__in' => $category_ids,
103 - 'post__not_in' => [$post->ID],
104 - 'posts_per_page' => $number,
105 - 'ignore_sticky_posts' => 1,
106 - ];
107 - }
108 - } elseif ($filter == 'tag') {
109 - $tags = wp_get_post_tags($post->ID);
178 + if ($tags) {
179 + $tag_ids = array_map(fn($tag) => $tag->term_id, $tags);
180 + $tax_query[] = [
181 + 'taxonomy' => 'post_tag',
182 + 'field' => 'term_id',
183 + 'terms' => $tag_ids,
184 + 'operator' => 'IN',
185 + ];
186 + }
110 187
111 - if ($tags) {
112 - $tag_ids = [];
113 - foreach ($tags as $individual_tag) {
114 - $tag_ids[] = $individual_tag->term_id;
115 - }
116 - $args = [
117 - 'tag__in' => $tag_ids,
118 - 'post__not_in' => [$post->ID],
119 - 'posts_per_page' => $number,
120 - 'ignore_sticky_posts' => 1,
121 - ];
122 - }
123 - } else {
124 - $args = [
125 - 'post__not_in' => [$post->ID],
126 - 'posts_per_page' => $number,
127 - 'orderby' => 'rand',
188 + if (!empty($tax_query)) {
189 + $args['tax_query'] = [
190 + 'relation' => 'OR',
191 + ...$tax_query,
128 192 ];
129 193 }
130 194
131 - $related_query = new \wp_query($args);
195 + return new \WP_Query($args);
196 + }
132 197
133 - if ($related_query->have_posts()) {
134 - return $related_query;
135 - } else {
136 - return false;
198 + /**
199 + * Returns an array of related products IDs.
200 + */
201 + public static function get_product_related($limit, $ID)
202 + {
203 + if (empty($ID)) {
204 + global $post;
205 + $ID = $post->ID;
137 206 }
207 +
208 + return wc_get_related_products($ID, $limit);
138 209 }
139 210
140 -
141 211 /*
142 212 * Get the current post id (used in Theme Builder - UiCore Framework)
143 213 */
144 214 static function get_current_meta_id()
145 215 {
146 - if(\class_exists('\UiCore\Blog\Frontend') && \UiCore\Blog\Frontend::is_blog() && !is_singular('post')){
216 + if (\class_exists('\UiCore\Blog\Frontend') && \UiCore\Blog\Frontend::is_blog() && !is_singular('post')) {
147 217 $post_id = get_option('page_for_posts', true);
148 - }elseif(\class_exists('\UiCore\Portfolio\Frontend') && \UiCore\Portfolio\Frontend::is_portfolio() && !is_singular('portfolio')){
218 + } elseif (\class_exists('\UiCore\Portfolio\Frontend') && \UiCore\Portfolio\Frontend::is_portfolio() && !is_singular('portfolio')) {
149 219 $post_id = \UiCore\Portfolio\Frontend::get_portfolio_page_id();
150 - }else{
220 + } else {
151 221 $post_id = get_queried_object_id();
152 222 }
153 223
154 224 return $post_id;
@@ -156,11 +226,11 @@
156 226
157 227 /**
158 228 * Return a list of textual html tags for Elementor Controls Options
159 229 */
230 + public static function get_title_tags()
231 + {
160 232
161 - public static function get_title_tags($type = null) {
162 -
163 233 $tags = [
164 234 'h1' => 'H1',
165 235 'h2' => 'H2',
166 236 'h3' => 'H3',
@@ -184,13 +254,14 @@
184 254 * @param string $custom The custom format to use if $format is set to 'custom'.
185 255 *
186 256 * @return string The formatted date value.
187 257 */
188 - public static function format_date($date, $format, $custom) {
258 + public static function format_date($date, $format, $custom)
259 + {
189 260
190 - if ( 'custom' === $format ) {
261 + if ('custom' === $format) {
191 262 $date_format = $custom;
192 - } else if ('default' === $format ) {
263 + } else if ('default' === $format) {
193 264 $date_format = get_option('date_format');
194 265 } else {
195 266 $date_format = $format;
196 267 }
@@ -200,17 +271,48 @@
200 271 return wp_kses_post($value);
201 272 }
202 273
203 274 /**
204 - * Sanitizes SVG content
275 + * Sanitizes HTML tags. Since is a custom sanitizer, require us, by wp plugin repo security standards,
276 + * to add `//phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped` comment.
205 277 *
278 + * @param mixed $raw_tag The HTML tag to sanitize.
279 + * @param string $default Default HTML value to fallback to in case an invalid tag is passed. Default is 'h3'.
280 + * @param bool $spacing Whether to add a trailing space after the tag. Default is false.
281 + * @return string The sanitized HTML tag.
282 + *
283 + * @since 1.3.5
284 + */
285 + public static function esc_tag($raw_tag, $default = 'h3', $spacing = false)
286 + {
287 +
288 + $allowed_tags_names = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div', 'span', 'p', 'a'];
289 + $tag = sanitize_key(strtolower($raw_tag)); // normalizes to [a-z0-9_]
290 +
291 + // fallback if tag not whitelisted
292 + if (! in_array($tag, $allowed_tags_names, true)) {
293 + $tag = $default;
294 + }
295 +
296 + if ($spacing) {
297 + return $tag . ' ';
298 + }
299 +
300 + return $tag;
301 + }
302 +
303 + /**
304 + * Sanitizes SVG content, also allowing `post` tags and atts. Since is a custom sanitizer, require us,
305 + * by wp plugin repo security standards, to add `//phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped` comment.
306 + *
206 307 * @param string $svg The raw SVG content to be sanitized.
207 308 * @return string The sanitized SVG content, with only allowed tags and attributes.
208 309 *
209 310 * @since 1.0.2
210 311 */
211 - public static function esc_svg($svg) {
212 - $default = wp_kses_allowed_html( 'post' );
312 + public static function esc_svg($svg)
313 + {
314 + $default = wp_kses_allowed_html('post');
213 315
214 316 $args = array(
215 317 'svg' => array(
216 318 'class' => true,
@@ -223,22 +325,23 @@
223 325 // has to be lowercase
224 326 'viewbox' => true,
225 327 'preserveaspectratio' => true
226 328 ),
227 - 'g' => array( 'fill' => true ),
228 - 'title' => array( 'title' => true ),
329 + 'g' => array('fill' => true),
330 + 'title' => array('title' => true),
229 331 'path' => array(
230 332 'd' => true,
231 333 'fill' => true
232 334 )
233 335 );
234 - $allowed_tags = array_merge( $default, $args );
336 + $allowed_tags = array_merge($default, $args);
235 337
236 - return wp_kses( $svg, $allowed_tags );
338 + return wp_kses($svg, $allowed_tags);
237 339 }
238 340
239 341 /**
240 - * Sanitizes text strings, but allowing some html tags usefull for styling and manipulating texts.
342 + * Sanitizes text strings, but allowing some html tags usefull for styling and manipulating texts. Since is a custom sanitizer,
343 + * require us, by wp plugin repo security standards, to add `//phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped` comment.
241 344 *
242 345 * @param string $content The content to be sanitized
243 346 * @return string The sanitized string content.
244 347 *
@@ -243,9 +346,10 @@
243 346 * @return string The sanitized string content.
244 347 *
245 348 * @since 1.0.3
246 349 */
247 - public static function esc_string($content) {
350 + public static function esc_string($content)
351 + {
248 352
249 353 $allowed_tags = [
250 354 'strong' => array(),
251 355 'em' => array(),
@@ -255,12 +359,18 @@
255 359 's' => array(),
256 360 'sub' => array(),
257 361 'sup' => array(),
258 362 'span' => array(),
259 - 'br' => array()
363 + 'br' => array(),
364 + 'a' => [
365 + 'href' => true,
366 + 'title' => true,
367 + 'target' => true,
368 + 'rel' => true
369 + ]
260 370 ];
261 371
262 - return wp_kses( $content, $allowed_tags );
372 + return wp_kses($content, $allowed_tags);
263 373 }
264 374
265 375 /**
266 376 * Retrieves the available image sizes.
@@ -268,9 +378,10 @@
268 378 * @return array An array of image sizes.
269 379 *
270 380 * @since 1.0.0
271 381 */
272 - public static function get_images_sizes() {
382 + public static function get_images_sizes()
383 + {
273 384 $sizes = [];
274 385 foreach (get_intermediate_image_sizes() as $size) {
275 386 $sizes[$size] = $size;
276 387 }
@@ -276,5 +387,133 @@
276 387 }
277 388 return $sizes;
278 389 }
279 390
391 + /**
392 + * @since 1.0.5
393 + */
394 + private static function get_element_recursive($elements, $form_id)
395 + {
396 +
397 + foreach ($elements as $element) {
398 + if ($form_id === $element['id']) {
399 + return $element;
400 + }
401 +
402 + if (!empty($element['elements'])) {
403 + $element = self::get_element_recursive($element['elements'], $form_id);
404 +
405 + if ($element) {
406 + return $element;
407 + }
408 + }
409 + }
410 +
411 + return false;
412 + }
413 +
414 + /**
415 + * Retrieves the settings of a specific widget without relying on transient data.
416 + *
417 + * @param int $post_id The ID of the post or page.
418 + * @param int $widget_id The ID of the widget.
419 + * @return array|string The settings of the widget, or an error message if the request is invalid.
420 + *
421 + * @since 1.0.5
422 + * @deprecated Deprecated since version 1.0.11 Use the transient method instead.
423 + */
424 + public static function get_widget_settings($post_id, $widget_id)
425 + {
426 +
427 + if (!$post_id || !$widget_id) {
428 + return false;
429 + }
430 +
431 + $elementor = Plugin::$instance;
432 + $pageMeta = $elementor->documents->get($post_id);
433 +
434 + if (!$pageMeta) {
435 + return false;
436 + }
437 + $metaData = $pageMeta->get_elements_data();
438 + if (!$metaData) {
439 + return false;
440 + }
441 +
442 + $widget_data = self::get_element_recursive($metaData, $widget_id);
443 + $settings = [];
444 +
445 + if (is_array($widget_data)) {
446 + $widget = $elementor->elements_manager->create_element_instance($widget_data);
447 + $settings = $widget->get_settings();
448 + }
449 +
450 + return $settings;
451 + }
452 +
453 + /**
454 + * Get the `posts per page` value from Framework or WordPress settings last case scenario.
455 + * Usefull if we're using `current` post type and don't have posts per page option.
456 + *
457 + * @param string $post_type The post type slug.
458 + *
459 + * @since 1.2.1
460 + * @return int The number of posts per page.
461 + */
462 + public static function get_framework_visible_posts(string $post_type)
463 + {
464 + // Get from Uicore Framework, if available
465 + if (defined('UICORE_ASSETS')) {
466 +
467 + switch ($post_type) {
468 + case 'product':
469 + return \Uicore\Helper::get_option('woocommerce_posts_number');
470 +
471 + case 'post':
472 + return \Uicore\Helper::get_option('blog_posts_number');
473 +
474 + case 'portfolio':
475 + return \Uicore\Helper::get_option('portfolio_posts_number');
476 +
477 + default:
478 + return get_option('posts_per_page');
479 + }
480 + }
481 +
482 + return get_option('posts_per_page');
483 + }
484 + /**
485 + * Retrieves the list of Uicore Framework registered popups.
486 + *
487 + * @return array
488 + *
489 + * @since 1.3.3
490 + */
491 + public static function get_uicore_popups(): array
492 + {
493 + // get elementor popups posts
494 + $args = [
495 + 'post_type' => 'uicore-tb',
496 + 'post_status' => 'publish',
497 + 'posts_per_page' => 50,
498 + 'tax_query' => [
499 + [
500 + 'taxonomy' => 'tb_type',
501 + 'field' => 'slug',
502 + 'terms' => '_type_popup',
503 + ]
504 + ]
505 + ];
506 +
507 + $query = new \WP_Query($args);
508 + $popups = [];
509 + if ($query->have_posts()) {
510 + while ($query->have_posts()) {
511 + $query->the_post();
512 + $popups[esc_html(get_the_ID())] = esc_html(html_entity_decode(get_the_title()));
513 + }
514 + wp_reset_postdata();
515 + }
516 +
517 + return $popups;
518 + }
280 519 }