Skip to content

Commit ff62840

Browse files
committed
Make sure we validate options and dependencies in build time
1 parent 82cbb60 commit ff62840

File tree

6 files changed

+95
-84
lines changed

6 files changed

+95
-84
lines changed

src/DependencyInjection/CacheAdapterExtension.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ public function load(array $configs, ContainerBuilder $container)
4444
$first = $name;
4545
}
4646

47+
$factoryClass = $container->getDefinition($arguments['factory'])->getClass();
48+
$factoryClass::validate($arguments['options'], $name);
49+
4750
$def = $container->register('cache.provider.'.$name, DummyAdapter::class);
4851
$def->setFactory([new Reference($arguments['factory']), 'createAdapter'])
4952
->addArgument($arguments['options']);
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
/*
4+
* This file is part of php-cache\adapter-bundle package.
5+
*
6+
* (c) 2015-2015 Aaron Scherer <[email protected]>, Tobias Nyholm <[email protected]>
7+
*
8+
* This source file is subject to the MIT license that is bundled
9+
* with this source code in the file LICENSE.
10+
*/
11+
12+
namespace Cache\AdapterBundle\Exception;
13+
14+
/**
15+
* @author Tobias Nyholm <[email protected]>
16+
*/
17+
class ConfigurationException extends \Exception
18+
{
19+
}

src/Factory/AbstractAdapterFactory.php

Lines changed: 47 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Cache\AdapterBundle\Factory;
1313

14+
use Cache\AdapterBundle\Exception\ConfigurationException;
1415
use Psr\Cache\CacheItemPoolInterface;
1516
use Symfony\Component\OptionsResolver\OptionsResolver;
1617

@@ -19,10 +20,7 @@
1920
*/
2021
abstract class AbstractAdapterFactory implements AdapterFactoryInterface
2122
{
22-
/**
23-
* @param OptionsResolver $resolver
24-
*/
25-
abstract protected function configureOptionResolver(OptionsResolver $resolver);
23+
protected static $dependencies = [];
2624

2725
/**
2826
* @param array $config
@@ -32,55 +30,70 @@ abstract protected function configureOptionResolver(OptionsResolver $resolver);
3230
abstract protected function getAdapter(array $config);
3331

3432
/**
35-
* Get the class name that is required for this adapter. This should more often than not be the cache pool.
36-
*
37-
* @return string
33+
* {@inheritdoc}
3834
*/
39-
abstract protected function getRequiredClass();
35+
public function createAdapter(array $options = [])
36+
{
37+
$this->verifyDependencies();
4038

41-
/**
42-
* Get the name of the package where require class lives.
43-
*
44-
* @return string
45-
*/
46-
abstract protected function getPackageName();
39+
$resolver = new OptionsResolver();
40+
static::configureOptionResolver($resolver);
41+
$config = $resolver->resolve($options);
4742

48-
/**
49-
* Get the name of the adapter.
50-
*
51-
* @return string
52-
*/
53-
abstract protected function getName();
43+
return $this->getAdapter($config);
44+
}
5445

5546
/**
5647
* {@inheritdoc}
5748
*/
58-
public function createAdapter(array $options = [])
49+
public static function validate(array $options = [], $adapterName)
5950
{
60-
$this->verifyDependencies();
51+
static::verifyDependencies();
6152

6253
$resolver = new OptionsResolver();
63-
$this->configureOptionResolver($resolver);
64-
$config = $resolver->resolve($options);
54+
static::configureOptionResolver($resolver);
6555

66-
return $this->getAdapter($config);
56+
try {
57+
$resolver->resolve($options);
58+
} catch (\Exception $e) {
59+
$message = sprintf(
60+
'Error while configure adapter %s. Verify your options under "cache_adapter.providers.%s.options". %s',
61+
$adapterName,
62+
$adapterName,
63+
$e->getMessage()
64+
);
65+
66+
throw new ConfigurationException($message, $e->getCode(), $e);
67+
}
6768
}
6869

6970
/**
7071
* Make sure that we have the required class and throws and exception if we dont.
7172
*
7273
* @throws \LogicException
7374
*/
74-
protected function verifyDependencies()
75+
protected static function verifyDependencies()
7576
{
76-
if (!class_exists($this->getRequiredClass())) {
77-
throw new \LogicException(
78-
sprintf(
79-
'You must install the "%s" package to use the "%s" provider.',
80-
$this->getPackageName(),
81-
$this->getName()
82-
)
83-
);
77+
foreach (static::$dependencies as $dependency) {
78+
if (!class_exists($dependency['requiredClass'])) {
79+
throw new \LogicException(
80+
sprintf(
81+
'You must install the "%s" package to use the "%s" factory.',
82+
$dependency['packageName'],
83+
static::class
84+
)
85+
);
86+
}
8487
}
8588
}
89+
90+
/**
91+
* By default we have not options ot configure. A factory should override this function and confgure
92+
* the options resolver.
93+
*
94+
* @param OptionsResolver $resolver
95+
*/
96+
protected static function configureOptionResolver(OptionsResolver $resolver)
97+
{
98+
}
8699
}

src/Factory/AdapterFactoryInterface.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,20 @@ interface AdapterFactoryInterface
2424
* @return CacheItemPoolInterface
2525
*/
2626
public function createAdapter(array $options = []);
27+
28+
/**
29+
* Make sure the options are valid and the dependencies are met.
30+
*
31+
* @param array $options the options the user has provided
32+
* @param string $adapterName the name the user has chosen for this adapter
33+
*
34+
* @throws \LogicException If the factory has missing dependencies
35+
* @throws \Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException If an option name is undefined
36+
* @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException If an option doesn't fulfill the specified validation rules
37+
* @throws \Symfony\Component\OptionsResolver\Exception\MissingOptionsException If a required option is missing
38+
* @throws \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException If there is a cyclic dependency between lazy options and/or normalizers
39+
* @throws \Symfony\Component\OptionsResolver\Exception\NoSuchOptionException If a lazy option reads an unavailable option
40+
* @throws \Symfony\Component\OptionsResolver\Exception\AccessException If called from a lazy option or normalizer
41+
*/
42+
public static function validate(array $options = [], $adapterName);
2743
}

src/Factory/DoctrineRedisFactory.php

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
*/
2121
class DoctrineRedisFactory extends AbstractAdapterFactory
2222
{
23+
protected static $dependencies = [
24+
['requiredClass' => 'Cache\Adapter\Doctrine\DoctrineCachePool', 'packageName' => 'cache/doctrine-adapter'],
25+
];
26+
2327
/**
2428
* {@inheritdoc}
2529
*/
@@ -41,7 +45,7 @@ public function getAdapter(array $config)
4145
/**
4246
* {@inheritdoc}
4347
*/
44-
protected function configureOptionResolver(OptionsResolver $resolver)
48+
protected static function configureOptionResolver(OptionsResolver $resolver)
4549
{
4650
$resolver->setDefaults([
4751
'host' => '127.0.0.1',
@@ -51,28 +55,4 @@ protected function configureOptionResolver(OptionsResolver $resolver)
5155
$resolver->setAllowedTypes('host', ['string']);
5256
$resolver->setAllowedTypes('port', ['string', 'int']);
5357
}
54-
55-
/**
56-
* {@inheritdoc}
57-
*/
58-
protected function getRequiredClass()
59-
{
60-
return 'Cache\Adapter\Doctrine\DoctrineCachePool';
61-
}
62-
63-
/**
64-
* {@inheritdoc}
65-
*/
66-
protected function getPackageName()
67-
{
68-
return 'cache/doctrine-adapter';
69-
}
70-
71-
/**
72-
* {@inheritdoc}
73-
*/
74-
protected function getName()
75-
{
76-
return 'doctrine_redis';
77-
}
7858
}

src/Factory/RedisFactory.php

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
*/
2121
class RedisFactory extends AbstractAdapterFactory
2222
{
23+
protected static $dependencies = [
24+
['requiredClass' => 'Cache\Adapter\Redis\RedisCachePool', 'packageName' => 'cache/redis-adapter'],
25+
];
26+
2327
/**
2428
* {@inheritdoc}
2529
*/
@@ -33,7 +37,7 @@ public function getAdapter(array $config)
3337
/**
3438
* {@inheritdoc}
3539
*/
36-
protected function configureOptionResolver(OptionsResolver $resolver)
40+
protected static function configureOptionResolver(OptionsResolver $resolver)
3741
{
3842
$resolver->setDefaults([
3943
'host' => '127.0.0.1',
@@ -45,28 +49,4 @@ protected function configureOptionResolver(OptionsResolver $resolver)
4549
$resolver->setAllowedTypes('port', ['string', 'int']);
4650
$resolver->setAllowedTypes('protocol', ['string']);
4751
}
48-
49-
/**
50-
* {@inheritdoc}
51-
*/
52-
protected function getRequiredClass()
53-
{
54-
return 'Cache\Adapter\Redis\RedisCachePool';
55-
}
56-
57-
/**
58-
* {@inheritdoc}
59-
*/
60-
protected function getPackageName()
61-
{
62-
return 'cache/redis-adapter';
63-
}
64-
65-
/**
66-
* {@inheritdoc}
67-
*/
68-
protected function getName()
69-
{
70-
return 'redis';
71-
}
7252
}

0 commit comments

Comments
 (0)