PluginProbe
BlockSpare – Gutenberg Blocks for News, Magazine, Blog & Business Websites / 1.3.2
BlockSpare – Gutenberg Blocks for News, Magazine, Blog & Business Websites v1.3.2
4.1.0 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.1.0 1.1.1 1.1.2 1.2.0 1.2.1 1.2.2 1.2.3 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 2.1.2 2.5.0 2.5.3 2.6.1 All 38 releases
blockspare / freemius / includes / fs-core-functions.php

fs-core-functions.php in BlockSpare – Gutenberg Blocks for News, Magazine, Blog & Business Websites 1.3.2, at freemius/includes/fs-core-functions.php

1,416 lines 49.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package Freemius
4 * @copyright Copyright (c) 2015, Freemius, Inc.
5 * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
6 * @since 1.0.3
7 */
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 if ( ! function_exists( 'fs_dummy' ) ) {
14 function fs_dummy() {
15 }
16 }
17
18 /* Url.
19 --------------------------------------------------------------------------------------------*/
20 if ( ! function_exists( 'fs_get_url_daily_cache_killer' ) ) {
21 function fs_get_url_daily_cache_killer() {
22 return date( '\YY\Mm\Dd' );
23 }
24 }
25
26 /* Templates / Views.
27 --------------------------------------------------------------------------------------------*/
28 if ( ! function_exists( 'fs_get_template_path' ) ) {
29 function fs_get_template_path( $path ) {
30 return WP_FS__DIR_TEMPLATES . '/' . trim( $path, '/' );
31 }
32
33 function fs_include_template( $path, &$params = null ) {
34 $VARS = &$params;
35 include fs_get_template_path( $path );
36 }
37
38 function fs_include_once_template( $path, &$params = null ) {
39 $VARS = &$params;
40 include_once fs_get_template_path( $path );
41 }
42
43 function fs_require_template( $path, &$params = null ) {
44 $VARS = &$params;
45 require fs_get_template_path( $path );
46 }
47
48 function fs_require_once_template( $path, &$params = null ) {
49 $VARS = &$params;
50 require_once fs_get_template_path( $path );
51 }
52
53 function fs_get_template( $path, &$params = null ) {
54 ob_start();
55
56 $VARS = &$params;
57 require fs_get_template_path( $path );
58
59 return ob_get_clean();
60 }
61 }
62
63 /* Scripts and styles including.
64 --------------------------------------------------------------------------------------------*/
65
66 if ( ! function_exists( 'fs_asset_url' ) ) {
67 /**
68 * Generates an absolute URL to the given path. This function ensures that the URL will be correct whether the asset
69 * is inside a plugin's folder or a theme's folder.
70 *
71 * Examples:
72 * 1. "themes" folder
73 * Path: C:/xampp/htdocs/fswp/wp-content/themes/twentytwelve/freemius/assets/css/admin/common.css
74 * URL: http://fswp:8080/wp-content/themes/twentytwelve/freemius/assets/css/admin/common.css
75 *
76 * 2. "plugins" folder
77 * Path: C:/xampp/htdocs/fswp/wp-content/plugins/rating-widget-premium/freemius/assets/css/admin/common.css
78 * URL: http://fswp:8080/wp-content/plugins/rating-widget-premium/freemius/assets/css/admin/common.css
79 *
80 * @author Leo Fajardo (@leorw)
81 * @since 1.2.2
82 *
83 * @param string $asset_abs_path Asset's absolute path.
84 *
85 * @return string Asset's URL.
86 */
87 function fs_asset_url( $asset_abs_path ) {
88 $wp_content_dir = fs_normalize_path( WP_CONTENT_DIR );
89 $asset_abs_path = fs_normalize_path( $asset_abs_path );
90
91 if ( 0 === strpos( $asset_abs_path, $wp_content_dir ) ) {
92 // Handle both theme and plugin assets located in the standard directories.
93 $asset_rel_path = str_replace( $wp_content_dir, '', $asset_abs_path );
94 $asset_url = content_url( fs_normalize_path( $asset_rel_path ) );
95 } else {
96 $wp_plugins_dir = fs_normalize_path( WP_PLUGIN_DIR );
97 if ( 0 === strpos( $asset_abs_path, $wp_plugins_dir ) ) {
98 // Try to handle plugin assets that may be located in a non-standard plugins directory.
99 $asset_rel_path = str_replace( $wp_plugins_dir, '', $asset_abs_path );
100 $asset_url = plugins_url( fs_normalize_path( $asset_rel_path ) );
101 } else {
102 // Try to handle theme assets that may be located in a non-standard themes directory.
103 $active_theme_stylesheet = get_stylesheet();
104 $wp_themes_dir = fs_normalize_path( trailingslashit( get_theme_root( $active_theme_stylesheet ) ) );
105 $asset_rel_path = str_replace( $wp_themes_dir, '', fs_normalize_path( $asset_abs_path ) );
106 $asset_url = trailingslashit( get_theme_root_uri( $active_theme_stylesheet ) ) . fs_normalize_path( $asset_rel_path );
107 }
108 }
109
110 return $asset_url;
111 }
112 }
113
114 if ( ! function_exists( 'fs_enqueue_local_style' ) ) {
115 function fs_enqueue_local_style( $handle, $path, $deps = array(), $ver = false, $media = 'all' ) {
116 wp_enqueue_style( $handle, fs_asset_url( WP_FS__DIR_CSS . '/' . trim( $path, '/' ) ), $deps, $ver, $media );
117 }
118 }
119
120 if ( ! function_exists( 'fs_enqueue_local_script' ) ) {
121 function fs_enqueue_local_script( $handle, $path, $deps = array(), $ver = false, $in_footer = 'all' ) {
122 wp_enqueue_script( $handle, fs_asset_url( WP_FS__DIR_JS . '/' . trim( $path, '/' ) ), $deps, $ver, $in_footer );
123 }
124 }
125
126 if ( ! function_exists( 'fs_img_url' ) ) {
127 function fs_img_url( $path, $img_dir = WP_FS__DIR_IMG ) {
128 return ( fs_asset_url( $img_dir . '/' . trim( $path, '/' ) ) );
129 }
130 }
131
132 #--------------------------------------------------------------------------------
133 #region Request handlers.
134 #--------------------------------------------------------------------------------
135
136 if ( ! function_exists( 'fs_request_get' ) ) {
137 /**
138 * A helper method to fetch GET/POST user input with an optional default value when the input is not set.
139 * @author Vova Feldman (@svovaf)
140 *
141 * @param string $key
142 * @param mixed $def
143 * @param string|bool $type Since 1.2.1.7 - when set to 'get' will look for the value passed via querystring, when
144 * set to 'post' will look for the value passed via the POST request's body, otherwise,
145 * will check if the parameter was passed in any of the two.
146 *
147 * @return mixed
148 */
149 function fs_request_get( $key, $def = false, $type = false ) {
150 if ( is_string( $type ) ) {
151 $type = strtolower( $type );
152 }
153
154 /**
155 * Note to WordPress.org Reviewers:
156 * This is a helper method to fetch GET/POST user input with an optional default value when the input is not set. The actual sanitization is done in the scope of the function's usage.
157 */
158 switch ( $type ) {
159 case 'post':
160 $value = isset( $_POST[ $key ] ) ? $_POST[ $key ] : $def;
161 break;
162 case 'get':
163 $value = isset( $_GET[ $key ] ) ? $_GET[ $key ] : $def;
164 break;
165 default:
166 $value = isset( $_REQUEST[ $key ] ) ? $_REQUEST[ $key ] : $def;
167 break;
168 }
169
170 return $value;
171 }
172 }
173
174 if ( ! function_exists( 'fs_request_has' ) ) {
175 function fs_request_has( $key ) {
176 return isset( $_REQUEST[ $key ] );
177 }
178 }
179
180 if ( ! function_exists( 'fs_request_get_bool' ) ) {
181 /**
182 * A helper method to fetch GET/POST user boolean input with an optional default value when the input is not set.
183 *
184 * @author Vova Feldman (@svovaf)
185 *
186 * @param string $key
187 * @param bool $def
188 *
189 * @return bool|mixed
190 */
191 function fs_request_get_bool( $key, $def = false ) {
192 $val = fs_request_get( $key, null );
193
194 if ( is_null( $val ) ) {
195 return $def;
196 }
197
198 if ( is_bool( $val ) ) {
199 return $val;
200 } else if ( is_numeric( $val ) ) {
201 if ( 1 == $val ) {
202 return true;
203 } else if ( 0 == $val ) {
204 return false;
205 }
206 } else if ( is_string( $val ) ) {
207 $val = strtolower( $val );
208
209 if ( 'true' === $val ) {
210 return true;
211 } else if ( 'false' === $val ) {
212 return false;
213 }
214 }
215
216 return $def;
217 }
218 }
219
220 if ( ! function_exists( 'fs_request_is_post' ) ) {
221 function fs_request_is_post() {
222 return ( 'post' === strtolower( $_SERVER['REQUEST_METHOD'] ) );
223 }
224 }
225
226 if ( ! function_exists( 'fs_request_is_get' ) ) {
227 function fs_request_is_get() {
228 return ( 'get' === strtolower( $_SERVER['REQUEST_METHOD'] ) );
229 }
230 }
231
232 if ( ! function_exists( 'fs_get_action' ) ) {
233 function fs_get_action( $action_key = 'action' ) {
234 if ( ! empty( $_REQUEST[ $action_key ] ) && is_string( $_REQUEST[ $action_key ] ) ) {
235 return strtolower( $_REQUEST[ $action_key ] );
236 }
237
238 if ( 'action' == $action_key ) {
239 $action_key = 'fs_action';
240
241 if ( ! empty( $_REQUEST[ $action_key ] ) && is_string( $_REQUEST[ $action_key ] ) ) {
242 return strtolower( $_REQUEST[ $action_key ] );
243 }
244 }
245
246 return false;
247 }
248 }
249
250 if ( ! function_exists( 'fs_request_is_action' ) ) {
251 function fs_request_is_action( $action, $action_key = 'action' ) {
252 return ( strtolower( $action ) === fs_get_action( $action_key ) );
253 }
254 }
255
256 if ( ! function_exists( 'fs_request_is_action_secure' ) ) {
257 /**
258 * @author Vova Feldman (@svovaf)
259 * @since 1.0.0
260 *
261 * @since 1.2.1.5 Allow nonce verification.
262 *
263 * @param string $action
264 * @param string $action_key
265 * @param string $nonce_key
266 *
267 * @return bool
268 */
269 function fs_request_is_action_secure(
270 $action,
271 $action_key = 'action',
272 $nonce_key = 'nonce'
273 ) {
274 if ( strtolower( $action ) !== fs_get_action( $action_key ) ) {
275 return false;
276 }
277
278 $nonce = ! empty( $_REQUEST[ $nonce_key ] ) ?
279 $_REQUEST[ $nonce_key ] :
280 '';
281
282 if ( empty( $nonce ) ||
283 ( false === wp_verify_nonce( $nonce, $action ) )
284 ) {
285 return false;
286 }
287
288 return true;
289 }
290 }
291
292 #endregion
293
294 if ( ! function_exists( 'fs_is_plugin_page' ) ) {
295 function fs_is_plugin_page( $page_slug ) {
296 return ( is_admin() && $page_slug === fs_request_get( 'page' ) );
297 }
298 }
299
300 if ( ! function_exists( 'fs_get_raw_referer' ) ) {
301 /**
302 * Retrieves unvalidated referer from '_wp_http_referer' or HTTP referer.
303 *
304 * Do not use for redirects, use {@see wp_get_referer()} instead.
305 *
306 * @since 1.2.3
307 *
308 * @return string|false Referer URL on success, false on failure.
309 */
310 function fs_get_raw_referer() {
311 if ( function_exists( 'wp_get_raw_referer' ) ) {
312 return wp_get_raw_referer();
313 }
314 if ( ! empty( $_REQUEST['_wp_http_referer'] ) ) {
315 return wp_unslash( $_REQUEST['_wp_http_referer'] );
316 } else if ( ! empty( $_SERVER['HTTP_REFERER'] ) ) {
317 return wp_unslash( $_SERVER['HTTP_REFERER'] );
318 }
319
320 return false;
321 }
322 }
323
324 /* Core UI.
325 --------------------------------------------------------------------------------------------*/
326 if ( ! function_exists( 'fs_ui_action_button' ) ) {
327 /**
328 * @param number $module_id
329 * @param string $page
330 * @param string $action
331 * @param string $title
332 * @param string $button_class
333 * @param array $params
334 * @param bool $is_primary
335 * @param bool $is_small
336 * @param string|bool $icon_class Optional class for an icon (since 1.1.7).
337 * @param string|bool $confirmation Optional confirmation message before submit (since 1.1.7).
338 * @param string $method Since 1.1.7
339 *
340 * @uses fs_ui_get_action_button()
341 */
342 function fs_ui_action_button(
343 $module_id,
344 $page,
345 $action,
346 $title,
347 $button_class = '',
348 $params = array(),
349 $is_primary = true,
350 $is_small = false,
351 $icon_class = false,
352 $confirmation = false,
353 $method = 'GET'
354 ) {
355 echo fs_ui_get_action_button(
356 $module_id,
357 $page,
358 $action,
359 $title,
360 $button_class,
361 $params,
362 $is_primary,
363 $is_small,
364 $icon_class,
365 $confirmation,
366 $method
367 );
368 }
369 }
370
371 if ( ! function_exists( 'fs_ui_get_action_button' ) ) {
372 /**
373 * @author Vova Feldman (@svovaf)
374 * @since 1.1.7
375 *
376 * @param number $module_id
377 * @param string $page
378 * @param string $action
379 * @param string $title
380 * @param string $button_class
381 * @param array $params
382 * @param bool $is_primary
383 * @param bool $is_small
384 * @param string|bool $icon_class Optional class for an icon.
385 * @param string|bool $confirmation Optional confirmation message before submit.
386 * @param string $method
387 *
388 * @return string
389 */
390 function fs_ui_get_action_button(
391 $module_id,
392 $page,
393 $action,
394 $title,
395 $button_class = '',
396 $params = array(),
397 $is_primary = true,
398 $is_small = false,
399 $icon_class = false,
400 $confirmation = false,
401 $method = 'GET'
402 ) {
403 // Prepend icon (if set).
404 $title = ( is_string( $icon_class ) ? '<i class="' . $icon_class . '"></i> ' : '' ) . $title;
405
406 if ( is_string( $confirmation ) ) {
407 return sprintf( '<form action="%s" method="%s"><input type="hidden" name="fs_action" value="%s">%s<a href="#" class="%s" onclick="if (confirm(\'%s\')) this.parentNode.submit(); return false;">%s</a></form>',
408 freemius( $module_id )->_get_admin_page_url( $page, $params ),
409 $method,
410 $action,
411 wp_nonce_field( $action, '_wpnonce', true, false ),
412 'button' . ( ! empty( $button_class ) ? ' ' . $button_class : '' ) . ( $is_primary ? ' button-primary' : '' ) . ( $is_small ? ' button-small' : '' ),
413 $confirmation,
414 $title
415 );
416 } else if ( 'GET' !== strtoupper( $method ) ) {
417 return sprintf( '<form action="%s" method="%s"><input type="hidden" name="fs_action" value="%s">%s<a href="#" class="%s" onclick="this.parentNode.submit(); return false;">%s</a></form>',
418 freemius( $module_id )->_get_admin_page_url( $page, $params ),
419 $method,
420 $action,
421 wp_nonce_field( $action, '_wpnonce', true, false ),
422 'button' . ( ! empty( $button_class ) ? ' ' . $button_class : '' ) . ( $is_primary ? ' button-primary' : '' ) . ( $is_small ? ' button-small' : '' ),
423 $title
424 );
425 } else {
426 return sprintf( '<a href="%s" class="%s">%s</a></form>',
427 wp_nonce_url( freemius( $module_id )->_get_admin_page_url( $page, array_merge( $params, array( 'fs_action' => $action ) ) ), $action ),
428 'button' . ( ! empty( $button_class ) ? ' ' . $button_class : '' ) . ( $is_primary ? ' button-primary' : '' ) . ( $is_small ? ' button-small' : '' ),
429 $title
430 );
431 }
432 }
433
434 function fs_ui_action_link( $module_id, $page, $action, $title, $params = array() ) {
435 ?><a class=""
436 href="<?php echo wp_nonce_url( freemius( $module_id )->_get_admin_page_url( $page, array_merge( $params, array( 'fs_action' => $action ) ) ), $action ) ?>"><?php echo $title ?></a><?php
437 }
438 }
439
440 if ( ! function_exists( 'fs_get_entity' ) ) {
441 /**
442 * @author Leo Fajardo (@leorw)
443 * @since 2.3.1
444 *
445 * @param mixed $entity
446 * @param string $class
447 *
448 * @return FS_Plugin|FS_User|FS_Site|FS_Plugin_License|FS_Plugin_Plan|FS_Plugin_Tag|FS_Subscription
449 */
450 function fs_get_entity( $entity, $class ) {
451 if ( ! is_object( $entity ) || $entity instanceof $class ) {
452 return $entity;
453 }
454
455 return new $class( $entity );
456 }
457 }
458
459 if ( ! function_exists( 'fs_get_entities' ) ) {
460 /**
461 * @author Leo Fajardo (@leorw)
462 * @since 2.3.1
463 *
464 * @param mixed $entities
465 * @param string $class_name
466 *
467 * @return FS_Plugin[]|FS_User[]|FS_Site[]|FS_Plugin_License[]|FS_Plugin_Plan[]|FS_Plugin_Tag[]|FS_Subscription[]
468 */
469 function fs_get_entities( $entities, $class_name ) {
470 if ( ! is_array( $entities ) || empty( $entities ) ) {
471 return $entities;
472 }
473
474 // Get first element.
475 $first_array_element = reset( $entities );
476
477 if ( $first_array_element instanceof $class_name ) {
478 /**
479 * If the first element of the array is an instance of the context class, assume that all other
480 * elements are instances of the class.
481 */
482 return $entities;
483 }
484
485 if (
486 is_array( $first_array_element ) &&
487 ! empty( $first_array_element )
488 ) {
489 $first_array_element = reset( $first_array_element );
490
491 if ( $first_array_element instanceof $class_name ) {
492 /**
493 * If the first element of the `$entities` array is an array whose first element is an instance of the
494 * context class, assume that all other objects are instances of the class.
495 */
496 return $entities;
497 }
498 }
499
500 foreach ( $entities as $key => $entities_or_entity ) {
501 if ( is_array( $entities_or_entity ) ) {
502 $entities[ $key ] = fs_get_entities( $entities_or_entity, $class_name );
503 } else {
504 $entities[ $key ] = fs_get_entity( $entities_or_entity, $class_name );
505 }
506 }
507
508 return $entities;
509 }
510 }
511
512 if ( ! function_exists( 'fs_nonce_url' ) ) {
513 /**
514 * Retrieve URL with nonce added to URL query.
515 *
516 * Originally was using `wp_nonce_url()` but the new version
517 * changed the return value to escaped URL, that's not the expected
518 * behaviour.
519 *
520 * @author Vova Feldman (@svovaf)
521 * @since ~1.1.3
522 *
523 * @param string $actionurl URL to add nonce action.
524 * @param int|string $action Optional. Nonce action name. Default -1.
525 * @param string $name Optional. Nonce name. Default '_wpnonce'.
526 *
527 * @return string Escaped URL with nonce action added.
528 */
529 function fs_nonce_url( $actionurl, $action = - 1, $name = '_wpnonce' ) {
530 return add_query_arg( $name, wp_create_nonce( $action ), $actionurl );
531 }
532 }
533
534 if ( ! function_exists( 'fs_starts_with' ) ) {
535 /**
536 * Check if string starts with.
537 *
538 * @author Vova Feldman (@svovaf)
539 * @since 1.1.3
540 *
541 * @param string $haystack
542 * @param string $needle
543 *
544 * @return bool
545 */
546 function fs_starts_with( $haystack, $needle ) {
547 $length = strlen( $needle );
548
549 return ( substr( $haystack, 0, $length ) === $needle );
550 }
551 }
552
553 if ( ! function_exists( 'fs_ends_with' ) ) {
554 /**
555 * Check if string ends with.
556 *
557 * @author Vova Feldman (@svovaf)
558 * @since 2.0.0
559 *
560 * @param string $haystack
561 * @param string $needle
562 *
563 * @return bool
564 */
565 function fs_ends_with( $haystack, $needle ) {
566 $length = strlen( $needle );
567 $start = $length * - 1; // negative
568
569 return ( substr( $haystack, $start ) === $needle );
570 }
571 }
572
573 if ( ! function_exists( 'fs_strip_url_protocol' ) ) {
574 function fs_strip_url_protocol( $url ) {
575 if ( ! fs_starts_with( $url, 'http' ) ) {
576 return $url;
577 }
578
579 $protocol_pos = strpos( $url, '://' );
580
581 if ( $protocol_pos > 5 ) {
582 return $url;
583 }
584
585 return substr( $url, $protocol_pos + 3 );
586 }
587 }
588
589 #region Url Canonization ------------------------------------------------------------------
590
591 if ( ! function_exists( 'fs_canonize_url' ) ) {
592 /**
593 * @author Vova Feldman (@svovaf)
594 * @since 1.1.3
595 *
596 * @param string $url
597 * @param bool $omit_host
598 * @param array $ignore_params
599 *
600 * @return string
601 */
602 function fs_canonize_url( $url, $omit_host = false, $ignore_params = array() ) {
603 $parsed_url = parse_url( strtolower( $url ) );
604
605 // if ( ! isset( $parsed_url['host'] ) ) {
606 // return $url;
607 // }
608
609 $canonical = ( ( $omit_host || ! isset( $parsed_url['host'] ) ) ? '' : $parsed_url['host'] ) . $parsed_url['path'];
610
611 if ( isset( $parsed_url['query'] ) ) {
612 parse_str( $parsed_url['query'], $queryString );
613 $canonical .= '?' . fs_canonize_query_string( $queryString, $ignore_params );
614 }
615
616 return $canonical;
617 }
618 }
619
620 if ( ! function_exists( 'fs_canonize_query_string' ) ) {
621 /**
622 * @author Vova Feldman (@svovaf)
623 * @since 1.1.3
624 *
625 * @param array $params
626 * @param array $ignore_params
627 * @param bool $params_prefix
628 *
629 * @return string
630 */
631 function fs_canonize_query_string( array $params, array &$ignore_params, $params_prefix = false ) {
632 if ( ! is_array( $params ) || 0 === count( $params ) ) {
633 return '';
634 }
635
636 // Url encode both keys and values
637 $keys = fs_urlencode_rfc3986( array_keys( $params ) );
638 $values = fs_urlencode_rfc3986( array_values( $params ) );
639 $params = array_combine( $keys, $values );
640
641 // Parameters are sorted by name, using lexicographical byte value ordering.
642 // Ref: Spec: 9.1.1 (1)
643 uksort( $params, 'strcmp' );
644
645 $pairs = array();
646 foreach ( $params as $parameter => $value ) {
647 $lower_param = strtolower( $parameter );
648
649 // Skip ignore params.
650 if ( in_array( $lower_param, $ignore_params ) ||
651 ( false !== $params_prefix && fs_starts_with( $lower_param, $params_prefix ) )
652 ) {
653 continue;
654 }
655
656 if ( is_array( $value ) ) {
657 // If two or more parameters share the same name, they are sorted by their value
658 // Ref: Spec: 9.1.1 (1)
659 natsort( $value );
660 foreach ( $value as $duplicate_value ) {
661 $pairs[] = $lower_param . '=' . $duplicate_value;
662 }
663 } else {
664 $pairs[] = $lower_param . '=' . $value;
665 }
666 }
667
668 if ( 0 === count( $pairs ) ) {
669 return '';
670 }
671
672 return implode( "&", $pairs );
673 }
674 }
675
676 if ( ! function_exists( 'fs_urlencode_rfc3986' ) ) {
677 /**
678 * @author Vova Feldman (@svovaf)
679 * @since 1.1.3
680 *
681 * @param string|string[] $input
682 *
683 * @return array|mixed|string
684 */
685 function fs_urlencode_rfc3986( $input ) {
686 if ( is_array( $input ) ) {
687 return array_map( 'fs_urlencode_rfc3986', $input );
688 } else if ( is_scalar( $input ) ) {
689 return str_replace( '+', ' ', str_replace( '%7E', '~', rawurlencode( $input ) ) );
690 }
691
692 return '';
693 }
694 }
695
696 #endregion Url Canonization ------------------------------------------------------------------
697
698 if ( ! function_exists( 'fs_download_image' ) ) {
699 /**
700 * @author Vova Feldman (@svovaf)
701 *
702 * @since 1.2.2 Changed to usage of WP_Filesystem_Direct.
703 *
704 * @param string $from URL
705 * @param string $to File path.
706 *
707 * @return bool Is successfully downloaded.
708 */
709 function fs_download_image( $from, $to ) {
710 $dir = dirname( $to );
711
712 if ( 'direct' !== get_filesystem_method( array(), $dir ) ) {
713 return false;
714 }
715
716 if ( ! class_exists( 'WP_Filesystem_Direct' ) ) {
717 require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php';
718 require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php';
719 }
720
721 $fs = new WP_Filesystem_Direct( '' );
722 $tmpfile = download_url( $from );
723
724 if ( $tmpfile instanceof WP_Error ) {
725 // Issue downloading the file.
726 return false;
727 }
728
729 $fs->copy( $tmpfile, $to );
730 $fs->delete( $tmpfile );
731
732 return true;
733 }
734 }
735
736 /* General Utilities
737 --------------------------------------------------------------------------------------------*/
738
739 if ( ! function_exists( 'fs_sort_by_priority' ) ) {
740 /**
741 * Sorts an array by the value of the priority key.
742 *
743 * @author Daniel Iser (@danieliser)
744 * @since 1.1.7
745 *
746 * @param $a
747 * @param $b
748 *
749 * @return int
750 */
751 function fs_sort_by_priority( $a, $b ) {
752
753 // If b has a priority and a does not, b wins.
754 if ( ! isset( $a['priority'] ) && isset( $b['priority'] ) ) {
755 return 1;
756 } // If b has a priority and a does not, b wins.
757 elseif ( isset( $a['priority'] ) && ! isset( $b['priority'] ) ) {
758 return - 1;
759 } // If neither has a priority or both priorities are equal its a tie.
760 elseif ( ( ! isset( $a['priority'] ) && ! isset( $b['priority'] ) ) || $a['priority'] === $b['priority'] ) {
761 return 0;
762 }
763
764 // If both have priority return the winner.
765 return ( $a['priority'] < $b['priority'] ) ? - 1 : 1;
766 }
767 }
768
769 #--------------------------------------------------------------------------------
770 #region Localization
771 #--------------------------------------------------------------------------------
772
773 if ( ! function_exists( 'fs_text' ) ) {
774 /**
775 * Retrieve a translated text by key.
776 *
777 * @author Vova Feldman (@svovaf)
778 * @since 1.2.1.7
779 *
780 * @param string $key
781 * @param string $slug
782 *
783 * @return string
784 *
785 * @global $fs_text , $fs_text_overrides
786 */
787 function fs_text( $key, $slug = 'freemius' ) {
788 global $fs_text,
789 $fs_module_info_text,
790 $fs_text_overrides;
791
792 if ( isset( $fs_text_overrides[ $slug ] ) ) {
793 if ( isset( $fs_text_overrides[ $slug ][ $key ] ) ) {
794 return $fs_text_overrides[ $slug ][ $key ];
795 }
796
797 $lower_key = strtolower( $key );
798 if ( isset( $fs_text_overrides[ $slug ][ $lower_key ] ) ) {
799 return $fs_text_overrides[ $slug ][ $lower_key ];
800 }
801 }
802
803 if ( ! isset( $fs_text ) ) {
804 $dir = defined( 'WP_FS__DIR_INCLUDES' ) ?
805 WP_FS__DIR_INCLUDES :
806 dirname( __FILE__ );
807
808 require_once $dir . '/i18n.php';
809 }
810
811 if ( isset( $fs_text[ $key ] ) ) {
812 return $fs_text[ $key ];
813 }
814
815 if ( isset( $fs_module_info_text[ $key ] ) ) {
816 return $fs_module_info_text[ $key ];
817 }
818
819 return $key;
820 }
821
822 #region Private
823
824 /**
825 * Retrieve an inline translated text by key with a context.
826 *
827 * @author Vova Feldman (@svovaf)
828 * @since 1.2.3
829 *
830 * @param string $text Translatable string.
831 * @param string $context Context information for the translators.
832 * @param string $key String key for overrides.
833 * @param string $slug Module slug for overrides.
834 *
835 * @return string
836 *
837 * @global $fs_text_overrides
838 */
839 function _fs_text_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
840 list( $text, $text_domain ) = fs_text_and_domain( $text, $key, $slug );
841
842 // Avoid misleading Theme Check warning.
843 $fn = 'translate_with_gettext_context';
844
845 return $fn( $text, $context, $text_domain );
846 }
847
848 #endregion
849
850 /**
851 * Retrieve an inline translated text by key with a context.
852 *
853 * @author Vova Feldman (@svovaf)
854 * @since 1.2.3
855 *
856 * @param string $text Translatable string.
857 * @param string $context Context information for the translators.
858 * @param string $key String key for overrides.
859 * @param string $slug Module slug for overrides.
860 *
861 * @return string
862 *
863 * @global $fs_text_overrides
864 */
865 function fs_text_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
866 return _fs_text_x_inline( $text, $context, $key, $slug );
867 }
868
869 /**
870 * Output a translated text by key.
871 *
872 * @author Vova Feldman (@svovaf)
873 * @since 1.2.1.7
874 *
875 * @param string $key
876 * @param string $slug
877 */
878 function fs_echo( $key, $slug = 'freemius' ) {
879 echo fs_text( $key, $slug );
880 }
881
882 /**
883 * Output an inline translated text.
884 *
885 * @author Vova Feldman (@svovaf)
886 * @since 1.2.3
887 *
888 * @param string $text Translatable string.
889 * @param string $key String key for overrides.
890 * @param string $slug Module slug for overrides.
891 */
892 function fs_echo_inline( $text, $key = '', $slug = 'freemius' ) {
893 echo _fs_text_inline( $text, $key, $slug );
894 }
895
896 /**
897 * Output an inline translated text with a context.
898 *
899 * @author Vova Feldman (@svovaf)
900 * @since 1.2.3
901 *
902 * @param string $text Translatable string.
903 * @param string $context Context information for the translators.
904 * @param string $key String key for overrides.
905 * @param string $slug Module slug for overrides.
906 */
907 function fs_echo_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
908 echo _fs_text_x_inline( $text, $context, $key, $slug );
909 }
910 }
911
912 if ( ! function_exists( 'fs_text_override' ) ) {
913 /**
914 * Get a translatable text override if exists, or `false`.
915 *
916 * @author Vova Feldman (@svovaf)
917 * @since 1.2.1.7
918 *
919 * @param string $text Translatable string.
920 * @param string $key String key for overrides.
921 * @param string $slug Module slug for overrides.
922 *
923 * @return string|false
924 */
925 function fs_text_override( $text, $key, $slug ) {
926 global $fs_text_overrides;
927
928 /**
929 * Check if string is overridden.
930 */
931 if ( ! isset( $fs_text_overrides[ $slug ] ) ) {
932 return false;
933 }
934
935 if ( empty( $key ) ) {
936 $key = strtolower( str_replace( ' ', '-', $text ) );
937 }
938
939 if ( isset( $fs_text_overrides[ $slug ][ $key ] ) ) {
940 return $fs_text_overrides[ $slug ][ $key ];
941 }
942
943 $lower_key = strtolower( $key );
944 if ( isset( $fs_text_overrides[ $slug ][ $lower_key ] ) ) {
945 return $fs_text_overrides[ $slug ][ $lower_key ];
946 }
947
948 return false;
949 }
950 }
951
952 if ( ! function_exists( 'fs_text_and_domain' ) ) {
953 /**
954 * Get a translatable text and its text domain.
955 *
956 * When the text is overridden by the module, returns the overridden text and the text domain of the module. Otherwise, returns the original text and 'freemius' as the text domain.
957 *
958 * @author Vova Feldman (@svovaf)
959 * @since 1.2.1.7
960 *
961 * @param string $text Translatable string.
962 * @param string $key String key for overrides.
963 * @param string $slug Module slug for overrides.
964 *
965 * @return string[]
966 */
967 function fs_text_and_domain( $text, $key, $slug ) {
968 $override = fs_text_override( $text, $key, $slug );
969
970 if ( false === $override ) {
971 // No override, use FS text domain.
972 $text_domain = 'freemius';
973 } else {
974 // Found an override.
975 $text = $override;
976 // Use the module's text domain.
977 $text_domain = $slug;
978 }
979
980 return array( $text, $text_domain );
981 }
982 }
983
984 if ( ! function_exists( '_fs_text_inline' ) ) {
985 /**
986 * Retrieve an inline translated text by key.
987 *
988 * @author Vova Feldman (@svovaf)
989 * @since 1.2.3
990 *
991 * @param string $text Translatable string.
992 * @param string $key String key for overrides.
993 * @param string $slug Module slug for overrides.
994 *
995 * @return string
996 *
997 * @global $fs_text_overrides
998 */
999 function _fs_text_inline( $text, $key = '', $slug = 'freemius' ) {
1000 list( $text, $text_domain ) = fs_text_and_domain( $text, $key, $slug );
1001
1002 // Avoid misleading Theme Check warning.
1003 $fn = 'translate';
1004
1005 return $fn( $text, $text_domain );
1006 }
1007 }
1008
1009 if ( ! function_exists( 'fs_text_inline' ) ) {
1010 /**
1011 * Retrieve an inline translated text by key.
1012 *
1013 * @author Vova Feldman (@svovaf)
1014 * @since 1.2.3
1015 *
1016 * @param string $text Translatable string.
1017 * @param string $key String key for overrides.
1018 * @param string $slug Module slug for overrides.
1019 *
1020 * @return string
1021 *
1022 * @global $fs_text_overrides
1023 */
1024 function fs_text_inline( $text, $key = '', $slug = 'freemius' ) {
1025 return _fs_text_inline( $text, $key, $slug );
1026 }
1027 }
1028
1029 if ( ! function_exists( 'fs_esc_attr' ) ) {
1030 /**
1031 * @author Vova Feldman
1032 * @since 1.2.1.6
1033 *
1034 * @param string $key
1035 * @param string $slug
1036 *
1037 * @return string
1038 */
1039 function fs_esc_attr( $key, $slug ) {
1040 return esc_attr( fs_text( $key, $slug ) );
1041 }
1042 }
1043
1044 if ( ! function_exists( 'fs_esc_attr_inline' ) ) {
1045 /**
1046 * @author Vova Feldman (@svovaf)
1047 * @since 1.2.3
1048 *
1049 * @param string $text Translatable string.
1050 * @param string $key String key for overrides.
1051 * @param string $slug Module slug for overrides.
1052 *
1053 * @return string
1054 */
1055 function fs_esc_attr_inline( $text, $key = '', $slug = 'freemius' ) {
1056 return esc_attr( _fs_text_inline( $text, $key, $slug ) );
1057 }
1058 }
1059
1060 if ( ! function_exists( 'fs_esc_attr_x_inline' ) ) {
1061 /**
1062 * @author Vova Feldman (@svovaf)
1063 * @since 1.2.3
1064 *
1065 * @param string $text Translatable string.
1066 * @param string $context Context information for the translators.
1067 * @param string $key String key for overrides.
1068 * @param string $slug Module slug for overrides.
1069 *
1070 * @return string
1071 */
1072 function fs_esc_attr_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
1073 return esc_attr( _fs_text_x_inline( $text, $context, $key, $slug ) );
1074 }
1075 }
1076
1077 if ( ! function_exists( 'fs_esc_attr_echo' ) ) {
1078 /**
1079 * @author Vova Feldman
1080 * @since 1.2.1.6
1081 *
1082 * @param string $key
1083 * @param string $slug
1084 */
1085 function fs_esc_attr_echo( $key, $slug ) {
1086 echo esc_attr( fs_text( $key, $slug ) );
1087 }
1088 }
1089
1090 if ( ! function_exists( 'fs_esc_attr_echo_inline' ) ) {
1091 /**
1092 * @author Vova Feldman (@svovaf)
1093 * @since 1.2.3
1094 *
1095 * @param string $text Translatable string.
1096 * @param string $key String key for overrides.
1097 * @param string $slug Module slug for overrides.
1098 */
1099 function fs_esc_attr_echo_inline( $text, $key = '', $slug = 'freemius' ) {
1100 echo esc_attr( _fs_text_inline( $text, $key, $slug ) );
1101 }
1102 }
1103
1104 if ( ! function_exists( 'fs_esc_js' ) ) {
1105 /**
1106 * @author Vova Feldman
1107 * @since 1.2.1.6
1108 *
1109 * @param string $key
1110 * @param string $slug
1111 *
1112 * @return string
1113 */
1114 function fs_esc_js( $key, $slug ) {
1115 return esc_js( fs_text( $key, $slug ) );
1116 }
1117 }
1118
1119 if ( ! function_exists( 'fs_esc_js_inline' ) ) {
1120 /**
1121 * @author Vova Feldman (@svovaf)
1122 * @since 1.2.3
1123 *
1124 * @param string $text Translatable string.
1125 * @param string $key String key for overrides.
1126 * @param string $slug Module slug for overrides.
1127 *
1128 * @return string
1129 */
1130 function fs_esc_js_inline( $text, $key = '', $slug = 'freemius' ) {
1131 return esc_js( _fs_text_inline( $text, $key, $slug ) );
1132 }
1133 }
1134
1135 if ( ! function_exists( 'fs_esc_js_x_inline' ) ) {
1136 /**
1137 * @author Vova Feldman (@svovaf)
1138 * @since 1.2.3
1139 *
1140 * @param string $text Translatable string.
1141 * @param string $context Context information for the translators.
1142 * @param string $key String key for overrides.
1143 * @param string $slug Module slug for overrides.
1144 *
1145 * @return string
1146 */
1147 function fs_esc_js_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
1148 return esc_js( _fs_text_x_inline( $text, $context, $key, $slug ) );
1149 }
1150 }
1151
1152 if ( ! function_exists( 'fs_esc_js_echo_x_inline' ) ) {
1153 /**
1154 * @author Vova Feldman (@svovaf)
1155 * @since 1.2.3
1156 *
1157 * @param string $text Translatable string.
1158 * @param string $context Context information for the translators.
1159 * @param string $key String key for overrides.
1160 * @param string $slug Module slug for overrides.
1161 *
1162 * @return string
1163 */
1164 function fs_esc_js_echo_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
1165 echo esc_js( _fs_text_x_inline( $text, $context, $key, $slug ) );
1166 }
1167 }
1168
1169 if ( ! function_exists( 'fs_esc_js_echo' ) ) {
1170 /**
1171 * @author Vova Feldman
1172 * @since 1.2.1.6
1173 *
1174 * @param string $key
1175 * @param string $slug
1176 */
1177 function fs_esc_js_echo( $key, $slug ) {
1178 echo esc_js( fs_text( $key, $slug ) );
1179 }
1180 }
1181
1182 if ( ! function_exists( 'fs_esc_js_echo_inline' ) ) {
1183 /**
1184 * @author Vova Feldman (@svovaf)
1185 * @since 1.2.3
1186 *
1187 * @param string $text Translatable string.
1188 * @param string $key String key for overrides.
1189 * @param string $slug Module slug for overrides.
1190 */
1191 function fs_esc_js_echo_inline( $text, $key = '', $slug = 'freemius' ) {
1192 echo esc_js( _fs_text_inline( $text, $key, $slug ) );
1193 }
1194 }
1195
1196 if ( ! function_exists( 'fs_json_encode_echo' ) ) {
1197 /**
1198 * @author Vova Feldman
1199 * @since 1.2.1.6
1200 *
1201 * @param string $key
1202 * @param string $slug
1203 */
1204 function fs_json_encode_echo( $key, $slug ) {
1205 echo json_encode( fs_text( $key, $slug ) );
1206 }
1207 }
1208
1209 if ( ! function_exists( 'fs_json_encode_echo_inline' ) ) {
1210 /**
1211 * @author Vova Feldman (@svovaf)
1212 * @since 1.2.3
1213 *
1214 * @param string $text Translatable string.
1215 * @param string $key String key for overrides.
1216 * @param string $slug Module slug for overrides.
1217 */
1218 function fs_json_encode_echo_inline( $text, $key = '', $slug = 'freemius' ) {
1219 echo json_encode( _fs_text_inline( $text, $key, $slug ) );
1220 }
1221 }
1222
1223 if ( ! function_exists( 'fs_esc_html' ) ) {
1224 /**
1225 * @author Vova Feldman
1226 * @since 1.2.1.6
1227 *
1228 * @param string $key
1229 * @param string $slug
1230 *
1231 * @return string
1232 */
1233 function fs_esc_html( $key, $slug ) {
1234 return esc_html( fs_text( $key, $slug ) );
1235 }
1236 }
1237
1238 if ( ! function_exists( 'fs_esc_html_inline' ) ) {
1239 /**
1240 * @author Vova Feldman (@svovaf)
1241 * @since 1.2.3
1242 *
1243 * @param string $text Translatable string.
1244 * @param string $key String key for overrides.
1245 * @param string $slug Module slug for overrides.
1246 *
1247 * @return string
1248 */
1249 function fs_esc_html_inline( $text, $key = '', $slug = 'freemius' ) {
1250 return esc_html( _fs_text_inline( $text, $key, $slug ) );
1251 }
1252 }
1253
1254 if ( ! function_exists( 'fs_esc_html_x_inline' ) ) {
1255 /**
1256 * @author Vova Feldman (@svovaf)
1257 * @since 1.2.3
1258 *
1259 * @param string $text Translatable string.
1260 * @param string $context Context information for the translators.
1261 * @param string $key String key for overrides.
1262 * @param string $slug Module slug for overrides.
1263 *
1264 * @return string
1265 */
1266 function fs_esc_html_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
1267 return esc_html( _fs_text_x_inline( $text, $context, $key, $slug ) );
1268 }
1269 }
1270
1271 if ( ! function_exists( 'fs_esc_html_echo_x_inline' ) ) {
1272 /**
1273 * @author Vova Feldman (@svovaf)
1274 * @since 1.2.3
1275 *
1276 * @param string $text Translatable string.
1277 * @param string $context Context information for the translators.
1278 * @param string $key String key for overrides.
1279 * @param string $slug Module slug for overrides.
1280 */
1281 function fs_esc_html_echo_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
1282 echo esc_html( _fs_text_x_inline( $text, $context, $key, $slug ) );
1283 }
1284 }
1285
1286 if ( ! function_exists( 'fs_esc_html_echo' ) ) {
1287 /**
1288 * @author Vova Feldman
1289 * @since 1.2.1.6
1290 *
1291 * @param string $key
1292 * @param string $slug
1293 */
1294 function fs_esc_html_echo( $key, $slug ) {
1295 echo esc_html( fs_text( $key, $slug ) );
1296 }
1297 }
1298
1299 if ( ! function_exists( 'fs_esc_html_echo_inline' ) ) {
1300 /**
1301 * @author Vova Feldman (@svovaf)
1302 * @since 1.2.3
1303 *
1304 * @param string $text Translatable string.
1305 * @param string $key String key for overrides.
1306 * @param string $slug Module slug for overrides.
1307 */
1308 function fs_esc_html_echo_inline( $text, $key = '', $slug = 'freemius' ) {
1309 echo esc_html( _fs_text_inline( $text, $key, $slug ) );
1310 }
1311 }
1312
1313 if ( ! function_exists( 'fs_override_i18n' ) ) {
1314 /**
1315 * Override default i18n text phrases.
1316 *
1317 * @author Vova Feldman (@svovaf)
1318 * @since 1.1.6
1319 *
1320 * @param array[string]string $key_value
1321 * @param string $slug
1322 *
1323 * @global $fs_text_overrides
1324 */
1325 function fs_override_i18n( array $key_value, $slug = 'freemius' ) {
1326 global $fs_text_overrides;
1327
1328 if ( ! isset( $fs_text_overrides[ $slug ] ) ) {
1329 $fs_text_overrides[ $slug ] = array();
1330 }
1331
1332 foreach ( $key_value as $key => $value ) {
1333 $fs_text_overrides[ $slug ][ $key ] = $value;
1334 }
1335 }
1336 }
1337
1338 #endregion
1339
1340 #--------------------------------------------------------------------------------
1341 #region Multisite Network
1342 #--------------------------------------------------------------------------------
1343
1344 if ( ! function_exists( 'fs_is_plugin_uninstall' ) ) {
1345 /**
1346 * @author Vova Feldman (@svovaf)
1347 * @since 2.0.0
1348 */
1349 function fs_is_plugin_uninstall() {
1350 return (
1351 defined( 'WP_UNINSTALL_PLUGIN' ) ||
1352 ( 0 < did_action( 'update_option_uninstall_plugins' ) )
1353 );
1354 }
1355 }
1356
1357 if ( ! function_exists( 'fs_is_network_admin' ) ) {
1358 /**
1359 * Unlike is_network_admin(), this one will also work properly when
1360 * the context execution is WP AJAX handler, and during plugin
1361 * uninstall.
1362 *
1363 * @author Vova Feldman (@svovaf)
1364 * @since 2.0.0
1365 */
1366 function fs_is_network_admin() {
1367 return (
1368 WP_FS__IS_NETWORK_ADMIN ||
1369 ( is_multisite() && fs_is_plugin_uninstall() )
1370 );
1371 }
1372 }
1373
1374 if ( ! function_exists( 'fs_is_blog_admin' ) ) {
1375 /**
1376 * Unlike is_blog_admin(), this one will also work properly when
1377 * the context execution is WP AJAX handler, and during plugin
1378 * uninstall.
1379 *
1380 * @author Vova Feldman (@svovaf)
1381 * @since 2.0.0
1382 */
1383 function fs_is_blog_admin() {
1384 return (
1385 WP_FS__IS_BLOG_ADMIN ||
1386 ( ! is_multisite() && fs_is_plugin_uninstall() )
1387 );
1388 }
1389 }
1390
1391 #endregion
1392
1393 if ( ! function_exists( 'fs_apply_filter' ) ) {
1394 /**
1395 * Apply filter for specific plugin.
1396 *
1397 * @author Vova Feldman (@svovaf)
1398 * @since 1.0.9
1399 *
1400 * @param string $module_unique_affix Module's unique affix.
1401 * @param string $tag The name of the filter hook.
1402 * @param mixed $value The value on which the filters hooked to `$tag` are applied on.
1403 *
1404 * @return mixed The filtered value after all hooked functions are applied to it.
1405 *
1406 * @uses apply_filters()
1407 */
1408 function fs_apply_filter( $module_unique_affix, $tag, $value ) {
1409 $args = func_get_args();
1410
1411 return call_user_func_array( 'apply_filters', array_merge(
1412 array( "fs_{$tag}_{$module_unique_affix}" ),
1413 array_slice( $args, 2 ) )
1414 );
1415 }
1416 }