Completed
Pull Request — master (#628)
by Richard
19:02 queued 04:58
created

CacheManager::createDefaultConfig()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
eloc 12
nc 4
nop 0
dl 0
loc 18
rs 9.8666
c 0
b 0
f 0
ccs 0
cts 13
cp 0
crap 20
1
<?php
2
/*
3
 You may not change or alter any portion of this comment or credits
4
 of supporting developers from this source code or any supporting source code
5
 which is considered copyrighted (c) material of the original comment or credit authors.
6
7
 This program is distributed in the hope that it will be useful,
8
 but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10
*/
11
12
namespace Xoops\Core\Cache;
13
14
use Stash\Pool;
15
use Stash\Interfaces\DriverInterface;
16
use Xmf\Yaml;
17
use Xoops\Core\Cache\DriverList;
18
use Xoops\Core\Cache\Access;
19
20
/**
21
 * Provides a standardized cache access
22
 *
23
 * @category  Xoops\Core\Cache
24
 * @package   CacheManager
25
 * @author    Richard Griffith <[email protected]>
26
 * @copyright 2015 The XOOPS Project https://github.com/XOOPS
27
 * @license   GNU GPL 2 or later (http://www.gnu.org/licenses/gpl-2.0.html)
28
 * @link      http://xoops.org
29
 */
30
class CacheManager
31
{
32
    /**
33
     * Cache Access objects for pools
34
     *
35
     * @var Access[]
36
     */
37
    protected $pools = [];
38
39
    /**
40
     * Pool definitions
41
     *
42
     * @var array
43
     */
44
    protected $poolDefs = [];
45
46
    /**
47
     * Xoops instance
48
     *
49
     * @var \Xoops
50
     */
51
    protected $xoops;
52
53
    /**
54
     * __construct
55
     */
56 1
    public function __construct()
57
    {
58 1
        $this->xoops = \Xoops::getInstance();
59 1
        $defaults = $this->getDefaults();
60 1
		$xoops_var_path = \XoopsBaseConfig::get('var-path');
61 1
		$cache_file = $xoops_var_path . '/configs/cache.php';
62 1
        $poolDefs = Yaml::readWrapped($cache_file);
63 1
        if (empty($poolDefs)) {
64
            Yaml::saveWrapped($defaults, $cache_file);
65
        }
66 1
        $poolDefs = is_array($poolDefs) ? $poolDefs : array();
67 1
        $this->poolDefs = array_merge($defaults, $poolDefs);
68 1
    }
69
70
    /**
71
     * getDefaults get default cache configuration used if there is no config file
72
     *
73
     * @return array cache configuration
74
     */
75 1
    private static function getDefaults()
76
    {
77
78
        $defaults = [
79 1
            'default' => [
80 1
                'driver' => 'Sqlite',
81 1
                'options' => ['path' => \XoopsBaseConfig::get('var-path') . '/stash/'],
82
                ],
83
            'temp' => [
84
                'driver' => 'Ephemeral',
85
                'options' => [],
86
                ],
87
            ];
88 1
        return $defaults;
89
    }
90
91
    /**
92
     * Create a default configuration file, used in installation
93
     *
94
     * SQLite is the recommended driver, and will be used by default if available.
95
     *
96
     * We will fall back to FileSystem if SQLite is not available.
97
     *
98
     * Note: some versions of the Stash FileSystem driver appear susceptible to
99
     * race conditions which may cause random failures.
100
     *
101
     * Note for Windows users:
102
     *
103
     * When using Windows NTFS, PHP has a maximum path length of 260 bytes. Each key level in a
104
     * Stash hierarchical key corresponds to a directory, and is normalized as an md5 hash. Also,
105
     * Stash uses 2 levels for its own integrity and locking mechanisms. The full key length used
106
     * in XoopCore can reach 202 characters.
107
     *
108
     * Installing the pdo_sqlite3 extension is highly recommended to avoid problems.
109
     *
110
     * @return void
111
     */
112
    public static function createDefaultConfig()
113
    {
114
        $configFile = \XoopsBaseConfig::get('var-path') . '/configs/cache.php';
115
        if (file_exists($configFile)) {
116
            return;
117
        }
118
        $defaults = self::getDefaults();
119
        if (!array_key_exists("SQLite", \Stash\DriverList::getAvailableDrivers())) {
120
            $defaults['default']['driver'] = 'FileSystem';
121
            $defaults['default']['options'] = [
122
                'dirSplit' => 1,
123
                'path' => \XoopsBaseConfig::get('var-path') . '/stash/'
124
            ];
125
            if (false !== stripos(PHP_OS, 'WIN')) {
126
                trigger_error("SQLite is strongly recommended on windows due to 260 character file path restrictions.");
127
            }
128
        }
129
        Yaml::saveWrapped($defaults, $configFile);
130
    }
131
132
    /**
133
     * Get a cache corresponding to the specified name
134
     *
135
     * @param string $name Name of cache definition
136
     *
137
     * @return Access object
138
     */
139 38
    public function getCache($name)
140
    {
141 38
        $pool = false;
142 38
        if (array_key_exists($name, $this->pools)) {
143 37
            $pool =  $this->pools[$name];
144 1
        } elseif (array_key_exists($name, $this->poolDefs)) {
145 1
            $pool =  $this->startPoolAccess($name);
146
        }
147 38
        if ($pool === false) {
148 1
            $pool = $this->getDefaultPool($name);
149
        }
150
151 38
        $this->pools[$name] = $pool;
152
153 38
        return $pool;
154
    }
155
156
    /**
157
     * Instantiate an Access object from named configuration, including
158
     * instantiating pool and driver
159
     *
160
     * @param string $name name of pool configuration to start
161
     *
162
     * @return Access|false pool or false if a pool cannot be created
163
     */
164 1
    protected function startPoolAccess($name)
165
    {
166 1
        $pool = false;
167 1
        $options = false;
168 1
        if (isset($this->poolDefs[$name]['options'])) {
169 1
            $options = $this->poolDefs[$name]['options'];
170
        }
171 1
        $driverName = $this->poolDefs[$name]['driver'];
172 1
        if (0 === strcasecmp($driverName, 'Composite')) {
173
            $drivers = array();
174
            foreach ($this->poolDefs[$name]['options']['drivers'] as $subDriver) {
175
                $drivers[] = $this->getDriver($subDriver['driver'], $subDriver['options']);
176
            }
177
            $options['drivers'] = $drivers;
178
        }
179
180 1
        $driver = $this->getDriver($driverName, $options);
181 1
        if ($driver!==false) {
182 1
            $pool = new Pool($driver);
183 1
            if (is_object($pool)) {
184 1
                $pool->setLogger($this->xoops->logger());
185 1
                $pool->setNamespace($this->xoops->db()->prefix());
186
            }
187
        }
188 1
        if (!$pool) {
189
            $this->xoops->logger()->warn('Could not create cache pool '.$name);
0 ignored issues
show
Deprecated Code introduced by
The function Xoops\Core\Logger::__call() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

189
            /** @scrutinizer ignore-deprecated */ $this->xoops->logger()->warn('Could not create cache pool '.$name);
Loading history...
Bug introduced by
The method warn() does not exist on Xoops\Core\Logger. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

189
            $this->xoops->logger()->/** @scrutinizer ignore-call */ warn('Could not create cache pool '.$name);
Loading history...
190
            return $pool;
191
        }
192
193 1
        return new Access($pool);
194
    }
195
196
    /**
197
     * getDriver
198
     *
199
     * @param string $driverName short name of the driver
200
     * @param array  $options    array of options for the driver
201
     *
202
     * @return DriverInterface|false driver object or false if it could not be instantiated
203
     */
204 1
    protected function getDriver($driverName, $options)
205
    {
206 1
        $driver = false;
207 1
        $driverClass = DriverList::getDriverClass($driverName);
208
209 1
        if ($driverClass!==false && $driverClass::isAvailable()) {
210 1
            $options = is_array($options) ? $options : array();
0 ignored issues
show
introduced by
The condition is_array($options) is always true.
Loading history...
211 1
            $driver = new $driverClass($options);
212
        }
213 1
        return ($driver instanceof DriverInterface) ? $driver : false;
214
    }
215
216
    /**
217
     * Get an Access object based on the default pool. If it isn't set, create it.
218
     * If no definition exists for default, use Stash default (Ephimeral.)
219
     *
220
     * @param string $originalName originally requested pool configuration name
221
     *
222
     * @return Access object
223
     */
224 1
    protected function getDefaultPool($originalName)
225
    {
226 1
        $this->xoops->events()->triggerEvent('debug.log', 'Substituting default cache pool for '.$originalName);
227 1
        $name = 'default';
228 1
        if (array_key_exists($name, $this->pools)) {
229 1
            return $this->pools[$name];
230
        }
231
        $pool = $this->startPoolAccess($name);
232
        if ($pool===false) {
233
            $this->xoops->logger()->error('Could not create default cache pool');
234
            $pool = new Access(new \Stash\Pool());
235
        }
236
        $this->pools[$name] = $pool;
237
        return $pool;
238
    }
239
}
240