Passed
Push — master ( 788146...671601 )
by Andreas
23:40
created

midcom_services_cache_module::prepare_memcached()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2.0625

Importance

Changes 0
Metric Value
cc 2
eloc 7
nc 2
nop 1
dl 0
loc 10
ccs 6
cts 8
cp 0.75
crap 2.0625
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @package midcom.services
4
 * @author The Midgard Project, http://www.midgard-project.org
5
 * @copyright The Midgard Project, http://www.midgard-project.org
6
 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License
7
 */
8
9
use Doctrine\Common\Cache;
10
use Doctrine\Common\Cache\CacheProvider;
11
12
/**
13
 * This is the base class for the MidCOM cache modules. It provides a basic infrastructure
14
 * for building your own caching service, providing hooks for initialization.
15
 *
16
 * It provides convenience methods to start up the cache module, for example for the creation
17
 * of a cache backend instance. There is no specific initialization done during startup, to
18
 * allow the modules to do their own magic during startup (it is difficult to generalize such
19
 * stuff).
20
 *
21
 * @package midcom.services
22
 */
23
abstract class midcom_services_cache_module
24
{
25
    /**
26
     * A list of all backends created by _create_backend(). They will be automatically
27
     * shut down when the module shuts down. They are indexed by their name.
28
     *
29
     * @var Doctrine\Common\Cache\CacheProvider[]
30
     */
31
    protected $_backends = [];
32
33
    /**
34
     * The cache key prefix.
35
     *
36
     * @var string
37
     */
38
    protected $_prefix;
39
40
    /**
41
     * Initialize the module. This will initialize the class configuration
42
     * and call the corresponding event handler.
43
     */
44 1
    public function __construct()
45
    {
46 1
        $this->_prefix = get_class($this) . $_SERVER['SERVER_NAME'];
47 1
    }
48
49
    /**
50
     * Creates an instance of the handler described by the configuration passed to
51
     * the function.
52
     *
53
     * The configuration array must include the configuration parameters driver and
54
     * directory, as outlined in the midcom_services_cache_backend class documentation.
55
     *
56
     * All backends will be collected in the $_backends array, indexed by their name.
57
     *
58
     * Any duplicate instantiation will be intercepted, throwing a critical error.
59
     *
60
     * @param string $name The name of the backend, must be unique throughout the system.
61
     * @param array $config The configuration of the backend to create. It must contain
62
     *     the key 'driver', which indicates which backend to use.
63
     */
64 1
    protected function _create_backend($name, array $config) : CacheProvider
65
    {
66 1
        $name = $this->_prefix . $name;
67
68 1
        if (array_key_exists($name, $this->_backends)) {
69
            throw new midcom_error("Cannot create backend driver instance {$name}: A backend with this name does already exist.");
70
        }
71
72 1
        if (!array_key_exists('driver', $config)) {
73
            throw new midcom_error("Cannot create backend driver instance {$name}: The driver class is not specified in the configuration.");
74
        }
75
76 1
        if (is_string($config['driver'])) {
77 1
            $backend = $this->prepare_backend($config, $name);
78
        } else {
79
            $backend = $config['driver'];
80
        }
81 1
        $backend->setNamespace($name);
82
83 1
        $this->_backends[$name] = $backend;
84
85 1
        return $backend;
86
    }
87
88 1
    private function prepare_backend(array $config, string $name) : CacheProvider
89
    {
90 1
        $directory = midcom::get()->getCacheDir();
91 1
        if (!empty($config['directory'])) {
92 1
            $directory .= '/' . $config['directory'];
93
        }
94
95 1
        switch ($config['driver']) {
96 1
            case 'apc':
97
                $backend = new Cache\ApcuCache();
98
                break;
99 1
            case 'memcached':
100 1
                if ($memcached = self::prepare_memcached($config)) {
101 1
                    $backend = new Cache\MemcachedCache();
102 1
                    $backend->setMemcached($memcached);
103 1
                    break;
104
                }
105
                debug_add("memcache: Failed to connect. Falling back to filecache", MIDCOM_LOG_ERROR);
106
                // fall-through
107
            case 'dba':
108
            case 'flatfile':
109
                $backend = new Cache\FilesystemCache($directory . '/' . $name);
110
                break;
111
            case 'sqlite':
112
                $sqlite = new SQLite3("{$directory}/{$name}.db");
113
                $table = str_replace(['.', '-'], '_', $name);
114
                $backend = new Cache\SQLite3Cache($sqlite, $table);
115
                break;
116
            case 'null':
117
            default:
118
                $backend = new Cache\VoidCache();
119
                break;
120
        }
121
122 1
        $cache = new Cache\ChainCache([new Cache\ArrayCache, $backend]);
123 1
        return $cache;
124
    }
125
126 2
    public static function prepare_memcached(array $config) : ?Memcached
127
    {
128 2
        $host = $config['host'] ?? 'localhost';
129 2
        $port = $config['port'] ?? 11211;
130 2
        $memcached = new Memcached;
131 2
        if (!$memcached->addServer($host, $port)) {
132
            midcom::get()->debug->log_php_error(MIDCOM_LOG_ERROR);
133
            return null;
134
        }
135 2
        return $memcached;
136
    }
137
138
    /**
139
     * Invalidate the cache completely, dropping all entries. The default implementation will
140
     * drop all entries from all registered cache backends using CacheProvider::flushAll().
141
     * Override this function if this behavior doesn't suit your needs.
142
     */
143
    public function invalidate_all()
144
    {
145
        foreach ($this->_backends as $name => $backend) {
146
            debug_add("Invalidating cache backend {$name}...", MIDCOM_LOG_INFO);
147
            $backend->flushAll();
148
        }
149
    }
150
151
    /**
152
     * Invalidate all cache objects related to the given GUID.
153
     *
154
     * @param string $guid The GUID that has to be invalidated.
155
     * @param object $object The object that has to be invalidated (if available).
156
     */
157
    abstract public function invalidate($guid, $object = null);
158
}
159