PluginProbe ʕ •ᴥ•ʔ
Code Manager / 1.0.3
Code Manager v1.0.3
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-key-value-storage.php
code-manager / freemius / includes / managers Last commit date
class-fs-admin-menu-manager.php 5 years ago class-fs-admin-notice-manager.php 5 years ago class-fs-cache-manager.php 5 years ago class-fs-gdpr-manager.php 5 years ago class-fs-key-value-storage.php 5 years ago class-fs-license-manager.php 5 years ago class-fs-option-manager.php 5 years ago class-fs-plan-manager.php 5 years ago class-fs-plugin-manager.php 5 years ago index.php 5 years ago
class-fs-key-value-storage.php
392 lines
1 <?php
2 /**
3 * @package Freemius
4 * @copyright Copyright (c) 2015, Freemius, Inc.
5 * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
6 * @since 1.0.7
7 */
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 /**
14 * Class FS_Key_Value_Storage
15 *
16 * @property int $install_timestamp
17 * @property int $activation_timestamp
18 * @property int $sync_timestamp
19 * @property object $sync_cron
20 * @property int $install_sync_timestamp
21 * @property array $connectivity_test
22 * @property array $is_on
23 * @property object $trial_plan
24 * @property bool $has_trial_plan
25 * @property bool $trial_promotion_shown
26 * @property string $sdk_version
27 * @property string $sdk_last_version
28 * @property bool $sdk_upgrade_mode
29 * @property bool $sdk_downgrade_mode
30 * @property bool $plugin_upgrade_mode
31 * @property bool $plugin_downgrade_mode
32 * @property string $plugin_version
33 * @property string $plugin_last_version
34 * @property bool $is_plugin_new_install
35 * @property bool $was_plugin_loaded
36 * @property object $plugin_main_file
37 * @property bool $prev_is_premium
38 * @property array $is_anonymous
39 * @property bool $is_pending_activation
40 * @property bool $sticky_optin_added
41 * @property object $uninstall_reason
42 * @property object $subscription
43 */
44 class FS_Key_Value_Storage implements ArrayAccess, Iterator, Countable {
45 /**
46 * @var string
47 */
48 protected $_id;
49
50 /**
51 * @since 1.2.2
52 *
53 * @var string
54 */
55 protected $_secondary_id;
56
57 /**
58 * @since 2.0.0
59 * @var int The ID of the blog that is associated with the current site level options.
60 */
61 private $_blog_id = 0;
62
63 /**
64 * @since 2.0.0
65 * @var bool
66 */
67 private $_is_multisite_storage;
68
69 /**
70 * @var array
71 */
72 protected $_data;
73
74 /**
75 * @var FS_Key_Value_Storage[]
76 */
77 private static $_instances = array();
78
79 /**
80 * @var FS_Logger
81 */
82 protected $_logger;
83
84 /**
85 * @param string $id
86 * @param string $secondary_id
87 * @param bool $network_level_or_blog_id
88 *
89 * @return FS_Key_Value_Storage
90 */
91 static function instance( $id, $secondary_id, $network_level_or_blog_id = false ) {
92 $key = $id . ':' . $secondary_id;
93
94 if ( is_multisite() ) {
95 if ( true === $network_level_or_blog_id ) {
96 $key .= ':ms';
97 } else if ( is_numeric( $network_level_or_blog_id ) && $network_level_or_blog_id > 0 ) {
98 $key .= ":{$network_level_or_blog_id}";
99 } else {
100 $network_level_or_blog_id = get_current_blog_id();
101
102 $key .= ":{$network_level_or_blog_id}";
103 }
104 }
105
106 if ( ! isset( self::$_instances[ $key ] ) ) {
107 self::$_instances[ $key ] = new FS_Key_Value_Storage( $id, $secondary_id, $network_level_or_blog_id );
108 }
109
110 return self::$_instances[ $key ];
111 }
112
113 protected function __construct( $id, $secondary_id, $network_level_or_blog_id = false ) {
114 $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $secondary_id . '_' . $id, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
115
116 $this->_id = $id;
117 $this->_secondary_id = $secondary_id;
118
119 if ( is_multisite() ) {
120 $this->_is_multisite_storage = ( true === $network_level_or_blog_id );
121
122 if ( is_numeric( $network_level_or_blog_id ) ) {
123 $this->_blog_id = $network_level_or_blog_id;
124 }
125 } else {
126 $this->_is_multisite_storage = false;
127 }
128
129 $this->load();
130 }
131
132 protected function get_option_manager() {
133 return FS_Option_Manager::get_manager(
134 WP_FS__ACCOUNTS_OPTION_NAME,
135 true,
136 $this->_is_multisite_storage ?
137 true :
138 ( $this->_blog_id > 0 ? $this->_blog_id : false )
139 );
140 }
141
142 protected function get_all_data() {
143 return $this->get_option_manager()->get_option( $this->_id, array() );
144 }
145
146 /**
147 * Load plugin data from local DB.
148 *
149 * @author Vova Feldman (@svovaf)
150 * @since 1.0.7
151 */
152 function load() {
153 $all_plugins_data = $this->get_all_data();
154 $this->_data = isset( $all_plugins_data[ $this->_secondary_id ] ) ?
155 $all_plugins_data[ $this->_secondary_id ] :
156 array();
157 }
158
159 /**
160 * @author Vova Feldman (@svovaf)
161 * @since 1.0.7
162 *
163 * @param string $key
164 * @param mixed $value
165 * @param bool $flush
166 */
167 function store( $key, $value, $flush = true ) {
168 if ( $this->_logger->is_on() ) {
169 $this->_logger->entrance( $key . ' = ' . var_export( $value, true ) );
170 }
171
172 if ( array_key_exists( $key, $this->_data ) && $value === $this->_data[ $key ] ) {
173 // No need to store data if the value wasn't changed.
174 return;
175 }
176
177 $all_data = $this->get_all_data();
178
179 $this->_data[ $key ] = $value;
180
181 $all_data[ $this->_secondary_id ] = $this->_data;
182
183 $options_manager = $this->get_option_manager();
184 $options_manager->set_option( $this->_id, $all_data, $flush );
185 }
186
187 /**
188 * @author Vova Feldman (@svovaf)
189 * @since 2.0.0
190 */
191 function save() {
192 $this->get_option_manager()->store();
193 }
194
195 /**
196 * @author Vova Feldman (@svovaf)
197 * @since 1.0.7
198 *
199 * @param bool $store
200 * @param string[] $exceptions Set of keys to keep and not clear.
201 */
202 function clear_all( $store = true, $exceptions = array() ) {
203 $new_data = array();
204 foreach ( $exceptions as $key ) {
205 if ( isset( $this->_data[ $key ] ) ) {
206 $new_data[ $key ] = $this->_data[ $key ];
207 }
208 }
209
210 $this->_data = $new_data;
211
212 if ( $store ) {
213 $all_data = $this->get_all_data();
214 $all_data[ $this->_secondary_id ] = $this->_data;
215 $options_manager = $this->get_option_manager();
216 $options_manager->set_option( $this->_id, $all_data, true );
217 }
218 }
219
220 /**
221 * Delete key-value storage.
222 *
223 * @author Vova Feldman (@svovaf)
224 * @since 1.0.9
225 */
226 function delete() {
227 $this->_data = array();
228
229 $all_data = $this->get_all_data();
230 unset( $all_data[ $this->_secondary_id ] );
231 $options_manager = $this->get_option_manager();
232 $options_manager->set_option( $this->_id, $all_data, true );
233 }
234
235 /**
236 * @author Vova Feldman (@svovaf)
237 * @since 1.0.7
238 *
239 * @param string $key
240 * @param bool $store
241 */
242 function remove( $key, $store = true ) {
243 if ( ! array_key_exists( $key, $this->_data ) ) {
244 return;
245 }
246
247 unset( $this->_data[ $key ] );
248
249 if ( $store ) {
250 $all_data = $this->get_all_data();
251 $all_data[ $this->_secondary_id ] = $this->_data;
252 $options_manager = $this->get_option_manager();
253 $options_manager->set_option( $this->_id, $all_data, true );
254 }
255 }
256
257 /**
258 * @author Vova Feldman (@svovaf)
259 * @since 1.0.7
260 *
261 * @param string $key
262 * @param mixed $default
263 *
264 * @return bool|\FS_Plugin
265 */
266 function get( $key, $default = false ) {
267 return array_key_exists( $key, $this->_data ) ?
268 $this->_data[ $key ] :
269 $default;
270 }
271
272 /**
273 * @author Vova Feldman (@svovaf)
274 * @since 2.0.0
275 *
276 * @return string
277 */
278 function get_secondary_id() {
279 return $this->_secondary_id;
280 }
281
282
283 /* ArrayAccess + Magic Access (better for refactoring)
284 -----------------------------------------------------------------------------------*/
285 function __set( $k, $v ) {
286 $this->store( $k, $v );
287 }
288
289 function __isset( $k ) {
290 return array_key_exists( $k, $this->_data );
291 }
292
293 function __unset( $k ) {
294 $this->remove( $k );
295 }
296
297 function __get( $k ) {
298 return $this->get( $k, null );
299 }
300
301 function offsetSet( $k, $v ) {
302 if ( is_null( $k ) ) {
303 throw new Exception( 'Can\'t append value to request params.' );
304 } else {
305 $this->{$k} = $v;
306 }
307 }
308
309 function offsetExists( $k ) {
310 return array_key_exists( $k, $this->_data );
311 }
312
313 function offsetUnset( $k ) {
314 unset( $this->$k );
315 }
316
317 function offsetGet( $k ) {
318 return $this->get( $k, null );
319 }
320
321 /**
322 * (PHP 5 &gt;= 5.0.0)<br/>
323 * Return the current element
324 *
325 * @link http://php.net/manual/en/iterator.current.php
326 * @return mixed Can return any type.
327 */
328 public function current() {
329 return current( $this->_data );
330 }
331
332 /**
333 * (PHP 5 &gt;= 5.0.0)<br/>
334 * Move forward to next element
335 *
336 * @link http://php.net/manual/en/iterator.next.php
337 * @return void Any returned value is ignored.
338 */
339 public function next() {
340 next( $this->_data );
341 }
342
343 /**
344 * (PHP 5 &gt;= 5.0.0)<br/>
345 * Return the key of the current element
346 *
347 * @link http://php.net/manual/en/iterator.key.php
348 * @return mixed scalar on success, or null on failure.
349 */
350 public function key() {
351 return key( $this->_data );
352 }
353
354 /**
355 * (PHP 5 &gt;= 5.0.0)<br/>
356 * Checks if current position is valid
357 *
358 * @link http://php.net/manual/en/iterator.valid.php
359 * @return boolean The return value will be casted to boolean and then evaluated.
360 * Returns true on success or false on failure.
361 */
362 public function valid() {
363 $key = key( $this->_data );
364
365 return ( $key !== null && $key !== false );
366 }
367
368 /**
369 * (PHP 5 &gt;= 5.0.0)<br/>
370 * Rewind the Iterator to the first element
371 *
372 * @link http://php.net/manual/en/iterator.rewind.php
373 * @return void Any returned value is ignored.
374 */
375 public function rewind() {
376 reset( $this->_data );
377 }
378
379 /**
380 * (PHP 5 &gt;= 5.1.0)<br/>
381 * Count elements of an object
382 *
383 * @link http://php.net/manual/en/countable.count.php
384 * @return int The custom count as an integer.
385 * </p>
386 * <p>
387 * The return value is cast to an integer.
388 */
389 public function count() {
390 return count( $this->_data );
391 }
392 }