Skip to content

Commit 61874d7

Browse files
committed
first draft of the doctrine cache bundle
1 parent 2b57823 commit 61874d7

File tree

8 files changed

+600
-0
lines changed

8 files changed

+600
-0
lines changed

.travis.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
language: php
2+
php:
3+
- "7.0"
4+
- "5.6"
5+
- "5.5"
6+
7+
env:
8+
- SYMFONY_VERSION=2.7.*
9+
- SYMFONY_VERSION=2.8.*
10+
- SYMFONY_VERSION=3.0.*
11+
12+
matrix:
13+
fast_finish: true
14+
15+
sudo: false
16+
17+
before_script:
18+
- composer self-update
19+
- composer require symfony/symfony:${SYMFONY_VERSION} --no-update
20+
- composer install --dev --prefer-source --no-interaction
21+
22+
script:
23+
- php vendor/bin/phpunit

composer.json

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"name": "php-cache/doctrine-cache-bundle",
3+
"type": "symfony2 bundle",
4+
"description": "",
5+
"keywords": [],
6+
"homepage": "https://github.com/php-cache/doctrine-cache-bundle",
7+
"license": "MIT",
8+
"authors": [
9+
{
10+
"name": "Aaron Scherer",
11+
"email": "[email protected]",
12+
"homepage": "https://github.com/aequasi"
13+
},
14+
{
15+
"name": "Tobias Nyholm",
16+
"email": "[email protected]",
17+
"homepage": "https://github.com/Nyholm"
18+
}
19+
],
20+
"require": {
21+
"php": "^5.5|^7",
22+
"symfony/framework-bundle": "^2.7|^3.0",
23+
"php-cache/doctrine-cache": "dev-master"
24+
},
25+
"require-dev": {
26+
"phpunit/phpunit": "^5.1|^4.0"
27+
},
28+
"autoload": {
29+
"psr-4": {
30+
"Cache\\DoctrineCacheBundle\\": "src/"
31+
}
32+
},
33+
"autoload-dev": {
34+
"psr-4": {
35+
"Cache\\DoctrineCacheBundle\\Tests\\": "tests/"
36+
}
37+
}
38+
}

phpunit.xml.dist

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<phpunit backupGlobals="false"
4+
backupStaticAttributes="false"
5+
colors="true"
6+
convertErrorsToExceptions="true"
7+
convertNoticesToExceptions="true"
8+
convertWarningsToExceptions="true"
9+
processIsolation="false"
10+
stopOnFailure="false"
11+
syntaxCheck="false"
12+
bootstrap="vendor/autoload.php"
13+
>
14+
<testsuites>
15+
<testsuite name="CacheBundle for the Symfony2 Framework">
16+
<directory>./tests/</directory>
17+
</testsuite>
18+
</testsuites>
19+
20+
<logging>
21+
<log type="coverage-text" target="php://stdout"/>
22+
</logging>
23+
24+
<groups>
25+
<exclude>
26+
<group>benchmark</group>
27+
</exclude>
28+
</groups>
29+
30+
<filter>
31+
<whitelist>
32+
<directory>src/</directory>
33+
<exclude>
34+
<directory>Resources</directory>
35+
</exclude>
36+
</whitelist>
37+
</filter>
38+
</phpunit>
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
<?php
2+
3+
namespace Cache\DoctrineCacheBundle\DependencyInjection\CompilerPass;
4+
5+
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
6+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
7+
use Symfony\Component\DependencyInjection\ContainerBuilder;
8+
use Symfony\Component\DependencyInjection\Definition;
9+
use Symfony\Component\DependencyInjection\Reference;
10+
11+
class ServiceBuilderPass implements CompilerPassInterface
12+
{
13+
/**
14+
* Array of types, and their options
15+
*
16+
* @var array $types
17+
*/
18+
protected static $types = [
19+
'memcache' => [
20+
'class' => 'Memcache',
21+
'connect' => 'addServer'
22+
],
23+
'memcached' => [
24+
'class' => 'Aequasi\Bundle\CacheBundle\Cache\Memcached',
25+
'connect' => 'addServer'
26+
],
27+
'redis' => [
28+
'class' => 'Redis',
29+
'connect' => 'connect'
30+
]
31+
];
32+
33+
/**
34+
*For each configured instance, build a service
35+
*
36+
* @param ContainerBuilder $container
37+
*/
38+
public function process(ContainerBuilder $container)
39+
{
40+
$instances = $container->getParameter('doctrine_cache.instance');
41+
42+
foreach ($instances as $name => $instance) {
43+
$typeId = 'doctrine_cache.abstract.'.$instance['type'];
44+
if (!$container->findDefinition($typeId)) {
45+
throw new InvalidConfigurationException(
46+
sprintf(
47+
"`%s` is not a valid cache type. If you are using a custom type, make sure to add your service. ",
48+
$instance['type']
49+
)
50+
);
51+
}
52+
53+
$service = $this->buildService($container, $typeId, $name, $instance);
54+
$this->prepareCacheClass($container, $service, $name, $instance);
55+
}
56+
}
57+
58+
/**
59+
* @param string $typeId
60+
* @param string $name
61+
* @param array $instance
62+
*
63+
* @return Definition
64+
*/
65+
private function buildService(ContainerBuilder $container, $typeId, $name, array $instance)
66+
{
67+
$namespace = is_null($instance['namespace']) ? $name : $instance['namespace'];
68+
$serviceId = 'doctrine_cache.instance.'.$name;
69+
70+
// Modify the core doctrine cache class
71+
$doctrine = $container->getDefinition($typeId);
72+
$doctrine->addMethodCall('setNamespace', [$namespace])
73+
->setPublic(false);
74+
75+
// Register the CacheItemPoolInterface definition
76+
$def = $container->setDefinition(
77+
$serviceId,
78+
\Cache\Doctrine\CachePoolItem::class
79+
);
80+
$def->addArgument(0, new Reference($typeId));
81+
82+
//TODO add alias
83+
84+
return $doctrine;
85+
}
86+
87+
/**
88+
* We need to prepare the doctrine cache providers
89+
*
90+
* @param Definition $service
91+
* @param string $name
92+
* @param array $instance
93+
*
94+
* @return Boolean
95+
*/
96+
private function prepareCacheClass(ContainerBuilder $container, Definition $service, $name, array $instance)
97+
{
98+
$type = $instance['type'];
99+
$id = sprintf("doctrine_cache.instance.%s.cache_instance", $name);
100+
switch ($type) {
101+
case 'memcache':
102+
case 'memcached':
103+
case 'redis':
104+
return $this->createCacheInstance($container, $service, $type, $id, $instance);
105+
case 'file_system':
106+
case 'php_file':
107+
$directory = '%kernel.cache_dir%/doctrine/cache';
108+
if (null !== $instance['directory']) {
109+
$directory = $instance['directory'];
110+
}
111+
$extension = is_null($instance['extension']) ? null : $instance['extension'];
112+
113+
$service->setArguments([$directory, $extension]);
114+
115+
return true;
116+
case 'mongo':
117+
case 'sqlite3':
118+
case 'sqlite':
119+
case 'riak':
120+
case 'chain':
121+
return false;
122+
default:
123+
return true;
124+
}
125+
}
126+
127+
/**
128+
* Creates a cache instance
129+
*
130+
* @param Definition $service
131+
* @param string $type
132+
* @param string $id
133+
* @param array $instance
134+
*
135+
* @return Boolean
136+
*/
137+
public function createCacheInstance(ContainerBuilder $container, Definition $service, $type, $id, array $instance)
138+
{
139+
if (empty($instance['id'])) {
140+
$cache = new Definition(self::$types[$type]['class']);
141+
142+
// set memcached options first as they need to be set before the servers are added.
143+
if ($type === 'memcached') {
144+
if (!empty($instance['options']['memcached'])) {
145+
foreach ($instance['options']['memcached'] as $option => $value) {
146+
switch ($option) {
147+
case 'serializer':
148+
case 'hash':
149+
case 'distribution':
150+
$value = constant(
151+
sprintf('\Memcached::%s_%s', strtoupper($option), strtoupper($value))
152+
);
153+
break;
154+
}
155+
$cache->addMethodCall(
156+
'setOption',
157+
[constant(sprintf('\Memcached::OPT_%s', strtoupper($option))), $value]
158+
);
159+
}
160+
}
161+
}
162+
163+
if (isset($instance['persistent']) && $instance['persistent'] !== false) {
164+
if ($instance['persistent'] !== true) {
165+
$persistentId = $instance['persistent'];
166+
} else {
167+
$persistentId = substr(md5(serialize($instance['hosts'])), 0, 5);
168+
}
169+
if ($type === 'memcached') {
170+
$cache->setArguments([$persistentId]);
171+
}
172+
if ($type === 'redis') {
173+
self::$types[$type]['connect'] = 'pconnect';
174+
}
175+
}
176+
177+
foreach ($instance['hosts'] as $config) {
178+
$arguments = [
179+
'host' => empty($config['host']) ? 'localhost' : $config['host'],
180+
'port' => empty($config['port']) ? 11211 : $config['port']
181+
];
182+
if ($type === 'memcached') {
183+
$arguments[] = is_null($config['weight']) ? 0 : $config['weight'];
184+
} else {
185+
$arguments[] = is_null($config['timeout']) ? 0 : $config['timeout'];
186+
if (isset($persistentId)) {
187+
$arguments[] = $persistentId;
188+
}
189+
}
190+
191+
$cache->addMethodCall(self::$types[$type]['connect'], $arguments);
192+
}
193+
unset($config);
194+
195+
if ($type === 'redis') {
196+
if (isset($instance['auth_password']) && null !== $instance['auth_password']) {
197+
$cache->addMethodCall('auth', [$instance['auth_password']]);
198+
}
199+
if (isset($instance['database'])) {
200+
$cache->addMethodCall('select', [$instance['database']]);
201+
}
202+
}
203+
204+
$container->setDefinition($id, $cache);
205+
} else {
206+
$id = $instance['id'];
207+
}
208+
$service->addMethodCall(sprintf('set%s', ucwords($type)), [new Reference($id)]);
209+
210+
return true;
211+
}
212+
}

0 commit comments

Comments
 (0)