Completed
Branch FET-10788-cache-uniqueness (48f3c7)
by
unknown
40:30 queued 26:03
created

BasicCacheManager::generateCacheIdentifier()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 2
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
1
<?php
2
namespace EventEspresso\core\services\cache;
3
4
use Closure;
5
use EventEspresso\core\domain\services\session\SessionIdentifierInterface;
6
7
defined('EVENT_ESPRESSO_VERSION') || exit;
8
9
10
11
/**
12
 * Class BasicCacheManager
13
 * Controls the creation and deletion of cached content
14
 *
15
 * @package       Event Espresso
16
 * @author        Brent Christensen
17
 * @since         4.9.31
18
 */
19
class BasicCacheManager implements CacheManagerInterface
20
{
21
22
    /**
23
     * @type string
24
     */
25
    const CACHE_PREFIX = 'ee_cache_';
26
27
    /**
28
     * set to true to monitor when content is being served from cache or not
29
     *
30
     * @type boolean
31
     */
32
    const DEBUG = false;
33
34
    /**
35
     * @var CacheStorageInterface $cache_storage
36
     */
37
    private $cache_storage;
38
39
    /**
40
     * @var SessionIdentifierInterface $session
41
     */
42
    private $session;
43
44
45
46
    /**
47
     * BasicCacheManager constructor.
48
     *
49
     * @param CacheStorageInterface      $cache_storage [required]
50
     * @param SessionIdentifierInterface $session
51
     */
52
    public function __construct(CacheStorageInterface $cache_storage, SessionIdentifierInterface $session)
53
    {
54
        $this->cache_storage = $cache_storage;
55
        $this->session = $session;
56
    }
57
58
59
60
    /**
61
     * returns a string that will be prepended to all cache identifiers
62
     *
63
     * @return string
64
     */
65
    public function cachePrefix()
66
    {
67
        return BasicCacheManager::CACHE_PREFIX;
68
    }
69
70
71
72
    /**
73
     * @param string  $id_prefix [required] Prepended to all cache IDs. Can be helpful in finding specific cache types.
74
     *                           May also be helpful to include an additional specific identifier,
75
     *                           such as a post ID as part of the $id_prefix so that individual caches
76
     *                           can be found and/or cleared. ex: "venue-28", or "shortcode-156".
77
     *                           BasicCacheManager::CACHE_PREFIX will also be prepended to the cache id.
78
     * @param string  $cache_id  [required] Additional identifying details that make this cache unique.
79
     *                           It is advisable to use some of the actual data
80
     *                           that is used to generate the content being cached,
81
     *                           in order to guarantee that the cache id is unique for that content.
82
     *                           The cache id will be md5'd before usage to make it more db friendly,
83
     *                           and the entire cache id string will be truncated to 190 characters.
84
     * @param Closure $callback  [required] since the point of caching is to avoid generating content when not
85
     *                           necessary,
86
     *                           we wrap our content creation in a Closure so that it is not executed until needed.
87
     * @param int     $expiration
88
     * @return Closure|mixed
89
     */
90
    public function get($id_prefix, $cache_id, Closure $callback, $expiration = HOUR_IN_SECONDS)
91
    {
92
        $content = '';
93
        $expiration = absint(
94
            apply_filters(
95
                'FHEE__CacheManager__get__cache_expiration',
96
                $expiration,
97
                $id_prefix,
98
                $cache_id
99
            )
100
        );
101
        $cache_id = $this->generateCacheIdentifier($id_prefix, $cache_id);
102
        // is caching enabled for this content ?
103
        if ($expiration) {
104
            $content = $this->cache_storage->get($cache_id);
105
        }
106
        // any existing content ?
107
        if (empty($content)) {
108
            // nope! let's generate some new stuff
109
            $content = $callback();
110
            // save the new content if caching is enabled
111
            if ($expiration) {
112
                $this->cache_storage->add($cache_id, $content, $expiration);
113
                if (BasicCacheManager::DEBUG || WP_DEBUG) {
114
                    $content .= $this->displayCacheNotice($cache_id, 'REFRESH CACHE');
115
                }
116
            }
117
        } else {
118
            if (BasicCacheManager::DEBUG || WP_DEBUG) {
119
                $content .= $this->displayCacheNotice($cache_id, 'CACHED CONTENT');
120
            }
121
        }
122
        return $content;
123
    }
124
125
126
127
    /**
128
     * Generates a unique identifier string for the cache
129
     *
130
     * @param string $id_prefix  [required] see BasicCacheManager::get()
131
     * @param string $cache_id   [required] see BasicCacheManager::get()
132
     * @return string
133
     */
134
    private function generateCacheIdentifier($id_prefix, $cache_id)
135
    {
136
        // let's make the cached content unique for this session
137
        $cache_id .= $this->session->id();
138
        // and for this "page"
139
        $cache_id .= filter_input(INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_URL);
140
        // with these parameters
141
        $cache_id .= filter_input(INPUT_SERVER, 'QUERY_STRING', FILTER_SANITIZE_URL);
142
        // then md5 the above to control it's length, add all of our prefixes, and truncate
143
        return substr($this->cachePrefix() . $id_prefix . '-' . md5($cache_id), 0, 182);
144
    }
145
146
147
148
    /**
149
     * @param array|string $cache_id [required] Could be an ID prefix affecting many caches
150
     *                               or a specific ID targeting a single cache item
151
     * @return void
152
     */
153
    public function clear($cache_id)
154
    {
155
        // ensure incoming arg is in an array
156
        $cache_id = is_array($cache_id) ? $cache_id : array($cache_id);
157
        // delete corresponding transients for the supplied id prefix
158
        $this->cache_storage->deleteMany($cache_id);
159
    }
160
161
162
163
    /**
164
     * @param array|string $cache_id [required] Could be an ID prefix affecting many caches
165
     *                               or a specific ID targeting a single cache item
166
     * @param string       $type
167
     * @return string
168
     */
169
    private function displayCacheNotice($cache_id, $type) {
170
        return '
171
<div class="ee-cached-content-notice" style="position:fixed; bottom:0; left: 0;">
172
    <p style="font-size:9px;font-weight:normal;color:#666;line-height: 12px;margin:0 0 3px 5px">
173
        <b>' . $type . '</b><span style="color:#999"> : </span>
174
        <span>' . $cache_id . '</span>
175
        <span style="margin-left:2em;">' . __FILE__ . '</span>
176
    </p>
177
</div>';
178
    }
179
180
}
181
// End of file BasicCacheManager.php
182
// Location: core/services/cache/BasicCacheManager.php