Completed
Branch master (fd853c)
by
unknown
04:08 queued 02:12
created

getTransientAsArray()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 0
loc 5
rs 10
c 0
b 0
f 0
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 );
0 ignored issues
show
Bug introduced by
It seems like $asKey defined by parameter $asKey on line 312 can also be of type array or string; however, AdminPageFramework_WPUti...tOptionByFunctionName() does only seem to accept null, 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...
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' );
0 ignored issues
show
Bug introduced by
It seems like $asKey defined by parameter $asKey on line 327 can also be of type array or string; however, AdminPageFramework_WPUti...tOptionByFunctionName() does only seem to accept null, 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...
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
}