diff --git a/src/Symfony/Bundle/CacheBundle/CacheBundle.php b/src/Symfony/Bundle/CacheBundle/CacheBundle.php new file mode 100644 index 0000000000000..39377742dae12 --- /dev/null +++ b/src/Symfony/Bundle/CacheBundle/CacheBundle.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + + +namespace Symfony\Bundle\CacheBundle; + +use Symfony\Bundle\CacheBundle\DependencyInjection\Compiler\ServiceCreationCompilerPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\HttpKernel\Bundle\Bundle; +use Symfony\Bundle\CacheBundle\DependencyInjection\CacheExtension; +use Symfony\Component\HttpKernel\KernelInterface; +use Symfony\Bundle\CacheBundle\DependencyInjection\Backend\MemcachedBackendFactory; +use Symfony\Bundle\CacheBundle\DependencyInjection\Provider\MemcachedProviderFactory; +use Symfony\Bundle\CacheBundle\DependencyInjection\Backend\ApcBackendFactory; +use Symfony\Bundle\CacheBundle\DependencyInjection\Provider\ApcProviderFactory; + +/** + * @author Victor Berchet + */ +class CacheBundle extends Bundle +{ + private $kernel; + + public function build(ContainerBuilder $container) + { + parent::build($container); + + $ext = $container->getExtension('cache'); + + $ext->addBackendFactory(new MemcachedBackendFactory()); + $ext->addBackendFactory(new ApcBackendFactory()); + + $ext->addProviderFactory(new MemcachedProviderFactory()); + //$ext->addProviderFactory(new ApcProviderFactory()); + + + //$container->addCompilerPass(new ServiceCreationCompilerPass()); + } +} diff --git a/src/Symfony/Bundle/CacheBundle/DependencyInjection/Backend/AbstractBackendFactory.php b/src/Symfony/Bundle/CacheBundle/DependencyInjection/Backend/AbstractBackendFactory.php new file mode 100644 index 0000000000000..88549a5b93c6d --- /dev/null +++ b/src/Symfony/Bundle/CacheBundle/DependencyInjection/Backend/AbstractBackendFactory.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\CacheBundle\DependencyInjection\Backend; + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * @author Victor Berchet + */ +abstract class AbstractBackendFactory implements BackendFactoryInterface +{ + public function init(ContainerBuilder $container, $config) + { + } + + public function getType() + { + return strtolower($this->getName()); + } + + public function getConfigKey() + { + return strtolower(preg_replace( + array('/[^a-z0-9.-_]/i', '/(?<=[a-zA-Z0-9])[A-Z]/'), + array('', '_\\0'), + $this->getName()) + ); + } + + protected function getName() + { + $class = get_class($this); + $pos = strrpos($class, '\\'); + $class = false === $pos ? $class : substr($class, $pos + 1); + + if ('BackendFactory' !== substr($class, -14)) { + throw new \LogicException('The factory name could not be determined.'); + } + + return substr($class,0, -14); + } +} \ No newline at end of file diff --git a/src/Symfony/Bundle/CacheBundle/DependencyInjection/Backend/ApcBackendFactory.php b/src/Symfony/Bundle/CacheBundle/DependencyInjection/Backend/ApcBackendFactory.php new file mode 100644 index 0000000000000..6e0cd76a1dede --- /dev/null +++ b/src/Symfony/Bundle/CacheBundle/DependencyInjection/Backend/ApcBackendFactory.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\CacheBundle\DependencyInjection\Backend; + +use Symfony\Component\Config\Definition\Builder\NodeBuilder; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * @author Victor Berchet + */ +class ApcBackendFactory extends AbstractBackendFactory +{ + public function addConfiguration(NodeBuilder $builder) + { + $builder->scalarNode($this->getConfigKey())->end(); + } + + public function createService($id, ContainerBuilder $container, $config) + { + } +} \ No newline at end of file diff --git a/src/Symfony/Bundle/CacheBundle/DependencyInjection/Backend/BackendFactoryInterface.php b/src/Symfony/Bundle/CacheBundle/DependencyInjection/Backend/BackendFactoryInterface.php new file mode 100644 index 0000000000000..8d375abfb04a8 --- /dev/null +++ b/src/Symfony/Bundle/CacheBundle/DependencyInjection/Backend/BackendFactoryInterface.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\CacheBundle\DependencyInjection\Backend; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; + +/** + * @author Victor Berchet + */ +interface BackendFactoryInterface +{ + function init(ContainerBuilder $container, $config); + function getType(); + function getConfigKey(); + function addConfiguration(NodeBuilder $builder); + function createService($id, ContainerBuilder $container, $config); +} \ No newline at end of file diff --git a/src/Symfony/Bundle/CacheBundle/DependencyInjection/Backend/MemcachedBackendFactory.php b/src/Symfony/Bundle/CacheBundle/DependencyInjection/Backend/MemcachedBackendFactory.php new file mode 100644 index 0000000000000..519af095bc0a1 --- /dev/null +++ b/src/Symfony/Bundle/CacheBundle/DependencyInjection/Backend/MemcachedBackendFactory.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\CacheBundle\DependencyInjection\Backend; + +use Symfony\Component\Config\Definition\Builder\NodeBuilder; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\DefinitionDecorator; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\Alias; + +/** + * Memcached backend. + * + * @author Victor Berchet + */ +class MemcachedBackendFactory extends AbstractBackendFactory +{ + private $factories = array(); + + public function addConfiguration(NodeBuilder $builder) + { + // TODO fix config + $builder + ->arrayNode($this->getConfigKey()) + ->fixXmlConfig('server') + ->children() + ->arrayNode('servers') + ->useAttributeAsKey('name') + ->prototype('array') + ->children() + ->scalarNode('host') + ->beforeNormalization() + ->ifInArray(array('127.0.0.1', '::1', '0:0:0:0:0:0:0:1')) + ->then(function($v) { return 'localhost'; }) + ->end() + ->defaultValue('%cache.memcached.defaults.host%') + ->end() + ->scalarNode('port')->defaultValue('%cache.memcached.defaults.port%')->end() + ->scalarNode('weight')->defaultValue('%cache.memcached.defaults.weight%')->end() + ; + } + + public function createService($id, ContainerBuilder $container, $config) + { + $signature = $this->getSignature($config); + $servers = array(); + + if (isset($this->factories[$signature])) { + $container->setAlias($id, $this->factories[$signature]); + } else { + $definition = new DefinitionDecorator('cache.backend.memcached'); + foreach ($config['servers'] as $server) { + $servers[] = array($server['host'], $server['port'], $server['weight']); + } + + if (count($servers) > 1) { + $definition->addMethodCall('addServers', $servers); + } else if (count($servers)) { + // TODO remove the if above once the config gets fixed + $definition->addMethodCall('addServer', $servers[0]); + } + + $container->setDefinition($id, $definition); + $this->factories[$signature] = $id; + } + } + + protected function getSignature(array $config) + { + // TODO check if the server ordering is significative + $description = ""; + foreach ($config['servers'] as $server) { + $description .= serialize($server); + } + return md5($description); + } + +} \ No newline at end of file diff --git a/src/Symfony/Bundle/CacheBundle/DependencyInjection/CacheExtension.php b/src/Symfony/Bundle/CacheBundle/DependencyInjection/CacheExtension.php new file mode 100644 index 0000000000000..3ef51c8ed04da --- /dev/null +++ b/src/Symfony/Bundle/CacheBundle/DependencyInjection/CacheExtension.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\CacheBundle\DependencyInjection; + +use Symfony\Component\Config\Definition\Processor; +use Symfony\Component\Config\FileLocator; +use Symfony\Component\HttpKernel\DependencyInjection\Extension; +use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Bundle\CacheBundle\DependencyInjection\Backend\BackendFactoryInterface; +use Symfony\Bundle\CacheBundle\DependencyInjection\Provider\ProviderFactoryInterface; + +/** + * CacheExtension is an extension for the Doctrine\Common\Cache interface. + * + * @author Lukas Kahwe Smith + * @author Victor Berchet + */ +class CacheExtension extends Extension +{ + private $beFactories = array(); + private $providerFactories = array(); + + public function load(array $configs, ContainerBuilder $container) + { + $processor = new Processor(); + $configuration = $this->getConfiguration($configs, $container); + $config = $processor->processConfiguration($configuration, $configs); + + $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); + $loader->load('services.xml'); + + $container->setParameter('cache.debug', $config['debug']); + + $this->initBackends($container, $config['backends']); + + $this->configureBackends($container, $config['backends']); + + //$this->configureProviders($container, $config['providers']); + + //$container->setParameter($this->getAlias().'.namespaces', $config['namespaces']); + } + + public function addBackendFactory(BackendFactoryInterface $beFactory) + { + $this->beFactories[$beFactory->getType()] = $beFactory; + } + + public function addProviderFactory(ProviderFactoryInterface $providerFactory) + { + $this->providerFactories[$providerFactory->getName()] = $providerFactory; + } + + private function initBackends(ContainerBuilder $container, $backends) + { + foreach ($backends as $name => $configs) { + foreach ($configs as $type => $config) { + $this->beFactories[$type]->init($container, $config); + } + } + } + + private function configureBackends(ContainerBuilder $container, $backends) + { + foreach ($backends as $name => $configs) { + foreach ($configs as $type => $config) { + $this->beFactories[$type]->createService('cache.backend.concrete.'.$name, $container, $config); + } + } + } + + private function configureProviders(ContainerBuilder $container, $configs) + { + foreach ($configs as $name => $config) { + $type = $config['type']; + $this->providerFactories[$type]->configure($container, $name, $config); + } + } + + public function getConfiguration(array $config, ContainerBuilder $container) + { + return new Configuration($this->beFactories, $this->providerFactories); + } + + public function getXsdValidationBasePath() + { + return __DIR__.'/../Resources/config/schema'; + } + + public function getNamespace() + { + return 'http://symfony.com/schema/dic/cache'; + } +} diff --git a/src/Symfony/Bundle/CacheBundle/DependencyInjection/Compiler/ServiceCreationCompilerPass.php b/src/Symfony/Bundle/CacheBundle/DependencyInjection/Compiler/ServiceCreationCompilerPass.php new file mode 100644 index 0000000000000..7f70ab557ee6f --- /dev/null +++ b/src/Symfony/Bundle/CacheBundle/DependencyInjection/Compiler/ServiceCreationCompilerPass.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\CacheBundle\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface, + Symfony\Component\DependencyInjection\ContainerBuilder, + Symfony\Component\DependencyInjection\Reference, + Symfony\Component\DependencyInjection\DefinitionDecorator; + +/** + * @author Lukas Kahwe Smith + */ +class ServiceCreationCompilerPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + $namespaces = $container->getParameter('cache.namespaces'); + + foreach ($namespaces as $name => $config) { + $id = 'cache.driver.'.$config['type']; + if (!$container->hasDefinition($id)) { + throw new \InvalidArgumentException('Supplied cache type is not supported: '.$config['type']); + } + + $namespace = empty($config['namespace']) ? $name : $config['namespace']; + $service = $container + ->setDefinition('cache.ns.'.$name, new DefinitionDecorator($id)) + ->addMethodCall('setNamespace', array($namespace)); + + switch ($config['type']) { + case 'memcache': + if (empty($config['id'])) { + throw new \InvalidArgumentException('Service id for memcache missing'); + } + $service->addMethodCall('setMemcache', array(new Reference($config['id']))); + break; + case 'memcached': + if (empty($config['id'])) { + throw new \InvalidArgumentException('Service id for memcached missing'); + } + $service->addMethodCall('setMemcached', array(new Reference($config['id']))); + break; + } + } + } +} diff --git a/src/Symfony/Bundle/CacheBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/CacheBundle/DependencyInjection/Configuration.php new file mode 100644 index 0000000000000..49925373ae6e9 --- /dev/null +++ b/src/Symfony/Bundle/CacheBundle/DependencyInjection/Configuration.php @@ -0,0 +1,93 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\CacheBundle\DependencyInjection; + +use Symfony\Component\Config\Definition\Builder\TreeBuilder; +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\ConfigurationInterface; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; + +/** + * Configuration for the Cache Bundle. + * + * @author Lukas Kahwe Smith + * @author Victor Berchet + */ +class Configuration implements ConfigurationInterface +{ + private $debug; + private $beFactories; + private $providerFactories; + + public function __construct(array $beFactories = array(), array $providerFactories = array()) + { + $this->beFactories = $beFactories; + $this->providerFactories = $providerFactories; + } + + /** + * Generates the configuration tree. + * + * @return TreeBuilder + */ + public function getConfigTreeBuilder() + { + $treeBuilder = new TreeBuilder(); + $rootNode = $treeBuilder->root('cache', 'array'); + + // main config + $rootNode + ->children() + ->scalarNode('debug')->defaultValue('%kernel.debug%')->end() + ; + + // backends + $beNode = $rootNode + ->fixXmlConfig('backend') + ->children() + ->arrayNode('backends') + ->useAttributeAsKey('type') + ->prototype('array') + ->validate() + ->ifTrue(function($v) { return 1 !== count($v); }) + ->thenInvalid('You must specify exactly one backend configuration') + ->end() + ->children() + ; + + $this->addBackendConfiguration($beNode); + + // providers +// $rootNode +// ->useAttributeAsKey('name') +// ->fixXmlConfig('provider') +// ->children() +// ->arrayNode('providers') +// ->useAttributeAsKey('name') +// ->prototype('array') +// ->children() +// ->scalarNode('type')->isRequired()->end() +// ->scalarNode('backend')->isRequired()->end() +// ->scalarNode('namespace')->defaultValue('')->end() +// ; + + return $treeBuilder; + } + + private function addBackendConfiguration(NodeBuilder $beNode) + { + foreach ($this->beFactories as $factory) { + $factory->addConfiguration($beNode); + } + } + +} diff --git a/src/Symfony/Bundle/CacheBundle/DependencyInjection/Provider/AbstractProviderFactory.php b/src/Symfony/Bundle/CacheBundle/DependencyInjection/Provider/AbstractProviderFactory.php new file mode 100644 index 0000000000000..9435c483ad8aa --- /dev/null +++ b/src/Symfony/Bundle/CacheBundle/DependencyInjection/Provider/AbstractProviderFactory.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\CacheBundle\DependencyInjection\Provider; + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * @author Victor Berchet + */ +abstract class AbstractProviderFactory implements ProviderFactoryInterface +{ + private $providers = array(); + + public function configure(ContainerBuilder $container, $name, array $config) + { + $signature = $this->getSignature($container, $config); + $type = $this->getName(); + + if (isset($this->providers[$type][$signature])) { + $container->setAlias($this->getId($name), $this->providers[$type][$signature]); + } else { + $definition = $this + ->getDefinition($config) + ->addMethodCall('setNamespace', array($config['namespace'])) + ->setPublic(true) + ; + $container->setDefinition($provider = $this->getId($name), $definition); + $this->providers[$type][$signature] = $provider; + } + } + + public function getName() + { + $class = get_class($this); + $pos = strrpos($class, '\\'); + $class = false === $pos ? $class : substr($class, $pos + 1); + + if ('ProviderFactory' !== substr($class, -15)) { + throw new \LogicException('The factory name could not be determined.'); + } + + return strtolower(substr($class,0, -15)); + } + + protected function getId($name) + { + return 'cache.provider.concrete.'.$name; + } + + +} \ No newline at end of file diff --git a/src/Symfony/Bundle/CacheBundle/DependencyInjection/Provider/ApcProviderFactory.php b/src/Symfony/Bundle/CacheBundle/DependencyInjection/Provider/ApcProviderFactory.php new file mode 100644 index 0000000000000..2a27cac3c6494 --- /dev/null +++ b/src/Symfony/Bundle/CacheBundle/DependencyInjection/Provider/ApcProviderFactory.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\CacheBundle\DependencyInjection\Provider; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\DefinitionDecorator; + +/** + * @author Victor Berchet + */ +class ApcProviderFactory extends AbstractProviderFactory +{ + public function getDefinition(array $config) + { + return new DefinitionDecorator('cache.provider.apc'); + } + + protected function getSignature(ContainerBuilder $container, array $config) + { + return $this->getName(); + } +} \ No newline at end of file diff --git a/src/Symfony/Bundle/CacheBundle/DependencyInjection/Provider/MemcachedProviderFactory.php b/src/Symfony/Bundle/CacheBundle/DependencyInjection/Provider/MemcachedProviderFactory.php new file mode 100644 index 0000000000000..f8195f072fec2 --- /dev/null +++ b/src/Symfony/Bundle/CacheBundle/DependencyInjection/Provider/MemcachedProviderFactory.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\CacheBundle\DependencyInjection\Provider; + +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\DefinitionDecorator; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\Alias; + +/** + * @author Victor Berchet + */ +class MemcachedProviderFactory extends AbstractProviderFactory +{ + public function getDefinition(array $config) + { + $definition = new DefinitionDecorator('cache.provider.memcached'); + + return $definition->addMethodCall('setMemcached', array(new Reference($config['backend']))); + } + + protected function getSignature(ContainerBuilder $container, array $config) + { + $backend = $config['backend']; + + return md5(serialize(array( + 'backend' => $container->hasAlias($backend) ? (string) $container->getAlias($backend) : $backend, + 'namespace' => $config['namespace'] + ))); + } +} \ No newline at end of file diff --git a/src/Symfony/Bundle/CacheBundle/DependencyInjection/Provider/ProviderFactoryInterface.php b/src/Symfony/Bundle/CacheBundle/DependencyInjection/Provider/ProviderFactoryInterface.php new file mode 100644 index 0000000000000..575ffefb2e757 --- /dev/null +++ b/src/Symfony/Bundle/CacheBundle/DependencyInjection/Provider/ProviderFactoryInterface.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\CacheBundle\DependencyInjection\Provider; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; + +/** + * @author Victor Berchet + */ +interface ProviderFactoryInterface +{ + function getName(); + //function configure(ContainerBuilder $container, $name, array $config); +} \ No newline at end of file diff --git a/src/Symfony/Bundle/CacheBundle/README.md b/src/Symfony/Bundle/CacheBundle/README.md new file mode 100644 index 0000000000000..0427b74f76369 --- /dev/null +++ b/src/Symfony/Bundle/CacheBundle/README.md @@ -0,0 +1,64 @@ +DoctrineCacheBundle +=================== + +This Bundle provides integration into Symfony2 with the Doctrine Common Cache layer + +Installation +============ + + 1. Add this bundle to your project as a Git submodule: + + $ git submodule add git://github.com/liip/LiipDoctrineCacheBundle.git vendor/bundles/Liip/DoctrineCacheBundle + + 2. Add the Liip namespace to your autoloader: + + // app/autoload.php + $loader->registerNamespaces(array( + 'Liip' => __DIR__.'/../vendor/bundles', + // your other namespaces + )); + + 3. Add this bundle to your application's kernel: + + // application/ApplicationKernel.php + public function registerBundles() + { + return array( + // ... + new Symfony\Bundle\CacheBundle\LiipDoctrineCacheBundle(), + // ... + ); + } + +Configuration +============= + +Simply configure any number of cache services: + + # app/config.yml + liip_doctrine_cache: + namespaces: + # name of the service (aka liip_doctrine_cache.ns.foo) + foo: + # cache namespace is "ding" + namespace: ding + # cache type is "apc" + type: apc + # name of the service (aka liip_doctrine_cache.ns.foo) and namespace + lala: + # cache type is "apc" + type: apc + # name of the service (aka liip_doctrine_cache.ns.bar) + bar: + # cache namespace is "ding" + namespace: ding + # cache type is "memcached" + type: memcached + # name of a service of class Memcached that is fully configured + id: my_memcached_service + +Custom cache types +================== + +Simply define a new type my defining a service named `liip_doctrine_cache.[type name]`. +Note the service needs to implement ``Doctrine\Common\Cache\Cache`` interface. diff --git a/src/Symfony/Bundle/CacheBundle/Resources/config/schema/cache-1.0.xsd b/src/Symfony/Bundle/CacheBundle/Resources/config/schema/cache-1.0.xsd new file mode 100644 index 0000000000000..d1094a26afbc7 --- /dev/null +++ b/src/Symfony/Bundle/CacheBundle/Resources/config/schema/cache-1.0.xsd @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/src/Symfony/Bundle/CacheBundle/Resources/config/services.xml b/src/Symfony/Bundle/CacheBundle/Resources/config/services.xml new file mode 100644 index 0000000000000..02909518c4449 --- /dev/null +++ b/src/Symfony/Bundle/CacheBundle/Resources/config/services.xml @@ -0,0 +1,37 @@ + + + + + + + Doctrine\Common\Cache\ApcCache + Doctrine\Common\Cache\ArrayCache + Doctrine\Common\Cache\MemcacheCache + Doctrine\Common\Cache\MemcachedCache + Doctrine\Common\Cache\WinCacheCache + Doctrine\Common\Cache\XcacheCache + Doctrine\Common\Cache\ZendDataCache + + localhost + 11211 + 0 + + + + + + + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/CacheBundle/Resources/meta/LICENSE b/src/Symfony/Bundle/CacheBundle/Resources/meta/LICENSE new file mode 100644 index 0000000000000..bc307fffd6080 --- /dev/null +++ b/src/Symfony/Bundle/CacheBundle/Resources/meta/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2011 Liip + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/Symfony/Bundle/CacheBundle/Tests/DependencyInjection/AbstractCacheExtensionTest.php b/src/Symfony/Bundle/CacheBundle/Tests/DependencyInjection/AbstractCacheExtensionTest.php new file mode 100644 index 0000000000000..996bff6fa23c7 --- /dev/null +++ b/src/Symfony/Bundle/CacheBundle/Tests/DependencyInjection/AbstractCacheExtensionTest.php @@ -0,0 +1,105 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\CacheBundle\Tests\DependencyInjection; + +use Symfony\Bundle\CacheBundle\DependencyInjection\CacheExtension; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; +use Symfony\Bundle\CacheBundle\CacheBundle; + +abstract class AbstractCacheExtensionTest extends \PHPUnit_Framework_TestCase +{ + abstract protected function loadFromFile(ContainerBuilder $container, $file); + +// public function testCsrfProtection() +// { +// $container = $this->createContainerFromFile('full'); +// +// $def = $container->getDefinition('form.type_extension.csrf'); +// +// $this->assertTrue($container->getParameter('form.type_extension.csrf.enabled')); +// $this->assertEquals('%form.type_extension.csrf.enabled%', $def->getArgument(0)); +// $this->assertEquals('_csrf', $container->getParameter('form.type_extension.csrf.field_name')); +// $this->assertEquals('%form.type_extension.csrf.field_name%', $def->getArgument(1)); +// $this->assertEquals('s3cr3t', $container->getParameterBag()->resolveValue($container->findDefinition('form.csrf_provider')->getArgument(1))); +// } + + public function testRootOptions() + { + $container = $this->createContainerFromFile('full'); + + $this->assertEquals($container->getParameter('kernel.debug'), $container->getParameter('cache.debug')); + } + + public function testOnlyOneBackedIsAllowedPerKey() + { + $this->markTestIncomplete('only one be allowed per key'); + } + + public function testAddABackendsFromABundle() + { + $this->markTestIncomplete(); + } + + // todo move the test below to backend specific files, create a container for each + + public function testMemcachedSingleServer() + { + $container = $this->createContainerFromFile('full'); + + $definition = $container->getDefinition('cache.backend.concrete.memcached_be'); + + $this->assertEquals('Memcached', $definition->getClass()); + $this->assertTrue($definition->isPublic()); + $calls = $definition->getMethodCalls(); + $this->assertEquals(array(array('addServer' , array('localhost', '11211', '0'))), $calls); + } + + public function testMemcachedMultipleServers() + { + $this->markTestIncomplete(); + } + + public function testMemcachedDefaults() + { + $this->markTestIncomplete('todo pending config fixes'); + } + + public function testMemcachedMerge() + { + $this->markTestIncomplete('todo merging when same config'); + } + + protected function createContainer() + { + return new ContainerBuilder(new ParameterBag(array( + 'kernel.bundles' => array('CacheBundle' => 'Symfony\\Bundle\\CacheBundle\\CacheBundle'), + 'kernel.cache_dir' => __DIR__, + 'kernel.compiled_classes' => array(), + 'kernel.debug' => true, + ))); + } + + protected function createContainerFromFile($file, $data = array()) + { + $container = $this->createContainer($data); + $container->registerExtension(new CacheExtension()); + $this->loadFromFile($container, $file); + + $bundle = new CacheBundle(); + $bundle->build($container); + + $container->compile(); + + return $container; + } +} diff --git a/src/Symfony/Bundle/CacheBundle/Tests/DependencyInjection/Backend/BackendFactoryTest.php b/src/Symfony/Bundle/CacheBundle/Tests/DependencyInjection/Backend/BackendFactoryTest.php new file mode 100644 index 0000000000000..b8d1b6d36a58c --- /dev/null +++ b/src/Symfony/Bundle/CacheBundle/Tests/DependencyInjection/Backend/BackendFactoryTest.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\CacheBundle\Tests\DependencyInjection\Backend; + +class BackendFactoryTest extends \PHPUnit_Framework_TestCase +{ + /** + * @dataProvider provideBackendFactoryClassName + */ + public function testGetName($className, $valid, $name = null) + { + $factory = $this->getBackendFactoryMock($className); + $getName = new \ReflectionMethod($factory, 'getName'); + $getName->setAccessible(true); + try { + $this->assertEquals($name, $getName->invoke($factory)); + $this->assertTrue($valid); + } catch (\LogicException $e) { + $this->assertFalse($valid); + } + } + + public function provideBackendFactoryClassName() + { + return array( + array('FooBackendFactory', true, 'Foo'), + array('Foo', false), + ); + } + + /** + * @dataProvider provideNameTypeKey + */ + public function testGenerateConfigKey($name, $type, $key) + { + $factory = $this->getBackendFactoryMock(null, $name); + + $factory + ->expects($this->once()) + ->method('getName') + ->will($this->returnValue($name)) + ; + + $factory->getType(); + + //$this->assertEquals($key, $factory->getConfigKey()); + } + + /** + * @dataProvider provideNameTypeKey + */ + public function testGenerateType($name, $type, $key) + { + $factory = $this->getBackendFactoryMock(null, $name); + + $factory + ->expects($this->once()) + ->method('getName') + ->will($this->returnValue($name)) + ; + + $this->assertEquals($type, $factory->getType()); + } + + public function provideNameTypeKey() + { + return array( + array('Foo', 'foo', 'foo'), + array('FooBar', 'foobar', 'foo_bar'), + array('Foo Bar', 'foo bar', 'foo_bar'), + array('Foo bar', 'foo bar', 'foobar'), + ); + } + + protected function getBackendFactoryMock($className = null, $name = null) + { + $methods = array('addConfiguration', 'createService'); + if ($name) { + $methods[] = 'getName'; + } + + $factory = $this + ->getMockBuilder('Symfony\\Bundle\\CacheBundle\\DependencyInjection\\Backend\\AbstractBackendFactory') + ->setMethods($methods) + ; + + if ($className) { + $factory->setMockClassName($className); + } + + return $factory->getMock(); + } +} \ No newline at end of file diff --git a/src/Symfony/Bundle/CacheBundle/Tests/DependencyInjection/Fixtures/php/full.php b/src/Symfony/Bundle/CacheBundle/Tests/DependencyInjection/Fixtures/php/full.php new file mode 100644 index 0000000000000..1592c940ef496 --- /dev/null +++ b/src/Symfony/Bundle/CacheBundle/Tests/DependencyInjection/Fixtures/php/full.php @@ -0,0 +1,18 @@ +loadFromExtension('cache', array( + 'debug' => '%kernel.debug%', + 'backends' => array( + 'memcached_be' => array( + 'memcached' => array( + 'servers' => array( + 'memcached_server' => array( + 'host' => '127.0.0.1', + 'port' => 11211, + 'weight' => 0 + ) + ) + ) + ) + ) +)); diff --git a/src/Symfony/Bundle/CacheBundle/Tests/DependencyInjection/Fixtures/xml/full.xml b/src/Symfony/Bundle/CacheBundle/Tests/DependencyInjection/Fixtures/xml/full.xml new file mode 100644 index 0000000000000..b0ef0eb29b779 --- /dev/null +++ b/src/Symfony/Bundle/CacheBundle/Tests/DependencyInjection/Fixtures/xml/full.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/CacheBundle/Tests/DependencyInjection/Fixtures/yml/full.yml b/src/Symfony/Bundle/CacheBundle/Tests/DependencyInjection/Fixtures/yml/full.yml new file mode 100644 index 0000000000000..718a72f20b294 --- /dev/null +++ b/src/Symfony/Bundle/CacheBundle/Tests/DependencyInjection/Fixtures/yml/full.yml @@ -0,0 +1,10 @@ +cache: + debug: %kernel.debug% + backends: + memcached_be: + memcached: + servers: + memcached_server: + host: 127.0.0.1 + port: 11211 + weight: 0 diff --git a/src/Symfony/Bundle/CacheBundle/Tests/DependencyInjection/PhpCacheExtensionTest.php b/src/Symfony/Bundle/CacheBundle/Tests/DependencyInjection/PhpCacheExtensionTest.php new file mode 100644 index 0000000000000..23941e422b3a5 --- /dev/null +++ b/src/Symfony/Bundle/CacheBundle/Tests/DependencyInjection/PhpCacheExtensionTest.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\CacheBundle\Tests\DependencyInjection; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; +use Symfony\Component\Config\FileLocator; + +class PhpCacheExtensionTest extends AbstractCacheExtensionTest +{ + protected function loadFromFile(ContainerBuilder $container, $file) + { + $loader = new PhpFileLoader($container, new FileLocator(__DIR__.'/Fixtures/php')); + $loader->load($file.'.php'); + } +} diff --git a/src/Symfony/Bundle/CacheBundle/Tests/DependencyInjection/XmlCacheExtensionTest.php b/src/Symfony/Bundle/CacheBundle/Tests/DependencyInjection/XmlCacheExtensionTest.php new file mode 100644 index 0000000000000..5b1969920f611 --- /dev/null +++ b/src/Symfony/Bundle/CacheBundle/Tests/DependencyInjection/XmlCacheExtensionTest.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\CacheBundle\Tests\DependencyInjection; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; +use Symfony\Component\Config\FileLocator; + +class XmlCacheExtensionTest extends AbstractCacheExtensionTest +{ + protected function loadFromFile(ContainerBuilder $container, $file) + { + $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/Fixtures/xml')); + $loader->load($file.'.xml'); + } +} diff --git a/src/Symfony/Bundle/CacheBundle/Tests/DependencyInjection/YamlCacheExtensionTest.php b/src/Symfony/Bundle/CacheBundle/Tests/DependencyInjection/YamlCacheExtensionTest.php new file mode 100644 index 0000000000000..6e7aac9be2550 --- /dev/null +++ b/src/Symfony/Bundle/CacheBundle/Tests/DependencyInjection/YamlCacheExtensionTest.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\CacheBundle\Tests\DependencyInjection; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; +use Symfony\Component\Config\FileLocator; + +class YamlCacheExtensionTest extends AbstractCacheExtensionTest +{ + protected function loadFromFile(ContainerBuilder $container, $file) + { + $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/Fixtures/yml')); + $loader->load($file.'.yml'); + } +} diff --git a/src/Symfony/Bundle/CacheBundle/composer.json b/src/Symfony/Bundle/CacheBundle/composer.json new file mode 100644 index 0000000000000..3668029a9a641 --- /dev/null +++ b/src/Symfony/Bundle/CacheBundle/composer.json @@ -0,0 +1,26 @@ +{ + "name": "symfony/cache-bundle", + "description": "This Bundle provides integration into Symfony2 with the Doctrine Common Cache layer.", + "keywords": ["symfony2", "cache"], + "type": "symfony-bundle", + "license": "MIT", + "authors": [ + { + "name": "Liip AG", + "homepage": "http://www.liip.ch/" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "require": { + "php": ">=5.3.0", + "symfony/symfony": ">=2.0", + "doctrine/common": ">=2.2" + }, + "autoload": { + "psr-0": { "Symfony\\Bundle\\CacheBundle": "" } + }, + "target-dir": "Symfony/Bundle/CacheBundle" +}