Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
69.23% covered (warning)
69.23%
27 / 39
40.00% covered (danger)
40.00%
2 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
Transient
69.23% covered (warning)
69.23%
27 / 39
40.00% covered (danger)
40.00%
2 / 5
23.46
0.00% covered (danger)
0.00%
0 / 1
 should_use_transients
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 get
84.62% covered (warning)
84.62%
11 / 13
0.00% covered (danger)
0.00%
0 / 1
6.13
 set
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
3
 delete
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
12
 __call
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2namespace NewfoldLabs\WP\Module\Data\Helpers;
3
4/**
5 * Custom Transient class to handle an Options API based fallback
6 */
7class Transient {
8
9    /**
10     * Whether to use transients to store temporary data
11     *
12     * If the site has an object-cache.php drop-in, then we can't reliably
13     * use the transients API. We'll try to fall back to the options API.
14     */
15    protected static function should_use_transients(): bool {
16        require_once constant( 'ABSPATH' ) . '/wp-admin/includes/plugin.php';
17        return ! array_key_exists( 'object-cache.php', get_dropins() )
18            || 'atomic' === \NewfoldLabs\WP\Context\getContext( 'platform' ); // Bluehost Cloud.
19    }
20
21    /**
22     * Wrapper for get_transient() with Options API fallback
23     *
24     * @see \get_transient()
25     * @see \get_option()
26     * @see \delete_option()
27     *
28     * @param string $key The key of the transient to retrieve
29     * @return mixed The value of the transient
30     */
31    public static function get( string $key ) {
32        if ( self::should_use_transients() ) {
33            return \get_transient( $key );
34        }
35
36        /**
37         * Implement the filters as used in {@see get_transient()}.
38         */
39        $pre = apply_filters( "pre_transient_{$key}", false, $key );
40        if ( false !== $pre ) {
41            return $pre;
42        }
43
44        /**
45         * The saved value and the Unix time it expires at.
46         *
47         * @var array{value:mixed, expires_at:int} $data
48         */
49        $data = \get_option( $key );
50        if ( is_array( $data ) && isset( $data['expires_at'], $data['value'] ) ) {
51            if ( $data['expires_at'] > time() ) {
52                $value = $data['value'];
53            } else {
54                \delete_option( $key );
55                $value = false;
56            }
57        } else {
58            /**
59             * Set $value to false if $data is not a valid array.
60             * This is to prevent PHP notices when trying to access $data['expires_at'].
61             */
62            $value = false;
63        }
64
65        /**
66         * Implement the filters as used in {@see get_transient()}.
67         */
68        return apply_filters( "transient_{$key}", $value, $key );
69    }
70
71    /**
72     * Wrapper for set_transient() with Options API fallback
73     *
74     * @see \set_transient()
75     * @see \update_option()
76     *
77     * @param string  $key        Key to use for storing the transient
78     * @param mixed   $value      Value to be saved
79     * @param integer $expires_in Optional expiration time in seconds from now. Default is 1 hour
80     *
81     * @return bool Whether the value was saved
82     */
83    public static function set( string $key, $value, int $expires_in = 3600 ): bool {
84        if ( self::should_use_transients() ) {
85            return \set_transient( $key, $value, $expires_in );
86        }
87
88        /**
89         * Implement the filters as used in {@see set_transient()}.
90         */
91        $value      = apply_filters( "pre_set_transient_{$key}", $value, $expires_in, $key );
92        $expires_in = apply_filters( "expiration_of_transient_{$key}", $expires_in, $value, $key );
93
94        $data = array(
95            'value'      => $value,
96            'expires_at' => $expires_in + time(),
97        );
98
99        $result = \update_option( $key, $data, false );
100
101        if ( $result ) {
102            do_action( "set_transient_{$key}", $value, $expires_in, $key );
103            do_action( 'setted_transient', $key, $value, $expires_in );
104        }
105
106        return $result;
107    }
108
109    /**
110     * Wrapper for delete_transient() with Options API fallback
111     *
112     * @see \delete_transient()
113     * @see \delete_option()
114     *
115     * @param string $key The key of the transient/option to delete
116     * @return bool Whether the value was deleted
117     */
118    public static function delete( $key ): bool {
119        if ( self::should_use_transients() ) {
120            return \delete_transient( $key );
121        }
122
123        /**
124         * Implement the filters as used in {@see set_transient()}.
125         *
126         * @param string $key Transient name.
127         */
128        do_action( "delete_transient_{$key}", $key );
129
130        $result = \delete_option( $key );
131
132        if ( $result ) {
133
134            /**
135             * Implement the filters as used in {@see set_transient()}.
136             *
137             * @param string $transient Deleted transient name.
138             */
139            do_action( 'deleted_transient', $key );
140        }
141
142        return $result;
143    }
144
145    /**
146     * Make the static functions callable as instance methods.
147     *
148     * @param string $name The function name being called.
149     * @param array  $arguments The arguments passed to that function.
150     *
151     * @return mixed
152     * @throws \BadMethodCallException If the method does not exist.
153     */
154    public function __call( $name, $arguments ) {
155        if ( ! method_exists( __CLASS__, $name ) ) {
156            throw new \BadMethodCallException( 'Method ' . esc_html( $name ) . ' does not exist' );
157        }
158        return self::$name( ...$arguments );
159    }
160}