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 +257 -100 1.0.71.3.17 View file →
@@ -1,5 +1,6 @@
1 1 <?php
2 +
2 3 namespace UiCoreElements;
3 4
4 5 use Elementor\Plugin;
5 6
@@ -14,24 +15,41 @@
14 15 {
15 16 return '<span class="uicore-meta-separator"></span>';
16 17 }
17 18
18 - public static function get_taxonomies($custom = true)
19 + public static function get_taxonomies($custom = true, $only_products = false)
19 20 {
20 - $taxonomies = get_taxonomies(['public' => true], 'objects');
21 - $exclusions = ['nav_menu', 'link_category', 'post_format']; // Exclude these taxonomies from the list
22 21
23 - $taxonomies = array_filter($taxonomies, function ($taxonomy) use ($exclusions) {
24 - return !in_array($taxonomy->name, $exclusions);
25 - });
22 + // Woo only taxonomies
23 + if ($only_products) {
24 + $taxonomies = [
25 + 'product_cat' => 'Product Categories',
26 + 'product_tag' => 'Product Tags'
27 + ];
26 28
27 - $taxonomies = array_map(function ($taxonomy) {
28 - if('portfolio_category' === $taxonomy->name){
29 - return 'Portfolio Category';
29 + $attributes = wc_get_attribute_taxonomies();
30 + foreach ($attributes as $att) {
31 + $taxonomies['pa_' . $att->attribute_name] = $att->attribute_label;
30 32 }
31 - return $taxonomy->label;
32 - }, $taxonomies);
33 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 +
34 52 if ($custom) {
35 53 $taxonomies = array_merge(['custom' => __('Custom Meta', 'uicore-elements')], $taxonomies);
36 54 }
37 55
@@ -40,15 +58,15 @@
40 58
41 59 static function get_taxonomy($name)
42 60 {
43 61 global $post;
62 + $categories = get_the_terms($post->ID, $name);
44 63
45 - $categories = get_the_terms( $post->ID, $name );
46 - if ( ! $categories || is_wp_error( $categories ) ) {
64 + if (! $categories || is_wp_error($categories)) {
47 65 return false;
48 66 }
49 67
50 - $categories = array_values( $categories );
68 + $categories = array_values($categories);
51 69 foreach ($categories as $t) {
52 70 $term_name[] =
53 71 '<a href="' . get_term_link($t) . '" title="View ' . \esc_attr($t->name) . ' posts">' . esc_html($t->name) . '</a>';
54 72 }
@@ -56,122 +74,151 @@
56 74
57 75 return $category;
58 76 }
59 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 +
60 96 static function get_reading_time()
61 97 {
62 98 global $post;
63 - // get the content
99 +
64 100 $the_content = $post->post_content;
65 - // count the number of words
66 - $words = str_word_count( wp_strip_all_tags( $the_content ) );
67 - // rounding off and deviding per 200 words per minute
68 - $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
69 103
70 - // calculate the amount of time needed to read
71 104 return $minute;
72 105 }
73 106
74 - static function get_site_domain() {
75 - return str_ireplace( 'www.', '', parse_url( home_url(), PHP_URL_HOST ) );
76 - }
107 + static function get_site_domain()
108 + {
109 + return str_ireplace('www.', '', parse_url(home_url(), PHP_URL_HOST));
110 + }
77 111
78 112 /**
79 113 * Returns the Uicore Elements settings page URL. You may pass a message so it'll be wrapped under a <a> tag.
80 114 *
81 115 * @param string $message Optional. A clickable message to be displayed that'll redirect, in a new tab, to settings page.
116 + *
82 117 * @return string Uicore Elements settings page URL or an <a> tag HTML with the url and the passed message.
83 118 */
84 - static function get_admin_settings_url(string $message = '') {
85 - $url = admin_url( 'options-general.php?page=uicore-elements' );
86 - return !empty($message) ? '<a href="'.esc_url($url).'" target="_blank">' . esc_html($message) . '</a>' : $url;
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;
87 125 }
88 126
89 - static function register_widget_style($name,$deps=[],$external=false)
127 + static function register_widget_style($name, $deps = [], $external = false)
90 128 {
91 - $handle = (!$external ? 'ui-e-' : '' ). $name;
92 - wp_register_style($handle, UICORE_ELEMENTS_ASSETS . '/css/elements/'.$name.'.css',$deps,UICORE_ELEMENTS_VERSION);
129 + $handle = (!$external ? 'ui-e-' : '') . $name;
130 + wp_register_style($handle, UICORE_ELEMENTS_ASSETS . '/css/elements/' . $name . '.css', $deps, UICORE_ELEMENTS_VERSION);
93 131 return $handle;
94 132 }
95 - static function register_widget_script($name,$deps=[],$external=false)
133 + static function register_widget_script($name, $deps = [], $external = false)
96 134 {
97 - $handle = (!$external ? 'ui-e-' : '' ). $name;
135 + $handle = (!$external ? 'ui-e-' : '') . $name;
98 136 //if name contains / then we need to set a custom path
99 - if(strpos($name,'/') !== false){
100 - $path ='';
101 - }else{
137 + if (strpos($name, '/') !== false) {
138 + $path = '';
139 + } else {
102 140 $path = 'elements/';
103 141 }
104 - wp_register_script($handle, UICORE_ELEMENTS_ASSETS . '/js/'.$path.$name.'.js',$deps,UICORE_ELEMENTS_VERSION,true);
142 + wp_register_script($handle, UICORE_ELEMENTS_ASSETS . '/js/' . $path . $name . '.js', $deps, UICORE_ELEMENTS_VERSION, true);
105 143 return $handle;
106 144 }
107 145
108 -
109 - 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)
110 156 {
111 - global $post;
157 + $args = [
158 + 'post__not_in' => [$pageID],
159 + 'posts_per_page' => $per_page,
160 + 'paged' => $page_number,
161 + ];
112 162
113 - $args = [];
163 + $categories = get_the_category($pageID);
164 + $tags = wp_get_post_tags($pageID);
114 165
115 - if ($filter == 'category') {
116 - $categories = get_the_category($post->ID);
166 + $tax_query = [];
117 167
118 - if ($categories) {
119 - $category_ids = [];
120 - foreach ($categories as $individual_category) {
121 - $category_ids[] = $individual_category->term_id;
122 - }
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 + }
123 177
124 - $args = [
125 - 'category__in' => $category_ids,
126 - 'post__not_in' => [$post->ID],
127 - 'posts_per_page' => $number,
128 - 'ignore_sticky_posts' => 1,
129 - ];
130 - }
131 - } elseif ($filter == 'tag') {
132 - $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 + }
133 187
134 - if ($tags) {
135 - $tag_ids = [];
136 - foreach ($tags as $individual_tag) {
137 - $tag_ids[] = $individual_tag->term_id;
138 - }
139 - $args = [
140 - 'tag__in' => $tag_ids,
141 - 'post__not_in' => [$post->ID],
142 - 'posts_per_page' => $number,
143 - 'ignore_sticky_posts' => 1,
144 - ];
145 - }
146 - } else {
147 - $args = [
148 - 'post__not_in' => [$post->ID],
149 - 'posts_per_page' => $number,
150 - 'orderby' => 'rand',
188 + if (!empty($tax_query)) {
189 + $args['tax_query'] = [
190 + 'relation' => 'OR',
191 + ...$tax_query,
151 192 ];
152 193 }
153 194
154 - $related_query = new \wp_query($args);
195 + return new \WP_Query($args);
196 + }
155 197
156 - if ($related_query->have_posts()) {
157 - return $related_query;
158 - } else {
159 - 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;
160 206 }
207 +
208 + return wc_get_related_products($ID, $limit);
161 209 }
162 210
163 -
164 211 /*
165 212 * Get the current post id (used in Theme Builder - UiCore Framework)
166 213 */
167 214 static function get_current_meta_id()
168 215 {
169 - 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')) {
170 217 $post_id = get_option('page_for_posts', true);
171 - }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')) {
172 219 $post_id = \UiCore\Portfolio\Frontend::get_portfolio_page_id();
173 - }else{
220 + } else {
174 221 $post_id = get_queried_object_id();
175 222 }
176 223
177 224 return $post_id;
@@ -179,11 +226,11 @@
179 226
180 227 /**
181 228 * Return a list of textual html tags for Elementor Controls Options
182 229 */
230 + public static function get_title_tags()
231 + {
183 232
184 - public static function get_title_tags($type = null) {
185 -
186 233 $tags = [
187 234 'h1' => 'H1',
188 235 'h2' => 'H2',
189 236 'h3' => 'H3',
@@ -207,13 +254,14 @@
207 254 * @param string $custom The custom format to use if $format is set to 'custom'.
208 255 *
209 256 * @return string The formatted date value.
210 257 */
211 - public static function format_date($date, $format, $custom) {
258 + public static function format_date($date, $format, $custom)
259 + {
212 260
213 - if ( 'custom' === $format ) {
261 + if ('custom' === $format) {
214 262 $date_format = $custom;
215 - } else if ('default' === $format ) {
263 + } else if ('default' === $format) {
216 264 $date_format = get_option('date_format');
217 265 } else {
218 266 $date_format = $format;
219 267 }
@@ -223,17 +271,48 @@
223 271 return wp_kses_post($value);
224 272 }
225 273
226 274 /**
227 - * 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.
228 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 + *
229 307 * @param string $svg The raw SVG content to be sanitized.
230 308 * @return string The sanitized SVG content, with only allowed tags and attributes.
231 309 *
232 310 * @since 1.0.2
233 311 */
234 - public static function esc_svg($svg) {
235 - $default = wp_kses_allowed_html( 'post' );
312 + public static function esc_svg($svg)
313 + {
314 + $default = wp_kses_allowed_html('post');
236 315
237 316 $args = array(
238 317 'svg' => array(
239 318 'class' => true,
@@ -246,22 +325,23 @@
246 325 // has to be lowercase
247 326 'viewbox' => true,
248 327 'preserveaspectratio' => true
249 328 ),
250 - 'g' => array( 'fill' => true ),
251 - 'title' => array( 'title' => true ),
329 + 'g' => array('fill' => true),
330 + 'title' => array('title' => true),
252 331 'path' => array(
253 332 'd' => true,
254 333 'fill' => true
255 334 )
256 335 );
257 - $allowed_tags = array_merge( $default, $args );
336 + $allowed_tags = array_merge($default, $args);
258 337
259 - return wp_kses( $svg, $allowed_tags );
338 + return wp_kses($svg, $allowed_tags);
260 339 }
261 340
262 341 /**
263 - * 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.
264 344 *
265 345 * @param string $content The content to be sanitized
266 346 * @return string The sanitized string content.
267 347 *
@@ -266,9 +346,10 @@
266 346 * @return string The sanitized string content.
267 347 *
268 348 * @since 1.0.3
269 349 */
270 - public static function esc_string($content) {
350 + public static function esc_string($content)
351 + {
271 352
272 353 $allowed_tags = [
273 354 'strong' => array(),
274 355 'em' => array(),
@@ -278,12 +359,18 @@
278 359 's' => array(),
279 360 'sub' => array(),
280 361 'sup' => array(),
281 362 'span' => array(),
282 - 'br' => array()
363 + 'br' => array(),
364 + 'a' => [
365 + 'href' => true,
366 + 'title' => true,
367 + 'target' => true,
368 + 'rel' => true
369 + ]
283 370 ];
284 371
285 - return wp_kses( $content, $allowed_tags );
372 + return wp_kses($content, $allowed_tags);
286 373 }
287 374
288 375 /**
289 376 * Retrieves the available image sizes.
@@ -291,9 +378,10 @@
291 378 * @return array An array of image sizes.
292 379 *
293 380 * @since 1.0.0
294 381 */
295 - public static function get_images_sizes() {
382 + public static function get_images_sizes()
383 + {
296 384 $sizes = [];
297 385 foreach (get_intermediate_image_sizes() as $size) {
298 386 $sizes[$size] = $size;
299 387 }
@@ -302,9 +390,10 @@
302 390
303 391 /**
304 392 * @since 1.0.5
305 393 */
306 - private static function get_element_recursive($elements, $form_id) {
394 + private static function get_element_recursive($elements, $form_id)
395 + {
307 396
308 397 foreach ($elements as $element) {
309 398 if ($form_id === $element['id']) {
310 399 return $element;
@@ -329,10 +418,12 @@
329 418 * @param int $widget_id The ID of the widget.
330 419 * @return array|string The settings of the widget, or an error message if the request is invalid.
331 420 *
332 421 * @since 1.0.5
422 + * @deprecated Deprecated since version 1.0.11 Use the transient method instead.
333 423 */
334 - public static function get_widget_settings($post_id, $widget_id) {
424 + public static function get_widget_settings($post_id, $widget_id)
425 + {
335 426
336 427 if (!$post_id || !$widget_id) {
337 428 return false;
338 429 }
@@ -358,5 +449,71 @@
358 449
359 450 return $settings;
360 451 }
361 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 + }
362 519 }