Skip to content

Commit

Permalink
improve context management
Browse files Browse the repository at this point in the history
  • Loading branch information
Thomas Rabaix committed Apr 22, 2014
1 parent 75e6dc2 commit 0f32640
Show file tree
Hide file tree
Showing 13 changed files with 134 additions and 43 deletions.
37 changes: 35 additions & 2 deletions Block/BlockServiceManager.php
Expand Up @@ -32,6 +32,8 @@ class BlockServiceManager implements BlockServiceManagerInterface

protected $inValidate;

protected $contexts;

/**
* @param ContainerInterface $container
* @param $debug
Expand All @@ -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;
}

Expand Down Expand Up @@ -96,17 +99,27 @@ 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;
}
}

/**
* {@inheritdoc}
*/
public function setServices(array $blockServices)
{
$this->services = $blockServices;
foreach($blockServices as $name => $service) {
$this->add($name, $service);
}
}

/**
Expand All @@ -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}
*/
Expand All @@ -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)
Expand Down
13 changes: 12 additions & 1 deletion Block/BlockServiceManagerInterface.php
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -60,6 +69,8 @@ public function has($name);
public function getService($name);

/**
* @deprecated will be remove in 2.4
*
* @return array
*/
public function getLoadedServices();
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -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.
Expand Down
11 changes: 10 additions & 1 deletion Command/DebugBlocksCommand.php
Expand Up @@ -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;
Expand All @@ -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);
Expand Down
4 changes: 3 additions & 1 deletion DependencyInjection/Compiler/TweakCompilerPass.php
Expand Up @@ -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();
Expand Down
23 changes: 15 additions & 8 deletions DependencyInjection/Configuration.php
Expand Up @@ -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')
Expand Down
3 changes: 0 additions & 3 deletions DependencyInjection/SonataBlockExtension.php
Expand Up @@ -197,9 +197,6 @@ public function configureForm(ContainerBuilder $container, array $config)
$contexts[$context][] = $service;
}
}

$container->getDefinition('sonata.block.form.type.block')
->replaceArgument(1, $contexts);
}

/**
Expand Down
26 changes: 8 additions & 18 deletions Form/Type/ServiceListType.php
Expand Up @@ -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;
}

/**
Expand All @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions Makefile
@@ -0,0 +1,5 @@
.PHONY: test

test:
phpunit
cd Resources/doc && sphinx-build -W -b html -d _build/doctrees . _build/html
1 change: 0 additions & 1 deletion Resources/config/form.xml
Expand Up @@ -8,7 +8,6 @@
<service id="sonata.block.form.type.block" class="Sonata\BlockBundle\Form\Type\ServiceListType">
<tag name="form.type" alias="sonata_block_service_choice" />
<argument type="service" id="sonata.block.manager" />
<argument />
</service>

<service id="sonata.block.form.type.container_template" class="Sonata\BlockBundle\Form\Type\ContainerTemplateType">
Expand Down
24 changes: 24 additions & 0 deletions Tests/Block/BlockServiceManagerTest.php
Expand Up @@ -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'));
}
}
11 changes: 9 additions & 2 deletions Tests/DependencyInjection/ConfigurationTest.php
Expand Up @@ -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())
)));


Expand Down Expand Up @@ -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(
Expand Down
15 changes: 9 additions & 6 deletions Tests/Form/Type/ServiceListTypeTest.php
Expand Up @@ -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');

Expand All @@ -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')
));
Expand Down

0 comments on commit 0f32640

Please sign in to comment.