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 +343 -91 1.0.31.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,18 +254,17 @@
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;
263 + } else if ('default' === $format) {
264 + $date_format = get_option('date_format');
192 265 } else {
193 266 $date_format = $format;
194 -
195 - if ( 'default' === $date_format ) {
196 - $date_format = get_option('date_format');
197 - }
198 267 }
199 268
200 269 $value = date_i18n($date_format, $date);
201 270
@@ -202,17 +271,48 @@
202 271 return wp_kses_post($value);
203 272 }
204 273
205 274 /**
206 - * 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.
207 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 + *
208 307 * @param string $svg The raw SVG content to be sanitized.
209 308 * @return string The sanitized SVG content, with only allowed tags and attributes.
210 309 *
211 310 * @since 1.0.2
212 311 */
213 - public static function esc_svg($svg) {
214 - $default = wp_kses_allowed_html( 'post' );
312 + public static function esc_svg($svg)
313 + {
314 + $default = wp_kses_allowed_html('post');
215 315
216 316 $args = array(
217 317 'svg' => array(
218 318 'class' => true,
@@ -225,22 +325,23 @@
225 325 // has to be lowercase
226 326 'viewbox' => true,
227 327 'preserveaspectratio' => true
228 328 ),
229 - 'g' => array( 'fill' => true ),
230 - 'title' => array( 'title' => true ),
329 + 'g' => array('fill' => true),
330 + 'title' => array('title' => true),
231 331 'path' => array(
232 332 'd' => true,
233 333 'fill' => true
234 334 )
235 335 );
236 - $allowed_tags = array_merge( $default, $args );
336 + $allowed_tags = array_merge($default, $args);
237 337
238 - return wp_kses( $svg, $allowed_tags );
338 + return wp_kses($svg, $allowed_tags);
239 339 }
240 340
241 341 /**
242 - * 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.
243 344 *
244 345 * @param string $content The content to be sanitized
245 346 * @return string The sanitized string content.
246 347 *
@@ -245,9 +346,10 @@
245 346 * @return string The sanitized string content.
246 347 *
247 348 * @since 1.0.3
248 349 */
249 - public static function esc_string($content) {
350 + public static function esc_string($content)
351 + {
250 352
251 353 $allowed_tags = [
252 354 'strong' => array(),
253 355 'em' => array(),
@@ -257,11 +359,161 @@
257 359 's' => array(),
258 360 'sub' => array(),
259 361 'sup' => array(),
260 362 'span' => array(),
261 - 'br' => array()
363 + 'br' => array(),
364 + 'a' => [
365 + 'href' => true,
366 + 'title' => true,
367 + 'target' => true,
368 + 'rel' => true
369 + ]
262 370 ];
263 371
264 - return wp_kses( $content, $allowed_tags );
372 + return wp_kses($content, $allowed_tags);
265 373 }
266 374
375 + /**
376 + * Retrieves the available image sizes.
377 + *
378 + * @return array An array of image sizes.
379 + *
380 + * @since 1.0.0
381 + */
382 + public static function get_images_sizes()
383 + {
384 + $sizes = [];
385 + foreach (get_intermediate_image_sizes() as $size) {
386 + $sizes[$size] = $size;
387 + }
388 + return $sizes;
389 + }
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 + }
267 519 }