PluginProbe
Buttonizer – Floating Menus, Sticky Buttons, & Popup Builder / 3.6.0
Buttonizer – Floating Menus, Sticky Buttons, & Popup Builder v3.6.0
3.6.0 3.5.0 trunk 1.0.10 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.6.1 1.0.7 1.0.8 1.0.9 1.1 1.1.1 1.2 1.3 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.5 1.5.1 All 110 releases
← All changes | freemius/includes/fs-core-functions.php +683 -296 1.4.43.6.0 View file →
@@ -62,48 +62,72 @@
62 62
63 63 /* Scripts and styles including.
64 64 --------------------------------------------------------------------------------------------*/
65 65
66 - /**
67 - * Generates an absolute URL to the given path. This function ensures that the URL will be correct whether the asset
68 - * is inside a plugin's folder or a theme's folder.
69 - *
70 - * Examples:
71 - * 1. "themes" folder
72 - * Path: C:/xampp/htdocs/fswp/wp-content/themes/twentytwelve/freemius/assets/css/admin/common.css
73 - * URL: http://fswp:8080/wp-content/themes/twentytwelve/freemius/assets/css/admin/common.css
74 - *
75 - * 2. "plugins" folder
76 - * Path: C:/xampp/htdocs/fswp/wp-content/plugins/rating-widget-premium/freemius/assets/css/admin/common.css
77 - * URL: http://fswp:8080/wp-content/plugins/rating-widget-premium/freemius/assets/css/admin/common.css
78 - *
79 - * @author Leo Fajardo (@leorw)
80 - * @since 1.2.2
81 - *
82 - * @param string $asset_abs_path Asset's absolute path.
83 - *
84 - * @return string Asset's URL.
85 - */
86 - function fs_asset_url( $asset_abs_path ) {
87 - $wp_content_dir = fs_normalize_path( WP_CONTENT_DIR );
88 - $asset_abs_path = fs_normalize_path( $asset_abs_path );
89 - $asset_rel_path = str_replace( $wp_content_dir, '', $asset_abs_path );
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 90
91 - $asset_url = content_url( fs_normalize_path( $asset_rel_path ) );
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 + }
92 109
93 - return $asset_url;
110 + return $asset_url;
111 + }
94 112 }
95 113
96 - function fs_enqueue_local_style( $handle, $path, $deps = array(), $ver = false, $media = 'all' ) {
97 - wp_enqueue_style( $handle, fs_asset_url( WP_FS__DIR_CSS . '/' . trim( $path, '/' ) ), $deps, $ver, $media );
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 + }
98 118 }
99 119
100 - function fs_enqueue_local_script( $handle, $path, $deps = array(), $ver = false, $in_footer = 'all' ) {
101 - wp_enqueue_script( $handle, fs_asset_url( WP_FS__DIR_JS . '/' . trim( $path, '/' ) ), $deps, $ver, $in_footer );
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 + }
102 124 }
103 125
104 - function fs_img_url( $path, $img_dir = WP_FS__DIR_IMG ) {
105 - return ( fs_asset_url( $img_dir . '/' . trim( $path, '/' ) ) );
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 + }
106 130 }
107 131
108 132 #--------------------------------------------------------------------------------
109 133 #region Request handlers.
@@ -108,57 +132,141 @@
108 132 #--------------------------------------------------------------------------------
109 133 #region Request handlers.
110 134 #--------------------------------------------------------------------------------
111 135
112 - if ( ! function_exists( 'fs_request_get' ) ) {
136 + if ( ! function_exists( 'fs_request_get_raw' ) ) {
113 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 + *
114 145 * @param string $key
115 146 * @param mixed $def
116 - * @param string|bool $type Since 1.2.1.7 - when set to 'get' will look for the value passed via querystring, when
117 - * set to 'post' will look for the value passed via the POST request's body, otherwise,
118 - * will check if the parameter was passed in any of the two.
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.
119 150 *
120 151 * @return mixed
121 152 */
122 - function fs_request_get( $key, $def = false, $type = false ) {
153 + function fs_request_get_raw( $key, $def = false, $type = false ) {
123 154 if ( is_string( $type ) ) {
124 155 $type = strtolower( $type );
125 156 }
126 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 + */
127 162 switch ( $type ) {
128 163 case 'post':
164 + // phpcs:ignore WordPress.Security.NonceVerification.Missing
129 165 $value = isset( $_POST[ $key ] ) ? $_POST[ $key ] : $def;
130 166 break;
131 167 case 'get':
168 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended
132 169 $value = isset( $_GET[ $key ] ) ? $_GET[ $key ] : $def;
133 170 break;
134 171 default:
172 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended
135 173 $value = isset( $_REQUEST[ $key ] ) ? $_REQUEST[ $key ] : $def;
136 174 break;
137 175 }
138 176
139 - return $value;
177 + // Don't unslash if the value itself is empty (empty string, null, empty array etc).
178 + return empty( $value ) ? $value : wp_unslash( $value );
140 179 }
141 180 }
142 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 +
143 228 if ( ! function_exists( 'fs_request_has' ) ) {
144 229 function fs_request_has( $key ) {
230 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended
145 231 return isset( $_REQUEST[ $key ] );
146 232 }
147 233 }
148 234
149 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 + */
150 246 function fs_request_get_bool( $key, $def = false ) {
151 - if ( ! isset( $_REQUEST[ $key ] ) ) {
247 + $val = fs_request_get( $key, null );
248 +
249 + if ( is_null( $val ) ) {
152 250 return $def;
153 251 }
154 252
155 - if ( 1 == $_REQUEST[ $key ] || 'true' === strtolower( $_REQUEST[ $key ] ) ) {
156 - return true;
157 - }
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 );
158 263
159 - if ( 0 == $_REQUEST[ $key ] || 'false' === strtolower( $_REQUEST[ $key ] ) ) {
160 - return false;
264 + if ( 'true' === $val ) {
265 + return true;
266 + } else if ( 'false' === $val ) {
267 + return false;
268 + }
161 269 }
162 270
163 271 return $def;
164 272 }
@@ -177,8 +285,9 @@
177 285 }
178 286
179 287 if ( ! function_exists( 'fs_get_action' ) ) {
180 288 function fs_get_action( $action_key = 'action' ) {
289 + // phpcs:disable WordPress.Security.NonceVerification.Recommended
181 290 if ( ! empty( $_REQUEST[ $action_key ] ) && is_string( $_REQUEST[ $action_key ] ) ) {
182 291 return strtolower( $_REQUEST[ $action_key ] );
183 292 }
184 293
@@ -190,8 +299,9 @@
190 299 }
191 300 }
192 301
193 302 return false;
303 + // phpcs:enable WordPress.Security.NonceVerification.Recommended
194 304 }
195 305 }
196 306
197 307 if ( ! function_exists( 'fs_request_is_action' ) ) {
@@ -269,131 +379,194 @@
269 379 }
270 380
271 381 /* Core UI.
272 382 --------------------------------------------------------------------------------------------*/
273 - /**
274 - * @param number $module_id
275 - * @param string $page
276 - * @param string $action
277 - * @param string $title
278 - * @param array $params
279 - * @param bool $is_primary
280 - * @param string|bool $icon_class Optional class for an icon (since 1.1.7).
281 - * @param string|bool $confirmation Optional confirmation message before submit (since 1.1.7).
282 - * @param string $method Since 1.1.7
283 - *
284 - * @uses fs_ui_get_action_button()
285 - */
286 - function fs_ui_action_button(
287 - $module_id,
288 - $page,
289 - $action,
290 - $title,
291 - $params = array(),
292 - $is_primary = true,
293 - $icon_class = false,
294 - $confirmation = false,
295 - $method = 'GET'
296 - ) {
297 - echo fs_ui_get_action_button(
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(
298 400 $module_id,
299 401 $page,
300 402 $action,
301 403 $title,
302 - $params,
303 - $is_primary,
304 - $icon_class,
305 - $confirmation,
306 - $method
307 - );
308 - }
309 -
310 - /**
311 - * @author Vova Feldman (@svovaf)
312 - * @since 1.1.7
313 - *
314 - * @param number $module_id
315 - * @param string $page
316 - * @param string $action
317 - * @param string $title
318 - * @param array $params
319 - * @param bool $is_primary
320 - * @param string|bool $icon_class Optional class for an icon.
321 - * @param string|bool $confirmation Optional confirmation message before submit.
322 - * @param string $method
323 - *
324 - * @return string
325 - */
326 - function fs_ui_get_action_button(
327 - $module_id,
328 - $page,
329 - $action,
330 - $title,
331 - $params = array(),
332 - $is_primary = true,
333 - $icon_class = false,
334 - $confirmation = false,
335 - $method = 'GET'
336 - ) {
337 - // Prepend icon (if set).
338 - $title = ( is_string( $icon_class ) ? '<i class="' . $icon_class . '"></i> ' : '' ) . $title;
339 -
340 - if ( is_string( $confirmation ) ) {
341 - 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>',
342 - freemius( $module_id )->_get_admin_page_url( $page, $params ),
343 - $method,
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,
344 415 $action,
345 - wp_nonce_field( $action, '_wpnonce', true, false ),
346 - 'button' . ( $is_primary ? ' button-primary' : '' ),
416 + $title,
417 + $button_class,
418 + $params,
419 + $is_primary,
420 + $is_small,
421 + $icon_class,
347 422 $confirmation,
348 - $title
423 + $method
349 424 );
350 - } else if ( 'GET' !== strtoupper( $method ) ) {
351 - 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>',
352 - freemius( $module_id )->_get_admin_page_url( $page, $params ),
353 - $method,
354 - $action,
355 - wp_nonce_field( $action, '_wpnonce', true, false ),
356 - 'button' . ( $is_primary ? ' button-primary' : '' ),
357 - $title
358 - );
359 - } else {
360 - return sprintf( '<a href="%s" class="%s">%s</a></form>',
361 - wp_nonce_url( freemius( $module_id )->_get_admin_page_url( $page, array_merge( $params, array( 'fs_action' => $action ) ) ), $action ),
362 - 'button' . ( $is_primary ? ' button-primary' : '' ),
363 - $title
364 - );
365 425 }
366 426 }
367 427
368 - function fs_ui_action_link( $module_id, $page, $action, $title, $params = array() ) {
369 - ?><a class=""
370 - 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
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 + }
371 495 }
372 496
373 - /*function fs_error_handler($errno, $errstr, $errfile, $errline)
374 - {
375 - if (false === strpos($errfile, 'freemius/'))
376 - {
377 - // @todo Dump Freemius errors to local log.
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 );
378 513 }
514 + }
379 515
380 -// switch ($errno) {
381 -// case E_USER_ERROR:
382 -// break;
383 -// case E_WARNING:
384 -// case E_USER_WARNING:
385 -// break;
386 -// case E_NOTICE:
387 -// case E_USER_NOTICE:
388 -// break;
389 -// default:
390 -// break;
391 -// }
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 + }
392 567 }
393 568
394 - set_error_handler('fs_error_handler');*/
395 -
396 569 if ( ! function_exists( 'fs_nonce_url' ) ) {
397 570 /**
398 571 * Retrieve URL with nonce added to URL query.
399 572 *
@@ -414,8 +587,35 @@
414 587 return add_query_arg( $name, wp_create_nonce( $action ), $actionurl );
415 588 }
416 589 }
417 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 +
418 618 if ( ! function_exists( 'fs_starts_with' ) ) {
419 619 /**
420 620 * Check if string starts with.
421 621 *
@@ -433,8 +633,44 @@
433 633 return ( substr( $haystack, 0, $length ) === $needle );
434 634 }
435 635 }
436 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 +
437 673 #region Url Canonization ------------------------------------------------------------------
438 674
439 675 if ( ! function_exists( 'fs_canonize_url' ) ) {
440 676 /**
@@ -542,73 +778,77 @@
542 778 }
543 779
544 780 #endregion Url Canonization ------------------------------------------------------------------
545 781
546 - /**
547 - * @author Vova Feldman (@svovaf)
548 - *
549 - * @since 1.2.2 Changed to usage of WP_Filesystem_Direct.
550 - *
551 - * @param string $from URL
552 - * @param string $to File path.
553 - *
554 - * @return bool Is successfully downloaded.
555 - */
556 - function fs_download_image( $from, $to ) {
557 - $dir = dirname( $to );
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 );
558 795
559 - if ( 'direct' !== get_filesystem_method( array(), $dir ) ) {
560 - return false;
561 - }
796 + if ( 'direct' !== get_filesystem_method( array(), $dir ) ) {
797 + return false;
798 + }
562 799
563 - if ( ! class_exists( 'WP_Filesystem_Direct' ) ) {
564 - require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php';
565 - require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php';
566 - }
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 + }
567 804
568 - $fs = new WP_Filesystem_Direct( '' );
569 - $tmpfile = download_url( $from );
805 + $fs = new WP_Filesystem_Direct( '' );
806 + $tmpfile = download_url( $from );
570 807
571 - if ( $tmpfile instanceof WP_Error ) {
572 - // Issue downloading the file.
573 - return false;
574 - }
808 + if ( $tmpfile instanceof WP_Error ) {
809 + // Issue downloading the file.
810 + return false;
811 + }
575 812
576 - $fs->copy( $tmpfile, $to );
577 - $fs->delete( $tmpfile );
813 + $fs->copy( $tmpfile, $to );
814 + $fs->delete( $tmpfile );
578 815
579 - return true;
816 + return true;
817 + }
580 818 }
581 819
582 820 /* General Utilities
583 821 --------------------------------------------------------------------------------------------*/
584 822
585 - /**
586 - * Sorts an array by the value of the priority key.
587 - *
588 - * @author Daniel Iser (@danieliser)
589 - * @since 1.1.7
590 - *
591 - * @param $a
592 - * @param $b
593 - *
594 - * @return int
595 - */
596 - function fs_sort_by_priority( $a, $b ) {
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 ) {
597 836
598 - // If b has a priority and a does not, b wins.
599 - if ( ! isset( $a['priority'] ) && isset( $b['priority'] ) ) {
600 - return 1;
601 - } // If b has a priority and a does not, b wins.
602 - elseif ( isset( $a['priority'] ) && ! isset( $b['priority'] ) ) {
603 - return - 1;
604 - } // If neither has a priority or both priorities are equal its a tie.
605 - elseif ( ( ! isset( $a['priority'] ) && ! isset( $b['priority'] ) ) || $a['priority'] === $b['priority'] ) {
606 - return 0;
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;
607 850 }
608 -
609 - // If both have priority return the winner.
610 - return ( $a['priority'] < $b['priority'] ) ? - 1 : 1;
611 851 }
612 852
613 853 #--------------------------------------------------------------------------------
614 854 #region Localization
@@ -613,8 +853,14 @@
613 853 #--------------------------------------------------------------------------------
614 854 #region Localization
615 855 #--------------------------------------------------------------------------------
616 856
857 + global $fs_text_overrides;
858 +
859 + if ( ! isset( $fs_text_overrides ) ) {
860 + $fs_text_overrides = array();
861 + }
862 +
617 863 if ( ! function_exists( 'fs_text' ) ) {
618 864 /**
619 865 * Retrieve a translated text by key.
620 866 *
@@ -625,15 +871,119 @@
625 871 * @param string $slug
626 872 *
627 873 * @return string
628 874 *
629 - * @global $fs_text , $fs_text_overrides
875 + * @global $fs_text_overrides
630 876 */
631 877 function fs_text( $key, $slug = 'freemius' ) {
632 - return __fs( $key, $slug );
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;
633 892 }
634 893
894 + #region Private
895 +
635 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 + /**
636 986 * Get a translatable text override if exists, or `false`.
637 987 *
638 988 * @author Vova Feldman (@svovaf)
639 989 * @since 1.2.1.7
@@ -668,9 +1018,11 @@
668 1018 }
669 1019
670 1020 return false;
671 1021 }
1022 + }
672 1023
1024 + if ( ! function_exists( 'fs_text_and_domain' ) ) {
673 1025 /**
674 1026 * Get a translatable text and its text domain.
675 1027 *
676 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.
@@ -698,11 +1050,11 @@
698 1050 }
699 1051
700 1052 return array( $text, $text_domain );
701 1053 }
1054 + }
702 1055
703 - #region Private
704 -
1056 + if ( ! function_exists( '_fs_text_inline' ) ) {
705 1057 /**
706 1058 * Retrieve an inline translated text by key.
707 1059 *
708 1060 * @author Vova Feldman (@svovaf)
@@ -723,36 +1075,12 @@
723 1075 $fn = 'translate';
724 1076
725 1077 return $fn( $text, $text_domain );
726 1078 }
1079 + }
727 1080
1081 + if ( ! function_exists( 'fs_text_inline' ) ) {
728 1082 /**
729 - * Retrieve an inline translated text by key with a context.
730 - *
731 - * @author Vova Feldman (@svovaf)
732 - * @since 1.2.3
733 - *
734 - * @param string $text Translatable string.
735 - * @param string $context Context information for the translators.
736 - * @param string $key String key for overrides.
737 - * @param string $slug Module slug for overrides.
738 - *
739 - * @return string
740 - *
741 - * @global $fs_text_overrides
742 - */
743 - function _fs_text_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
744 - list( $text, $text_domain ) = fs_text_and_domain( $text, $key, $slug );
745 -
746 - // Avoid misleading Theme Check warning.
747 - $fn = 'translate_with_gettext_context';
748 -
749 - return $fn( $text, $context, $text_domain );
750 - }
751 -
752 - #endregion
753 -
754 - /**
755 1083 * Retrieve an inline translated text by key.
756 1084 *
757 1085 * @author Vova Feldman (@svovaf)
758 1086 * @since 1.2.3
@@ -767,69 +1095,8 @@
767 1095 */
768 1096 function fs_text_inline( $text, $key = '', $slug = 'freemius' ) {
769 1097 return _fs_text_inline( $text, $key, $slug );
770 1098 }
771 -
772 - /**
773 - * Retrieve an inline translated text by key with a context.
774 - *
775 - * @author Vova Feldman (@svovaf)
776 - * @since 1.2.3
777 - *
778 - * @param string $text Translatable string.
779 - * @param string $context Context information for the translators.
780 - * @param string $key String key for overrides.
781 - * @param string $slug Module slug for overrides.
782 - *
783 - * @return string
784 - *
785 - * @global $fs_text_overrides
786 - */
787 - function fs_text_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
788 - return _fs_text_x_inline( $text, $context, $key, $slug );
789 - }
790 -
791 - /**
792 - * Output a translated text by key.
793 - *
794 - * @author Vova Feldman (@svovaf)
795 - * @since 1.2.1.7
796 - *
797 - * @param string $key
798 - * @param string $slug
799 - */
800 - function fs_echo( $key, $slug = 'freemius' ) {
801 - echo fs_text( $key, $slug );
802 - }
803 -
804 - /**
805 - * Output an inline translated text.
806 - *
807 - * @author Vova Feldman (@svovaf)
808 - * @since 1.2.3
809 - *
810 - * @param string $text Translatable string.
811 - * @param string $key String key for overrides.
812 - * @param string $slug Module slug for overrides.
813 - */
814 - function fs_echo_inline( $text, $key = '', $slug = 'freemius' ) {
815 - echo _fs_text_inline( $text, $key, $slug );
816 - }
817 -
818 - /**
819 - * Output an inline translated text with a context.
820 - *
821 - * @author Vova Feldman (@svovaf)
822 - * @since 1.2.3
823 - *
824 - * @param string $text Translatable string.
825 - * @param string $context Context information for the translators.
826 - * @param string $key String key for overrides.
827 - * @param string $slug Module slug for overrides.
828 - */
829 - function fs_echo_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
830 - echo _fs_text_x_inline( $text, $context, $key, $slug );
831 - }
832 1099 }
833 1100
834 1101 if ( ! function_exists( 'fs_esc_attr' ) ) {
835 1102 /**
@@ -963,9 +1230,9 @@
963 1230 * @param string $context Context information for the translators.
964 1231 * @param string $key String key for overrides.
965 1232 * @param string $slug Module slug for overrides.
966 1233 *
967 - * @return string
1234 + * @return void
968 1235 */
969 1236 function fs_esc_js_echo_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
970 1237 echo esc_js( _fs_text_x_inline( $text, $context, $key, $slug ) );
971 1238 }
@@ -1114,5 +1381,125 @@
1114 1381 echo esc_html( _fs_text_inline( $text, $key, $slug ) );
1115 1382 }
1116 1383 }
1117 1384
1118 -#endregion
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 + }