fooplugins /
foogallery
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
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
|
|||
| 2 | /** |
||
| 3 | * @package Freemius |
||
| 4 | * @copyright Copyright (c) 2015, Freemius, Inc. |
||
| 5 | * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3 |
||
| 6 | * @since 1.0.3 |
||
| 7 | */ |
||
| 8 | |||
| 9 | if ( ! defined( 'ABSPATH' ) ) { |
||
| 10 | exit; |
||
| 11 | } |
||
| 12 | |||
| 13 | /** |
||
| 14 | * 3-layer lazy options manager. |
||
| 15 | * layer 3: Memory |
||
| 16 | * layer 2: Cache (if there's any caching plugin and if WP_FS__DEBUG_SDK is FALSE) |
||
| 17 | * layer 1: Database (options table). All options stored as one option record in the DB to reduce number of DB |
||
| 18 | * queries. |
||
| 19 | * |
||
| 20 | * If load() is not explicitly called, starts as empty manager. Same thing about saving the data - you have to |
||
| 21 | * explicitly call store(). |
||
| 22 | * |
||
| 23 | * Class Freemius_Option_Manager |
||
| 24 | */ |
||
| 25 | class FS_Option_Manager { |
||
|
0 ignored issues
–
show
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...
|
|||
| 26 | /** |
||
| 27 | * @var string |
||
| 28 | */ |
||
| 29 | private $_id; |
||
| 30 | /** |
||
| 31 | * @var array|object |
||
| 32 | */ |
||
| 33 | private $_options; |
||
| 34 | /** |
||
| 35 | * @var FS_Logger |
||
| 36 | */ |
||
| 37 | private $_logger; |
||
| 38 | |||
| 39 | /** |
||
| 40 | * @since 2.0.0 |
||
| 41 | * @var int The ID of the blog that is associated with the current site level options. |
||
| 42 | */ |
||
| 43 | private $_blog_id = 0; |
||
| 44 | |||
| 45 | /** |
||
| 46 | * @since 2.0.0 |
||
| 47 | * @var bool |
||
| 48 | */ |
||
| 49 | private $_is_network_storage; |
||
| 50 | |||
| 51 | /** |
||
| 52 | * @var array[string]FS_Option_Manager { |
||
| 53 | * @key string |
||
| 54 | * @value FS_Option_Manager |
||
| 55 | * } |
||
| 56 | */ |
||
| 57 | private static $_MANAGERS = array(); |
||
| 58 | |||
| 59 | /** |
||
| 60 | * @author Vova Feldman (@svovaf) |
||
| 61 | * @since 1.0.3 |
||
| 62 | * |
||
| 63 | * @param string $id |
||
| 64 | * @param bool $load |
||
| 65 | * @param bool|int $network_level_or_blog_id Since 2.0.0 |
||
| 66 | */ |
||
| 67 | private function __construct( $id, $load = false, $network_level_or_blog_id = false ) { |
||
| 68 | $id = strtolower( $id ); |
||
| 69 | |||
| 70 | $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_opt_mngr_' . $id, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); |
||
| 71 | |||
| 72 | $this->_logger->entrance(); |
||
| 73 | $this->_logger->log( 'id = ' . $id ); |
||
| 74 | |||
| 75 | $this->_id = $id; |
||
| 76 | |||
| 77 | if ( is_multisite() ) { |
||
| 78 | $this->_is_network_storage = ( true === $network_level_or_blog_id ); |
||
| 79 | |||
| 80 | if ( is_numeric( $network_level_or_blog_id ) ) { |
||
| 81 | $this->_blog_id = $network_level_or_blog_id; |
||
|
0 ignored issues
–
show
It seems like
$network_level_or_blog_id can also be of type double or string. However, the property $_blog_id is declared as type integer. Maybe add an additional type check?
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly. For example, imagine you have a variable Either this assignment is in error or a type check should be added for that assignment. class Id
{
public $id;
public function __construct($id)
{
$this->id = $id;
}
}
class Account
{
/** @var Id $id */
public $id;
}
$account_id = false;
if (starsAreRight()) {
$account_id = new Id(42);
}
$account = new Account();
if ($account instanceof Id)
{
$account->id = $account_id;
}
Loading history...
|
|||
| 82 | } |
||
| 83 | } else { |
||
| 84 | $this->_is_network_storage = false; |
||
| 85 | } |
||
| 86 | |||
| 87 | if ( $load ) { |
||
| 88 | $this->load(); |
||
| 89 | } |
||
| 90 | } |
||
| 91 | |||
| 92 | /** |
||
| 93 | * @author Vova Feldman (@svovaf) |
||
| 94 | * @since 1.0.3 |
||
| 95 | * |
||
| 96 | * @param string $id |
||
| 97 | * @param bool $load |
||
| 98 | * @param bool|int $network_level_or_blog_id Since 2.0.0 |
||
| 99 | * |
||
| 100 | * @return FS_Option_Manager |
||
| 101 | */ |
||
| 102 | static function get_manager( $id, $load = false, $network_level_or_blog_id = false ) { |
||
|
0 ignored issues
–
show
|
|||
| 103 | $key = strtolower( $id ); |
||
| 104 | |||
| 105 | if ( is_multisite() ) { |
||
| 106 | if ( true === $network_level_or_blog_id ) { |
||
| 107 | $key .= ':ms'; |
||
| 108 | } else if ( is_numeric( $network_level_or_blog_id ) && $network_level_or_blog_id > 0 ) { |
||
| 109 | $key .= ":{$network_level_or_blog_id}"; |
||
| 110 | } else { |
||
| 111 | $network_level_or_blog_id = get_current_blog_id(); |
||
| 112 | |||
| 113 | $key .= ":{$network_level_or_blog_id}"; |
||
| 114 | } |
||
| 115 | } |
||
| 116 | |||
| 117 | if ( ! isset( self::$_MANAGERS[ $key ] ) ) { |
||
| 118 | self::$_MANAGERS[ $key ] = new FS_Option_Manager( $id, $load, $network_level_or_blog_id ); |
||
| 119 | } // If load required but not yet loaded, load. |
||
| 120 | else if ( $load && ! self::$_MANAGERS[ $key ]->is_loaded() ) { |
||
| 121 | self::$_MANAGERS[ $key ]->load(); |
||
| 122 | } |
||
| 123 | |||
| 124 | return self::$_MANAGERS[ $key ]; |
||
| 125 | } |
||
| 126 | |||
| 127 | /** |
||
| 128 | * @author Vova Feldman (@svovaf) |
||
| 129 | * @since 1.0.3 |
||
| 130 | * |
||
| 131 | * @param bool $flush |
||
| 132 | */ |
||
| 133 | function load( $flush = false ) { |
||
|
0 ignored issues
–
show
|
|||
| 134 | $this->_logger->entrance(); |
||
| 135 | |||
| 136 | $option_name = $this->get_option_manager_name(); |
||
| 137 | |||
| 138 | if ( $flush || ! isset( $this->_options ) ) { |
||
| 139 | if ( isset( $this->_options ) ) { |
||
| 140 | // Clear prev options. |
||
| 141 | $this->clear(); |
||
| 142 | } |
||
| 143 | |||
| 144 | $cache_group = $this->get_cache_group(); |
||
| 145 | |||
| 146 | if ( ! WP_FS__DEBUG_SDK ) { |
||
| 147 | |||
| 148 | $this->_options = wp_cache_get( |
||
| 149 | $option_name, |
||
| 150 | $cache_group |
||
| 151 | ); |
||
| 152 | } |
||
| 153 | |||
| 154 | $cached = true; |
||
| 155 | |||
| 156 | if ( empty( $this->_options ) ) { |
||
| 157 | if ( $this->_is_network_storage ) { |
||
| 158 | $this->_options = get_site_option( $option_name ); |
||
| 159 | } else if ( $this->_blog_id > 0 ) { |
||
| 160 | $this->_options = get_blog_option( $this->_blog_id, $option_name ); |
||
| 161 | } else { |
||
| 162 | $this->_options = get_option( $option_name ); |
||
| 163 | } |
||
| 164 | |||
| 165 | if ( is_string( $this->_options ) ) { |
||
| 166 | $this->_options = json_decode( $this->_options ); |
||
| 167 | } |
||
| 168 | |||
| 169 | // $this->_logger->info('get_option = ' . var_export($this->_options, true)); |
||
|
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
60% 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...
|
|||
| 170 | |||
| 171 | if ( false === $this->_options ) { |
||
| 172 | $this->clear(); |
||
| 173 | } |
||
| 174 | |||
| 175 | $cached = false; |
||
| 176 | } |
||
| 177 | |||
| 178 | if ( ! WP_FS__DEBUG_SDK && ! $cached ) { |
||
| 179 | // Set non encoded cache. |
||
| 180 | wp_cache_set( $option_name, $this->_options, $cache_group ); |
||
| 181 | } |
||
| 182 | } |
||
| 183 | } |
||
| 184 | |||
| 185 | /** |
||
| 186 | * @author Vova Feldman (@svovaf) |
||
| 187 | * @since 1.0.3 |
||
| 188 | * |
||
| 189 | * @return bool |
||
| 190 | */ |
||
| 191 | function is_loaded() { |
||
|
0 ignored issues
–
show
|
|||
| 192 | return isset( $this->_options ); |
||
| 193 | } |
||
| 194 | |||
| 195 | /** |
||
| 196 | * @author Vova Feldman (@svovaf) |
||
| 197 | * @since 1.0.3 |
||
| 198 | * |
||
| 199 | * @return bool |
||
| 200 | */ |
||
| 201 | function is_empty() { |
||
|
0 ignored issues
–
show
|
|||
| 202 | return ( $this->is_loaded() && false === $this->_options ); |
||
| 203 | } |
||
| 204 | |||
| 205 | /** |
||
| 206 | * @author Vova Feldman (@svovaf) |
||
| 207 | * @since 1.0.6 |
||
| 208 | * |
||
| 209 | * @param bool $flush |
||
| 210 | */ |
||
| 211 | function clear( $flush = false ) { |
||
|
0 ignored issues
–
show
|
|||
| 212 | $this->_logger->entrance(); |
||
| 213 | |||
| 214 | $this->_options = array(); |
||
| 215 | |||
| 216 | if ( $flush ) { |
||
| 217 | $this->store(); |
||
| 218 | } |
||
| 219 | } |
||
| 220 | |||
| 221 | /** |
||
| 222 | * Delete options manager from DB. |
||
| 223 | * |
||
| 224 | * @author Vova Feldman (@svovaf) |
||
| 225 | * @since 1.0.9 |
||
| 226 | */ |
||
| 227 | function delete() { |
||
|
0 ignored issues
–
show
|
|||
| 228 | $option_name = $this->get_option_manager_name(); |
||
| 229 | |||
| 230 | if ( $this->_is_network_storage ) { |
||
| 231 | delete_site_option( $option_name ); |
||
| 232 | } else if ( $this->_blog_id > 0 ) { |
||
| 233 | delete_blog_option( $this->_blog_id, $option_name ); |
||
| 234 | } else { |
||
| 235 | delete_option( $option_name ); |
||
| 236 | } |
||
| 237 | } |
||
| 238 | |||
| 239 | /** |
||
| 240 | * @author Vova Feldman (@svovaf) |
||
| 241 | * @since 1.0.6 |
||
| 242 | * |
||
| 243 | * @param string $option |
||
| 244 | * |
||
| 245 | * @return bool |
||
| 246 | */ |
||
| 247 | function has_option( $option ) { |
||
|
0 ignored issues
–
show
|
|||
| 248 | return array_key_exists( $option, $this->_options ); |
||
| 249 | } |
||
| 250 | |||
| 251 | /** |
||
| 252 | * @author Vova Feldman (@svovaf) |
||
| 253 | * @since 1.0.3 |
||
| 254 | * |
||
| 255 | * @param string $option |
||
| 256 | * @param mixed $default |
||
| 257 | * |
||
| 258 | * @return mixed |
||
| 259 | */ |
||
| 260 | function get_option( $option, $default = null ) { |
||
|
0 ignored issues
–
show
|
|||
| 261 | $this->_logger->entrance( 'option = ' . $option ); |
||
| 262 | |||
| 263 | if ( ! $this->is_loaded() ) { |
||
| 264 | $this->load(); |
||
| 265 | } |
||
| 266 | |||
| 267 | if ( is_array( $this->_options ) ) { |
||
| 268 | $value = isset( $this->_options[ $option ] ) ? |
||
| 269 | $this->_options[ $option ] : |
||
| 270 | $default; |
||
| 271 | } else if ( is_object( $this->_options ) ) { |
||
| 272 | $value = isset( $this->_options->{$option} ) ? |
||
| 273 | $this->_options->{$option} : |
||
| 274 | $default; |
||
| 275 | } else { |
||
| 276 | $value = $default; |
||
| 277 | } |
||
| 278 | |||
| 279 | /** |
||
| 280 | * If it's an object, return a clone of the object, otherwise, |
||
| 281 | * external changes of the object will actually change the value |
||
| 282 | * of the object in the options manager which may lead to an unexpected |
||
| 283 | * behaviour and data integrity when a store() call is triggered. |
||
| 284 | * |
||
| 285 | * Example: |
||
| 286 | * $object1 = $options->get_option( 'object1' ); |
||
| 287 | * $object1->x = 123; |
||
| 288 | * |
||
| 289 | * $object2 = $options->get_option( 'object2' ); |
||
| 290 | * $object2->y = 'dummy'; |
||
| 291 | * |
||
| 292 | * $options->set_option( 'object2', $object2, true ); |
||
| 293 | * |
||
| 294 | * If we don't return a clone of option 'object1', setting 'object2' |
||
| 295 | * will also store the updated value of 'object1' which is quite not |
||
| 296 | * an expected behaviour. |
||
| 297 | * |
||
| 298 | * @author Vova Feldman |
||
| 299 | */ |
||
| 300 | return is_object( $value ) ? clone $value : $value; |
||
| 301 | } |
||
| 302 | |||
| 303 | /** |
||
| 304 | * @author Vova Feldman (@svovaf) |
||
| 305 | * @since 1.0.3 |
||
| 306 | * |
||
| 307 | * @param string $option |
||
| 308 | * @param mixed $value |
||
| 309 | * @param bool $flush |
||
| 310 | */ |
||
| 311 | function set_option( $option, $value, $flush = false ) { |
||
|
0 ignored issues
–
show
|
|||
| 312 | $this->_logger->entrance( 'option = ' . $option ); |
||
| 313 | |||
| 314 | if ( ! $this->is_loaded() ) { |
||
| 315 | $this->clear(); |
||
| 316 | } |
||
| 317 | |||
| 318 | /** |
||
| 319 | * If it's an object, store a clone of the object, otherwise, |
||
| 320 | * external changes of the object will actually change the value |
||
| 321 | * of the object in the options manager which may lead to an unexpected |
||
| 322 | * behaviour and data integrity when a store() call is triggered. |
||
| 323 | * |
||
| 324 | * Example: |
||
| 325 | * $object1 = new stdClass(); |
||
| 326 | * $object1->x = 123; |
||
| 327 | * |
||
| 328 | * $options->set_option( 'object1', $object1 ); |
||
| 329 | * |
||
| 330 | * $object1->x = 456; |
||
| 331 | * |
||
| 332 | * $options->set_option( 'object2', $object2, true ); |
||
| 333 | * |
||
| 334 | * If we don't set the option as a clone of option 'object1', setting 'object2' |
||
| 335 | * will also store the updated value of 'object1' ($object1->x = 456 instead of |
||
| 336 | * $object1->x = 123) which is quite not an expected behaviour. |
||
| 337 | * |
||
| 338 | * @author Vova Feldman |
||
| 339 | */ |
||
| 340 | $copy = is_object( $value ) ? clone $value : $value; |
||
| 341 | |||
| 342 | if ( is_array( $this->_options ) ) { |
||
| 343 | $this->_options[ $option ] = $copy; |
||
| 344 | } else if ( is_object( $this->_options ) ) { |
||
| 345 | $this->_options->{$option} = $copy; |
||
| 346 | } |
||
| 347 | |||
| 348 | if ( $flush ) { |
||
| 349 | $this->store(); |
||
| 350 | } |
||
| 351 | } |
||
| 352 | |||
| 353 | /** |
||
| 354 | * Unset option. |
||
| 355 | * |
||
| 356 | * @author Vova Feldman (@svovaf) |
||
| 357 | * @since 1.0.3 |
||
| 358 | * |
||
| 359 | * @param string $option |
||
| 360 | * @param bool $flush |
||
| 361 | */ |
||
| 362 | function unset_option( $option, $flush = false ) { |
||
|
0 ignored issues
–
show
|
|||
| 363 | $this->_logger->entrance( 'option = ' . $option ); |
||
| 364 | |||
| 365 | if ( is_array( $this->_options ) ) { |
||
| 366 | if ( ! isset( $this->_options[ $option ] ) ) { |
||
| 367 | return; |
||
| 368 | } |
||
| 369 | |||
| 370 | unset( $this->_options[ $option ] ); |
||
| 371 | |||
| 372 | } else if ( is_object( $this->_options ) ) { |
||
| 373 | if ( ! isset( $this->_options->{$option} ) ) { |
||
| 374 | return; |
||
| 375 | } |
||
| 376 | |||
| 377 | unset( $this->_options->{$option} ); |
||
| 378 | } |
||
| 379 | |||
| 380 | if ( $flush ) { |
||
| 381 | $this->store(); |
||
| 382 | } |
||
| 383 | } |
||
| 384 | |||
| 385 | /** |
||
| 386 | * Dump options to database. |
||
| 387 | * |
||
| 388 | * @author Vova Feldman (@svovaf) |
||
| 389 | * @since 1.0.3 |
||
| 390 | */ |
||
| 391 | function store() { |
||
|
0 ignored issues
–
show
|
|||
| 392 | $this->_logger->entrance(); |
||
| 393 | |||
| 394 | $option_name = $this->get_option_manager_name(); |
||
| 395 | |||
| 396 | if ( $this->_logger->is_on() ) { |
||
| 397 | $this->_logger->info( $option_name . ' = ' . var_export( $this->_options, true ) ); |
||
| 398 | } |
||
| 399 | |||
| 400 | // Update DB. |
||
| 401 | if ( $this->_is_network_storage ) { |
||
| 402 | update_site_option( $option_name, $this->_options ); |
||
| 403 | } else if ( $this->_blog_id > 0 ) { |
||
| 404 | update_blog_option( $this->_blog_id, $option_name, $this->_options ); |
||
| 405 | } else { |
||
| 406 | update_option( $option_name, $this->_options ); |
||
| 407 | } |
||
| 408 | |||
| 409 | if ( ! WP_FS__DEBUG_SDK ) { |
||
| 410 | wp_cache_set( $option_name, $this->_options, $this->get_cache_group() ); |
||
| 411 | } |
||
| 412 | } |
||
| 413 | |||
| 414 | /** |
||
| 415 | * Get options keys. |
||
| 416 | * |
||
| 417 | * @author Vova Feldman (@svovaf) |
||
| 418 | * @since 1.0.3 |
||
| 419 | * |
||
| 420 | * @return string[] |
||
| 421 | */ |
||
| 422 | function get_options_keys() { |
||
|
0 ignored issues
–
show
|
|||
| 423 | if ( is_array( $this->_options ) ) { |
||
| 424 | return array_keys( $this->_options ); |
||
| 425 | } else if ( is_object( $this->_options ) ) { |
||
| 426 | return array_keys( get_object_vars( $this->_options ) ); |
||
| 427 | } |
||
| 428 | |||
| 429 | return array(); |
||
| 430 | } |
||
| 431 | |||
| 432 | #-------------------------------------------------------------------------------- |
||
| 433 | #region Migration |
||
| 434 | #-------------------------------------------------------------------------------- |
||
| 435 | |||
| 436 | /** |
||
| 437 | * Migrate options from site level. |
||
| 438 | * |
||
| 439 | * @author Vova Feldman (@svovaf) |
||
| 440 | * @since 2.0.0 |
||
| 441 | */ |
||
| 442 | function migrate_to_network() { |
||
|
0 ignored issues
–
show
|
|||
| 443 | $site_options = FS_Option_Manager::get_manager($this->_id, true, false); |
||
| 444 | |||
| 445 | $options = is_object( $site_options->_options ) ? |
||
| 446 | get_object_vars( $site_options->_options ) : |
||
| 447 | $site_options->_options; |
||
| 448 | |||
| 449 | if ( ! empty( $options ) ) { |
||
| 450 | foreach ( $options as $key => $val ) { |
||
| 451 | $this->set_option( $key, $val, false ); |
||
| 452 | } |
||
| 453 | |||
| 454 | $this->store(); |
||
| 455 | } |
||
| 456 | } |
||
| 457 | |||
| 458 | #endregion |
||
| 459 | |||
| 460 | #-------------------------------------------------------------------------------- |
||
| 461 | #region Helper Methods |
||
| 462 | #-------------------------------------------------------------------------------- |
||
| 463 | |||
| 464 | /** |
||
| 465 | * @return string |
||
| 466 | */ |
||
| 467 | private function get_option_manager_name() { |
||
| 468 | return $this->_id; |
||
| 469 | } |
||
| 470 | |||
| 471 | /** |
||
| 472 | * @author Vova Feldman (@svovaf) |
||
| 473 | * @since 2.0.0 |
||
| 474 | * |
||
| 475 | * @return string |
||
| 476 | */ |
||
| 477 | private function get_cache_group() { |
||
| 478 | $group = WP_FS__SLUG; |
||
| 479 | |||
| 480 | if ( $this->_is_network_storage ) { |
||
| 481 | $group .= '_ms'; |
||
| 482 | } else if ( $this->_blog_id > 0 ) { |
||
| 483 | $group .= "_s{$this->_blog_id}"; |
||
| 484 | } |
||
| 485 | |||
| 486 | return $group; |
||
| 487 | } |
||
| 488 | |||
| 489 | #endregion |
||
| 490 | } |
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.