diff --git a/Block/BlockServiceManager.php b/Block/BlockServiceManager.php index e2f39fbd..3c607704 100644 --- a/Block/BlockServiceManager.php +++ b/Block/BlockServiceManager.php @@ -32,6 +32,8 @@ class BlockServiceManager implements BlockServiceManagerInterface protected $inValidate; + protected $contexts; + /** * @param ContainerInterface $container * @param $debug @@ -40,6 +42,7 @@ class BlockServiceManager implements BlockServiceManagerInterface public function __construct(ContainerInterface $container, $debug, LoggerInterface $logger = null) { $this->services = array(); + $this->contexts = array(); $this->container = $container; } @@ -96,9 +99,17 @@ public function has($id) /** * {@inheritdoc} */ - public function add($name, $service) + public function add($name, $service, $contexts = array()) { $this->services[$name] = $service; + + foreach ($contexts as $context) { + if (!array_key_exists($context, $this->contexts)) { + $this->contexts[$context] = array(); + } + + $this->contexts[$context][] = $name; + } } /** @@ -106,7 +117,9 @@ public function add($name, $service) */ public function setServices(array $blockServices) { - $this->services = $blockServices; + foreach($blockServices as $name => $service) { + $this->add($name, $service); + } } /** @@ -123,6 +136,24 @@ public function getServices() return $this->services; } + /** + * {@inheritdoc} + */ + public function getServicesByContext($context) + { + if (!array_key_exists($context, $this->contexts)) { + return array(); + } + + $services = array(); + + foreach ($this->contexts[$context] as $name) { + $services[$name] = $this->getService($name); + } + + return $services; + } + /** * {@inheritdoc} */ @@ -142,6 +173,8 @@ public function getLoadedServices() } /** + * @todo: this function should be remove into a proper statefull object + * * {@inheritdoc} */ public function validate(ErrorElement $errorElement, BlockInterface $block) diff --git a/Block/BlockServiceManagerInterface.php b/Block/BlockServiceManagerInterface.php index 3f509544..c8e6404f 100644 --- a/Block/BlockServiceManagerInterface.php +++ b/Block/BlockServiceManagerInterface.php @@ -18,10 +18,11 @@ interface BlockServiceManagerInterface /** * @param string $name * @param string $service + * @param array $contexts * * @return void */ - public function add($name, $service); + public function add($name, $service, $contexts = array()); /** * Return the block service linked to the link @@ -33,6 +34,8 @@ public function add($name, $service); public function get(BlockInterface $block); /** + * @deprecated will be remove in 2.4, use the add method instead + * * @param array $blockServices * * @return void @@ -45,7 +48,13 @@ public function setServices(array $blockServices); public function getServices(); /** + * @param string $name * + * @return array + */ + public function getServicesByContext($name); + + /** * @param string $name * * @return boolean @@ -60,6 +69,8 @@ public function has($name); public function getService($name); /** + * @deprecated will be remove in 2.4 + * * @return array */ public function getLoadedServices(); diff --git a/CHANGELOG.md b/CHANGELOG.md index 31be2fb6..1aadc06c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ A [BC BREAK] means the update will break the project for many reasons: * new dependencies * class refactoring +### 2014-04-23 + +* [BC BREAK] Complete support for context, add new method in BlockServiceManager (getServicesByContext) + ### 2014-03-10 * [BC BREAK] Updated configuration: ``sonata_block.profiler.container_types`` is deprecated in favor of ``sonata_block.container.types``; please update your configuration accordingly. diff --git a/Command/DebugBlocksCommand.php b/Command/DebugBlocksCommand.php index 4cfb11fd..ce1708c7 100644 --- a/Command/DebugBlocksCommand.php +++ b/Command/DebugBlocksCommand.php @@ -12,6 +12,7 @@ namespace Sonata\BlockBundle\Command; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\Output; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -22,11 +23,19 @@ public function configure() { $this->setName('sonata:block:debug'); $this->setDescription('Debug all blocks available, show default settings of each block'); + + $this->addOption('context', 'c', InputOption::VALUE_REQUIRED, 'display service for the specified context'); } public function execute(InputInterface $input, OutputInterface $output) { - foreach ($this->getBlockServiceManager()->getServices() as $code => $service) { + if ($input->getOption('context')) { + $services = $this->getBlockServiceManager()->getServicesByContext($input->getOption('context')); + } else { + $services = $this->getBlockServiceManager()->getServices(); + } + + foreach ($services as $code => $service) { $resolver = new OptionsResolver(); $service->setDefaultSettings($resolver); diff --git a/DependencyInjection/Compiler/TweakCompilerPass.php b/DependencyInjection/Compiler/TweakCompilerPass.php index b23d688e..c5b33244 100644 --- a/DependencyInjection/Compiler/TweakCompilerPass.php +++ b/DependencyInjection/Compiler/TweakCompilerPass.php @@ -29,8 +29,10 @@ public function process(ContainerBuilder $container) { $manager = $container->getDefinition('sonata.block.manager'); + $parameters = $container->getParameter('sonata_block.blocks'); + foreach ($container->findTaggedServiceIds('sonata.block') as $id => $attributes) { - $manager->addMethodCall('add', array($id, $id)); + $manager->addMethodCall('add', array($id, $id, isset($parameters[$id]) ? $parameters[$id]['contexts'] : array())); } $services = array(); diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 6ae23765..3b2c6d57 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -47,14 +47,21 @@ public function getConfigTreeBuilder() ->fixXmlConfig('block') ->fixXmlConfig('block_by_class') ->validate() - ->ifTrue(function ($v) { - if (isset($v['profiler']['container_types']) && !empty($v['profiler']['container_types']) - && isset($v['container']['types']) && !empty($v['container']['types'])) { - return 0 !== count(array_diff($v['profiler']['container_types'], $v['container']['types'])); - } - return false; - }) - ->thenInvalid("You cannot have different config options for sonata_block.profiler.container_types and sonata_block.container.types; the first one is deprecated, in case of doubt use the latter") + ->always(function($value) { + foreach ($value['blocks'] as $name => &$block) { + if (count($block['contexts']) == 0) { + $block['contexts'] = $value['default_contexts']; + } + } + + if (isset($value['profiler']['container_types']) && !empty($value['profiler']['container_types']) + && isset($value['container']['types']) && !empty($value['container']['types']) + && 0 !== count(array_diff($value['profiler']['container_types'], $value['container']['types']))) { + throw new \RuntimeException("You cannot have different config options for sonata_block.profiler.container_types and sonata_block.container.types; the first one is deprecated, in case of doubt use the latter"); + } + + return $value; + }) ->end() ->children() ->arrayNode('profiler') diff --git a/DependencyInjection/SonataBlockExtension.php b/DependencyInjection/SonataBlockExtension.php index 029d8ed2..c0c71795 100644 --- a/DependencyInjection/SonataBlockExtension.php +++ b/DependencyInjection/SonataBlockExtension.php @@ -197,9 +197,6 @@ public function configureForm(ContainerBuilder $container, array $config) $contexts[$context][] = $service; } } - - $container->getDefinition('sonata.block.form.type.block') - ->replaceArgument(1, $contexts); } /** diff --git a/Form/Type/ServiceListType.php b/Form/Type/ServiceListType.php index 56910f9b..6480eeea 100644 --- a/Form/Type/ServiceListType.php +++ b/Form/Type/ServiceListType.php @@ -23,16 +23,12 @@ class ServiceListType extends AbstractType { protected $manager; - protected $contexts; - /** * @param BlockServiceManagerInterface $manager - * @param array $contexts */ - public function __construct(BlockServiceManagerInterface $manager, array $contexts = array()) + public function __construct(BlockServiceManagerInterface $manager) { $this->manager = $manager; - $this->contexts = $contexts; } /** @@ -56,25 +52,19 @@ public function getParent() */ public function setDefaultOptions(OptionsResolverInterface $resolver) { - $contexts = $this->contexts; $manager = $this->manager; + $resolver->setRequired(array( + 'context', + )); + $resolver->setDefaults(array( - 'context' => false, 'multiple' => false, 'expanded' => false, - 'choices' => function (Options $options, $previousValue) use ($contexts, $manager) { - if (!isset($contexts[$options['context']])) { - if (Kernel::MINOR_VERSION < 3) { - throw new \RuntimeException(sprintf('Invalid context: `%s`', $options['context'])); - } - - throw new InvalidArgumentException(sprintf('Invalid context: `%s`', $options['context'])); - } - + 'choices' => function (Options $options, $previousValue) use ($manager) { $types = array(); - foreach ($contexts[$options['context']] as $service) { - $types[$service] = sprintf('%s - %s', $manager->getService($service)->getName(), $service); + foreach ($manager->getServicesByContext($options['context']) as $code => $service) { + $types[$code] = sprintf('%s - %s', $service->getName(), $code); } return $types; diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..829424a5 --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +.PHONY: test + +test: + phpunit + cd Resources/doc && sphinx-build -W -b html -d _build/doctrees . _build/html diff --git a/Resources/config/form.xml b/Resources/config/form.xml index 6ba5fc66..22ad265b 100644 --- a/Resources/config/form.xml +++ b/Resources/config/form.xml @@ -8,7 +8,6 @@ - diff --git a/Tests/Block/BlockServiceManagerTest.php b/Tests/Block/BlockServiceManagerTest.php index f5cfdf34..8004ed0b 100644 --- a/Tests/Block/BlockServiceManagerTest.php +++ b/Tests/Block/BlockServiceManagerTest.php @@ -67,4 +67,28 @@ public function testGetBlockServiceException() $manager->get($block); } + + public function testGetEmptyListFromInvalidContext() + { + $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); + $manager = new BlockServiceManager($container, true); + + $service = $this->getMock('Sonata\BlockBundle\Block\BlockServiceInterface'); + + $manager->add('foo.bar', $service); + + $this->assertEmpty($manager->getServicesByContext('fake')); + } + + public function testGetListFromValidContext() + { + $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); + $manager = new BlockServiceManager($container, true); + + $service = $this->getMock('Sonata\BlockBundle\Block\BlockServiceInterface'); + + $manager->add('foo.bar', $service, array('fake')); + + $this->assertNotEmpty($manager->getServicesByContext('fake')); + } } diff --git a/Tests/DependencyInjection/ConfigurationTest.php b/Tests/DependencyInjection/ConfigurationTest.php index 0237cba8..67fb8d3a 100644 --- a/Tests/DependencyInjection/ConfigurationTest.php +++ b/Tests/DependencyInjection/ConfigurationTest.php @@ -26,7 +26,8 @@ public function testOptions() $processor = new Processor(); $config = $processor->processConfiguration(new Configuration($defaultTemplates), array(array( - 'default_contexts' => array('cms') + 'default_contexts' => array('cms'), + 'blocks' => array('my.block.type' => array()) ))); @@ -62,7 +63,13 @@ public function testOptions() ), 'templates' => $defaultTemplates, ), - 'blocks' => array(), + 'blocks' => array( + 'my.block.type' => array( + 'contexts' => array('cms'), + 'cache' => 'sonata.cache.noop', + 'settings' => array () + ) + ), 'menus' => array(), 'blocks_by_class' => array(), 'exception' => array( diff --git a/Tests/Form/Type/ServiceListTypeTest.php b/Tests/Form/Type/ServiceListTypeTest.php index 8b3281de..e5cf66d2 100644 --- a/Tests/Form/Type/ServiceListTypeTest.php +++ b/Tests/Form/Type/ServiceListTypeTest.php @@ -27,13 +27,11 @@ public function testFormType() $this->assertEquals('choice', $type->getParent()); } + /** + * @expectedException Symfony\Component\OptionsResolver\Exception\MissingOptionsException + */ public function testOptionsWithInvalidContext() { - if (Kernel::MINOR_VERSION < 3) { - $this->setExpectedException('RuntimeException'); - } else { - $this->setExpectedException('\Symfony\Component\Form\Exception\InvalidArgumentException'); - } $blockServiceManager = $this->getMock('Sonata\BlockBundle\Block\BlockServiceManagerInterface'); @@ -52,7 +50,12 @@ public function testOptionWithValidContext() $blockService->expects($this->once())->method('getName')->will($this->returnValue('value')); $blockServiceManager = $this->getMock('Sonata\BlockBundle\Block\BlockServiceManagerInterface'); - $blockServiceManager->expects($this->once())->method('getService')->will($this->returnValue($blockService)); + $blockServiceManager + ->expects($this->once()) + ->method('getServicesByContext') + ->with($this->equalTo('cms')) + ->will($this->returnValue(array('my.service.code' => $blockService))); + $type = new ServiceListType($blockServiceManager, array( 'cms' => array('my.service.code') ));