GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Issues (1881)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

freemius/includes/class-fs-storage.php (27 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 22 and the first side effect is on line 10.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
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.2.3
7
     */
8
9
    if ( ! defined( 'ABSPATH' ) ) {
10
        exit;
11
    }
12
13
    /**
14
     * Class FS_Storage
15
     *
16
     * A wrapper class for handling network level and single site level storage.
17
     *
18
     * @property bool   $is_network_activation
19
     * @property int    $network_install_blog_id
20
     * @property object $sync_cron
21
     */
22
    class FS_Storage {
0 ignored issues
show
Since you have declared the constructor as private, maybe you should also declare the class as final.
Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
23
        /**
24
         * @var FS_Storage[]
25
         */
26
        private static $_instances = array();
27
        /**
28
         * @var FS_Key_Value_Storage Site level storage.
29
         */
30
        private $_storage;
31
32
        /**
33
         * @var FS_Key_Value_Storage Network level storage.
34
         */
35
        private $_network_storage;
36
37
        /**
38
         * @var string
39
         */
40
        private $_module_type;
41
42
        /**
43
         * @var string
44
         */
45
        private $_module_slug;
46
47
        /**
48
         * @var int The ID of the blog that is associated with the current site level options.
49
         */
50
        private $_blog_id = 0;
51
52
        /**
53
         * @var bool
54
         */
55
        private $_is_multisite;
56
57
        /**
58
         * @var bool
59
         */
60
        private $_is_network_active = false;
61
62
        /**
63
         * @var bool
64
         */
65
        private $_is_delegated_connection = false;
66
67
        /**
68
         * @var array {
69
         * @key   string Option name.
70
         * @value int If 0 store on the network level. If 1, store on the network level only if module was network level activated. If 2, store on the network level only if network activated and NOT delegated the connection.
71
         * }
72
         */
73
        private static $_NETWORK_OPTIONS_MAP;
74
75
        /**
76
         * @author Leo Fajardo (@leorw)
77
         *
78
         * @param string $module_type
79
         * @param string $slug
80
         *
81
         * @return FS_Storage
82
         */
83
        static function instance( $module_type, $slug ) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
84
            $key = $module_type . ':' . $slug;
85
86
            if ( ! isset( self::$_instances[ $key ] ) ) {
87
                self::$_instances[ $key ] = new FS_Storage( $module_type, $slug );
88
            }
89
90
            return self::$_instances[ $key ];
91
        }
92
93
        /**
94
         * @author Leo Fajardo (@leorw)
95
         *
96
         * @param string $module_type
97
         * @param string $slug
98
         */
99
        private function __construct( $module_type, $slug ) {
100
            $this->_module_type  = $module_type;
101
            $this->_module_slug  = $slug;
102
            $this->_is_multisite = is_multisite();
103
104
            if ( $this->_is_multisite ) {
105
                $this->_blog_id         = get_current_blog_id();
106
                $this->_network_storage = FS_Key_Value_Storage::instance( $module_type . '_data', $slug, true );
107
            }
108
109
            $this->_storage = FS_Key_Value_Storage::instance( $module_type . '_data', $slug, $this->_blog_id );
110
        }
111
112
        /**
113
         * Tells this storage wrapper class that the context plugin is network active. This flag will affect how values
114
         * are retrieved/stored from/into the storage.
115
         *
116
         * @author Leo Fajardo (@leorw)
117
         *
118
         * @param bool $is_network_active
119
         * @param bool $is_delegated_connection
120
         */
121
        function set_network_active( $is_network_active = true, $is_delegated_connection = false ) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
122
            $this->_is_network_active       = $is_network_active;
123
            $this->_is_delegated_connection = $is_delegated_connection;
124
        }
125
126
        /**
127
         * Switch the context of the site level storage manager.
128
         *
129
         * @author Vova Feldman (@svovaf)
130
         * @since  2.0.0
131
         *
132
         * @param int $blog_id
133
         */
134
        function set_site_blog_context( $blog_id ) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
135
            $this->_storage = $this->get_site_storage( $blog_id );
136
            $this->_blog_id = $blog_id;
137
        }
138
139
        /**
140
         * @author Leo Fajardo (@leorw)
141
         *
142
         * @param string        $key
143
         * @param mixed         $value
144
         * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_BINARY_MAP).
145
         * @param bool          $flush
146
         */
147
        function store( $key, $value, $network_level_or_blog_id = null, $flush = true ) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
148
            if ( $this->should_use_network_storage( $key, $network_level_or_blog_id ) ) {
149
                $this->_network_storage->store( $key, $value, $flush );
150
            } else {
151
                $storage = $this->get_site_storage( $network_level_or_blog_id );
0 ignored issues
show
It seems like $network_level_or_blog_id defined by parameter $network_level_or_blog_id on line 147 can also be of type boolean or null; however, FS_Storage::get_site_storage() does only seem to accept integer, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
152
                $storage->store( $key, $value, $flush );
153
            }
154
        }
155
156
        /**
157
         * @author Leo Fajardo (@leorw)
158
         *
159
         * @param bool          $store
160
         * @param string[]      $exceptions Set of keys to keep and not clear.
161
         * @param int|null|bool $network_level_or_blog_id
162
         */
163
        function clear_all( $store = true, $exceptions = array(), $network_level_or_blog_id = null ) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
164
            if ( ! $this->_is_multisite ||
165
                 false === $network_level_or_blog_id ||
166
                 is_null( $network_level_or_blog_id ) ||
167
                 is_numeric( $network_level_or_blog_id )
168
            ) {
169
                $storage = $this->get_site_storage( $network_level_or_blog_id );
0 ignored issues
show
It seems like $network_level_or_blog_id defined by parameter $network_level_or_blog_id on line 163 can also be of type boolean or null; however, FS_Storage::get_site_storage() does only seem to accept integer, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
170
                $storage->clear_all( $store, $exceptions );
171
            }
172
173
            if ( $this->_is_multisite &&
174
                 ( true === $network_level_or_blog_id || is_null( $network_level_or_blog_id ) )
175
            ) {
176
                $this->_network_storage->clear_all( $store, $exceptions );
177
            }
178
        }
179
180
        /**
181
         * @author Leo Fajardo (@leorw)
182
         *
183
         * @param string        $key
184
         * @param bool          $store
185
         * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_BINARY_MAP).
186
         */
187
        function remove( $key, $store = true, $network_level_or_blog_id = null ) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
188
            if ( $this->should_use_network_storage( $key, $network_level_or_blog_id ) ) {
189
                $this->_network_storage->remove( $key, $store );
190
            } else {
191
                $storage = $this->get_site_storage( $network_level_or_blog_id );
0 ignored issues
show
It seems like $network_level_or_blog_id defined by parameter $network_level_or_blog_id on line 187 can also be of type boolean or null; however, FS_Storage::get_site_storage() does only seem to accept integer, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
192
                $storage->remove( $key, $store );
193
            }
194
        }
195
196
        /**
197
         * @author Leo Fajardo (@leorw)
198
         *
199
         * @param string        $key
200
         * @param mixed         $default
201
         * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_BINARY_MAP).
202
         *
203
         * @return mixed
204
         */
205
        function get( $key, $default = false, $network_level_or_blog_id = null ) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
206
            if ( $this->should_use_network_storage( $key, $network_level_or_blog_id ) ) {
207
                return $this->_network_storage->get( $key, $default );
208
            } else {
209
                $storage = $this->get_site_storage( $network_level_or_blog_id );
0 ignored issues
show
It seems like $network_level_or_blog_id defined by parameter $network_level_or_blog_id on line 205 can also be of type boolean or null; however, FS_Storage::get_site_storage() does only seem to accept integer, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
210
211
                return $storage->get( $key, $default );
212
            }
213
        }
214
215
        /**
216
         * Multisite activated:
217
         *      true:    Save network storage.
218
         *      int:     Save site specific storage.
219
         *      false|0: Save current site storage.
220
         *      null:    Save network and current site storage.
221
         * Site level activated:
222
         *               Save site storage.
223
         *
224
         * @author Vova Feldman (@svovaf)
225
         * @since  2.0.0
226
         *
227
         * @param bool|int|null $network_level_or_blog_id
228
         */
229
        function save( $network_level_or_blog_id = null ) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
230
            if ( $this->_is_network_active &&
231
                 ( true === $network_level_or_blog_id || is_null( $network_level_or_blog_id ) )
232
            ) {
233
                $this->_network_storage->save();
234
            }
235
236
            if ( ! $this->_is_network_active || true !== $network_level_or_blog_id ) {
237
                $storage = $this->get_site_storage( $network_level_or_blog_id );
0 ignored issues
show
It seems like $network_level_or_blog_id defined by parameter $network_level_or_blog_id on line 229 can also be of type boolean or null; however, FS_Storage::get_site_storage() does only seem to accept integer, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
238
                $storage->save();
239
            }
240
        }
241
242
        /**
243
         * @author Vova Feldman (@svovaf)
244
         * @since  2.0.0
245
         *
246
         * @return string
247
         */
248
        function get_module_slug() {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
249
            return $this->_module_slug;
250
        }
251
252
        /**
253
         * @author Vova Feldman (@svovaf)
254
         * @since  2.0.0
255
         *
256
         * @return string
257
         */
258
        function get_module_type() {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
259
            return $this->_module_type;
260
        }
261
262
        /**
263
         * Migration script to the new storage data structure that is network compatible.
264
         *
265
         * IMPORTANT:
266
         *      This method should be executed only after it is determined if this is a network
267
         *      level compatible product activation.
268
         *
269
         * @author Vova Feldman (@svovaf)
270
         * @since  2.0.0
271
         */
272
        function migrate_to_network() {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
273
            if ( ! $this->_is_multisite ) {
274
                return;
275
            }
276
277
            $updated = false;
278
279
            if ( ! isset( self::$_NETWORK_OPTIONS_MAP ) ) {
280
                self::load_network_options_map();
281
            }
282
283
            foreach ( self::$_NETWORK_OPTIONS_MAP as $option => $storage_level ) {
0 ignored issues
show
The expression self::$_NETWORK_OPTIONS_MAP of type null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
284
                if ( ! $this->is_multisite_option( $option ) ) {
285
                    continue;
286
                }
287
288
                if ( isset( $this->_storage->{$option} ) && ! isset( $this->_network_storage->{$option} ) ) {
289
                    // Migrate option to the network storage.
290
                    $this->_network_storage->store( $option, $this->_storage->{$option}, false );
291
292
                    /**
293
                     * Remove the option from site level storage.
294
                     *
295
                     * IMPORTANT:
296
                     *      The line below is intentionally commented since we want to preserve the option
297
                     *      on the site storage level for "downgrade compatibility". Basically, if the user
298
                     *      will downgrade to an older version of the plugin with the prev storage structure,
299
                     *      it will continue working.
300
                     *
301
                     * @todo After a few releases we can remove this.
302
                     */
303
//                    $this->_storage->remove($option, false);
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
304
305
                    $updated = true;
306
                }
307
            }
308
309
            if ( ! $updated ) {
310
                return;
311
            }
312
313
            // Update network level storage.
314
            $this->_network_storage->save();
315
//            $this->_storage->save();
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
316
        }
317
318
        #--------------------------------------------------------------------------------
319
        #region Helper Methods
320
        #--------------------------------------------------------------------------------
321
322
        /**
323
         * We don't want to load the map right away since it's not even needed in a non-MS environment.
324
         *
325
         * Example:
326
         * array(
327
         *      'option1' => 0, // Means that the option should always be stored on the network level.
328
         *      'option2' => 1, // Means that the option should be stored on the network level only when the module was network level activated.
329
         *      'option2' => 2, // Means that the option should be stored on the network level only when the module was network level activated AND the connection was NOT delegated.
330
         *      'option3' => 3, // Means that the option should always be stored on the site level.
331
         * )
332
         *
333
         * @author Vova Feldman (@svovaf)
334
         * @since  2.0.0
335
         */
336
        private static function load_network_options_map() {
337
            self::$_NETWORK_OPTIONS_MAP = array(
338
                // Network level options.
339
                'affiliate_application_data' => 0,
340
                'connectivity_test'          => 0,
341
                'handle_gdpr_admin_notice'   => 0,
342
                'has_trial_plan'             => 0,
343
                'install_sync_timestamp'     => 0,
344
                'install_sync_cron'          => 0,
345
                'is_anonymous_ms'            => 0,
346
                'is_on'                      => 0,
347
                'is_plugin_new_install'      => 0,
348
                'network_install_blog_id'    => 0,
349
                'pending_sites_info'         => 0,
350
                'plugin_last_version'        => 0,
351
                'plugin_main_file'           => 0,
352
                'plugin_version'             => 0,
353
                'sdk_downgrade_mode'         => 0,
354
                'sdk_last_version'           => 0,
355
                'sdk_upgrade_mode'           => 0,
356
                'sdk_version'                => 0,
357
                'sticky_optin_added_ms'      => 0,
358
                'subscriptions'              => 0,
359
                'sync_timestamp'             => 0,
360
                'sync_cron'                  => 0,
361
                'was_plugin_loaded'          => 0,
362
                'network_user_id'            => 0,
363
                'plugin_upgrade_mode'        => 0,
364
                'plugin_downgrade_mode'      => 0,
365
                'is_network_connected'       => 0,
366
                /**
367
                 * Special flag that is used when a super-admin upgrades to the new version of the SDK that
368
                 * supports network level integration, when the connection decision wasn't made for all of the
369
                 * sites in the network.
370
                 */
371
                'is_network_activation'      => 0,
372
373
                // When network activated, then network level.
374
                'install_timestamp'          => 1,
375
                'prev_is_premium'            => 1,
376
                'require_license_activation' => 1,
377
378
                // If not network activated OR delegated, then site level.
379
                'activation_timestamp'       => 2,
380
                'prev_user_id'               => 2,
381
                'sticky_optin_added'         => 2,
382
                'uninstall_reason'           => 2,
383
                'is_pending_activation'      => 2,
384
                'pending_license_key'        => 2,
385
386
                // Site level options.
387
                'is_anonymous'               => 3,
388
            );
389
        }
390
391
        /**
392
         * This method will and should only be executed when is_multisite() is true.
393
         *
394
         * @author Vova Feldman (@svovaf)
395
         * @since  2.0.0
396
         *
397
         * @param string $key
398
         *
399
         * @return bool|mixed
400
         */
401
        private function is_multisite_option( $key ) {
402
            if ( ! isset( self::$_NETWORK_OPTIONS_MAP ) ) {
403
                self::load_network_options_map();
404
            }
405
406
            if ( ! isset( self::$_NETWORK_OPTIONS_MAP[ $key ] ) ) {
407
                // Option not found -> use site level storage.
408
                return false;
409
            }
410
411
            if ( 0 === self::$_NETWORK_OPTIONS_MAP[ $key ] ) {
412
                // Option found and set to always use the network level storage on a multisite.
413
                return true;
414
            }
415
416
            if ( 3 === self::$_NETWORK_OPTIONS_MAP[ $key ] ) {
417
                // Option found and set to always use the site level storage on a multisite.
418
                return false;
419
            }
420
421
            if ( ! $this->_is_network_active ) {
422
                return false;
423
            }
424
425
            if ( 1 === self::$_NETWORK_OPTIONS_MAP[ $key ] ) {
426
                // Network activated.
427
                return true;
428
            }
429
430
            if ( 2 === self::$_NETWORK_OPTIONS_MAP[ $key ] && ! $this->_is_delegated_connection ) {
431
                // Network activated and not delegated.
432
                return true;
433
            }
434
435
            return false;
436
        }
437
438
        /**
439
         * @author Leo Fajardo
440
         *
441
         * @param string        $key
442
         * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_BINARY_MAP).
443
         *
444
         * @return bool
445
         */
446
        private function should_use_network_storage( $key, $network_level_or_blog_id = null ) {
447
            if ( ! $this->_is_multisite ) {
448
                // Not a multisite environment.
449
                return false;
450
            }
451
452
            if ( is_numeric( $network_level_or_blog_id ) ) {
453
                // Explicitly asked to use a specified blog storage.
454
                return false;
455
            }
456
457
            if ( is_bool( $network_level_or_blog_id ) ) {
458
                // Explicitly specified whether should use the network or blog level storage.
459
                return $network_level_or_blog_id;
460
            }
461
462
            // Determine which storage to use based on the option.
463
            return $this->is_multisite_option( $key );
464
        }
465
466
        /**
467
         * @author Vova Feldman (@svovaf)
468
         * @since  2.0.0
469
         *
470
         * @param int $blog_id
471
         *
472
         * @return \FS_Key_Value_Storage
473
         */
474
        private function get_site_storage( $blog_id = 0 ) {
475
            if ( ! is_numeric( $blog_id ) ||
476
                 $blog_id == $this->_blog_id ||
477
                 0 == $blog_id
478
            ) {
479
                return $this->_storage;
480
            }
481
482
            return FS_Key_Value_Storage::instance(
483
                $this->_module_type . '_data',
484
                $this->_storage->get_secondary_id(),
485
                $blog_id
0 ignored issues
show
$blog_id is of type integer|double|string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
486
            );
487
        }
488
489
        #endregion
490
491
        #--------------------------------------------------------------------------------
492
        #region Magic methods
493
        #--------------------------------------------------------------------------------
494
495
        function __set( $k, $v ) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
496
            if ( $this->should_use_network_storage( $k ) ) {
497
                $this->_network_storage->{$k} = $v;
498
            } else {
499
                $this->_storage->{$k} = $v;
500
            }
501
        }
502
503
        function __isset( $k ) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
504
            return $this->should_use_network_storage( $k ) ?
505
                isset( $this->_network_storage->{$k} ) :
506
                isset( $this->_storage->{$k} );
507
        }
508
509
        function __unset( $k ) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
510
            if ( $this->should_use_network_storage( $k ) ) {
511
                unset( $this->_network_storage->{$k} );
512
            } else {
513
                unset( $this->_storage->{$k} );
514
            }
515
        }
516
517
        function __get( $k ) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
518
            return $this->should_use_network_storage( $k ) ?
519
                $this->_network_storage->{$k} :
520
                $this->_storage->{$k};
521
        }
522
523
        #endregion
524
    }