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