Completed
Pull Request — master (#563)
by Richard
10:42
created

CacheManager::createDefaultConfig()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 13
c 1
b 0
f 0
nc 4
nop 0
dl 0
loc 19
ccs 0
cts 14
cp 0
crap 20
rs 9.2
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 39
    public function getCache($name)
140
    {
141 39
        $pool = false;
142 39
        if (array_key_exists($name, $this->pools)) {
143 38
            $pool =  $this->pools[$name];
144 1
        } elseif (array_key_exists($name, $this->poolDefs)) {
145 1
            $pool =  $this->startPoolAccess($name);
146
        }
147 39
        if ($pool === false) {
148 1
            $pool = $this->getDefaultPool($name);
149
        }
150
151 39
        $this->pools[$name] = $pool;
152
153 39
        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);
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();
211 1
            $driver = new $driverClass($options);
212
        }
213 1
        return ($driver instanceof DriverInterface) ? $driver : false;
0 ignored issues
show
Bug introduced by
The class Stash\Interfaces\DriverInterface does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
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