Upgrade 1-11.38

This commit is contained in:
xesmyd
2026-03-30 14:10:30 +02:00
parent f2a7e6d1fc
commit ac648ef29d
24665 changed files with 69682 additions and 2205004 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2010-2016 Thomas Rabaix
Copyright (c) 2010 Thomas Rabaix
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+17 -3
View File
@@ -14,7 +14,7 @@ lint-composer:
.PHONY: lint-composer
lint-yaml:
find . -name '*.yml' -not -path './vendor/*' -not -path './src/Resources/public/vendor/*' | xargs yaml-lint
yaml-lint --ignore-non-yaml-files --quiet --exclude vendor .
.PHONY: lint-yaml
@@ -51,8 +51,22 @@ cs-fix-xml:
done
.PHONY: cs-fix-xml
test:
phpunit -c phpunit.xml.dist --coverage-clover build/logs/clover.xml
build:
mkdir $@
HAS_XDEBUG=$(shell php --modules|grep --quiet xdebug;echo $$?)
build/xdebug-filter.php: phpunit.xml.dist build
ifeq ($(HAS_XDEBUG), 0)
phpunit --dump-xdebug-filter $@
endif
test: build/xdebug-filter.php
ifeq ($(HAS_XDEBUG), 0)
phpunit --prepend build/xdebug-filter.php -c phpunit.xml.dist --coverage-clover build/logs/clover.xml
else
phpunit -c phpunit.xml.dist
endif
.PHONY: test
docs:
+15 -4
View File
@@ -20,13 +20,23 @@
}
],
"require": {
"php": "^5.6 || ^7.0",
"doctrine/common": "^2.3",
"php": "^7.1",
"doctrine/collections": "^1.6",
"doctrine/common": "^2.3 || ^3.0",
"psr/cache": "^1.0",
"sonata-project/cache": "^1.0 || ^2.0",
"sonata-project/core-bundle": "^3.4",
"sonata-project/core-bundle": "^3.15.1",
"sonata-project/doctrine-extensions": "^1.1",
"symfony/asset": "^2.8 || ^3.2 || ^4.0",
"symfony/config": "^2.8 || ^3.2 || ^4.0",
"symfony/console": "^2.8 || ^3.2 || ^4.0",
"symfony/dependency-injection": "^2.8 || ^3.2 || ^4.0",
"symfony/event-dispatcher": "^2.8 || ^3.2 || ^4.0",
"symfony/form": "^2.8 || ^3.2 || ^4.0",
"symfony/framework-bundle": "^2.8 || ^3.2 || ^4.0",
"symfony/http-foundation": "^2.8 || ^3.2 || ^4.0",
"symfony/http-kernel": "^2.8 || ^3.2 || ^4.0",
"symfony/options-resolver": "^2.8 || ^3.2 || ^4.0",
"symfony/templating": "^2.8 || ^3.2 || ^4.0",
"symfony/twig-bundle": "^2.8 || ^3.2 || ^4.0",
"twig/twig": "^1.34 || ^2.0"
@@ -38,7 +48,8 @@
"jms/di-extra-bundle": "^1.7",
"knplabs/knp-menu-bundle": "^2.0",
"sonata-project/admin-bundle": "^3.22",
"symfony/phpunit-bridge": "^4.0",
"symfony/debug": "^2.8 || ^3.2 || ^4.0",
"symfony/phpunit-bridge": "^4.2",
"symfony/stopwatch": "^2.8 || ^3.2 || ^4.0"
},
"suggest": {
+11 -2
View File
@@ -1,5 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
DO NOT EDIT THIS FILE!
It's auto-generated by sonata-project/dev-kit package.
-->
<phpunit backupGlobals="false"
backupStaticAttributes="false"
colors="true"
@@ -8,15 +14,18 @@
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
bootstrap="tests/bootstrap.php"
>
<testsuites>
<testsuite name="SonataBlockBundle Test Suite">
<testsuite name="Sonata Block Bundle Test Suite">
<directory suffix="Test.php">./tests/</directory>
</testsuite>
</testsuites>
<listeners>
<listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener" />
</listeners>
<filter>
<whitelist>
<directory suffix=".php">./src/</directory>
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -18,8 +20,12 @@ use Symfony\Component\DependencyInjection\Reference;
/**
* Use annotations to define block classes.
*
* @final since sonata-project/block-bundle 3.0
*
* @Annotation
* @Target("CLASS")
*
* @deprecated since sonata-project/block-bundle 3.16, to be removed in 4.0.
*/
class Block implements MetadataProcessorInterface
{
@@ -30,9 +36,6 @@ class Block implements MetadataProcessorInterface
*/
public $id;
/**
* @param ClassMetadata $metadata
*/
public function processMetadata(ClassMetadata $metadata)
{
if (!empty($this->id)) {
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -23,7 +25,7 @@ namespace Sonata\BlockBundle\Block;
*
* @author Sullivan Senechal <soullivaneuh@gmail.com>
*
* @deprecated since 3.2, to be removed with 4.0
* @deprecated since sonata-project/block-bundle 3.2, to be removed with 4.0
*/
abstract class AbstractBlockService extends \Sonata\BlockBundle\Block\Service\AbstractBlockService
{
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -27,7 +29,7 @@ use Sonata\BlockBundle\Block\Service\AbstractAdminBlockService;
*
* @author Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* @deprecated since 3.2, to be removed with 4.0
* @deprecated since sonata-project/block-bundle 3.2, to be removed with 4.0
*/
abstract class BaseBlockService extends AbstractAdminBlockService implements BlockAdminServiceInterface
{
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -23,7 +25,7 @@ use Sonata\BlockBundle\Block\Service\AdminBlockServiceInterface;
/**
* NEXT_MAJOR: remove this interface.
*
* @deprecated since 3.2, to be removed with 4.0
* @deprecated since sonata-project/block-bundle 3.2, to be removed with 4.0
*/
interface BlockAdminServiceInterface extends AdminBlockServiceInterface
{
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -13,6 +15,9 @@ namespace Sonata\BlockBundle\Block;
use Sonata\BlockBundle\Model\BlockInterface;
/**
* @final since sonata-project/block-bundle 3.0
*/
class BlockContext implements BlockContextInterface
{
/**
@@ -25,50 +30,34 @@ class BlockContext implements BlockContextInterface
*/
protected $settings;
/**
* @param BlockInterface $block
* @param array $settings
*/
public function __construct(BlockInterface $block, array $settings = [])
{
$this->block = $block;
$this->settings = $settings;
}
/**
* {@inheritdoc}
*/
public function getBlock()
{
return $this->block;
}
/**
* {@inheritdoc}
*/
public function getSettings()
{
return $this->settings;
}
/**
* {@inheritdoc}
*/
public function getSetting($name)
{
if (!array_key_exists($name, $this->settings)) {
if (!\array_key_exists($name, $this->settings)) {
throw new \RuntimeException(sprintf('Unable to find the option `%s` (%s) - define the option in the related BlockServiceInterface', $name, $this->block->getType()));
}
return $this->settings[$name];
}
/**
* {@inheritdoc}
*/
public function setSetting($name, $value)
{
if (!array_key_exists($name, $this->settings)) {
if (!\array_key_exists($name, $this->settings)) {
throw new \RuntimeException(sprintf('It\'s not possible add non existing setting `%s`.', $name));
}
@@ -77,9 +66,6 @@ class BlockContext implements BlockContextInterface
return $this;
}
/**
* {@inheritdoc}
*/
public function getTemplate()
{
return $this->getSetting('template');
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -18,6 +20,9 @@ use Symfony\Component\OptionsResolver\Exception\ExceptionInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
/**
* @final since sonata-project/block-bundle 3.0
*/
class BlockContextManager implements BlockContextManagerInterface
{
/**
@@ -58,12 +63,6 @@ class BlockContextManager implements BlockContextManagerInterface
*/
private $reflectionCache;
/**
* @param BlockLoaderInterface $blockLoader
* @param BlockServiceManagerInterface $blockService
* @param array $cacheBlocks
* @param LoggerInterface|null $logger
*/
public function __construct(BlockLoaderInterface $blockLoader, BlockServiceManagerInterface $blockService,
array $cacheBlocks = [], LoggerInterface $logger = null
) {
@@ -74,9 +73,6 @@ class BlockContextManager implements BlockContextManagerInterface
$this->reflectionCache = [];
}
/**
* {@inheritdoc}
*/
public function addSettingsByType($type, array $settings, $replace = false)
{
$typeSettings = isset($this->settingsByType[$type]) ? $this->settingsByType[$type] : [];
@@ -87,9 +83,6 @@ class BlockContextManager implements BlockContextManagerInterface
}
}
/**
* {@inheritdoc}
*/
public function addSettingsByClass($class, array $settings, $replace = false)
{
$classSettings = isset($this->settingsByClass[$class]) ? $this->settingsByClass[$class] : [];
@@ -112,15 +105,12 @@ class BlockContextManager implements BlockContextManagerInterface
return $this->blockLoader->exists($type);
}
/**
* {@inheritdoc}
*/
public function get($meta, array $settings = [])
{
if (!$meta instanceof BlockInterface) {
$block = $this->blockLoader->load($meta);
if (is_array($meta) && isset($meta['settings'])) {
if (\is_array($meta) && isset($meta['settings'])) {
// merge user settings
$settings = array_merge($meta['settings'], $settings);
}
@@ -158,15 +148,12 @@ class BlockContextManager implements BlockContextManagerInterface
/**
* NEXT_MAJOR: remove this method.
*
* @param OptionsResolverInterface $optionsResolver
* @param BlockInterface $block
*
* @deprecated since version 2.3, to be renamed in 4.0.
* @deprecated since sonata-project/block-bundle 2.3, to be renamed in 4.0.
* Use the method configureSettings instead
*/
protected function setDefaultSettings(OptionsResolverInterface $optionsResolver, BlockInterface $block)
{
if (__CLASS__ !== get_called_class()) {
if (__CLASS__ !== static::class) {
@trigger_error(
'The '.__METHOD__.' is deprecated since version 2.3, to be renamed in 4.0.'
.' Use '.__CLASS__.'::configureSettings instead.',
@@ -205,9 +192,6 @@ class BlockContextManager implements BlockContextManagerInterface
/**
* Adds context settings, to be able to rebuild a block context, to the
* extra_cache_keys.
*
* @param BlockContextInterface $blockContext
* @param array $settings
*/
protected function setDefaultExtraCacheKeys(BlockContextInterface $blockContext, array $settings)
{
@@ -244,8 +228,7 @@ class BlockContextManager implements BlockContextManagerInterface
}
/**
* @param BlockInterface $block
* @param array $settings
* @param array $settings
*
* @return array
*/
@@ -257,25 +240,19 @@ class BlockContextManager implements BlockContextManagerInterface
$service = $this->blockService->get($block);
/* use new interface method whenever possible */
if (method_exists($service, 'configureSettings')) {
$service->configureSettings($optionsResolver);
} else {
$service->setDefaultSettings($optionsResolver);
}
// Caching method reflection
$serviceClass = get_class($service);
// NEXT_MAJOR: Remove everything here
$serviceClass = \get_class($service);
if (!isset($this->reflectionCache[$serviceClass])) {
$reflector = new \ReflectionMethod($service, 'setDefaultSettings');
$isOldOverwritten = 'Sonata\BlockBundle\Block\AbstractBlockService' !== $reflector->getDeclaringClass()->getName();
$isOldOverwritten = \get_class($service) === $reflector->getDeclaringClass()->getName();
// Prevention for service classes implementing directly the interface and not extends the new base class
if (!method_exists($service, 'configureSettings')) {
$isNewOverwritten = false;
} else {
$reflector = new \ReflectionMethod($service, 'configureSettings');
$isNewOverwritten = 'Sonata\BlockBundle\Block\AbstractBlockService' !== $reflector->getDeclaringClass()->getName();
$isNewOverwritten = \get_class($service) === $reflector->getDeclaringClass()->getName();
}
$this->reflectionCache[$serviceClass] = [
@@ -284,6 +261,7 @@ class BlockContextManager implements BlockContextManagerInterface
];
}
// NEXT_MAJOR: Keep Only else case
if ($this->reflectionCache[$serviceClass]['isOldOverwritten'] && !$this->reflectionCache[$serviceClass]['isNewOverwritten']) {
@trigger_error(
'The Sonata\BlockBundle\Block\BlockServiceInterface::setDefaultSettings() method is deprecated'
@@ -291,6 +269,9 @@ class BlockContextManager implements BlockContextManagerInterface
.' This method will be added to the BlockServiceInterface with SonataBlockBundle 4.0.',
E_USER_DEPRECATED
);
$service->setDefaultSettings($optionsResolver);
} else {
$service->configureSettings($optionsResolver);
}
return $optionsResolver->resolve($settings);
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -12,35 +14,33 @@
namespace Sonata\BlockBundle\Block;
use Sonata\BlockBundle\Exception\BlockOptionsException;
use Sonata\BlockBundle\Model\BlockInterface;
/**
* Interface BlockContextManagerInterface.
*/
interface BlockContextManagerInterface
{
const CACHE_KEY = 'context';
public const CACHE_KEY = 'context';
/**
* Add settings for a block service.
*
* @param string $type block service
* @param array $settings
* @param bool $replace replace existing settings
* @param string $type block service
* @param bool $replace replace existing settings
*/
public function addSettingsByType($type, array $settings, $replace = false);
/**
* Add settings for a block class.
*
* @param string $class block class
* @param array $settings
* @param bool $replace replace existing settings
* @param string $class block class
* @param bool $replace replace existing settings
*/
public function addSettingsByClass($class, array $settings, $replace = false);
/**
* @param mixed $meta Data send to the loader to load a block, can be anything...
* @param array $settings
* @param BlockInterface|array $meta Data send to the loader to load a block, can be anything...
*
* @throws BlockOptionsException
*
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -13,6 +15,9 @@ namespace Sonata\BlockBundle\Block;
use Sonata\BlockBundle\Exception\BlockNotFoundException;
/**
* @final since sonata-project/block-bundle 3.0
*/
class BlockLoaderChain implements BlockLoaderInterface
{
/**
@@ -46,9 +51,6 @@ class BlockLoaderChain implements BlockLoaderInterface
return false;
}
/**
* {@inheritdoc}
*/
public function load($block)
{
foreach ($this->loaders as $loader) {
@@ -60,9 +62,6 @@ class BlockLoaderChain implements BlockLoaderInterface
throw new BlockNotFoundException();
}
/**
* {@inheritdoc}
*/
public function support($name)
{
return true;
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -21,6 +23,8 @@ use Symfony\Component\HttpFoundation\Response;
* This function render a block and make sure the cacheable information are correctly retrieved
* and set to the upper response (container can have child blocks, so the smallest ttl from a child
* must be used in the container).
*
* @final since sonata-project/block-bundle 3.0
*/
class BlockRenderer implements BlockRendererInterface
{
@@ -66,9 +70,6 @@ class BlockRenderer implements BlockRendererInterface
$this->debug = $debug;
}
/**
* {@inheritdoc}
*/
public function render(BlockContextInterface $blockContext, Response $response = null)
{
$block = $blockContext->getBlock();
@@ -109,9 +110,6 @@ class BlockRenderer implements BlockRendererInterface
}
/**
* @param BlockContextInterface $blockContext
* @param Response $response
*
* @return Response
*/
protected function createResponse(BlockContextInterface $blockContext, Response $response = null)
@@ -131,10 +129,6 @@ class BlockRenderer implements BlockRendererInterface
/**
* This method is responsible to cascade ttl to the parent block.
*
* @param Response $response
* @param BlockContextInterface $blockContext
* @param BlockServiceInterface $service
*
* @return Response
*/
protected function addMetaInformation(Response $response, BlockContextInterface $blockContext, BlockServiceInterface $service)
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -16,9 +18,6 @@ use Symfony\Component\HttpFoundation\Response;
interface BlockRendererInterface
{
/**
* @param BlockContextInterface $name
* @param null|Response $response
*
* @return Response
*/
public function render(BlockContextInterface $name, Response $response = null);
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -20,19 +22,18 @@ use Symfony\Component\OptionsResolver\OptionsResolverInterface;
*
* NEXT_MAJOR: remove this interface.
*
* @deprecated since 3.2, to be removed with 4.0
* @deprecated since sonata-project/block-bundle 3.2, to be removed with 4.0
*/
interface BlockServiceInterface
{
/**
* @param BlockContextInterface $blockContext
* @param Response $response
*
* @return Response
*/
public function execute(BlockContextInterface $blockContext, Response $response = null);
/**
* @deprecated since sonata-project/block-bundle 3.16, to be removed in 4.0
*
* @return string
*/
public function getName();
@@ -42,20 +43,17 @@ interface BlockServiceInterface
*
* NEXT_MAJOR: rename this method.
*
* @param OptionsResolverInterface $resolver
*
* @deprecated since version 2.3, to be renamed in 4.0.
* @deprecated since sonata-project/block-bundle 2.3, to be renamed in 4.0.
* Use the method configureSettings instead.
* This method will be added to the BlockServiceInterface with SonataBlockBundle 4.0
*/
public function setDefaultSettings(OptionsResolverInterface $resolver);
/**
* @param BlockInterface $block
*/
public function load(BlockInterface $block);
/**
* @deprecated since sonata-project/block-bundle 3.13.0, to be removed in 4.0
*
* @param string $media
*
* @return array
@@ -63,6 +61,8 @@ interface BlockServiceInterface
public function getJavascripts($media);
/**
* @deprecated since sonata-project/block-bundle 3.13.0, to be removed in 4.0
*
* @param string $media
*
* @return array
@@ -70,8 +70,6 @@ interface BlockServiceInterface
public function getStylesheets($media);
/**
* @param BlockInterface $block
*
* @return array
*/
public function getCacheKeys(BlockInterface $block);
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -11,11 +13,14 @@
namespace Sonata\BlockBundle\Block;
use Psr\Log\LoggerInterface;
use Sonata\BlockBundle\Block\Service\EditableBlockService;
use Sonata\BlockBundle\Model\BlockInterface;
use Sonata\CoreBundle\Validator\ErrorElement;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* @final since sonata-project/block-bundle 3.0
*/
class BlockServiceManager implements BlockServiceManagerInterface
{
/**
@@ -38,21 +43,13 @@ class BlockServiceManager implements BlockServiceManagerInterface
*/
protected $contexts;
/**
* @param ContainerInterface $container
* @param mixed $debug
* @param null|LoggerInterface $logger
*/
public function __construct(ContainerInterface $container, $debug, LoggerInterface $logger = null)
public function __construct(ContainerInterface $container)
{
$this->services = [];
$this->contexts = [];
$this->container = $container;
}
/**
* {@inheritdoc}
*/
public function get(BlockInterface $block)
{
$this->load($block->getType());
@@ -60,31 +57,22 @@ class BlockServiceManager implements BlockServiceManagerInterface
return $this->services[$block->getType()];
}
/**
* {@inheritdoc}
*/
public function getService($id)
{
return $this->load($id);
}
/**
* {@inheritdoc}
*/
public function has($id)
{
return isset($this->services[$id]) ? true : false;
}
/**
* {@inheritdoc}
*/
public function add($name, $service, $contexts = [])
{
$this->services[$name] = $service;
foreach ($contexts as $context) {
if (!array_key_exists($context, $this->contexts)) {
if (!\array_key_exists($context, $this->contexts)) {
$this->contexts[$context] = [];
}
@@ -92,9 +80,6 @@ class BlockServiceManager implements BlockServiceManagerInterface
}
}
/**
* {@inheritdoc}
*/
public function setServices(array $blockServices)
{
foreach ($blockServices as $name => $service) {
@@ -102,13 +87,10 @@ class BlockServiceManager implements BlockServiceManagerInterface
}
}
/**
* {@inheritdoc}
*/
public function getServices()
{
foreach ($this->services as $name => $id) {
if (is_string($id)) {
if (\is_string($id)) {
$this->load($id);
}
}
@@ -116,12 +98,9 @@ class BlockServiceManager implements BlockServiceManagerInterface
return $this->sortServices($this->services);
}
/**
* {@inheritdoc}
*/
public function getServicesByContext($context, $includeContainers = true)
{
if (!array_key_exists($context, $this->contexts)) {
if (!\array_key_exists($context, $this->contexts)) {
return [];
}
@@ -130,7 +109,7 @@ class BlockServiceManager implements BlockServiceManagerInterface
$containers = $this->container->getParameter('sonata.block.container.types');
foreach ($this->contexts[$context] as $name) {
if (!$includeContainers && in_array($name, $containers)) {
if (!$includeContainers && \in_array($name, $containers, true)) {
continue;
}
@@ -140,9 +119,6 @@ class BlockServiceManager implements BlockServiceManagerInterface
return $this->sortServices($services);
}
/**
* {@inheritdoc}
*/
public function getLoadedServices()
{
$services = [];
@@ -176,7 +152,16 @@ class BlockServiceManager implements BlockServiceManagerInterface
// As block can be nested, we only need to validate the main block, no the children
try {
$this->inValidate = true;
$this->get($block)->validateBlock($errorElement, $block);
$blockService = $this->get($block);
if ($blockService instanceof EditableBlockService) {
$blockService->validate($errorElement, $block);
} else {
// NEXT_MAJOR: Remove this case
$this->get($block)->validateBlock($errorElement, $block);
}
$this->inValidate = false;
} catch (\Exception $e) {
$this->inValidate = false;
@@ -216,8 +201,8 @@ class BlockServiceManager implements BlockServiceManagerInterface
*/
private function sortServices($services)
{
uasort($services, function ($a, $b) {
if ($a->getName() == $b->getName()) {
uasort($services, static function ($a, $b) {
if ($a->getName() === $b->getName()) {
return 0;
}
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -26,8 +28,6 @@ interface BlockServiceManagerInterface
/**
* Return the block service linked to the link.
*
* @param BlockInterface $block
*
* @return BlockServiceInterface
*/
public function get(BlockInterface $block);
@@ -36,8 +36,6 @@ interface BlockServiceManagerInterface
* NEXT_MAJOR: remove this method.
*
* @deprecated will be removed in 2.4, use the add method instead
*
* @param array $blockServices
*/
public function setServices(array $blockServices);
@@ -77,9 +75,5 @@ interface BlockServiceManagerInterface
*/
public function getLoadedServices();
/**
* @param ErrorElement $errorElement
* @param BlockInterface $block
*/
public function validate(ErrorElement $errorElement, BlockInterface $block);
}
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -14,6 +16,9 @@ namespace Sonata\BlockBundle\Block\Loader;
use Sonata\BlockBundle\Block\BlockLoaderInterface;
use Sonata\BlockBundle\Model\Block;
/**
* @final since sonata-project/block-bundle 3.0
*/
class ServiceLoader implements BlockLoaderInterface
{
/**
@@ -38,15 +43,12 @@ class ServiceLoader implements BlockLoaderInterface
*/
public function exists($type)
{
return in_array($type, $this->types, true);
return \in_array($type, $this->types, true);
}
/**
* {@inheritdoc}
*/
public function load($configuration)
{
if (!in_array($configuration['type'], $this->types)) {
if (!\in_array($configuration['type'], $this->types, true)) {
throw new \RuntimeException(sprintf(
'The block type "%s" does not exist',
$configuration['type']
@@ -54,22 +56,19 @@ class ServiceLoader implements BlockLoaderInterface
}
$block = new Block();
$block->setId(uniqid());
$block->setId(uniqid('', true));
$block->setType($configuration['type']);
$block->setEnabled(true);
$block->setCreatedAt(new \DateTime());
$block->setUpdatedAt(new \DateTime());
$block->setSettings(isset($configuration['settings']) ? $configuration['settings'] : []);
$block->setSettings($configuration['settings'] ?? []);
return $block;
}
/**
* {@inheritdoc}
*/
public function support($configuration)
{
if (!is_array($configuration)) {
if (!\is_array($configuration)) {
return false;
}
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -12,93 +14,60 @@
namespace Sonata\BlockBundle\Block\Service;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\BlockBundle\Meta\Metadata;
use Sonata\BlockBundle\Model\BlockInterface;
use Sonata\CoreBundle\Model\Metadata;
use Sonata\CoreBundle\Validator\ErrorElement;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
@trigger_error(
'The '.__NAMESPACE__.'\AbstractAdminBlockService class is deprecated since sonata-project/block-bundle 3.16 '.
'and will be removed with the 4.0 release.',
E_USER_DEPRECATED
);
/**
* @author Christian Gripp <mail@core23.de>
*
* @deprecated since sonata-project/block-bundle 3.16 without any replacement
*/
abstract class AbstractAdminBlockService extends AbstractBlockService implements AdminBlockServiceInterface
{
/**
* @param string $name
* @param EngineInterface $templating
*/
public function __construct($name, EngineInterface $templating)
{
parent::__construct($name, $templating);
}
/**
* {@inheritdoc}
*/
public function buildCreateForm(FormMapper $formMapper, BlockInterface $block)
{
$this->buildEditForm($formMapper, $block);
}
/**
* @param BlockInterface $block
*/
public function prePersist(BlockInterface $block)
{
}
/**
* @param BlockInterface $block
*/
public function postPersist(BlockInterface $block)
{
}
/**
* @param BlockInterface $block
*/
public function preUpdate(BlockInterface $block)
{
}
/**
* @param BlockInterface $block
*/
public function postUpdate(BlockInterface $block)
{
}
/**
* @param BlockInterface $block
*/
public function preRemove(BlockInterface $block)
{
}
/**
* @param BlockInterface $block
*/
public function postRemove(BlockInterface $block)
{
}
/**
* {@inheritdoc}
*/
public function buildEditForm(FormMapper $form, BlockInterface $block)
{
}
/**
* @param ErrorElement $errorElement
* @param BlockInterface $block
*/
public function validateBlock(ErrorElement $errorElement, BlockInterface $block)
{
}
/**
* {@inheritdoc}
*/
public function getBlockMetadata($code = null)
{
return new Metadata($this->getName(), (null !== $code ? $code : $this->getName()), false, 'SonataBlockBundle', ['class' => 'fa fa-file']);
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -13,10 +15,11 @@ namespace Sonata\BlockBundle\Block\Service;
use Sonata\BlockBundle\Block\BlockContextInterface;
use Sonata\BlockBundle\Model\BlockInterface;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Templating\EngineInterface;
use Twig\Environment;
/**
* @author Sullivan Senechal <soullivaneuh@gmail.com>
@@ -29,48 +32,95 @@ abstract class AbstractBlockService implements BlockServiceInterface
protected $name;
/**
* NEXT_MAJOR: Remove this property.
*
* @var EngineInterface|null
*/
protected $templating;
/**
* @param string $name
* @param EngineInterface $templating
* @var Environment
*/
public function __construct($name = null, EngineInterface $templating = null)
{
if (null === $name || null === $templating) {
@trigger_error(
'The $name and $templating parameters will be required fields with the 4.0 release.',
E_USER_DEPRECATED
);
}
private $twig;
$this->name = $name;
$this->templating = $templating;
/**
* NEXT_MAJOR: Make `$twig` argument mandatory and remove other arguments.
*
* @param Environment|EngineInterface|string $templatingOrDeprecatedName
*/
public function __construct($templatingOrDeprecatedName = null, ?EngineInterface $templating = null)
{
// $this->twig = $twig;
// NEXT_MAJOR: Uncomment the previous assignment and remove the following lines in this method.
if ($templatingOrDeprecatedName instanceof Environment) {
$this->name = '';
$this->twig = $templatingOrDeprecatedName;
} else {
if (0 !== strpos(static::class, __NAMESPACE__.'\\')) {
$class = 'c' === static::class[0] && 0 === strpos(static::class, "class@anonymous\0") ? get_parent_class(static::class).'@anonymous' : static::class;
@trigger_error(
sprintf(
'Passing %s as argument 1 to %s::%s() is deprecated since sonata-project/block-bundle 3.16 and will throw a \TypeError as of 4.0. You must pass an instance of %s instead.',
\is_object($templatingOrDeprecatedName) ? 'instance of '.\get_class($templatingOrDeprecatedName) : \gettype($templatingOrDeprecatedName),
$class,
__FUNCTION__,
Environment::class
),
E_USER_DEPRECATED
);
}
if ($templatingOrDeprecatedName instanceof EngineInterface) {
$this->name = '';
$this->templating = $templatingOrDeprecatedName;
} elseif (\is_string($templatingOrDeprecatedName)) {
$this->name = $templatingOrDeprecatedName;
$this->templating = $templating;
} else {
$class = 'c' === static::class[0] && 0 === strpos(static::class, "class@anonymous\0") ? get_parent_class(static::class).'@anonymous' : static::class;
throw new \TypeError(sprintf(
'Argument 1 passed to %s::%s() must be a string or an instance of %s or %s, %s given.',
$class,
__FUNCTION__,
Environment::class,
EngineInterface::class,
\is_object($templatingOrDeprecatedName) ? 'instance of '.\get_class($templatingOrDeprecatedName) : \gettype($templatingOrDeprecatedName)
));
}
}
}
/**
* Returns a Response object than can be cacheable.
*
* @param string $view
* @param array $parameters
* @param Response $response
* @param string $view
*
* @return Response
*/
public function renderResponse($view, array $parameters = [], Response $response = null)
{
return $this->getTemplating()->renderResponse($view, $parameters, $response);
if (null === $this->twig) {
return $this->getTemplating()->renderResponse($view, $parameters, $response);
}
// NEXT_MAJOR: Remove the previous condition
if (null === $response) {
$response = new Response();
}
$response->setContent($this->twig->render($view, $parameters));
return $response;
}
/**
* Returns a Response object that cannot be cacheable, this must be used if the Response is related to the user.
* A good solution to make the page cacheable is to configure the block to be cached with javascript ...
*
* @param string $view
* @param array $parameters
* @param Response $response
* @param string $view
*
* @return Response
*/
@@ -82,26 +132,24 @@ abstract class AbstractBlockService implements BlockServiceInterface
;
}
/**
* {@inheritdoc}
*/
public function setDefaultSettings(OptionsResolverInterface $resolver)
{
if (!$resolver instanceof OptionsResolver) {
throw new \BadMethodCallException(
sprintf('Calling %s with %s is unsupported', __METHOD__, \get_class($resolver))
);
}
$this->configureSettings($resolver);
}
/**
* Define the default options for the block.
*
* @param OptionsResolver $resolver
*/
public function configureSettings(OptionsResolver $resolver)
{
}
/**
* {@inheritdoc}
*/
public function getCacheKeys(BlockInterface $block)
{
return [
@@ -110,32 +158,20 @@ abstract class AbstractBlockService implements BlockServiceInterface
];
}
/**
* {@inheritdoc}
*/
public function load(BlockInterface $block)
{
}
/**
* {@inheritdoc}
*/
public function getJavascripts($media)
{
return [];
}
/**
* {@inheritdoc}
*/
public function getStylesheets($media)
{
return [];
}
/**
* {@inheritdoc}
*/
public function execute(BlockContextInterface $blockContext, Response $response = null)
{
return $this->renderResponse($blockContext->getTemplate(), [
@@ -144,19 +180,38 @@ abstract class AbstractBlockService implements BlockServiceInterface
], $response);
}
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->name;
}
/**
* {@inheritdoc}
* NEXT_MAJOR: Remove this method.
*
* @deprecated since sonata-project/block-bundle 3.17
*/
public function getTemplating()
{
$class = 'c' === static::class[0] && 0 === strpos(static::class, "class@anonymous\0") ? get_parent_class(static::class).'@anonymous' : static::class;
@trigger_error(
sprintf(
'Method %s::%s() is deprecated since sonata-project/block-bundle 3.17 and will be removed as of version 4.0.',
$class,
__FUNCTION__
),
E_USER_DEPRECATED
);
if (null !== $this->twig) {
throw new \BadMethodCallException(sprintf(
'Calling %1$s::%2$s() is not allowed when an instance of %3$s is passed as argument 1 to %1$s::__construct().',
$class,
__FUNCTION__,
Environment::class
));
}
return $this->templating;
}
}
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -12,31 +14,28 @@
namespace Sonata\BlockBundle\Block\Service;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\BlockBundle\Meta\MetadataInterface;
use Sonata\BlockBundle\Model\BlockInterface;
use Sonata\CoreBundle\Model\MetadataInterface;
use Sonata\CoreBundle\Validator\ErrorElement;
@trigger_error(
'The '.__NAMESPACE__.'\AdminBlockServiceInterface interface is deprecated since sonata-project/block-bundle 3.16 '.
'and will be removed with the 4.0 release. '.
'Use '.__NAMESPACE__.'\Service\EditableBlockService instead.',
E_USER_DEPRECATED
);
/**
* @author Christian Gripp <mail@core23.de>
*
* @deprecated since sonata-project/block-bundle 3.16, to be removed with 4.0
*/
interface AdminBlockServiceInterface extends BlockServiceInterface
{
/**
* @param FormMapper $form
* @param BlockInterface $block
*/
public function buildEditForm(FormMapper $form, BlockInterface $block);
/**
* @param FormMapper $form
* @param BlockInterface $block
*/
public function buildCreateForm(FormMapper $form, BlockInterface $block);
/**
* @param ErrorElement $errorElement
* @param BlockInterface $block
*/
public function validateBlock(ErrorElement $errorElement, BlockInterface $block);
/**
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -14,9 +16,10 @@ namespace Sonata\BlockBundle\Block\Service;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\BlockBundle\Block\BlockContextInterface;
use Sonata\BlockBundle\Form\Type\ContainerTemplateType;
use Sonata\BlockBundle\Meta\Metadata;
use Sonata\BlockBundle\Model\BlockInterface;
use Sonata\CoreBundle\Form\Type\ImmutableArrayType;
use Sonata\CoreBundle\Model\Metadata;
use Sonata\Form\Type\CollectionType;
use Sonata\Form\Type\ImmutableArrayType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\HttpFoundation\Response;
@@ -25,13 +28,12 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* Render children pages.
*
* @final since sonata-project/block-bundle 3.0
*
* @author Thomas Rabaix <thomas.rabaix@sonata-project.org>
*/
class ContainerBlockService extends AbstractAdminBlockService
{
/**
* {@inheritdoc}
*/
public function buildEditForm(FormMapper $formMapper, BlockInterface $block)
{
$formMapper->add('enabled');
@@ -56,7 +58,7 @@ class ContainerBlockService extends AbstractAdminBlockService
'translation_domain' => 'SonataBlockBundle',
]);
$formMapper->add('children', 'sonata_type_collection', [], [
$formMapper->add('children', CollectionType::class, [], [
'admin_code' => 'sonata.page.admin.block',
'edit' => 'inline',
'inline' => 'table',
@@ -64,9 +66,6 @@ class ContainerBlockService extends AbstractAdminBlockService
]);
}
/**
* {@inheritdoc}
*/
public function execute(BlockContextInterface $blockContext, Response $response = null)
{
return $this->renderResponse($blockContext->getTemplate(), [
@@ -76,9 +75,6 @@ class ContainerBlockService extends AbstractAdminBlockService
], $response);
}
/**
* {@inheritdoc}
*/
public function configureSettings(OptionsResolver $resolver)
{
$resolver->setDefaults([
@@ -89,9 +85,6 @@ class ContainerBlockService extends AbstractAdminBlockService
]);
}
/**
* {@inheritdoc}
*/
public function getBlockMetadata($code = null)
{
return new Metadata($this->getName(), (null !== $code ? $code : $this->getName()), false, 'SonataBlockBundle', [
@@ -115,8 +108,8 @@ class ContainerBlockService extends AbstractAdminBlockService
$segments = explode($key, $layout);
$decorator = [
'pre' => isset($segments[0]) ? $segments[0] : '',
'post' => isset($segments[1]) ? $segments[1] : '',
'pre' => $segments[0] ?? '',
'post' => $segments[1] ?? '',
];
return $decorator;
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -17,31 +19,23 @@ use Sonata\BlockBundle\Model\BlockInterface;
use Sonata\CoreBundle\Validator\ErrorElement;
use Symfony\Component\HttpFoundation\Response;
/**
* @final since sonata-project/block-bundle 3.0
*/
class EmptyBlockService extends AbstractBlockService
{
// NEXT_MAJOR: Remove this method
/**
* {@inheritdoc}
*/
public function buildEditForm(FormMapper $form, BlockInterface $block)
{
throw new \RuntimeException('Not used, this block renders an empty result if no block document can be found');
}
// NEXT_MAJOR: Remove this method
/**
* {@inheritdoc}
*/
public function validateBlock(ErrorElement $errorElement, BlockInterface $block)
{
throw new \RuntimeException('Not used, this block renders an empty result if no block document can be found');
}
/**
* {@inheritdoc}
*/
public function execute(BlockContextInterface $blockContext, Response $response = null)
{
return new Response();
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -17,19 +19,21 @@ use Sonata\AdminBundle\Form\FormMapper;
use Sonata\BlockBundle\Block\BlockContextInterface;
use Sonata\BlockBundle\Menu\MenuRegistry;
use Sonata\BlockBundle\Menu\MenuRegistryInterface;
use Sonata\BlockBundle\Meta\Metadata;
use Sonata\BlockBundle\Model\BlockInterface;
use Sonata\CoreBundle\Form\Type\ImmutableArrayType;
use Sonata\CoreBundle\Model\Metadata;
use Sonata\CoreBundle\Validator\ErrorElement;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
use Sonata\Form\Type\ImmutableArrayType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormTypeInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Templating\EngineInterface;
/**
* @final since sonata-project/block-bundle 3.0
*
* @author Hugo Briand <briand@ekino.com>
*/
class MenuBlockService extends AbstractAdminBlockService
@@ -44,7 +48,7 @@ class MenuBlockService extends AbstractAdminBlockService
*
* @var array
*
* @deprecated since 3.3, to be removed in 4.0
* @deprecated since sonata-project/block-bundle 3.3, to be removed in 4.0
*/
protected $menus;
@@ -55,8 +59,6 @@ class MenuBlockService extends AbstractAdminBlockService
/**
* @param string $name
* @param EngineInterface $templating
* @param MenuProviderInterface $menuProvider
* @param MenuRegistryInterface|null $menuRegistry
*/
public function __construct($name, EngineInterface $templating, MenuProviderInterface $menuProvider, $menuRegistry = null)
@@ -69,7 +71,7 @@ class MenuBlockService extends AbstractAdminBlockService
$this->menuRegistry = $menuRegistry;
} elseif (null === $menuRegistry) {
$this->menuRegistry = new MenuRegistry();
} elseif (is_array($menuRegistry)) { //NEXT_MAJOR: Remove this case
} elseif (\is_array($menuRegistry)) { //NEXT_MAJOR: Remove this case
@trigger_error(
'Initializing '.__CLASS__.' with an array parameter is deprecated since 3.3 and will be removed in 4.0.',
E_USER_DEPRECATED
@@ -86,9 +88,6 @@ class MenuBlockService extends AbstractAdminBlockService
}
}
/**
* {@inheritdoc}
*/
public function execute(BlockContextInterface $blockContext, Response $response = null)
{
$responseSettings = [
@@ -105,9 +104,6 @@ class MenuBlockService extends AbstractAdminBlockService
return $this->renderResponse($blockContext->getTemplate(), $responseSettings, $response);
}
/**
* {@inheritdoc}
*/
public function buildEditForm(FormMapper $form, BlockInterface $block)
{
$form->add('settings', ImmutableArrayType::class, [
@@ -116,9 +112,6 @@ class MenuBlockService extends AbstractAdminBlockService
]);
}
/**
* {@inheritdoc}
*/
public function validateBlock(ErrorElement $errorElement, BlockInterface $block)
{
if (($name = $block->getSetting('menu_name')) && '' !== $name && !$this->menuProvider->has($name)) {
@@ -129,9 +122,6 @@ class MenuBlockService extends AbstractAdminBlockService
}
}
/**
* {@inheritdoc}
*/
public function configureSettings(OptionsResolver $resolver)
{
$resolver->setDefaults([
@@ -150,9 +140,6 @@ class MenuBlockService extends AbstractAdminBlockService
]);
}
/**
* {@inheritdoc}
*/
public function getBlockMetadata($code = null)
{
return new Metadata($this->getName(), (null !== $code ? $code : $this->getName()), false, 'SonataBlockBundle', [
@@ -222,8 +209,6 @@ class MenuBlockService extends AbstractAdminBlockService
/**
* Gets the menu to render.
*
* @param BlockContextInterface $blockContext
*
* @return ItemInterface|string
*/
protected function getMenu(BlockContextInterface $blockContext)
@@ -236,8 +221,6 @@ class MenuBlockService extends AbstractAdminBlockService
/**
* Replaces setting keys with knp menu item options keys.
*
* @param array $settings
*
* @return array
*/
protected function getMenuOptions(array $settings)
@@ -253,7 +236,7 @@ class MenuBlockService extends AbstractAdminBlockService
$options = [];
foreach ($settings as $key => $value) {
if (array_key_exists($key, $mapping) && null !== $value) {
if (\array_key_exists($key, $mapping) && null !== $value) {
$options[$mapping[$key]] = $value;
}
}
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -13,23 +15,22 @@ namespace Sonata\BlockBundle\Block\Service;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\BlockBundle\Block\BlockContextInterface;
use Sonata\BlockBundle\Meta\Metadata;
use Sonata\BlockBundle\Model\BlockInterface;
use Sonata\CoreBundle\Form\Type\ImmutableArrayType;
use Sonata\CoreBundle\Model\Metadata;
use Sonata\CoreBundle\Validator\ErrorElement;
use Sonata\Form\Type\ImmutableArrayType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\UrlType;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* @final since sonata-project/block-bundle 3.0
*
* @author Thomas Rabaix <thomas.rabaix@sonata-project.org>
*/
class RssBlockService extends AbstractAdminBlockService
{
/**
* {@inheritdoc}
*/
public function configureSettings(OptionsResolver $resolver)
{
$resolver->setDefaults([
@@ -42,9 +43,6 @@ class RssBlockService extends AbstractAdminBlockService
]);
}
/**
* {@inheritdoc}
*/
public function buildEditForm(FormMapper $formMapper, BlockInterface $block)
{
$formMapper->add('settings', ImmutableArrayType::class, [
@@ -74,9 +72,6 @@ class RssBlockService extends AbstractAdminBlockService
]);
}
/**
* {@inheritdoc}
*/
public function validateBlock(ErrorElement $errorElement, BlockInterface $block)
{
$errorElement
@@ -91,9 +86,6 @@ class RssBlockService extends AbstractAdminBlockService
->end();
}
/**
* {@inheritdoc}
*/
public function execute(BlockContextInterface $blockContext, Response $response = null)
{
// merge settings
@@ -129,9 +121,6 @@ class RssBlockService extends AbstractAdminBlockService
], $response);
}
/**
* {@inheritdoc}
*/
public function getBlockMetadata($code = null)
{
return new Metadata($this->getName(), (null !== $code ? $code : $this->getName()), false, 'SonataBlockBundle', [
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -13,20 +15,19 @@ namespace Sonata\BlockBundle\Block\Service;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\BlockBundle\Block\BlockContextInterface;
use Sonata\BlockBundle\Meta\Metadata;
use Sonata\BlockBundle\Model\BlockInterface;
use Sonata\CoreBundle\Form\Type\ImmutableArrayType;
use Sonata\CoreBundle\Model\Metadata;
use Sonata\Form\Type\ImmutableArrayType;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* @final since sonata-project/block-bundle 3.0
*
* @author Thomas Rabaix <thomas.rabaix@sonata-project.org>
*/
class TemplateBlockService extends AbstractAdminBlockService
{
/**
* {@inheritdoc}
*/
public function execute(BlockContextInterface $blockContext, Response $response = null)
{
return $this->renderResponse($blockContext->getTemplate(), [
@@ -35,9 +36,6 @@ class TemplateBlockService extends AbstractAdminBlockService
], $response);
}
/**
* {@inheritdoc}
*/
public function buildEditForm(FormMapper $formMapper, BlockInterface $block)
{
$formMapper->add('settings', ImmutableArrayType::class, [
@@ -50,9 +48,6 @@ class TemplateBlockService extends AbstractAdminBlockService
]);
}
/**
* {@inheritdoc}
*/
public function configureSettings(OptionsResolver $resolver)
{
$resolver->setDefaults([
@@ -60,9 +55,6 @@ class TemplateBlockService extends AbstractAdminBlockService
]);
}
/**
* {@inheritdoc}
*/
public function getBlockMetadata($code = null)
{
return new Metadata($this->getName(), (null !== $code ? $code : $this->getName()), false, 'SonataBlockBundle', [
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -13,21 +15,20 @@ namespace Sonata\BlockBundle\Block\Service;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\BlockBundle\Block\BlockContextInterface;
use Sonata\BlockBundle\Meta\Metadata;
use Sonata\BlockBundle\Model\BlockInterface;
use Sonata\CoreBundle\Form\Type\ImmutableArrayType;
use Sonata\CoreBundle\Model\Metadata;
use Sonata\Form\Type\ImmutableArrayType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* @final since sonata-project/block-bundle 3.0
*
* @author Thomas Rabaix <thomas.rabaix@sonata-project.org>
*/
class TextBlockService extends AbstractAdminBlockService
{
/**
* {@inheritdoc}
*/
public function execute(BlockContextInterface $blockContext, Response $response = null)
{
return $this->renderResponse($blockContext->getTemplate(), [
@@ -36,9 +37,6 @@ class TextBlockService extends AbstractAdminBlockService
], $response);
}
/**
* {@inheritdoc}
*/
public function buildEditForm(FormMapper $formMapper, BlockInterface $block)
{
$formMapper->add('settings', ImmutableArrayType::class, [
@@ -51,9 +49,6 @@ class TextBlockService extends AbstractAdminBlockService
]);
}
/**
* {@inheritdoc}
*/
public function configureSettings(OptionsResolver $resolver)
{
$resolver->setDefaults([
@@ -62,9 +57,6 @@ class TextBlockService extends AbstractAdminBlockService
]);
}
/**
* {@inheritdoc}
*/
public function getBlockMetadata($code = null)
{
return new Metadata($this->getName(), (null !== $code ? $code : $this->getName()), false, 'SonataBlockBundle', [
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -15,6 +17,9 @@ use Sonata\BlockBundle\Block\BlockContextInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
/**
* @final since sonata-project/block-bundle 3.0
*/
class HttpCacheHandler implements HttpCacheHandlerInterface
{
/**
@@ -22,9 +27,6 @@ class HttpCacheHandler implements HttpCacheHandlerInterface
*/
protected $currentTtl = null;
/**
* {@inheritdoc}
*/
public function alterResponse(Response $response)
{
if (!$response->isCacheable()) {
@@ -44,9 +46,6 @@ class HttpCacheHandler implements HttpCacheHandlerInterface
}
}
/**
* {@inheritdoc}
*/
public function updateMetadata(Response $response, BlockContextInterface $blockContext = null)
{
if (null === $this->currentTtl) {
@@ -58,9 +57,6 @@ class HttpCacheHandler implements HttpCacheHandlerInterface
}
}
/**
* {@inheritdoc}
*/
public function onKernelResponse(FilterResponseEvent $event)
{
$this->alterResponse($event->getResponse());
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -21,8 +23,6 @@ interface HttpCacheHandlerInterface
* Add valid http cache information.
*
* The Response object is the final object returned to the client
*
* @param Response $response
*/
public function alterResponse(Response $response);
@@ -30,15 +30,10 @@ interface HttpCacheHandlerInterface
* This function can update a state to store the final ttl used for the page
* The response object point to the Response generated by a block service and
* not the final response rendered to the client.
*
* @param Response $response
* @param BlockContextInterface $blockContext
*/
public function updateMetadata(Response $response, BlockContextInterface $blockContext = null);
/**
* @param FilterResponseEvent $event
*
* @return mixed
*/
public function onKernelResponse(FilterResponseEvent $event);
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -15,25 +17,19 @@ use Sonata\BlockBundle\Block\BlockContextInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
/**
* @final since sonata-project/block-bundle 3.0
*/
class NoopHttpCacheHandler implements HttpCacheHandlerInterface
{
/**
* {@inheritdoc}
*/
public function alterResponse(Response $response)
{
}
/**
* {@inheritdoc}
*/
public function updateMetadata(Response $response, BlockContextInterface $blockContext = null)
{
}
/**
* {@inheritdoc}
*/
public function onKernelResponse(FilterResponseEvent $event)
{
}
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -12,15 +14,49 @@
namespace Sonata\BlockBundle\Command;
use Sonata\BlockBundle\Block\BlockServiceManagerInterface;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Command\Command;
abstract class BaseCommand extends ContainerAwareCommand
/**
* @deprecated since sonata-project/block-bundle 3.16, to be removed in 4.0
*/
abstract class BaseCommand extends Command
{
/**
* @var BlockServiceManagerInterface
*/
protected $blockManager;
public function __construct(string $name = null, BlockServiceManagerInterface $blockManager = null)
{
// NEXT_MAJOR: Remove the default value for argument 2 and the following condition
if (null === $blockManager) {
throw new \InvalidArgumentException(sprintf(
'Argument 2 passed to %s::%s() must be an instance of %s, %s given.',
static::class,
__FUNCTION__,
BlockServiceManagerInterface::class,
\gettype($blockManager)
));
}
$this->blockManager = $blockManager;
parent::__construct($name);
}
/**
* @return BlockServiceManagerInterface
*/
public function getBlockServiceManager()
{
return $this->getContainer()->get('sonata.block.manager');
// NEXT_MAJOR: Remove this method
@trigger_error(sprintf(
'Method %1$s::%2$s() is deprecated since sonata-project/block-bundle 3.16 and will be removed with the 4.0 release.'.
'Use the %1$s::$blockManager property instead.',
static::class,
__FUNCTION__
), E_USER_DEPRECATED);
return $this->blockManager;
}
}
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -14,33 +16,53 @@ 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\OptionsResolver\Exception\MissingOptionsException;
use Symfony\Component\OptionsResolver\OptionsResolver;
class DebugBlocksCommand extends BaseCommand
/**
* @final since sonata-project/block-bundle 3.0
*
* NEXT_MAJOR: Uncomment the "final" class declaration
*/
/* final */class DebugBlocksCommand extends BaseCommand
{
/**
* {@inheritdoc}
*
* NEXT_MAJOR: Rename to "debug:sonata:block"
*/
protected static $defaultName = 'sonata:block:debug';
public function configure()
{
$this->setName('sonata:block:debug');
$this->setName(static::$defaultName); // BC for symfony/console < 3.4.0
// NEXT_MAJOR: Replace the current alias by "sonata:block:debug"
$this->setAliases(['debug:sonata:block']);
$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');
}
/**
* {@inheritdoc}
*/
public function execute(InputInterface $input, OutputInterface $output)
{
if ('sonata:block:debug' === $input->getArgument('command')) {
// NEXT_MAJOR: Remove this check
@trigger_error(
'Command "sonata:block:debug" is deprecated since sonata-project/block-bundle 3.16 and will be removed with the 4.0 release.'.
' Use the "debug:sonata:block" command instead.',
E_USER_DEPRECATED
);
}
if ($input->getOption('context')) {
$services = $this->getBlockServiceManager()->getServicesByContext($input->getOption('context'));
$services = $this->blockManager->getServicesByContext($input->getOption('context'));
} else {
$services = $this->getBlockServiceManager()->getServices();
$services = $this->blockManager->getServices();
}
foreach ($services as $code => $service) {
$output->writeln('');
$output->writeln(sprintf('<info>>> %s</info> (<comment>%s</comment>)', $service->getName(), $code));
$resolver = new OptionsResolver();
// NEXT_MAJOR: Remove this check
@@ -50,13 +72,14 @@ class DebugBlocksCommand extends BaseCommand
$service->setDefaultSettings($resolver);
}
$settings = $resolver->resolve();
$output->writeln('');
$output->writeln(sprintf('<info>>> %s</info> (<comment>%s</comment>)', $service->getName(), $code));
foreach ($settings as $key => $val) {
$output->writeln(sprintf(' %-30s%s', $key, json_encode($val)));
try {
foreach ($resolver->resolve() as $key => $val) {
$output->writeln(sprintf(' %-30s%s', $key, json_encode($val)));
}
} catch (MissingOptionsException $e) {
foreach ($resolver->getDefinedOptions() as $option) {
$output->writeln(sprintf(' %s', $option));
}
}
}
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -18,13 +20,12 @@ use Symfony\Component\DependencyInjection\Reference;
/**
* GlobalVariablesCompilerPass.
*
* @final since sonata-project/block-bundle 3.0
*
* @author Thomas Rabaix <thomas.rabaix@sonata-project.org>
*/
class GlobalVariablesCompilerPass implements CompilerPassInterface
{
/**
* {@inheritdoc}
*/
public function process(ContainerBuilder $container)
{
$container->getDefinition('twig')
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -11,53 +13,54 @@
namespace Sonata\BlockBundle\DependencyInjection\Compiler;
use Sonata\BlockBundle\Naming\ConvertFromFqcn;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
/**
* Link the block service to the Page Manager.
*
* @final since sonata-project/block-bundle 3.0
*
* @author Thomas Rabaix <thomas.rabaix@sonata-project.org>
*/
class TweakCompilerPass implements CompilerPassInterface
{
/**
* {@inheritdoc}
*/
public function process(ContainerBuilder $container)
{
$manager = $container->getDefinition('sonata.block.manager');
$registry = $container->getDefinition('sonata.block.menu.registry');
$parameters = $container->getParameter('sonata_block.blocks');
$blocks = $container->getParameter('sonata_block.blocks');
$blockTypes = $container->getParameter('sonata_blocks.block_types');
$cacheBlocks = $container->getParameter('sonata_block.cache_blocks');
$defaultContexs = $container->getParameter('sonata_blocks.default_contexts');
foreach ($container->findTaggedServiceIds('sonata.block') as $id => $tags) {
$definition = $container->getDefinition($id);
$definition->setPublic(true);
$arguments = $definition->getArguments();
// Replace empty block id with service id
if (empty($arguments) || 0 == strlen($arguments[0])) {
// NEXT_MAJOR: Remove the condition when Symfony 2.8 support will be dropped.
if (method_exists($definition, 'setArgument')) {
$definition->setArgument(0, $id);
} else {
$definition->replaceArgument(0, $id);
}
} elseif ($id != $arguments[0] && 0 !== strpos(
$container->getParameterBag()->resolveValue($definition->getClass()),
'Sonata\\BlockBundle\\Block\\Service\\'
)) {
// NEXT_MAJOR: Remove deprecation notice
@trigger_error(
sprintf('Using service id %s different from block id %s is deprecated since 3.3 and will be removed in 4.0.', $id, $arguments[0]),
E_USER_DEPRECATED
);
if (!$definition->isAutowired()) {
$this->replaceBlockName($container, $definition, $id);
}
$manager->addMethodCall('add', [$id, $id, isset($parameters[$id]) ? $parameters[$id]['contexts'] : []]);
$blockId = $this->getBlockId($id);
$settings = $this->createBlockSettings($id, $tags, $defaultContexs);
// Register blocks dynamicaly
if (!\array_key_exists($blockId, $blocks)) {
$blocks[$blockId] = $settings;
}
if (!\in_array($blockId, $blockTypes, true)) {
$blockTypes[] = $blockId;
}
if (isset($cacheBlocks['by_type']) && !\array_key_exists($blockId, $cacheBlocks['by_type'])) {
$cacheBlocks['by_type'][$blockId] = $settings['cache'];
}
$manager->addMethodCall('add', [$id, $id, $settings['contexts']]);
}
foreach ($container->findTaggedServiceIds('knp_menu.menu') as $id => $tags) {
@@ -74,6 +77,11 @@ class TweakCompilerPass implements CompilerPassInterface
$services[] = new Reference($id);
}
$container->setParameter('sonata_block.blocks', $blocks);
$container->setParameter('sonata_blocks.block_types', $blockTypes);
$container->setParameter('sonata_block.cache_blocks', $cacheBlocks);
$container->getDefinition('sonata.block.loader.service')->replaceArgument(0, $blockTypes);
$container->getDefinition('sonata.block.loader.chain')->replaceArgument(0, $services);
$this->applyContext($container);
@@ -81,22 +89,94 @@ class TweakCompilerPass implements CompilerPassInterface
/**
* Apply configurations to the context manager.
*
* @param ContainerBuilder $container
*/
public function applyContext(ContainerBuilder $container)
{
$definition = $container->findDefinition('sonata.block.context_manager');
foreach ($container->getParameter('sonata_block.blocks') as $service => $settings) {
if (count($settings['settings']) > 0) {
if (\count($settings['settings']) > 0) {
$definition->addMethodCall('addSettingsByType', [$service, $settings['settings'], true]);
}
}
foreach ($container->getParameter('sonata_block.blocks_by_class') as $class => $settings) {
if (count($settings['settings']) > 0) {
if (\count($settings['settings']) > 0) {
$definition->addMethodCall('addSettingsByClass', [$class, $settings['settings'], true]);
}
}
}
private function getBlockId(string $id): string
{
$blockId = $id;
// Only convert class service names
if (false !== strpos($blockId, '\\')) {
$convert = (new ConvertFromFqcn());
$blockId = $convert($blockId);
}
return $blockId;
}
private function createBlockSettings(string $id, array $tags = [], array $defaultContexts = []): array
{
$contexts = $this->getContextFromTags($tags);
if (0 === \count($contexts)) {
$contexts = $defaultContexts;
}
return [
'contexts' => $contexts,
'templates' => [],
'cache' => 'sonata.cache.noop',
'settings' => [],
];
}
/**
* Replaces the empty service name with the service id.
*/
private function replaceBlockName(ContainerBuilder $container, Definition $definition, $id)
{
$arguments = $definition->getArguments();
// Replace empty block id with service id
if ($this->serviceDefinitionNeedsFirstArgument($definition)) {
// NEXT_MAJOR: Remove the if block when Symfony 2.8 support will be dropped.
if (method_exists($definition, 'setArgument')) {
$definition->setArgument(0, $id);
return;
}
$definition->replaceArgument(0, $id);
}
}
private function serviceDefinitionNeedsFirstArgument(Definition $definition): bool
{
$arguments = $definition->getArguments();
return empty($arguments) ||
null === ($arguments[0]) ||
\is_string($arguments[0]) && 0 === \strlen($arguments[0]);
}
/**
* @param string[][]
*
* @return string[]
*/
private function getContextFromTags(array $tags)
{
return array_filter(array_map(static function (array $attribute) {
if (\array_key_exists('context', $attribute) && \is_string($attribute['context'])) {
return $attribute['context'];
}
return null;
}, $tags));
}
}
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -19,6 +21,8 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
* This is the class that validates and merges configuration from your app/config files.
*
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
*
* @final since sonata-project/block-bundle 3.0
*/
class Configuration implements ConfigurationInterface
{
@@ -27,21 +31,21 @@ class Configuration implements ConfigurationInterface
*/
protected $defaultContainerTemplates;
/**
* @param array $defaultContainerTemplates
*/
public function __construct(array $defaultContainerTemplates)
{
$this->defaultContainerTemplates = $defaultContainerTemplates;
}
/**
* {@inheritdoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$node = $treeBuilder->root('sonata_block');
$treeBuilder = new TreeBuilder('sonata_block');
// Keep compatibility with symfony/config < 4.2
if (!method_exists($treeBuilder, 'getRootNode')) {
$node = $treeBuilder->root('sonata_block');
} else {
$node = $treeBuilder->getRootNode();
}
$node
->fixXmlConfig('default_context')
@@ -49,16 +53,16 @@ class Configuration implements ConfigurationInterface
->fixXmlConfig('block')
->fixXmlConfig('block_by_class')
->validate()
->always(function ($value) {
->always(static function ($value) {
foreach ($value['blocks'] as $name => &$block) {
if (0 == count($block['contexts'])) {
if (0 === \count($block['contexts'])) {
$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']))) {
&& 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');
}
@@ -164,8 +168,8 @@ class Configuration implements ConfigurationInterface
->useAttributeAsKey('id')
->prototype('scalar')->end()
->validate()
->always(function ($value) {
if (count($value) > 0) {
->always(static function ($value) {
if (\count($value) > 0) {
@trigger_error(
'The menus configuration key is deprecated since 3.3 and will be removed in 4.0.',
E_USER_DEPRECATED
@@ -234,9 +238,6 @@ class Configuration implements ConfigurationInterface
}
/**
* @param array $config
* @param ContainerBuilder $container
*
* @return Configuration
*/
public function getConfiguration(array $config, ContainerBuilder $container)
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -20,13 +22,12 @@ use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
/**
* @final since sonata-project/block-bundle 3.0
*
* @author Thomas Rabaix <thomas.rabaix@sonata-project.org>
*/
class SonataBlockExtension extends Extension
{
/**
* {@inheritdoc}
*/
final public function getConfiguration(array $config, ContainerBuilder $container)
{
$bundles = $container->getParameter('kernel.bundles');
@@ -45,9 +46,6 @@ class SonataBlockExtension extends Extension
return new Configuration($defaultTemplates);
}
/**
* {@inheritdoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$bundles = $container->getParameter('kernel.bundles');
@@ -77,7 +75,7 @@ class SonataBlockExtension extends Extension
$this->configureClassesToCompile();
}
if ($config['templates']['block_base'] === null) {
if (null === $config['templates']['block_base']) {
if (isset($bundles['SonataPageBundle'])) {
$config['templates']['block_base'] = '@SonataPage/Block/block_base.html.twig';
$config['templates']['block_container'] = '@SonataPage/Block/block_container.html.twig';
@@ -90,10 +88,6 @@ class SonataBlockExtension extends Extension
$container->getDefinition('sonata.block.twig.global')->replaceArgument(0, $config['templates']);
}
/**
* @param ContainerBuilder $container
* @param array $config
*/
public function configureBlockContainers(ContainerBuilder $container, array $config)
{
$container->setParameter('sonata.block.container.types', $config['container']['types']);
@@ -101,20 +95,13 @@ class SonataBlockExtension extends Extension
$container->getDefinition('sonata.block.form.type.container_template')->replaceArgument(0, $config['container']['templates']);
}
/**
* @param array $config
*/
public function fixConfigurationDeprecation(array &$config)
{
if (count(array_diff($config['profiler']['container_types'], $config['container']['types']))) {
if (\count(array_diff($config['profiler']['container_types'], $config['container']['types']))) {
$config['container']['types'] = array_merge($config['profiler']['container_types'], $config['container']['types']);
}
}
/**
* @param ContainerBuilder $container
* @param array $config
*/
public function configureMenus(ContainerBuilder $container, array $config)
{
$bundles = $container->getParameter('kernel.bundles');
@@ -127,10 +114,6 @@ class SonataBlockExtension extends Extension
$container->getDefinition('sonata.block.menu.registry')->replaceArgument(0, $config['menus']);
}
/**
* @param ContainerBuilder $container
* @param array $config
*/
public function configureContext(ContainerBuilder $container, array $config)
{
$container->setParameter($this->getAlias().'.blocks', $config['blocks']);
@@ -139,10 +122,6 @@ class SonataBlockExtension extends Extension
$container->setAlias('sonata.block.context_manager', $config['context_manager']);
}
/**
* @param ContainerBuilder $container
* @param array $config
*/
public function configureCache(ContainerBuilder $container, array $config)
{
$container->setAlias('sonata.block.cache.handler', $config['http_cache']['handler']);
@@ -163,10 +142,6 @@ class SonataBlockExtension extends Extension
$container->setParameter($this->getAlias().'.cache_blocks', $cacheBlocks);
}
/**
* @param ContainerBuilder $container
* @param array $config
*/
public function configureLoaderChain(ContainerBuilder $container, array $config)
{
$types = [];
@@ -174,13 +149,9 @@ class SonataBlockExtension extends Extension
$types[] = $service;
}
$container->getDefinition('sonata.block.loader.service')->replaceArgument(0, $types);
$container->setParameter('sonata_blocks.block_types', $types);
}
/**
* @param ContainerBuilder $container
* @param array $config
*/
public function configureForm(ContainerBuilder $container, array $config)
{
$defaults = $config['default_contexts'];
@@ -188,7 +159,7 @@ class SonataBlockExtension extends Extension
$contexts = [];
foreach ($config['blocks'] as $service => $settings) {
if (0 == count($settings['contexts'])) {
if (0 === \count($settings['contexts'])) {
$settings['contexts'] = $defaults;
}
@@ -200,6 +171,8 @@ class SonataBlockExtension extends Extension
$contexts[$context][] = $service;
}
}
$container->setParameter('sonata_blocks.default_contexts', $defaults);
}
/**
@@ -276,6 +249,10 @@ class SonataBlockExtension extends Extension
*/
public function configureClassesToCompile()
{
if (!\is_callable([$this, 'addClassesToCompile'])) {
return;
}
$this->addClassesToCompile([
'Sonata\\BlockBundle\\Block\\BlockLoaderChain',
'Sonata\\BlockBundle\\Block\\BlockLoaderInterface',
@@ -313,9 +290,6 @@ class SonataBlockExtension extends Extension
]);
}
/**
* {@inheritdoc}
*/
public function getNamespace()
{
return 'http://sonata-project.com/schema/dic/block';
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -14,6 +16,9 @@ namespace Sonata\BlockBundle\Event;
use Sonata\BlockBundle\Model\BlockInterface;
use Symfony\Component\EventDispatcher\Event;
/**
* @final since sonata-project/block-bundle 3.0
*/
class BlockEvent extends Event
{
/**
@@ -26,17 +31,11 @@ class BlockEvent extends Event
*/
protected $blocks = [];
/**
* @param array $settings
*/
public function __construct(array $settings = [])
{
$this->settings = $settings;
}
/**
* @param BlockInterface $block
*/
public function addBlock(BlockInterface $block)
{
$this->blocks[] = $block;
@@ -51,7 +50,7 @@ class BlockEvent extends Event
}
/**
* @return mixed
* @return BlockInterface[]
*/
public function getBlocks()
{
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -28,20 +30,17 @@ use Symfony\Component\EventDispatcher\Event;
*/
class TextBlockListener
{
/**
* @param BlockEvent $event
*/
public function onBlock(BlockEvent $event)
{
$content = 'This block is coming from inline event from the template';
if ($event->getSetting('admin') instanceof AdminInterface && 'edit' == $event->getSetting('action')) {
if ($event->getSetting('admin') instanceof AdminInterface && 'edit' === $event->getSetting('action')) {
$admin = $event->getSetting('admin');
$content = sprintf("<p class='well'>The admin subject is <strong>%s</strong></p>", $admin->toString($admin->getSubject()));
}
$block = new Block();
$block->setId(uniqid());
$block->setId(uniqid('', true));
$block->setSettings([
'content' => $event->getSetting('content', $content),
]);
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -13,6 +15,9 @@ namespace Sonata\BlockBundle\Exception;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* @final since sonata-project/block-bundle 3.0
*/
class BlockNotFoundException extends NotFoundHttpException
{
}
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -13,6 +15,9 @@ namespace Sonata\BlockBundle\Exception;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* @final since sonata-project/block-bundle 3.0
*/
class BlockOptionsException extends NotFoundHttpException
{
}
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -16,6 +18,8 @@ use Sonata\BlockBundle\Model\BlockInterface;
/**
* This filter handles exceptions only when debug mode is enabled.
*
* @final since sonata-project/block-bundle 3.0
*
* @author Olivier Paradis <paradis.olivier@gmail.com>
*/
class DebugOnlyFilter implements FilterInterface
@@ -33,9 +37,6 @@ class DebugOnlyFilter implements FilterInterface
$this->debug = $debug;
}
/**
* {@inheritdoc}
*/
public function handle(\Exception $exception, BlockInterface $block)
{
return $this->debug ? true : false;
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -17,6 +19,8 @@ use Sonata\BlockBundle\Model\BlockInterface;
* This filter ignores exceptions that inherit a given class or interface, or in other words, it will only handle
* exceptions that do not inherit the given class or interface.
*
* @final since sonata-project/block-bundle 3.0
*
* @author Olivier Paradis <paradis.olivier@gmail.com>
*/
class IgnoreClassFilter implements FilterInterface
@@ -34,9 +38,6 @@ class IgnoreClassFilter implements FilterInterface
$this->class = $class;
}
/**
* {@inheritdoc}
*/
public function handle(\Exception $exception, BlockInterface $block)
{
return !$exception instanceof $this->class;
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -16,13 +18,12 @@ use Sonata\BlockBundle\Model\BlockInterface;
/**
* This filter will handle all exceptions.
*
* @final since sonata-project/block-bundle 3.0
*
* @author Olivier Paradis <paradis.olivier@gmail.com>
*/
class KeepAllFilter implements FilterInterface
{
/**
* {@inheritdoc}
*/
public function handle(\Exception $exception, BlockInterface $block)
{
return true;
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -16,13 +18,12 @@ use Sonata\BlockBundle\Model\BlockInterface;
/**
* This filters will ignore all exceptions.
*
* @final since sonata-project/block-bundle 3.0
*
* @author Olivier Paradis <paradis.olivier@gmail.com>
*/
class KeepNoneFilter implements FilterInterface
{
/**
* {@inheritdoc}
*/
public function handle(\Exception $exception, BlockInterface $block)
{
return false;
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -19,6 +21,8 @@ use Symfony\Component\Templating\EngineInterface;
/**
* This renderer uses a template to display an error message at the block position with extensive debug information.
*
* @final since sonata-project/block-bundle 3.0
*
* @author Olivier Paradis <paradis.olivier@gmail.com>
*/
class InlineDebugRenderer implements RendererInterface
@@ -57,9 +61,6 @@ class InlineDebugRenderer implements RendererInterface
$this->forceStyle = $forceStyle;
}
/**
* {@inheritdoc}
*/
public function render(\Exception $exception, BlockInterface $block, Response $response = null)
{
$response = $response ?: new Response();
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -18,6 +20,8 @@ use Symfony\Component\Templating\EngineInterface;
/**
* This renderer uses a template to display an error message at the block position.
*
* @final since sonata-project/block-bundle 3.0
*
* @author Olivier Paradis <paradis.olivier@gmail.com>
*/
class InlineRenderer implements RendererInterface
@@ -42,9 +46,6 @@ class InlineRenderer implements RendererInterface
$this->template = $template;
}
/**
* {@inheritdoc}
*/
public function render(\Exception $exception, BlockInterface $block, Response $response = null)
{
$parameters = [
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -17,13 +19,12 @@ use Symfony\Component\HttpFoundation\Response;
/**
* This renderer re-throws the exception and lets the framework handle the exception.
*
* @final since sonata-project/block-bundle 3.0
*
* @author Olivier Paradis <paradis.olivier@gmail.com>
*/
class MonkeyThrowRenderer implements RendererInterface
{
/**
* {@inheritdoc}
*/
public function render(\Exception $banana, BlockInterface $block, Response $response = null)
{
throw $banana;
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -21,6 +23,8 @@ use Symfony\Component\HttpFoundation\Response;
* The strategy manager handles exceptions thrown by a block. It uses an exception filter to identify which exceptions
* it should handle or ignore. It then uses an exception renderer to "somehow" display the exception.
*
* @final since sonata-project/block-bundle 3.0
*
* @author Olivier Paradis <paradis.olivier@gmail.com>
*/
class StrategyManager implements StrategyManagerInterface
@@ -85,7 +89,7 @@ class StrategyManager implements StrategyManagerInterface
*/
public function setDefaultFilter($name)
{
if (!array_key_exists($name, $this->filters)) {
if (!\array_key_exists($name, $this->filters)) {
throw new \InvalidArgumentException(sprintf('Cannot set default exception filter "%s". It does not exist.', $name));
}
@@ -101,16 +105,13 @@ class StrategyManager implements StrategyManagerInterface
*/
public function setDefaultRenderer($name)
{
if (!array_key_exists($name, $this->renderers)) {
if (!\array_key_exists($name, $this->renderers)) {
throw new \InvalidArgumentException(sprintf('Cannot set default exception renderer "%s". It does not exist.', $name));
}
$this->defaultRenderer = $name;
}
/**
* {@inheritdoc}
*/
public function handleException(\Exception $exception, BlockInterface $block, Response $response = null)
{
$response = $response ?: new Response();
@@ -129,8 +130,6 @@ class StrategyManager implements StrategyManagerInterface
/**
* Returns the exception renderer for given block.
*
* @param BlockInterface $block
*
* @throws \RuntimeException
*
* @return RendererInterface
@@ -152,8 +151,6 @@ class StrategyManager implements StrategyManagerInterface
/**
* Returns the exception filter for given block.
*
* @param BlockInterface $block
*
* @throws \RuntimeException
*
* @return FilterInterface
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -11,11 +13,13 @@
namespace Sonata\BlockBundle\Form\Type;
use Sonata\AdminBundle\Form\Type\Filter\ChoiceType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* @final since sonata-project/block-bundle 3.0
*
* @author Hugo Briand <briand@ekino.com>
*/
class ContainerTemplateType extends AbstractType
@@ -25,41 +29,26 @@ class ContainerTemplateType extends AbstractType
*/
protected $templateChoices;
/**
* @param array $templateChoices
*/
public function __construct(array $templateChoices)
{
$this->templateChoices = $templateChoices;
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'sonata_type_container_template_choice';
}
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->getBlockPrefix();
}
/**
* {@inheritdoc}
*/
public function getParent()
{
return ChoiceType::class;
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -17,45 +19,33 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* @final since sonata-project/block-bundle 3.0
*/
class ServiceListType extends AbstractType
{
protected $manager;
/**
* @param BlockServiceManagerInterface $manager
*/
public function __construct(BlockServiceManagerInterface $manager)
{
$this->manager = $manager;
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'sonata_block_service_choice';
}
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->getBlockPrefix();
}
/**
* {@inheritdoc}
*/
public function getParent()
{
return ChoiceType::class;
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$manager = $this->manager;
@@ -67,7 +57,7 @@ class ServiceListType extends AbstractType
$resolver->setDefaults([
'multiple' => false,
'expanded' => false,
'choices' => function (Options $options, $previousValue) use ($manager) {
'choices' => static function (Options $options, $previousValue) use ($manager) {
$types = [];
foreach ($manager->getServicesByContext($options['context'], $options['include_containers']) as $code => $service) {
$types[$code] = sprintf('%s - %s', $service->getName(), $code);
@@ -76,13 +66,13 @@ class ServiceListType extends AbstractType
return $types;
},
'preferred_choices' => [],
'empty_data' => function (Options $options) {
'empty_data' => static function (Options $options) {
$multiple = isset($options['multiple']) && $options['multiple'];
$expanded = isset($options['expanded']) && $options['expanded'];
return $multiple || $expanded ? [] : '';
},
'empty_value' => function (Options $options, $previousValue) {
'empty_value' => static function (Options $options, $previousValue) {
$multiple = isset($options['multiple']) && $options['multiple'];
$expanded = isset($options['expanded']) && $options['expanded'];
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -17,16 +19,13 @@ use Knp\Menu\ItemInterface;
/**
* @author Christian Gripp <mail@core23.de>
*
* @deprecated since 3.9, to be removed with 4.0.
* @deprecated since sonata-project/block-bundle 3.9, to be removed with 4.0.
*/
interface MenuBuilderInterface
{
/**
* Create a knp menu.
*
* @param FactoryInterface $factory
* @param array $options
*
* @return ItemInterface
*/
public function buildMenu(FactoryInterface $factory, array $options);
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -40,9 +42,6 @@ final class MenuRegistry implements MenuRegistryInterface
}
}
/**
* {@inheritdoc}
*/
public function add($menu)
{
if ($menu instanceof MenuBuilderInterface) {
@@ -57,9 +56,6 @@ final class MenuRegistry implements MenuRegistryInterface
$this->names[$menu] = $menu;
}
/**
* {@inheritdoc}
*/
public function getAliasNames()
{
return $this->names;
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
+3 -73
View File
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -73,145 +75,91 @@ abstract class BaseBlock implements BlockInterface
$this->children = [];
}
/**
* {@inheritdoc}
*/
public function __toString()
{
return sprintf('%s ~ #%s', $this->getName(), $this->getId());
}
/**
* {@inheritdoc}
*/
public function setName($name)
{
$this->name = $name;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->name;
}
/**
* {@inheritdoc}
*/
public function setType($type)
{
$this->type = $type;
}
/**
* {@inheritdoc}
*/
public function getType()
{
return $this->type;
}
/**
* {@inheritdoc}
*/
public function setSettings(array $settings = [])
{
$this->settings = $settings;
}
/**
* {@inheritdoc}
*/
public function getSettings()
{
return $this->settings;
}
/**
* {@inheritdoc}
*/
public function setSetting($name, $value)
{
$this->settings[$name] = $value;
}
/**
* {@inheritdoc}
*/
public function getSetting($name, $default = null)
{
return isset($this->settings[$name]) ? $this->settings[$name] : $default;
}
/**
* {@inheritdoc}
*/
public function setEnabled($enabled)
{
$this->enabled = $enabled;
}
/**
* {@inheritdoc}
*/
public function getEnabled()
{
return $this->enabled;
}
/**
* {@inheritdoc}
*/
public function setPosition($position)
{
$this->position = $position;
}
/**
* {@inheritdoc}
*/
public function getPosition()
{
return $this->position;
}
/**
* {@inheritdoc}
*/
public function setCreatedAt(\DateTime $createdAt = null)
{
$this->createdAt = $createdAt;
}
/**
* {@inheritdoc}
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* {@inheritdoc}
*/
public function setUpdatedAt(\DateTime $updatedAt = null)
{
$this->updatedAt = $updatedAt;
}
/**
* {@inheritdoc}
*/
public function getUpdatedAt()
{
return $this->updatedAt;
}
/**
* {@inheritdoc}
*/
public function addChildren(BlockInterface $child)
{
$this->children[] = $child;
@@ -219,41 +167,26 @@ abstract class BaseBlock implements BlockInterface
$child->setParent($this);
}
/**
* {@inheritdoc}
*/
public function getChildren()
{
return $this->children;
}
/**
* {@inheritdoc}
*/
public function setParent(BlockInterface $parent = null)
{
$this->parent = $parent;
}
/**
* {@inheritdoc}
*/
public function getParent()
{
return $this->parent;
}
/**
* {@inheritdoc}
*/
public function hasParent()
{
return $this->getParent() instanceof self;
}
/**
* {@inheritdoc}
*/
public function getTtl()
{
if (!$this->getSetting('use_cache', true)) {
@@ -273,11 +206,8 @@ abstract class BaseBlock implements BlockInterface
return $this->ttl;
}
/**
* {@inheritdoc}
*/
public function hasChildren()
{
return count($this->children) > 0;
return \count($this->children) > 0;
}
}
+2 -6
View File
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -21,17 +23,11 @@ class Block extends BaseBlock
*/
protected $id;
/**
* {@inheritdoc}
*/
public function setId($id)
{
$this->id = $id;
}
/**
* {@inheritdoc}
*/
public function getId()
{
return $this->id;
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -88,8 +90,6 @@ interface BlockInterface
/**
* Sets the creation date and time.
*
* @param \DateTime $createdAt
*/
public function setCreatedAt(\DateTime $createdAt = null);
@@ -102,8 +102,6 @@ interface BlockInterface
/**
* Set the last update date and time.
*
* @param \DateTime $updatedAt
*/
public function setUpdatedAt(\DateTime $updatedAt = null);
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -11,8 +13,8 @@
namespace Sonata\BlockBundle\Model;
use Sonata\CoreBundle\Model\ManagerInterface;
use Sonata\CoreBundle\Model\PageableManagerInterface;
use Sonata\Doctrine\Model\ManagerInterface;
use Sonata\Doctrine\Model\PageableManagerInterface;
interface BlockManagerInterface extends ManagerInterface, PageableManagerInterface
{
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -13,6 +15,8 @@ namespace Sonata\BlockBundle\Model;
/**
* EmptyBlock model to be used to return an empty result if a block is not found or not valid.
*
* @final since sonata-project/block-bundle 3.0
*/
class EmptyBlock extends Block
{
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -14,45 +16,27 @@ namespace Sonata\BlockBundle\Profiler\DataCollector;
use Sonata\BlockBundle\Templating\Helper\BlockHelper;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface;
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
/**
* Block data collector for the symfony web profiling.
*
* @final since sonata-project/block-bundle 3.0
*
* @author Olivier Paradis <paradis.olivier@gmail.com>
*/
class BlockDataCollector implements DataCollectorInterface, \Serializable
class BlockDataCollector extends DataCollector
{
/**
* @var BlockHelper
*/
protected $blocksHelper;
/**
* @var array
*/
protected $blocks = [];
/**
* @var array
*/
protected $containers = [];
/**
* @var array
*/
protected $realBlocks = [];
/**
* @var array
*/
protected $containerTypes = [];
/**
* @var array
*/
protected $events = [];
/**
* @param BlockHelper $blockHelper Block renderer
* @param array $containerTypes array of container types
@@ -61,33 +45,31 @@ class BlockDataCollector implements DataCollectorInterface, \Serializable
{
$this->blocksHelper = $blockHelper;
$this->containerTypes = $containerTypes;
$this->reset();
}
/**
* {@inheritdoc}
*/
public function collect(Request $request, Response $response, \Exception $exception = null)
{
$this->blocks = $this->blocksHelper->getTraces();
$this->data['blocks'] = $this->blocksHelper->getTraces();
// split into containers & real blocks
foreach ($this->blocks as $id => $block) {
if (!is_array($block)) {
foreach ($this->data['blocks'] as $id => $block) {
if (!\is_array($block)) {
return; // something went wrong while collecting information
}
if ('_events' == $id) {
if ('_events' === $id) {
foreach ($block as $uniqid => $event) {
$this->events[$uniqid] = $event;
$this->data['events'][$uniqid] = $event;
}
continue;
}
if (in_array($block['type'], $this->containerTypes)) {
$this->containers[$id] = $block;
if (\in_array($block['type'], $this->containerTypes, true)) {
$this->data['containers'][$id] = $block;
} else {
$this->realBlocks[$id] = $block;
$this->data['realBlocks'][$id] = $block;
}
}
}
@@ -99,7 +81,7 @@ class BlockDataCollector implements DataCollectorInterface, \Serializable
*/
public function getTotalBlock()
{
return count($this->realBlocks) + count($this->containers);
return \count($this->data['realBlocks']) + \count($this->data['containers']);
}
/**
@@ -109,7 +91,7 @@ class BlockDataCollector implements DataCollectorInterface, \Serializable
*/
public function getEvents()
{
return $this->events;
return $this->data['events'];
}
/**
@@ -119,7 +101,7 @@ class BlockDataCollector implements DataCollectorInterface, \Serializable
*/
public function getBlocks()
{
return $this->blocks;
return $this->data['blocks'];
}
/**
@@ -129,7 +111,7 @@ class BlockDataCollector implements DataCollectorInterface, \Serializable
*/
public function getContainers()
{
return $this->containers;
return $this->data['containers'];
}
/**
@@ -139,53 +121,19 @@ class BlockDataCollector implements DataCollectorInterface, \Serializable
*/
public function getRealBlocks()
{
return $this->realBlocks;
return $this->data['realBlocks'];
}
/**
* {@inheritdoc}
*/
public function serialize()
{
$data = [
'blocks' => $this->blocks,
'containers' => $this->containers,
'realBlocks' => $this->realBlocks,
'events' => $this->events,
];
return serialize($data);
}
/**
* {@inheritdoc}
*/
public function unserialize($data)
{
$merged = unserialize($data);
$this->blocks = $merged['blocks'];
$this->containers = $merged['containers'];
$this->realBlocks = $merged['realBlocks'];
$this->events = $merged['events'];
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'block';
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->blocks = [];
$this->containers = [];
$this->realBlocks = [];
$this->events = [];
$this->data['blocks'] = [];
$this->data['containers'] = [];
$this->data['realBlocks'] = [];
$this->data['events'] = [];
}
}
@@ -2,6 +2,8 @@
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="Sonata\BlockBundle\Command\DebugBlocksCommand" class="Sonata\BlockBundle\Command\DebugBlocksCommand">
<argument>null</argument>
<argument type="service" id="sonata.block.manager"/>
<tag name="console.command"/>
</service>
</services>
@@ -4,16 +4,19 @@
<service id="sonata.templating.locator" class="Sonata\BlockBundle\Templating\TemplateLocator">
<argument type="service" id="file_locator"/>
<argument>%kernel.cache_dir%</argument>
<deprecated>The "%service_id%" service is deprecated since sonata-project/block-bundle 3.17 and will be removed in version 4.0.</deprecated>
</service>
<service id="sonata.templating.name_parser" class="Sonata\BlockBundle\Templating\TemplateNameParser">
<argument type="service" id="kernel"/>
<deprecated>The "%service_id%" service is deprecated since sonata-project/block-bundle 3.17 and will be removed in version 4.0.</deprecated>
</service>
<service id="sonata.templating" class="Sonata\BlockBundle\Templating\TwigEngine">
<argument type="service" id="twig"/>
<argument type="service" id="sonata.templating.name_parser"/>
<argument type="service" id="sonata.templating.locator"/>
<deprecated>The "%service_id%" service is deprecated since sonata-project/block-bundle 3.17 and will be removed in version 4.0.</deprecated>
</service>
<service id="sonata.block.manager" class="Sonata\BlockBundle\Block\BlockServiceManager" public="false">
<service id="sonata.block.manager" class="Sonata\BlockBundle\Block\BlockServiceManager" public="true">
<argument type="service" id="service_container"/>
<argument>%kernel.debug%</argument>
<argument type="service" id="logger" on-invalid="ignore"/>
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -13,7 +15,7 @@ namespace Symfony\Component\OptionsResolver;
if (!interface_exists('Symfony\Component\OptionsResolver\OptionsResolverInterface')) {
/**
* @deprecated since 3.9, to be removed in 4.0. Use \Symfony\Component\OptionsResolver\OptionsResolver instead.
* @deprecated since sonata-project/block-bundle 3.9, to be removed in 4.0. Use \Symfony\Component\OptionsResolver\OptionsResolver instead.
*/
interface OptionsResolverInterface
{
@@ -22,6 +22,74 @@
<source>sonata.block.template</source>
<target>Template</target>
</trans-unit>
<trans-unit id="form.label_template">
<source>form.label_template</source>
<target>Template</target>
</trans-unit>
<trans-unit id="form.label_content">
<source>form.label_content</source>
<target>Contenuto</target>
</trans-unit>
<trans-unit id="form.label_url">
<source>form.label_url</source>
<target>URL</target>
</trans-unit>
<trans-unit id="form.label_title">
<source>form.label_title</source>
<target>Titolo</target>
</trans-unit>
<trans-unit id="form.label_code">
<source>form.label_code</source>
<target>Codice</target>
</trans-unit>
<trans-unit id="form.label_layout">
<source>form.label_layout</source>
<target>Layout</target>
</trans-unit>
<trans-unit id="form.label_class">
<source>form.label_class</source>
<target>Classe CSS</target>
</trans-unit>
<trans-unit id="form.label_cache_policy">
<source>form.label_cache_policy</source>
<target>Politica cache</target>
</trans-unit>
<trans-unit id="form.label_safe_labels">
<source>form.label_safe_labels</source>
<target>Label sicure</target>
</trans-unit>
<trans-unit id="form.label_current_class">
<source>form.label_current_class</source>
<target>Classe CSS corrente</target>
</trans-unit>
<trans-unit id="form.label_first_class">
<source>form.label_first_class</source>
<target>Classe CSS primo el.</target>
</trans-unit>
<trans-unit id="form.label_last_class">
<source>form.label_last_class</source>
<target>Classe CSS ultimo el.</target>
</trans-unit>
<trans-unit id="form.label_menu_class">
<source>form.label_menu_class</source>
<target>Classe CSS menu</target>
</trans-unit>
<trans-unit id="form.label_children_class">
<source>form.label_children_class</source>
<target>Classe CSS figli</target>
</trans-unit>
<trans-unit id="form.label_menu_template">
<source>form.label_menu_template</source>
<target>Template menu</target>
</trans-unit>
<trans-unit id="form.label_translation_domain">
<source>form.label_translation_domain</source>
<target>Dominio traduzioni</target>
</trans-unit>
<trans-unit id="form.label_icon">
<source>form.label_icon</source>
<target>Icona</target>
</trans-unit>
</body>
</file>
</xliff>
@@ -11,8 +11,9 @@ file that was distributed with this source code.
{% extends 'knp_menu.html.twig' %}
{% block list %}
{% import 'knp_menu.html.twig' as macros %}
{% block list %}
{% if item.hasChildren and options.depth is not same as(0) and item.displayChildren %}
<div{{ macros.attributes(listAttributes) }}>
{{ block('children') }}
@@ -21,7 +22,6 @@ file that was distributed with this source code.
{% endblock %}
{% block item %}
{% import 'knp_menu.html.twig' as macros %}
{% if item.displayed %}
{# building the class of the item #}
{%- set classes = item.attribute('class') is not empty ? [item.attribute('class')] : [] %}
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -17,11 +19,11 @@ use Sonata\CoreBundle\Form\FormHelper;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
/**
* @final since sonata-project/block-bundle 3.0
*/
class SonataBlockBundle extends Bundle
{
/**
* {@inheritdoc}
*/
public function build(ContainerBuilder $container)
{
$container->addCompilerPass(new TweakCompilerPass());
@@ -30,9 +32,6 @@ class SonataBlockBundle extends Bundle
$this->registerFormMapping();
}
/**
* {@inheritdoc}
*/
public function boot()
{
$this->registerFormMapping();
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -12,9 +14,11 @@
namespace Sonata\BlockBundle\Templating\Helper;
use Doctrine\Common\Util\ClassUtils;
use Psr\Cache\CacheItemPoolInterface;
use Sonata\BlockBundle\Block\BlockContextInterface;
use Sonata\BlockBundle\Block\BlockContextManagerInterface;
use Sonata\BlockBundle\Block\BlockRendererInterface;
use Sonata\BlockBundle\Block\BlockServiceInterface;
use Sonata\BlockBundle\Block\BlockServiceManagerInterface;
use Sonata\BlockBundle\Cache\HttpCacheHandlerInterface;
use Sonata\BlockBundle\Event\BlockEvent;
@@ -40,7 +44,12 @@ class BlockHelper extends Helper
private $cacheManager;
/**
* @var array
* @var CacheItemPoolInterface|null
*/
private $cachePool;
/**
* @var array<string, mixed>
*/
private $cacheBlocks;
@@ -83,24 +92,41 @@ class BlockHelper extends Helper
private $stopwatch;
/**
* @param BlockServiceManagerInterface $blockServiceManager
* @param array $cacheBlocks
* @param BlockRendererInterface $blockRenderer
* @param BlockContextManagerInterface $blockContextManager
* @param EventDispatcherInterface $eventDispatcher
* @param CacheManagerInterface $cacheManager
* @param HttpCacheHandlerInterface $cacheHandler
* @param Stopwatch $stopwatch
* @param CacheManagerInterface|CacheItemPoolInterface|null $cacheManagerOrCachePool
* @param array<string, mixed> $cacheBlocks
*/
public function __construct(BlockServiceManagerInterface $blockServiceManager, array $cacheBlocks, BlockRendererInterface $blockRenderer,
BlockContextManagerInterface $blockContextManager, EventDispatcherInterface $eventDispatcher,
CacheManagerInterface $cacheManager = null, HttpCacheHandlerInterface $cacheHandler = null, Stopwatch $stopwatch = null)
{
public function __construct(
BlockServiceManagerInterface $blockServiceManager,
array $cacheBlocks,
BlockRendererInterface $blockRenderer,
BlockContextManagerInterface $blockContextManager,
EventDispatcherInterface $eventDispatcher,
$cacheManagerOrCachePool = null,
HttpCacheHandlerInterface $cacheHandler = null,
Stopwatch $stopwatch = null
) {
$this->blockServiceManager = $blockServiceManager;
$this->cacheBlocks = $cacheBlocks;
$this->blockRenderer = $blockRenderer;
$this->eventDispatcher = $eventDispatcher;
$this->cacheManager = $cacheManager;
if ($cacheManagerOrCachePool instanceof CacheManagerInterface) {
@trigger_error(
sprintf(
'Passing %s as argument 6 to %s::%s() is deprecated since sonata-project/block-bundle 3.18 and will throw a \TypeError as of 4.0. You must pass an instance of %s instead.',
CacheManagerInterface::class,
static::class,
__FUNCTION__,
CacheItemPoolInterface::class
),
E_USER_DEPRECATED
);
$this->cacheManager = $cacheManagerOrCachePool;
} elseif ($cacheManagerOrCachePool instanceof CacheItemPoolInterface) {
$this->cachePool = $cacheManagerOrCachePool;
}
$this->blockContextManager = $blockContextManager;
$this->cacheHandler = $cacheHandler;
$this->stopwatch = $stopwatch;
@@ -115,9 +141,6 @@ class BlockHelper extends Helper
];
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'sonata_block';
@@ -147,7 +170,7 @@ class BlockHelper extends Helper
*/
public function includeStylesheets($media, $basePath = '')
{
if (0 === count($this->assets['css'])) {
if (0 === \count($this->assets['css'])) {
return '';
}
@@ -164,7 +187,6 @@ class BlockHelper extends Helper
/**
* @param string $name
* @param array $options
*
* @return string
*/
@@ -172,8 +194,16 @@ class BlockHelper extends Helper
{
$eventName = sprintf('sonata.block.event.%s', $name);
/** @var BlockEvent $event */
$event = $this->eventDispatcher->dispatch($eventName, new BlockEvent($options));
// NEXT_MAJOR: remove this when dropping support for symfony/event-dispatcher 3.x
$reflectionMethod = new \ReflectionMethod($this->eventDispatcher, 'dispatch');
$param2 = $reflectionMethod->getParameters()[1] ?? null;
/* @var BlockEvent $event */
if (null === $param2 || !$param2->hasType() || $param2->getType()->isBuiltin()) {
$event = $this->eventDispatcher->dispatch(new BlockEvent($options), $eventName);
} else {
$event = $this->eventDispatcher->dispatch($eventName, new BlockEvent($options));
}
$content = '';
@@ -182,7 +212,7 @@ class BlockHelper extends Helper
}
if ($this->stopwatch) {
$this->traces['_events'][uniqid()] = [
$this->traces['_events'][uniqid('', true)] = [
'template_code' => $name,
'event_name' => $eventName,
'blocks' => $this->getEventBlocks($event),
@@ -206,10 +236,9 @@ class BlockHelper extends Helper
}
/**
* @param mixed $block
* @param array $options
* @param BlockInterface|array $block
*
* @return null|string
* @return string|null
*/
public function render($block, array $options = [])
{
@@ -231,38 +260,14 @@ class BlockHelper extends Helper
$useCache = $blockContext->getSetting('use_cache');
$cacheKeys = $response = false;
$cacheService = $useCache ? $this->getCacheService($blockContext->getBlock(), $stats) : false;
if ($cacheService) {
$cacheKeys = array_merge(
$service->getCacheKeys($blockContext->getBlock()),
$blockContext->getSetting('extra_cache_keys')
$response = null;
if ($useCache) {
$response = $this->getCachedBlock(
$blockContext,
$service,
$stats
);
if ($this->stopwatch) {
$stats['cache']['keys'] = $cacheKeys;
}
// Please note, some cache handler will always return true (js for instance)
// This will allows to have a non cacheable block, but the global page can still be cached by
// a reverse proxy, as the generated page will never get the generated Response from the block.
if ($cacheService->has($cacheKeys)) {
$cacheElement = $cacheService->get($cacheKeys);
if ($this->stopwatch) {
$stats['cache']['from_cache'] = false;
}
if (!$cacheElement->isExpired() && $cacheElement->getData() instanceof Response) {
/* @var Response $response */
if ($this->stopwatch) {
$stats['cache']['from_cache'] = true;
}
$response = $cacheElement->getData();
}
}
}
if (!$response) {
@@ -283,13 +288,14 @@ class BlockHelper extends Helper
$stats['cache']['contextual_keys'] = $contextualKeys;
}
if ($response->isCacheable() && $cacheKeys && $cacheService) {
$cacheService->set($cacheKeys, $response, (int) $response->getTtl(), $contextualKeys);
if ($useCache) {
$this->saveCache($blockContext, $service, $response, $contextualKeys);
}
}
if ($this->stopwatch) {
$stats['cache']['created_at'] = $response->getDate();
// avoid \DateTime because of serialize/unserialize issue in PHP7.3 (https://bugs.php.net/bug.php?id=77302)
$stats['cache']['created_at'] = null === $response->getDate() ? null : $response->getDate()->getTimestamp();
$stats['cache']['ttl'] = $response->getTtl() ?: 0;
$stats['cache']['age'] = $response->getAge();
}
@@ -318,9 +324,6 @@ class BlockHelper extends Helper
/**
* Traverse the parent block and its children to retrieve the correct list css and javascript only for main block.
*
* @param BlockContextInterface $blockContext
* @param array $stats
*/
protected function computeAssets(BlockContextInterface $blockContext, array &$stats = null)
{
@@ -335,6 +338,20 @@ class BlockHelper extends Helper
'css' => $service->getStylesheets('all'),
];
if (\count($assets['js']) > 0) {
@trigger_error(
'Defining javascripts assets inside a block is deprecated since 3.3.0 and will be removed in 4.0',
E_USER_DEPRECATED
);
}
if (\count($assets['css']) > 0) {
@trigger_error(
'Defining css assets inside a block is deprecated since 3.2.0 and will be removed in 4.0',
E_USER_DEPRECATED
);
}
if ($blockContext->getBlock()->hasChildren()) {
$iterator = new \RecursiveIteratorIterator(new RecursiveBlockIterator($blockContext->getBlock()->getChildren()));
@@ -357,9 +374,9 @@ class BlockHelper extends Helper
}
/**
* @param BlockInterface $block
*
* @return array
*
* @internal since sonata-project/block-bundle 3.16
*/
protected function startTracing(BlockInterface $block)
{
@@ -394,8 +411,7 @@ class BlockHelper extends Helper
}
/**
* @param BlockInterface $block
* @param array $stats
* @internal since sonata-project/block-bundle 3.16
*/
protected function stopTracing(BlockInterface $block, array $stats)
{
@@ -411,9 +427,9 @@ class BlockHelper extends Helper
}
/**
* @param BlockEvent $event
*
* @return array
*
* @internal since sonata-project/block-bundle 3.16
*/
protected function getEventBlocks(BlockEvent $event)
{
@@ -430,6 +446,8 @@ class BlockHelper extends Helper
* @param string $eventName
*
* @return array
*
* @internal since sonata-project/block-bundle 3.16
*/
protected function getEventListeners($eventName)
{
@@ -438,9 +456,9 @@ class BlockHelper extends Helper
foreach ($this->eventDispatcher->getListeners($eventName) as $listener) {
if ($listener instanceof \Closure) {
$results[] = '{closure}()';
} elseif (is_object($listener[0])) {
$results[] = get_class($listener[0]);
} elseif (is_string($listener[0])) {
} elseif (\is_object($listener[0])) {
$results[] = \get_class($listener[0]);
} elseif (\is_string($listener[0])) {
$results[] = $listener[0];
} else {
$results[] = 'Unknown type!';
@@ -451,10 +469,9 @@ class BlockHelper extends Helper
}
/**
* @param BlockInterface $block
* @param array $stats
*
* @return CacheAdapterInterface|false
*
* @internal since sonata-project/block-bundle 3.16
*/
protected function getCacheService(BlockInterface $block, array &$stats = null)
{
@@ -481,4 +498,86 @@ class BlockHelper extends Helper
return $this->cacheManager->getCacheService($cacheServiceId);
}
/**
* @param array<string, mixed> $stats
*/
private function getCachedBlock(BlockContextInterface $blockContext, BlockServiceInterface $service, array &$stats): ?Response
{
$cacheKeys = $this->getCacheKey($service, $blockContext);
if (null !== $this->cachePool) {
$item = $this->cachePool->getItem(json_encode($cacheKeys));
return $item->get();
}
$cacheService = $this->getCacheService($blockContext->getBlock(), $stats);
if (!$cacheService) {
return null;
}
if ($this->stopwatch) {
$stats['cache']['keys'] = $cacheKeys;
}
// Please note, some cache handler will always return true (js for instance)
// This will allows to have a non cacheable block, but the global page can still be cached by
// a reverse proxy, as the generated page will never get the generated Response from the block.
if ($cacheService->has($cacheKeys)) {
$cacheElement = $cacheService->get($cacheKeys);
if ($this->stopwatch) {
$stats['cache']['from_cache'] = false;
}
if (!$cacheElement->isExpired() && $cacheElement->getData() instanceof Response) {
/* @var Response $response */
if ($this->stopwatch) {
$stats['cache']['from_cache'] = true;
}
return $cacheElement->getData();
}
}
return null;
}
private function saveCache(BlockContextInterface $blockContext, BlockServiceInterface $service, Response $response, array $contextualKeys): void
{
if (!$response->isCacheable()) {
return;
}
$cacheKeys = $this->getCacheKey($service, $blockContext);
if (null !== $this->cachePool) {
$item = $this->cachePool->getItem(json_encode($cacheKeys));
$item->set($response);
$item->expiresAfter((int) $response->getTtl());
$this->cachePool->save($item);
return;
}
$cacheService = $this->getCacheService($blockContext->getBlock(), $stats);
if (!$cacheService) {
return;
}
$cacheService->set($cacheKeys, $response, (int) $response->getTtl(), $contextualKeys);
}
private function getCacheKey(BlockServiceInterface $service, BlockContextInterface $blockContext): array
{
return array_merge(
$service->getCacheKeys($blockContext->getBlock()),
$blockContext->getSetting('extra_cache_keys')
);
}
}
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -11,91 +13,20 @@
namespace Sonata\BlockBundle\Test;
use PHPUnit\Framework\TestCase;
use Sonata\BlockBundle\Block\BlockContextInterface;
use Sonata\BlockBundle\Block\BlockContextManager;
use Sonata\BlockBundle\Block\BlockContextManagerInterface;
use Sonata\BlockBundle\Block\BlockServiceInterface;
use Sonata\BlockBundle\Block\BlockServiceManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
@trigger_error(
'The '.__NAMESPACE__.'\AbstractBlockServiceTestCase class is deprecated since sonata-project/block-bundle 3.16 '.
'and will be removed with the 4.0 release. '.
'Use '.__NAMESPACE__.'\BlockServiceTestCase instead.',
E_USER_DEPRECATED
);
/**
* Abstract test class for block service tests.
*
* @author Sullivan Senechal <soullivaneuh@gmail.com>
*
* @deprecated since sonata-project/block-bundle 3.16, to be removed in 4.0. Use Sonata\BlockBundle\Test\BlockServiceTestCase instead.
*/
abstract class AbstractBlockServiceTestCase extends TestCase
abstract class AbstractBlockServiceTestCase extends BlockServiceTestCase
{
/**
* @var \PHPUnit_Framework_MockObject_MockObject|ContainerInterface
*/
protected $container;
/**
* @var \PHPUnit_Framework_MockObject_MockObject|BlockServiceManagerInterface
*/
protected $blockServiceManager;
/**
* @var BlockContextManagerInterface
*/
protected $blockContextManager;
/**
* @var FakeTemplating
*/
protected $templating;
protected function setUp()
{
$this->container = $this->createMock('Symfony\Component\DependencyInjection\ContainerInterface');
$this->templating = new FakeTemplating();
$blockLoader = $this->createMock('Sonata\BlockBundle\Block\BlockLoaderInterface');
$this->blockServiceManager = $this->createMock('Sonata\BlockBundle\Block\BlockServiceManagerInterface');
$this->blockContextManager = new BlockContextManager($blockLoader, $this->blockServiceManager);
}
/**
* Create a mocked block service.
*
* @param BlockServiceInterface $blockService A block service
*
* @return BlockContextInterface
*/
protected function getBlockContext(BlockServiceInterface $blockService)
{
$this->blockServiceManager->expects($this->once())->method('get')->will($this->returnValue($blockService));
$block = $this->createMock('Sonata\BlockBundle\Model\BlockInterface');
$block->expects($this->once())->method('getSettings')->will($this->returnValue([]));
$blockContext = $this->blockContextManager->get($block);
$this->assertInstanceOf('Sonata\BlockBundle\Block\BlockContextInterface', $blockContext);
return $blockContext;
}
/**
* Asserts that the block settings have the expected values.
*
* @param array $expected Expected settings
* @param BlockContextInterface $blockContext BlockContext object
*/
protected function assertSettings(array $expected, BlockContextInterface $blockContext)
{
$completeExpectedOptions = array_merge([
'use_cache' => true,
'extra_cache_keys' => [],
'attr' => [],
'template' => false,
'ttl' => 0,
], $expected);
ksort($completeExpectedOptions);
$blockSettings = $blockContext->getSettings();
ksort($blockSettings);
$this->assertSame($completeExpectedOptions, $blockSettings);
}
}
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -14,9 +16,19 @@ namespace Sonata\BlockBundle\Test;
use Sonata\BlockBundle\Templating\EngineInterface;
use Symfony\Component\HttpFoundation\Response;
@trigger_error(
'The '.__NAMESPACE__.'\FakeTemplating class is deprecated since 3.17 '.
'and will be removed in version 4.0.',
E_USER_DEPRECATED
);
/**
* Mocking class for template usage.
*
* NEXT_MAJOR: Remove this class.
*
* @deprecated since sonata-project/block-bundle 3.17, will be removed in version 4.0.
*
* @author Thomas Rabaix <thomas.rabaix@sonata-project.org>
*/
class FakeTemplating implements EngineInterface
@@ -41,18 +53,12 @@ class FakeTemplating implements EngineInterface
*/
public $name;
/**
* {@inheritdoc}
*/
public function render($name, array $parameters = [])
{
$this->name = $name;
$this->parameters = $parameters;
}
/**
* {@inheritdoc}
*/
public function renderResponse($view, array $parameters = [], Response $response = null)
{
$this->view = $view;
@@ -66,17 +72,11 @@ class FakeTemplating implements EngineInterface
return new Response();
}
/**
* {@inheritdoc}
*/
public function supports($name)
{
return true;
}
/**
* {@inheritdoc}
*/
public function exists($name)
{
return true;
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -15,6 +17,9 @@ use Sonata\BlockBundle\Templating\Helper\BlockHelper;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
/**
* @final since sonata-project/block-bundle 3.0
*/
class BlockExtension extends AbstractExtension
{
/**
@@ -24,17 +29,12 @@ class BlockExtension extends AbstractExtension
/**
* BlockExtension constructor.
*
* @param BlockHelper $blockHelper
*/
public function __construct(BlockHelper $blockHelper)
{
$this->blockHelper = $blockHelper;
}
/**
* {@inheritdoc}
*/
public function getFunctions()
{
return [
@@ -65,9 +65,6 @@ class BlockExtension extends AbstractExtension
];
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'sonata_block';
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -14,6 +16,8 @@ namespace Sonata\BlockBundle\Twig;
/**
* GlobalVariables.
*
* @final since sonata-project/block-bundle 3.0
*
* @author Thomas Rabaix <thomas.rabaix@sonata-project.org>
*/
class GlobalVariables
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
@@ -16,6 +18,8 @@ use Doctrine\Common\Collections\Collection;
/**
* RecursiveBlockIterator.
*
* @final since sonata-project/block-bundle 3.0
*
* @author Thomas Rabaix <thomas.rabaix@sonata-project.org>
*/
class RecursiveBlockIterator extends \RecursiveArrayIterator implements \RecursiveIterator
@@ -25,24 +29,18 @@ class RecursiveBlockIterator extends \RecursiveArrayIterator implements \Recursi
*/
public function __construct($array)
{
if (is_object($array)) {
if (\is_object($array)) {
$array = $array->toArray();
}
parent::__construct($array);
}
/**
* {@inheritdoc}
*/
public function getChildren()
{
return new self($this->current()->getChildren());
}
/**
* {@inheritdoc}
*/
public function hasChildren()
{
return $this->current()->hasChildren();
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*