PluginProbe ʕ •ᴥ•ʔ
Code Manager / 1.0.20
Code Manager v1.0.20
1.0.48 1.0.47 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.19 1.0.2 1.0.20 1.0.21 1.0.22 1.0.23 1.0.24 1.0.25 1.0.26 1.0.27 1.0.28 1.0.3 1.0.30 1.0.31 1.0.32 1.0.33 1.0.34 1.0.35 1.0.36 1.0.37 1.0.38 1.0.39 1.0.4 1.0.40 1.0.41 1.0.42 1.0.43 1.0.44 1.0.45 1.0.46 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9
code-manager / freemius / includes / managers / class-fs-permission-manager.php
code-manager / freemius / includes / managers Last commit date
class-fs-admin-menu-manager.php 3 years ago class-fs-admin-notice-manager.php 3 years ago class-fs-cache-manager.php 3 years ago class-fs-clone-manager.php 3 years ago class-fs-gdpr-manager.php 3 years ago class-fs-key-value-storage.php 3 years ago class-fs-license-manager.php 3 years ago class-fs-option-manager.php 3 years ago class-fs-permission-manager.php 3 years ago class-fs-plan-manager.php 3 years ago class-fs-plugin-manager.php 3 years ago index.php 3 years ago
class-fs-permission-manager.php
698 lines
1 <?php
2 /**
3 * @package Freemius
4 * @copyright Copyright (c) 2022, Freemius, Inc.
5 * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
6 * @since 2.5.1
7 */
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 /**
14 * This class is responsible for managing the user permissions.
15 *
16 * @author Vova Feldman (@svovaf)
17 * @since 2.5.1
18 */
19 class FS_Permission_Manager {
20 /**
21 * @var Freemius
22 */
23 private $_fs;
24 /**
25 * @var FS_Storage
26 */
27 private $_storage;
28
29 /**
30 * @var array<number,self>
31 */
32 private static $_instances = array();
33
34 const PERMISSION_USER = 'user';
35 const PERMISSION_SITE = 'site';
36 const PERMISSION_EVENTS = 'events';
37 const PERMISSION_ESSENTIALS = 'essentials';
38 const PERMISSION_DIAGNOSTIC = 'diagnostic';
39 const PERMISSION_EXTENSIONS = 'extensions';
40 const PERMISSION_NEWSLETTER = 'newsletter';
41
42 /**
43 * @param Freemius $fs
44 *
45 * @return self
46 */
47 static function instance( Freemius $fs ) {
48 $id = $fs->get_id();
49
50 if ( ! isset( self::$_instances[ $id ] ) ) {
51 self::$_instances[ $id ] = new self( $fs );
52 }
53
54 return self::$_instances[ $id ];
55 }
56
57 /**
58 * @param Freemius $fs
59 */
60 protected function __construct( Freemius $fs ) {
61 $this->_fs = $fs;
62 $this->_storage = FS_Storage::instance( $fs->get_module_type(), $fs->get_slug() );
63 }
64
65 /**
66 * @return string[]
67 */
68 static function get_all_permission_ids() {
69 return array(
70 self::PERMISSION_USER,
71 self::PERMISSION_SITE,
72 self::PERMISSION_EVENTS,
73 self::PERMISSION_ESSENTIALS,
74 self::PERMISSION_DIAGNOSTIC,
75 self::PERMISSION_EXTENSIONS,
76 self::PERMISSION_NEWSLETTER,
77 );
78 }
79
80 /**
81 * @return string[]
82 */
83 static function get_api_managed_permission_ids() {
84 return array(
85 self::PERMISSION_USER,
86 self::PERMISSION_SITE,
87 self::PERMISSION_EXTENSIONS,
88 );
89 }
90
91 /**
92 * @param string $permission
93 *
94 * @return bool
95 */
96 static function is_supported_permission( $permission ) {
97 return in_array( $permission, self::get_all_permission_ids() );
98 }
99
100 /**
101 * @param bool $is_license_activation
102 * @param array[] $extra_permissions
103 *
104 * @return array[]
105 */
106 function get_permissions( $is_license_activation, array $extra_permissions = array() ) {
107 return $is_license_activation ?
108 $this->get_license_activation_permissions( $extra_permissions ) :
109 $this->get_opt_in_permissions( $extra_permissions );
110 }
111
112 #--------------------------------------------------------------------------------
113 #region Opt-In Permissions
114 #--------------------------------------------------------------------------------
115
116 /**
117 * @param array[] $extra_permissions
118 *
119 * @return array[]
120 */
121 function get_opt_in_permissions(
122 array $extra_permissions = array(),
123 $load_default_from_storage = false,
124 $is_optional = false
125 ) {
126 $permissions = array_merge(
127 $this->get_opt_in_required_permissions( $load_default_from_storage ),
128 $this->get_opt_in_optional_permissions( $load_default_from_storage, $is_optional ),
129 $extra_permissions
130 );
131
132 return $this->get_sorted_permissions_by_priority( $permissions );
133 }
134
135 /**
136 * @param bool $load_default_from_storage
137 *
138 * @return array[]
139 */
140 function get_opt_in_required_permissions( $load_default_from_storage = false ) {
141 return array( $this->get_user_permission( $load_default_from_storage ) );
142 }
143
144 /**
145 * @param bool $load_default_from_storage
146 * @param bool $is_optional
147 *
148 * @return array[]
149 */
150 function get_opt_in_optional_permissions(
151 $load_default_from_storage = false,
152 $is_optional = false
153 ) {
154 return array_merge(
155 $this->get_opt_in_diagnostic_permissions( $load_default_from_storage, $is_optional ),
156 array( $this->get_extensions_permission(
157 false,
158 false,
159 $load_default_from_storage
160 ) )
161 );
162 }
163
164 /**
165 * @param bool $load_default_from_storage
166 * @param bool $is_optional
167 *
168 * @return array[]
169 */
170 function get_opt_in_diagnostic_permissions(
171 $load_default_from_storage = false,
172 $is_optional = false
173 ) {
174 // Alias.
175 $fs = $this->_fs;
176
177 $permissions = array();
178
179 $permissions[] = $this->get_permission(
180 self::PERMISSION_SITE,
181 'admin-links',
182 $fs->get_text_inline( 'View Basic Website Info', 'permissions-site' ),
183 $fs->get_text_inline( 'Homepage URL & title, WP & PHP versions, and site language', 'permissions-site_desc' ),
184 sprintf(
185 /* translators: %s: 'Plugin' or 'Theme' */
186 $fs->get_text_inline( 'To provide additional functionality that\'s relevant to your website, avoid WordPress or PHP version incompatibilities that can break your website, and recognize which languages & regions the %s should be translated and tailored to.', 'permissions-site_tooltip' ),
187 $fs->get_module_label( true )
188 ),
189 10,
190 $is_optional,
191 true,
192 $load_default_from_storage
193 );
194
195 $permissions[] = $this->get_permission(
196 self::PERMISSION_EVENTS,
197 'admin-' . ( $fs->is_plugin() ? 'plugins' : 'appearance' ),
198 sprintf( $fs->get_text_inline( 'View Basic %s Info', 'permissions-events' ), $fs->get_module_label() ),
199 sprintf(
200 /* translators: %s: 'Plugin' or 'Theme' */
201 $fs->get_text_inline( 'Current %s & SDK versions, and if active or uninstalled', 'permissions-events_desc' ),
202 $fs->get_module_label( true )
203 ),
204 '',
205 20,
206 $is_optional,
207 true,
208 $load_default_from_storage
209 );
210
211 return $permissions;
212 }
213
214 #endregion
215
216 #--------------------------------------------------------------------------------
217 #region License Activation Permissions
218 #--------------------------------------------------------------------------------
219
220 /**
221 * @param array[] $extra_permissions
222 *
223 * @return array[]
224 */
225 function get_license_activation_permissions(
226 array $extra_permissions = array(),
227 $include_optional_label = true
228 ) {
229 $permissions = array_merge(
230 $this->get_license_required_permissions(),
231 $this->get_license_optional_permissions( $include_optional_label ),
232 $extra_permissions
233 );
234
235 return $this->get_sorted_permissions_by_priority( $permissions );
236 }
237
238 /**
239 * @param bool $load_default_from_storage
240 *
241 * @return array[]
242 */
243 function get_license_required_permissions( $load_default_from_storage = false ) {
244 // Alias.
245 $fs = $this->_fs;
246
247 $permissions = array();
248
249 $permissions[] = $this->get_permission(
250 self::PERMISSION_ESSENTIALS,
251 'admin-links',
252 $fs->get_text_inline( 'View License Essentials', 'permissions-essentials' ),
253 $fs->get_text_inline(
254 sprintf(
255 /* translators: %s: 'Plugin' or 'Theme' */
256 'Homepage URL, %s version, SDK version',
257 $fs->get_module_label()
258 ),
259 'permissions-essentials_desc'
260 ),
261 sprintf(
262 /* translators: %s: 'Plugin' or 'Theme' */
263 $fs->get_text_inline( 'To let you manage & control where the license is activated and ensure %s security & feature updates are only delivered to websites you authorize.', 'permissions-essentials_tooltip' ),
264 $fs->get_module_label( true )
265 ),
266 10,
267 false,
268 true,
269 $load_default_from_storage
270 );
271
272 $permissions[] = $this->get_permission(
273 self::PERMISSION_EVENTS,
274 'admin-' . ( $fs->is_plugin() ? 'plugins' : 'appearance' ),
275 sprintf( $fs->get_text_inline( 'View %s State', 'permissions-events' ), $fs->get_module_label() ),
276 sprintf(
277 /* translators: %s: 'Plugin' or 'Theme' */
278 $fs->get_text_inline( 'Is active, deactivated, or uninstalled', 'permissions-events_desc-paid' ),
279 $fs->get_module_label( true )
280 ),
281 sprintf( $fs->get_text_inline( 'So you can reuse the license when the %s is no longer active.', 'permissions-events_tooltip' ), $fs->get_module_label( true ) ),
282 20,
283 false,
284 true,
285 $load_default_from_storage
286 );
287
288 return $permissions;
289 }
290
291 /**
292 * @return array[]
293 */
294 function get_license_optional_permissions(
295 $include_optional_label = false,
296 $load_default_from_storage = false
297 ) {
298 return array(
299 $this->get_diagnostic_permission( $include_optional_label, $load_default_from_storage ),
300 $this->get_extensions_permission( true, $include_optional_label, $load_default_from_storage ),
301 );
302 }
303
304 /**
305 * @param bool $include_optional_label
306 * @param bool $load_default_from_storage
307 *
308 * @return array
309 */
310 function get_diagnostic_permission(
311 $include_optional_label = false,
312 $load_default_from_storage = false
313 ) {
314 return $this->get_permission(
315 self::PERMISSION_DIAGNOSTIC,
316 'wordpress-alt',
317 $this->_fs->get_text_inline( 'View Diagnostic Info', 'permissions-diagnostic' ) . ( $include_optional_label ? ' (' . $this->_fs->get_text_inline( 'optional' ) . ')' : '' ),
318 $this->_fs->get_text_inline( 'WordPress & PHP versions, site language & title', 'permissions-diagnostic_desc' ),
319 sprintf(
320 /* translators: %s: 'Plugin' or 'Theme' */
321 $this->_fs->get_text_inline( 'To avoid breaking your website due to WordPress or PHP version incompatibilities, and recognize which languages & regions the %s should be translated and tailored to.', 'permissions-diagnostic_tooltip' ),
322 $this->_fs->get_module_label( true )
323 ),
324 25,
325 true,
326 true,
327 $load_default_from_storage
328 );
329 }
330
331 #endregion
332
333 #--------------------------------------------------------------------------------
334 #region Common Permissions
335 #--------------------------------------------------------------------------------
336
337 /**
338 * @param bool $is_license_activation
339 * @param bool $include_optional_label
340 * @param bool $load_default_from_storage
341 *
342 * @return array
343 */
344 function get_extensions_permission(
345 $is_license_activation,
346 $include_optional_label = false,
347 $load_default_from_storage = false
348 ) {
349 $is_on_by_default = ! $is_license_activation;
350
351 return $this->get_permission(
352 self::PERMISSION_EXTENSIONS,
353 'block-default',
354 $this->_fs->get_text_inline( 'View Plugins & Themes List', 'permissions-extensions' ) . ( $is_license_activation ? ( $include_optional_label ? ' (' . $this->_fs->get_text_inline( 'optional' ) . ')' : '' ) : '' ),
355 $this->_fs->get_text_inline( 'Names, slugs, versions, and if active or not', 'permissions-extensions_desc' ),
356 $this->_fs->get_text_inline( 'To ensure compatibility and avoid conflicts with your installed plugins and themes.', 'permissions-events_tooltip' ),
357 25,
358 true,
359 $is_on_by_default,
360 $load_default_from_storage
361 );
362 }
363
364 /**
365 * @param bool $load_default_from_storage
366 *
367 * @return array
368 */
369 function get_user_permission( $load_default_from_storage = false ) {
370 return $this->get_permission(
371 self::PERMISSION_USER,
372 'admin-users',
373 $this->_fs->get_text_inline( 'View Basic Profile Info', 'permissions-profile' ),
374 $this->_fs->get_text_inline( 'Your WordPress user\'s: first & last name, and email address', 'permissions-profile_desc' ),
375 $this->_fs->get_text_inline( 'Never miss important updates, get security warnings before they become public knowledge, and receive notifications about special offers and awesome new features.', 'permissions-profile_tooltip' ),
376 5,
377 false,
378 true,
379 $load_default_from_storage
380 );
381 }
382
383 #endregion
384
385 #--------------------------------------------------------------------------------
386 #region Optional Permissions
387 #--------------------------------------------------------------------------------
388
389 /**
390 * @return array[]
391 */
392 function get_newsletter_permission() {
393 return $this->get_permission(
394 self::PERMISSION_NEWSLETTER,
395 'email-alt',
396 $this->_fs->get_text_inline( 'Newsletter', 'permissions-newsletter' ),
397 $this->_fs->get_text_inline( 'Updates, announcements, marketing, no spam', 'permissions-newsletter_desc' ),
398 '',
399 15
400 );
401 }
402
403 #endregion
404
405 #--------------------------------------------------------------------------------
406 #region Permissions Storage
407 #--------------------------------------------------------------------------------
408
409 /**
410 * @param int|null $blog_id
411 *
412 * @return bool
413 */
414 function is_extensions_tracking_allowed( $blog_id = null ) {
415 return $this->is_permission_allowed( self::PERMISSION_EXTENSIONS, ! $this->_fs->is_premium(), $blog_id );
416 }
417
418 /**
419 * @param int|null $blog_id
420 *
421 * @return bool
422 */
423 function is_essentials_tracking_allowed( $blog_id = null ) {
424 return $this->is_permission_allowed( self::PERMISSION_ESSENTIALS, true, $blog_id );
425 }
426
427 /**
428 * @param bool $default
429 *
430 * @return bool
431 */
432 function is_diagnostic_tracking_allowed( $default = true ) {
433 return $this->_fs->is_premium() ?
434 $this->is_permission_allowed( self::PERMISSION_DIAGNOSTIC, $default ) :
435 $this->is_permission_allowed( self::PERMISSION_SITE, $default );
436 }
437
438 /**
439 * @param int|null $blog_id
440 *
441 * @return bool
442 */
443 function is_homepage_url_tracking_allowed( $blog_id = null ) {
444 return $this->is_permission_allowed( $this->get_site_permission_name(), true, $blog_id );
445 }
446
447 /**
448 * @param int|null $blog_id
449 *
450 * @return bool
451 */
452 function update_site_tracking( $is_enabled, $blog_id = null, $only_if_not_set = false ) {
453 $permissions = $this->get_site_tracking_permission_names();
454
455 $result = true;
456 foreach ( $permissions as $permission ) {
457 if ( ! $only_if_not_set || ! $this->is_permission_set( $permission, $blog_id ) ) {
458 $result = ( $result && $this->update_permission_tracking_flag( $permission, $is_enabled, $blog_id ) );
459 }
460 }
461
462 return $result;
463 }
464
465 /**
466 * @param string $permission
467 * @param bool $default
468 * @param int|null $blog_id
469 *
470 * @return bool
471 */
472 function is_permission_allowed( $permission, $default = false, $blog_id = null ) {
473 if ( ! self::is_supported_permission( $permission ) ) {
474 return $default;
475 }
476
477 return $this->is_permission( $permission, true, $blog_id );
478 }
479
480 /**
481 * @param string $permission
482 * @param bool $is_allowed
483 * @param int|null $blog_id
484 *
485 * @return bool
486 */
487 function is_permission( $permission, $is_allowed, $blog_id = null ) {
488 if ( ! self::is_supported_permission( $permission ) ) {
489 return false;
490 }
491
492 $tag = "is_{$permission}_tracking_allowed";
493
494 return ( $is_allowed === $this->_fs->apply_filters(
495 $tag,
496 $this->_storage->get(
497 $tag,
498 $this->get_permission_default( $permission ),
499 $blog_id,
500 FS_Storage::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED
501 )
502 ) );
503 }
504
505 /**
506 * @param string $permission
507 * @param int|null $blog_id
508 *
509 * @return bool
510 */
511 function is_permission_set( $permission, $blog_id = null ) {
512 $tag = "is_{$permission}_tracking_allowed";
513
514 $permission = $this->_storage->get(
515 $tag,
516 null,
517 $blog_id,
518 FS_Storage::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED
519 );
520
521 return is_bool( $permission );
522 }
523
524 /**
525 * @param string[] $permissions
526 * @param bool $is_allowed
527 *
528 * @return bool `true` if all given permissions are in sync with `$is_allowed`.
529 */
530 function are_permissions( $permissions, $is_allowed, $blog_id = null ) {
531 foreach ( $permissions as $permission ) {
532 if ( ! $this->is_permission( $permission, $is_allowed, $blog_id ) ) {
533 return false;
534 }
535 }
536
537 return true;
538 }
539
540 /**
541 * @param string $permission
542 * @param bool $is_enabled
543 * @param int|null $blog_id
544 *
545 * @return bool `false` if permission not supported or `$is_enabled` is not a boolean.
546 */
547 function update_permission_tracking_flag( $permission, $is_enabled, $blog_id = null ) {
548 if ( is_bool( $is_enabled ) && self::is_supported_permission( $permission ) ) {
549 $this->_storage->store(
550 "is_{$permission}_tracking_allowed",
551 $is_enabled,
552 $blog_id,
553 FS_Storage::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED
554 );
555
556 return true;
557 }
558
559 return false;
560 }
561
562 /**
563 * @param array<string,bool> $permissions
564 */
565 function update_permissions_tracking_flag( $permissions ) {
566 foreach ( $permissions as $permission => $is_enabled ) {
567 $this->update_permission_tracking_flag( $permission, $is_enabled );
568 }
569 }
570
571 #endregion
572
573
574 /**
575 * @param string $permission
576 *
577 * @return bool
578 */
579 function get_permission_default( $permission ) {
580 if (
581 $this->_fs->is_premium() &&
582 self::PERMISSION_EXTENSIONS === $permission
583 ) {
584 return false;
585 }
586
587 // All permissions except for the extensions in paid version are on by default when the user opts in to usage tracking.
588 return true;
589 }
590
591 /**
592 * @return string
593 */
594 function get_site_permission_name() {
595 return $this->_fs->is_premium() ?
596 self::PERMISSION_ESSENTIALS :
597 self::PERMISSION_SITE;
598 }
599
600 /**
601 * @return string[]
602 */
603 function get_site_tracking_permission_names() {
604 return $this->_fs->is_premium() ?
605 array(
606 FS_Permission_Manager::PERMISSION_ESSENTIALS,
607 FS_Permission_Manager::PERMISSION_EVENTS,
608 ) :
609 array( FS_Permission_Manager::PERMISSION_SITE );
610 }
611
612 #--------------------------------------------------------------------------------
613 #region Rendering
614 #--------------------------------------------------------------------------------
615
616 /**
617 * @param array $permission
618 */
619 function render_permission( array $permission ) {
620 fs_require_template( 'connect/permission.php', $permission );
621 }
622
623 /**
624 * @param array $permissions_group
625 */
626 function render_permissions_group( array $permissions_group ) {
627 $permissions_group[ 'fs' ] = $this->_fs;
628
629 fs_require_template( 'connect/permissions-group.php', $permissions_group );
630 }
631
632 function require_permissions_js() {
633 fs_require_once_template( 'js/permissions.php', $params );
634 }
635
636 #endregion
637
638 #--------------------------------------------------------------------------------
639 #region Helper Methods
640 #--------------------------------------------------------------------------------
641
642 /**
643 * @param string $id
644 * @param string $dashicon
645 * @param string $label
646 * @param string $desc
647 * @param string $tooltip
648 * @param int $priority
649 * @param bool $is_optional
650 * @param bool $is_on_by_default
651 * @param bool $load_from_storage
652 *
653 * @return array
654 */
655 private function get_permission(
656 $id,
657 $dashicon,
658 $label,
659 $desc,
660 $tooltip = '',
661 $priority = 10,
662 $is_optional = false,
663 $is_on_by_default = true,
664 $load_from_storage = false
665 ) {
666 $is_on = $load_from_storage ?
667 $this->is_permission_allowed( $id, $is_on_by_default ) :
668 $is_on_by_default;
669
670 return array(
671 'id' => $id,
672 'icon-class' => $this->_fs->apply_filters( "permission_{$id}_icon", "dashicons dashicons-{$dashicon}" ),
673 'label' => $this->_fs->apply_filters( "permission_{$id}_label", $label ),
674 'tooltip' => $this->_fs->apply_filters( "permission_{$id}_tooltip", $tooltip ),
675 'desc' => $this->_fs->apply_filters( "permission_{$id}_desc", $desc ),
676 'priority' => $this->_fs->apply_filters( "permission_{$id}_priority", $priority ),
677 'optional' => $is_optional,
678 'default' => $this->_fs->apply_filters( "permission_{$id}_default", $is_on ),
679 );
680 }
681
682 /**
683 * @param array $permissions
684 *
685 * @return array[]
686 */
687 private function get_sorted_permissions_by_priority( array $permissions ) {
688 // Allow filtering of the permissions list.
689 $permissions = $this->_fs->apply_filters( 'permission_list', $permissions );
690
691 // Sort by priority.
692 uasort( $permissions, 'fs_sort_by_priority' );
693
694 return $permissions;
695 }
696
697 #endregion
698 }