Passed
Push — master ( 1c42c4...cb4ab7 )
by Rafael
38:41
created

TwoLevelCache::sanitizeCacheId()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
1
<?php
2
namespace ApacheSolrForTypo3\Solr\System\Cache;
3
4
/***************************************************************
5
 *  Copyright notice
6
 *
7
 *  (c) 2016 Timo Schmidt <[email protected]>
8
 *  All rights reserved
9
 *
10
 *  This script is part of the TYPO3 project. The TYPO3 project is
11
 *  free software; you can redistribute it and/or modify
12
 *  it under the terms of the GNU General Public License as published by
13
 *  the Free Software Foundation; either version 3 of the License, or
14
 *  (at your option) any later version.
15
 *
16
 *  The GNU General Public License can be found at
17
 *  http://www.gnu.org/copyleft/gpl.html.
18
 *  A copy is found in the textfile GPL.txt and important notices to the license
19
 *  from the author is found in LICENSE.txt distributed with these scripts.
20
 *
21
 *
22
 *  This script is distributed in the hope that it will be useful,
23
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
24
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25
 *  GNU General Public License for more details.
26
 *
27
 *  This copyright notice MUST APPEAR in all copies of the script!
28
 ***************************************************************/
29
30
use TYPO3\CMS\Core\Cache\CacheManager;
31
use TYPO3\CMS\Core\Utility\GeneralUtility;
32
use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
33
34
/**
35
 * Provides a two level cache that uses an in memory cache as the first level cache and
36
 * the TYPO3 caching framework cache as the second level cache.
37
 *
38
 * @author Timo Schmidt <[email protected]>
39
 */
40
class TwoLevelCache
41
{
42
    /**
43
     * @var string
44
     */
45
    protected $cacheName = '';
46
47
    /**
48
     * @var array
49
     */
50
    protected static $firstLevelCache = [];
51
52
    /**
53
     * @var FrontendInterface
54
     */
55
    protected $secondLevelCache = null;
56
57
    /**
58
     * @param string $cacheName
59
     * @param FrontendInterface $secondaryCacheFrontend
60
     */
61 178
    public function __construct(string $cacheName, FrontendInterface $secondaryCacheFrontend = null)
62
    {
63 178
        $this->cacheName = $cacheName;
64 178
        if ($secondaryCacheFrontend == null) {
65 175
            $cacheManager = GeneralUtility::makeInstance(CacheManager::class);
66 175
            $this->secondLevelCache = $cacheManager->getCache($cacheName);
67
        } else {
68 3
            $this->secondLevelCache = $secondaryCacheFrontend;
69
        }
70 178
    }
71
72
    /**
73
     * Retrieves a value from the first level cache.
74
     *
75
     * @param string $cacheId
76
     * @return mixed|null
77
     */
78 153
    protected function getFromFirstLevelCache(string $cacheId)
79
    {
80 153
        if (!empty(self::$firstLevelCache[$this->cacheName][$cacheId])) {
81 104
            return self::$firstLevelCache[$this->cacheName][$cacheId];
82
        }
83
84 152
        return null;
85
    }
86
87
    /**
88
     * Write a value to the first level cache.
89
     *
90
     * @param string $cacheId
91
     * @param mixed $value
92
     */
93 154
    protected function setToFirstLevelCache(string $cacheId, $value): void
94
    {
95 154
        self::$firstLevelCache[$this->cacheName][$cacheId] = $value;
96 154
    }
97
98
    /**
99
     * Retrieves a value from the first level cache if present and
100
     * from the second level if not.
101
     *
102
     * @param string $cacheId
103
     * @return mixed
104
     */
105 153
    public function get(string $cacheId)
106
    {
107 153
        $cacheId = $this->sanitizeCacheId($cacheId);
108
109 153
        $firstLevelResult = $this->getFromFirstLevelCache($cacheId);
110 153
        if ($firstLevelResult !== null) {
111 104
            return $firstLevelResult;
112
        }
113
114 152
        $secondLevelResult = $this->secondLevelCache->get($cacheId);
115 152
        $this->setToFirstLevelCache($cacheId, $secondLevelResult);
116
117 152
        return $secondLevelResult;
118
    }
119
120
    /**
121
     * Write a value to the first and second level cache.
122
     *
123
     * @param string $cacheId
124
     * @param mixed $value
125
     */
126 145
    public function set(string $cacheId, $value): void
127
    {
128 145
        $cacheId = $this->sanitizeCacheId($cacheId);
129
130 145
        $this->setToFirstLevelCache($cacheId, $value);
131 145
        $this->secondLevelCache->set($cacheId, $value);
132 145
    }
133
134
    /**
135
     * Flushes the cache
136
     */
137 3
    public function flush(): void
138
    {
139 3
        self::$firstLevelCache[$this->cacheName] = [];
140 3
        $this->secondLevelCache->flush();
141 3
    }
142
143
    /**
144
     * Sanitizes the cache id to ensure compatibility with the FrontendInterface::PATTERN_ENTRYIDENTIFIER
145
     *
146
     * @see \TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::isValidEntryIdentifier()
147
     *
148
     * @param string $cacheEntryIdentifier
149
     * @return string
150
     */
151 154
    protected function sanitizeCacheId(string $cacheId): string
152
    {
153 154
        return preg_replace('/[^a-zA-Z0-9_%\\-&]/', '-', $cacheId);
154
    }
155
}
156