1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Admin Page Framework |
4
|
|
|
* |
5
|
|
|
* http://admin-page-framework.michaeluno.jp/ |
6
|
|
|
* Copyright (c) 2013-2020, Michael Uno; Licensed MIT |
7
|
|
|
* |
8
|
|
|
*/ |
9
|
|
|
|
10
|
|
|
/** |
11
|
|
|
* Provides utility methods dealing with the options table which use WordPress functions. |
12
|
|
|
* |
13
|
|
|
* @since 3.0.1 |
14
|
|
|
* @extends AdminPageFramework_Utility |
15
|
|
|
* @package AdminPageFramework/Utility |
16
|
|
|
* @internal |
17
|
|
|
*/ |
18
|
|
|
class AdminPageFramework_WPUtility_Option extends AdminPageFramework_WPUtility_File { |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* @since 3.8.23 |
22
|
|
|
* @return bool |
23
|
|
|
*/ |
24
|
|
|
static public function isNetworkAdmin() { |
25
|
|
|
if ( isset( self::$_bIsNetworkAdmin ) ) { |
26
|
|
|
return self::$_bIsNetworkAdmin; |
27
|
|
|
} |
28
|
|
|
self::$_bIsNetworkAdmin = is_network_admin(); |
29
|
|
|
return self::$_bIsNetworkAdmin; |
30
|
|
|
} |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* Deletes transient items by prefix of a transient key. |
34
|
|
|
* |
35
|
|
|
* @since 3.8.23 |
36
|
|
|
* @param array|string $asPrefixes |
37
|
|
|
* @retuen void |
38
|
|
|
*/ |
39
|
|
|
public static function cleanTransients( $asPrefixes=array( 'apf' ) ) { |
40
|
|
|
|
41
|
|
|
$_aPrefixes = self::getAsArray( $asPrefixes ); |
42
|
|
|
if ( self::isNetworkAdmin() ) { |
43
|
|
|
self::cleanTransientsForNetwork( $asPrefixes ); |
44
|
|
|
return; |
45
|
|
|
} |
46
|
|
|
/** |
47
|
|
|
* @var wpdb |
48
|
|
|
*/ |
49
|
|
|
$_oWPDB = $GLOBALS[ 'wpdb' ]; |
50
|
|
|
foreach( $_aPrefixes as $_sPrefix ) { |
51
|
|
|
$_sSQLQuery = "DELETE FROM `{$_oWPDB->options}` " |
52
|
|
|
. "WHERE `option_name` " |
53
|
|
|
. "LIKE ( '_transient_%{$_sPrefix}%' )"; // this also matches _transient_timeout_{prefix} |
54
|
|
|
$_oWPDB->query( $_sSQLQuery ); |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* @param $asPrefixes |
61
|
|
|
* @sicne 3.8.23 |
62
|
|
|
* @return void |
63
|
|
|
*/ |
64
|
|
|
public static function cleanTransientsForNetwork( $asPrefixes ) { |
65
|
|
|
$_aPrefixes = self::getAsArray( $asPrefixes ); |
66
|
|
|
/** |
67
|
|
|
* @var wpdb |
68
|
|
|
*/ |
69
|
|
|
$_oWPDB = $GLOBALS[ 'wpdb' ]; |
70
|
|
|
foreach( $_aPrefixes as $_sPrefix ) { |
71
|
|
|
$_sSQLQuery = "DELETE FROM `{$_oWPDB->sitemeta}` " |
72
|
|
|
. "WHERE " |
73
|
|
|
// this matches _site_transient_timeout_{...} as well |
74
|
|
|
. "`meta_key` LIKE ( '_site_transient_%{$_sPrefix}%' )"; |
75
|
|
|
$_oWPDB->query( $_sSQLQuery ); |
76
|
|
|
} |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* @param $sTransientKey |
81
|
|
|
* @param mixed $mDefault |
82
|
|
|
* @return array |
83
|
|
|
* @since 3.8.23 |
84
|
|
|
*/ |
85
|
|
|
static public function getTransientAsArray( $sTransientKey, $mDefault=null ) { |
86
|
|
|
return self::getAsArray( |
87
|
|
|
self::getTransient( $sTransientKey, $mDefault ) |
88
|
|
|
); |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* @param $sTransientKey |
93
|
|
|
* @param null $mDefault |
94
|
|
|
* @return array |
95
|
|
|
* @since 3.8.23 |
96
|
|
|
*/ |
97
|
|
|
static public function getTransientWithoutCacheAsArray( $sTransientKey, $mDefault=null ) { |
98
|
|
|
return self::getAsArray( |
99
|
|
|
self::getTransientWithoutCache( $sTransientKey, $mDefault ) |
100
|
|
|
); |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* Retrieve the transient value directly from the database. |
105
|
|
|
* |
106
|
|
|
* Similar to the built-in get_transient() method but this one does not use the stored cache in the memory. |
107
|
|
|
* Used for checking a lock in a sub-routine that should not run simultaneously. |
108
|
|
|
* |
109
|
|
|
* @param string $sTransientKey |
110
|
|
|
* @param mixed $mDefault |
111
|
|
|
* @sicne 3.8.23 |
112
|
|
|
* @return mixed|false `false` on failing to retrieve the transient value. |
113
|
|
|
*/ |
114
|
|
|
static public function getTransientWithoutCache( $sTransientKey, $mDefault=null ) { |
115
|
|
|
|
116
|
|
|
$sTransientKey = self::_getCompatibleTransientKey( $sTransientKey ); |
117
|
|
|
if ( self::isNetworkAdmin() ) { |
118
|
|
|
return self::getTransientWithoutCacheForNetwork( $sTransientKey, $mDefault ); |
119
|
|
|
} |
120
|
|
|
/** |
121
|
|
|
* @var wpdb $_oWPDB |
122
|
|
|
*/ |
123
|
|
|
$_oWPDB = $GLOBALS[ 'wpdb' ]; |
124
|
|
|
$_sTableName = $_oWPDB->options; |
125
|
|
|
$_sSQLQuery = "SELECT o1.option_value FROM `{$_sTableName}` o1" |
126
|
|
|
. " INNER JOIN `{$_sTableName}` o2" |
127
|
|
|
. " WHERE o1.option_name = %s " |
128
|
|
|
. " AND o2.option_name = %s " |
129
|
|
|
. " AND o2.option_value >= UNIX_TIMESTAMP() " // timeout value >= current time |
130
|
|
|
. " LIMIT 1"; |
131
|
|
|
$_mData = $_oWPDB->get_var( |
132
|
|
|
$_oWPDB->prepare( |
133
|
|
|
$_sSQLQuery, |
134
|
|
|
'_transient_' . $sTransientKey, |
135
|
|
|
'_transient_timeout_' . $sTransientKey |
136
|
|
|
) |
137
|
|
|
); |
138
|
|
|
return is_null( $_mData ) ? $mDefault : maybe_unserialize( $_mData ); |
139
|
|
|
|
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
/** |
143
|
|
|
* @param string $sTransientKey |
144
|
|
|
* @param mixed $mDefault |
145
|
|
|
* @since 3.8.23 |
146
|
|
|
* @return mixed |
147
|
|
|
*/ |
148
|
|
|
static public function getTransientWithoutCacheForNetwork($sTransientKey, $mDefault ) { |
149
|
|
|
|
150
|
|
|
/** |
151
|
|
|
* @var wpdb $_oWPDB |
152
|
|
|
*/ |
153
|
|
|
$_oWPDB = $GLOBALS[ 'wpdb' ]; |
154
|
|
|
$_sSQLQuery = "SELECT o1.meta_value FROM `{$_oWPDB->sitemeta}` o1" |
155
|
|
|
. " INNER JOIN `{$_oWPDB->sitemeta}` o2" |
156
|
|
|
. " WHERE o1.meta_key = %s " |
157
|
|
|
. " AND o2.meta_key = %s " |
158
|
|
|
. " AND o2.site_id = %d " |
159
|
|
|
. " AND o2.meta_value >= UNIX_TIMESTAMP() " // timeout value >= current time |
160
|
|
|
. " LIMIT 1"; |
161
|
|
|
$_mData = $_oWPDB->get_var( |
162
|
|
|
$_oWPDB->prepare( |
163
|
|
|
$_sSQLQuery, |
164
|
|
|
'_site_transient_' . $sTransientKey, |
165
|
|
|
'_site_transient_timeout_' . $sTransientKey, |
166
|
|
|
get_current_network_id() |
167
|
|
|
) |
168
|
|
|
); |
169
|
|
|
return is_null( $_mData ) ? $mDefault : maybe_unserialize( $_mData ); |
170
|
|
|
|
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
/** |
174
|
|
|
* Stores whether the page is loaded in the network admin or not. |
175
|
|
|
* @since 3.1.3 |
176
|
|
|
*/ |
177
|
|
|
static private $_bIsNetworkAdmin; |
178
|
|
|
|
179
|
|
|
/** |
180
|
|
|
* Deletes the given transient. |
181
|
|
|
* |
182
|
|
|
* @since 3.1.3 |
183
|
|
|
* @param string $sTransientKey |
184
|
|
|
* @return boolean True if the transient was deleted, false otherwise. |
185
|
|
|
*/ |
186
|
|
|
static public function deleteTransient( $sTransientKey ) { |
187
|
|
|
|
188
|
|
|
// Temporarily disable `$_wp_using_ext_object_cache`. |
189
|
|
|
global $_wp_using_ext_object_cache; |
190
|
|
|
$_bWpUsingExtObjectCacheTemp = $_wp_using_ext_object_cache; |
191
|
|
|
$_wp_using_ext_object_cache = false; |
192
|
|
|
|
193
|
|
|
$sTransientKey = self::_getCompatibleTransientKey( $sTransientKey ); |
194
|
|
|
$_aFunctionNames = array( |
195
|
|
|
0 => 'delete_transient', |
196
|
|
|
1 => 'delete_site_transient', |
197
|
|
|
); |
198
|
|
|
$_vTransient = $_aFunctionNames[ ( integer ) self::isNetworkAdmin() ]( $sTransientKey ); |
199
|
|
|
|
200
|
|
|
// reset prior value of $_wp_using_ext_object_cache |
201
|
|
|
$_wp_using_ext_object_cache = $_bWpUsingExtObjectCacheTemp; |
202
|
|
|
|
203
|
|
|
return $_vTransient; |
204
|
|
|
} |
205
|
|
|
/** |
206
|
|
|
* Retrieves the given transient. |
207
|
|
|
* |
208
|
|
|
* @since 3.1.3 |
209
|
|
|
* @since 3.1.5 Added the $vDefault parameter. |
210
|
|
|
* @param string $sTransientKey |
211
|
|
|
* @param mixed $vDefault |
212
|
|
|
* @return mixed |
213
|
|
|
*/ |
214
|
|
|
static public function getTransient( $sTransientKey, $vDefault=null ) { |
215
|
|
|
|
216
|
|
|
// Temporarily disable $_wp_using_ext_object_cache |
217
|
|
|
global $_wp_using_ext_object_cache; |
218
|
|
|
$_bWpUsingExtObjectCacheTemp = $_wp_using_ext_object_cache; |
219
|
|
|
$_wp_using_ext_object_cache = false; |
220
|
|
|
|
221
|
|
|
$sTransientKey = self::_getCompatibleTransientKey( $sTransientKey ); |
222
|
|
|
$_aFunctionNames = array( |
223
|
|
|
0 => 'get_transient', |
224
|
|
|
1 => 'get_site_transient', |
225
|
|
|
); |
226
|
|
|
$_vTransient = $_aFunctionNames[ ( integer ) self::isNetworkAdmin() ]( $sTransientKey ); |
227
|
|
|
|
228
|
|
|
// Restore the prior value of `$_wp_using_ext_object_cache`. |
229
|
|
|
$_wp_using_ext_object_cache = $_bWpUsingExtObjectCacheTemp; |
230
|
|
|
|
231
|
|
|
return null === $vDefault |
232
|
|
|
? $_vTransient |
233
|
|
|
: ( false === $_vTransient |
234
|
|
|
? $vDefault |
235
|
|
|
: $_vTransient |
236
|
|
|
); |
237
|
|
|
|
238
|
|
|
} |
239
|
|
|
/** |
240
|
|
|
* Sets the given transient. |
241
|
|
|
* |
242
|
|
|
* @since 3.1.3 |
243
|
|
|
* @return boolean True if set; otherwise, false. |
244
|
|
|
* @param string $sTransientKey |
245
|
|
|
* @param mixed $vValue |
246
|
|
|
* @param integer $iExpiration |
247
|
|
|
*/ |
248
|
|
|
static public function setTransient( $sTransientKey, $vValue, $iExpiration=0 ) { |
249
|
|
|
|
250
|
|
|
// Temporarily disable `$_wp_using_ext_object_cache`. |
251
|
|
|
global $_wp_using_ext_object_cache; |
252
|
|
|
$_bWpUsingExtObjectCacheTemp = $_wp_using_ext_object_cache; |
253
|
|
|
$_wp_using_ext_object_cache = false; |
254
|
|
|
|
255
|
|
|
$sTransientKey = self::_getCompatibleTransientKey( $sTransientKey ); |
256
|
|
|
$_aFunctionNames = array( |
257
|
|
|
0 => 'set_transient', |
258
|
|
|
1 => 'set_site_transient', |
259
|
|
|
); |
260
|
|
|
$_bIsSet = $_aFunctionNames[ ( integer ) self::isNetworkAdmin() ]( $sTransientKey, $vValue, $iExpiration ); |
261
|
|
|
|
262
|
|
|
// Restore the prior value of $_wp_using_ext_object_cache |
263
|
|
|
$_wp_using_ext_object_cache = $_bWpUsingExtObjectCacheTemp; |
264
|
|
|
|
265
|
|
|
return $_bIsSet; |
266
|
|
|
} |
267
|
|
|
/** |
268
|
|
|
* Returns a compatible transient key when it is too long. |
269
|
|
|
* |
270
|
|
|
* @since 3.5.9 |
271
|
|
|
* @since 3.8.23 Deprecated the second parameter. |
272
|
|
|
* @see https://codex.wordpress.org/Function_Reference/set_transient |
273
|
|
|
* @param string $sSubject The subject string to format. |
274
|
|
|
* @param integer $iDeprecated Deprecated. Previously, the allowed character length for the transient key: 40 for network and 45 for regular sites. |
275
|
|
|
* The method will replace last ending 33 characters if the given string in the first parameter exceeds the limit. So this number must be greater than 33. |
276
|
|
|
* @return string |
277
|
|
|
* @todo it is said as of WordPress 4.3, it will be 255 since the database table column type becomes VARCHAR(255). |
278
|
|
|
*/ |
279
|
|
|
static public function _getCompatibleTransientKey( $sSubject, $iDeprecated=null ) { |
280
|
|
|
|
281
|
|
|
$_iAllowedCharacterLength = isset( $iDeprecated ) |
282
|
|
|
? $iDeprecated |
283
|
|
|
: ( self::isNetworkAdmin() ? 40 : 45 ); |
284
|
|
|
|
285
|
|
|
// Check if the given string exceeds the length limit. |
286
|
|
|
if ( strlen( $sSubject ) <= $_iAllowedCharacterLength ) { |
287
|
|
|
return $sSubject; |
288
|
|
|
} |
289
|
|
|
|
290
|
|
|
// Otherwise, a too long option key is given. |
291
|
|
|
$_iPrefixLengthToKeep = $_iAllowedCharacterLength - 33; // _ + {md5 32 characters} |
292
|
|
|
$_sPrefixToKeep = substr( |
293
|
|
|
$sSubject, |
294
|
|
|
0, // start position |
295
|
|
|
$_iPrefixLengthToKeep - 1 // how many characters to extract |
296
|
|
|
); |
297
|
|
|
return $_sPrefixToKeep . '_' . md5( $sSubject ); |
298
|
|
|
|
299
|
|
|
} |
300
|
|
|
|
301
|
|
|
/** |
302
|
|
|
* Retrieves the saved option value from the options table with the given option key, field ID, and section ID by giving a function name. |
303
|
|
|
* |
304
|
|
|
* @since 3.0.1 |
305
|
|
|
* @since 3.3.0 Added the <var>$aAdditionalOptions</var> parameter. |
306
|
|
|
* @param string $sOptionKey the option key of the options table. |
307
|
|
|
* @param string|array $asKey the field id or the array that represents the key structure consisting of the section ID and the field ID. |
308
|
|
|
* @param mixed $vDefault the default value that will be returned if nothing is stored. |
309
|
|
|
* @param array $aAdditionalOptions an additional options array to merge with the options array. |
310
|
|
|
* @return mixed |
311
|
|
|
*/ |
312
|
|
|
static public function getOption( $sOptionKey, $asKey=null, $vDefault=null, array $aAdditionalOptions=array() ) { |
313
|
|
|
return self::_getOptionByFunctionName( $sOptionKey, $asKey, $vDefault, $aAdditionalOptions ); |
|
|
|
|
314
|
|
|
} |
315
|
|
|
/** |
316
|
|
|
* Retrieves the saved option value from the site options table with the given option key, field ID, and section ID by giving a function name. |
317
|
|
|
* |
318
|
|
|
* @since 3.1.0 |
319
|
|
|
* @since 3.5.3 Added the $aAdditionalOptions parameter. |
320
|
|
|
* @param string $sOptionKey the option key of the options table. |
321
|
|
|
* @param array|string $asKey the field id or the array that represents the key structure consisting of the section ID and the field ID. |
322
|
|
|
* @param mixed $vDefault the default value that will be returned if nothing is stored. |
323
|
|
|
* @param array $aAdditionalOptions an additional options array to merge with the options array. |
324
|
|
|
* @remark Used in the network admin area. |
325
|
|
|
* @return mixed |
326
|
|
|
*/ |
327
|
|
|
static public function getSiteOption( $sOptionKey, $asKey=null, $vDefault=null, array $aAdditionalOptions=array() ) { |
328
|
|
|
return self::_getOptionByFunctionName( $sOptionKey, $asKey, $vDefault, $aAdditionalOptions, 'get_site_option' ); |
|
|
|
|
329
|
|
|
} |
330
|
|
|
|
331
|
|
|
/** |
332
|
|
|
* Retrieves the saved option value from the options table |
333
|
|
|
* with the given option key, field ID, and section ID by giving a function name. |
334
|
|
|
* |
335
|
|
|
* @param $sOptionKey |
336
|
|
|
* @param null $asKey |
337
|
|
|
* @param null $vDefault |
338
|
|
|
* @param array $aAdditionalOptions |
339
|
|
|
* @param string $sFunctionName |
340
|
|
|
* @return mixed |
341
|
|
|
* @since 3.5.3 |
342
|
|
|
*/ |
343
|
|
|
static private function _getOptionByFunctionName( $sOptionKey, $asKey=null, $vDefault=null, array $aAdditionalOptions=array(), $sFunctionName='get_option' ) { |
344
|
|
|
|
345
|
|
|
// Entire options |
346
|
|
|
if ( ! isset( $asKey ) ) { |
347
|
|
|
$_aOptions = $sFunctionName( |
348
|
|
|
$sOptionKey, |
349
|
|
|
isset( $vDefault ) |
350
|
|
|
? $vDefault |
351
|
|
|
: array() |
352
|
|
|
);; |
353
|
|
|
return empty( $aAdditionalOptions ) |
354
|
|
|
? $_aOptions |
355
|
|
|
: self::uniteArrays( |
356
|
|
|
$_aOptions, |
357
|
|
|
$aAdditionalOptions |
358
|
|
|
); |
359
|
|
|
} |
360
|
|
|
|
361
|
|
|
// Now either the section ID or field ID is given. |
362
|
|
|
return self::getArrayValueByArrayKeys( |
363
|
|
|
|
364
|
|
|
// subject array |
365
|
|
|
self::uniteArrays( |
366
|
|
|
self::getAsArray( |
367
|
|
|
$sFunctionName( $sOptionKey, array() ), // options data |
368
|
|
|
true // preserve empty |
369
|
|
|
), |
370
|
|
|
$aAdditionalOptions |
371
|
|
|
), |
372
|
|
|
|
373
|
|
|
// dimensional keys |
374
|
|
|
self::getAsArray( |
375
|
|
|
$asKey, |
376
|
|
|
true // preserve empty. e.g. '0' -> array( 0 ) |
377
|
|
|
), |
378
|
|
|
|
379
|
|
|
// default |
380
|
|
|
$vDefault |
381
|
|
|
|
382
|
|
|
); |
383
|
|
|
|
384
|
|
|
} |
385
|
|
|
|
386
|
|
|
} |
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.