1
|
|
|
<?php |
|
|
|
|
2
|
|
|
/** |
3
|
|
|
* @package Freemius |
4
|
|
|
* @copyright Copyright (c) 2015, Freemius, Inc. |
5
|
|
|
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License |
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
|
|
|
* @var string |
51
|
|
|
*/ |
52
|
|
|
protected $_slug; |
53
|
|
|
/** |
54
|
|
|
* @var array |
55
|
|
|
*/ |
56
|
|
|
protected $_data; |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* @var FS_Plugin_Manager[] |
60
|
|
|
*/ |
61
|
|
|
private static $_instances = array(); |
62
|
|
|
/** |
63
|
|
|
* @var FS_Logger |
64
|
|
|
*/ |
65
|
|
|
protected $_logger; |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* @param string $id |
69
|
|
|
* @param string $slug |
70
|
|
|
* |
71
|
|
|
* @return FS_Key_Value_Storage |
72
|
|
|
*/ |
73
|
|
|
static function instance( $id, $slug ) { |
|
|
|
|
74
|
|
|
$key = $id . ':' . $slug; |
75
|
|
|
if ( ! isset( self::$_instances[ $key ] ) ) { |
76
|
|
|
self::$_instances[ $key ] = new FS_Key_Value_Storage( $id, $slug ); |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
return self::$_instances[ $key ]; |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
protected function __construct( $id, $slug ) { |
83
|
|
|
$this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $slug . '_' . $id, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); |
84
|
|
|
|
85
|
|
|
$this->_slug = $slug; |
86
|
|
|
$this->_id = $id; |
87
|
|
|
$this->load(); |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
protected function get_option_manager() { |
91
|
|
|
return FS_Option_Manager::get_manager( WP_FS__ACCOUNTS_OPTION_NAME, true ); |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
protected function get_all_data() { |
95
|
|
|
return $this->get_option_manager()->get_option( $this->_id, array() ); |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* Load plugin data from local DB. |
100
|
|
|
* |
101
|
|
|
* @author Vova Feldman (@svovaf) |
102
|
|
|
* @since 1.0.7 |
103
|
|
|
*/ |
104
|
|
|
function load() { |
|
|
|
|
105
|
|
|
$all_plugins_data = $this->get_all_data(); |
106
|
|
|
$this->_data = isset( $all_plugins_data[ $this->_slug ] ) ? |
107
|
|
|
$all_plugins_data[ $this->_slug ] : |
108
|
|
|
array(); |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
/** |
112
|
|
|
* @author Vova Feldman (@svovaf) |
113
|
|
|
* @since 1.0.7 |
114
|
|
|
* |
115
|
|
|
* @param string $key |
116
|
|
|
* @param mixed $value |
117
|
|
|
* @param bool $flush |
118
|
|
|
*/ |
119
|
|
|
function store( $key, $value, $flush = true ) { |
|
|
|
|
120
|
|
|
if ( $this->_logger->is_on() ) { |
121
|
|
|
$this->_logger->entrance( $key . ' = ' . var_export( $value, true ) ); |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
if ( array_key_exists( $key, $this->_data ) && $value === $this->_data[ $key ] ) { |
125
|
|
|
// No need to store data if the value wasn't changed. |
126
|
|
|
return; |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
$all_data = $this->get_all_data(); |
130
|
|
|
|
131
|
|
|
$this->_data[ $key ] = $value; |
132
|
|
|
|
133
|
|
|
$all_data[ $this->_slug ] = $this->_data; |
134
|
|
|
|
135
|
|
|
$options_manager = $this->get_option_manager(); |
136
|
|
|
$options_manager->set_option( $this->_id, $all_data, $flush ); |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
/** |
140
|
|
|
* @author Vova Feldman (@svovaf) |
141
|
|
|
* @since 1.0.7 |
142
|
|
|
* |
143
|
|
|
* @param bool $store |
144
|
|
|
* @param string[] $exceptions Set of keys to keep and not clear. |
145
|
|
|
*/ |
146
|
|
|
function clear_all( $store = true, $exceptions = array() ) { |
|
|
|
|
147
|
|
|
$new_data = array(); |
148
|
|
|
foreach ( $exceptions as $key ) { |
149
|
|
|
if ( isset( $this->_data[ $key ] ) ) { |
150
|
|
|
$new_data[ $key ] = $this->_data[ $key ]; |
151
|
|
|
} |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
$this->_data = $new_data; |
155
|
|
|
|
156
|
|
|
if ( $store ) { |
157
|
|
|
$all_data = $this->get_all_data(); |
158
|
|
|
$all_data[ $this->_slug ] = $this->_data; |
159
|
|
|
$options_manager = $this->get_option_manager(); |
160
|
|
|
$options_manager->set_option( $this->_id, $all_data, true ); |
161
|
|
|
} |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
/** |
165
|
|
|
* Delete key-value storage. |
166
|
|
|
* |
167
|
|
|
* @author Vova Feldman (@svovaf) |
168
|
|
|
* @since 1.0.9 |
169
|
|
|
*/ |
170
|
|
|
function delete() { |
|
|
|
|
171
|
|
|
$this->_data = array(); |
172
|
|
|
|
173
|
|
|
$all_data = $this->get_all_data(); |
174
|
|
|
unset( $all_data[ $this->_slug ] ); |
175
|
|
|
$options_manager = $this->get_option_manager(); |
176
|
|
|
$options_manager->set_option( $this->_id, $all_data, true ); |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
/** |
180
|
|
|
* @author Vova Feldman (@svovaf) |
181
|
|
|
* @since 1.0.7 |
182
|
|
|
* |
183
|
|
|
* @param string $key |
184
|
|
|
* @param bool $store |
185
|
|
|
*/ |
186
|
|
|
function remove( $key, $store = true ) { |
|
|
|
|
187
|
|
|
if ( ! array_key_exists( $key, $this->_data ) ) { |
188
|
|
|
return; |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
unset( $this->_data[ $key ] ); |
192
|
|
|
|
193
|
|
|
if ( $store ) { |
194
|
|
|
$all_data = $this->get_all_data(); |
195
|
|
|
$all_data[ $this->_slug ] = $this->_data; |
196
|
|
|
$options_manager = $this->get_option_manager(); |
197
|
|
|
$options_manager->set_option( $this->_id, $all_data, true ); |
198
|
|
|
} |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
/** |
202
|
|
|
* @author Vova Feldman (@svovaf) |
203
|
|
|
* @since 1.0.7 |
204
|
|
|
* |
205
|
|
|
* @param string $key |
206
|
|
|
* @param mixed $default |
207
|
|
|
* |
208
|
|
|
* @return bool|\FS_Plugin |
209
|
|
|
*/ |
210
|
|
|
function get( $key, $default = false ) { |
|
|
|
|
211
|
|
|
return array_key_exists( $key, $this->_data ) ? |
212
|
|
|
$this->_data[ $key ] : |
213
|
|
|
$default; |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
|
217
|
|
|
/* ArrayAccess + Magic Access (better for refactoring) |
218
|
|
|
-----------------------------------------------------------------------------------*/ |
219
|
|
|
function __set( $k, $v ) { |
|
|
|
|
220
|
|
|
$this->store( $k, $v ); |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
function __isset( $k ) { |
|
|
|
|
224
|
|
|
return array_key_exists( $k, $this->_data ); |
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
function __unset( $k ) { |
|
|
|
|
228
|
|
|
$this->remove( $k ); |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
function __get( $k ) { |
|
|
|
|
232
|
|
|
return $this->get( $k, null ); |
233
|
|
|
} |
234
|
|
|
|
235
|
|
|
function offsetSet( $k, $v ) { |
|
|
|
|
236
|
|
|
if ( is_null( $k ) ) { |
237
|
|
|
throw new Exception( 'Can\'t append value to request params.' ); |
238
|
|
|
} else { |
239
|
|
|
$this->{$k} = $v; |
240
|
|
|
} |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
function offsetExists( $k ) { |
|
|
|
|
244
|
|
|
return array_key_exists( $k, $this->_data ); |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
function offsetUnset( $k ) { |
|
|
|
|
248
|
|
|
unset( $this->$k ); |
249
|
|
|
} |
250
|
|
|
|
251
|
|
|
function offsetGet( $k ) { |
|
|
|
|
252
|
|
|
return $this->get( $k, null ); |
253
|
|
|
} |
254
|
|
|
|
255
|
|
|
/** |
256
|
|
|
* (PHP 5 >= 5.0.0)<br/> |
257
|
|
|
* Return the current element |
258
|
|
|
* |
259
|
|
|
* @link http://php.net/manual/en/iterator.current.php |
260
|
|
|
* @return mixed Can return any type. |
261
|
|
|
*/ |
262
|
|
|
public function current() { |
263
|
|
|
return current( $this->_data ); |
264
|
|
|
} |
265
|
|
|
|
266
|
|
|
/** |
267
|
|
|
* (PHP 5 >= 5.0.0)<br/> |
268
|
|
|
* Move forward to next element |
269
|
|
|
* |
270
|
|
|
* @link http://php.net/manual/en/iterator.next.php |
271
|
|
|
* @return void Any returned value is ignored. |
272
|
|
|
*/ |
273
|
|
|
public function next() { |
274
|
|
|
next( $this->_data ); |
275
|
|
|
} |
276
|
|
|
|
277
|
|
|
/** |
278
|
|
|
* (PHP 5 >= 5.0.0)<br/> |
279
|
|
|
* Return the key of the current element |
280
|
|
|
* |
281
|
|
|
* @link http://php.net/manual/en/iterator.key.php |
282
|
|
|
* @return mixed scalar on success, or null on failure. |
283
|
|
|
*/ |
284
|
|
|
public function key() { |
285
|
|
|
return key( $this->_data ); |
286
|
|
|
} |
287
|
|
|
|
288
|
|
|
/** |
289
|
|
|
* (PHP 5 >= 5.0.0)<br/> |
290
|
|
|
* Checks if current position is valid |
291
|
|
|
* |
292
|
|
|
* @link http://php.net/manual/en/iterator.valid.php |
293
|
|
|
* @return boolean The return value will be casted to boolean and then evaluated. |
294
|
|
|
* Returns true on success or false on failure. |
295
|
|
|
*/ |
296
|
|
|
public function valid() { |
297
|
|
|
$key = key( $this->_data ); |
298
|
|
|
|
299
|
|
|
return ( $key !== null && $key !== false ); |
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
/** |
303
|
|
|
* (PHP 5 >= 5.0.0)<br/> |
304
|
|
|
* Rewind the Iterator to the first element |
305
|
|
|
* |
306
|
|
|
* @link http://php.net/manual/en/iterator.rewind.php |
307
|
|
|
* @return void Any returned value is ignored. |
308
|
|
|
*/ |
309
|
|
|
public function rewind() { |
310
|
|
|
reset( $this->_data ); |
311
|
|
|
} |
312
|
|
|
|
313
|
|
|
/** |
314
|
|
|
* (PHP 5 >= 5.1.0)<br/> |
315
|
|
|
* Count elements of an object |
316
|
|
|
* |
317
|
|
|
* @link http://php.net/manual/en/countable.count.php |
318
|
|
|
* @return int The custom count as an integer. |
319
|
|
|
* </p> |
320
|
|
|
* <p> |
321
|
|
|
* The return value is cast to an integer. |
322
|
|
|
*/ |
323
|
|
|
public function count() { |
324
|
|
|
return count( $this->_data ); |
325
|
|
|
} |
326
|
|
|
} |
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.