diff --git a/UPGRADE-3.x.md b/UPGRADE-3.x.md index f6f0783777..141fc50bc8 100644 --- a/UPGRADE-3.x.md +++ b/UPGRADE-3.x.md @@ -1,6 +1,21 @@ UPGRADE 3.x =========== +UPGRADE FROM 3.x to 3.x +========================= + +### Template registry structure and responsibilities. + +The `Sonata\AdminBundle\Templating\TemplateRegistry` class has been splitted into 3 classes: + - `TemplateRegistry`, implementing `Sonata\AdminBundle\Templating\TemplateRegistryInterface` + - `MutableTemplateRegistry`, implementing `Sonata\AdminBundle\Templating\MutableTemplateRegistryInterface` + - `AbstractTemplateRegistry`, implementing `Sonata\AdminBundle\Templating\TemplateRegistryInterface`. You MUST extend this class if you want to create your own template registry. + +The interface `Sonata\AdminBundle\Templating\TemplateRegistryAwareInterface` was updated in order to handle instances of `TemplateRegistryInterface`. +The interface `Sonata\AdminBundle\Templating\MutableTemplateRegistryAwareInterface` was added to provide a simple contract for classes depending on a `MutableTemplateRegistryInterface`. + +`TemplateRegistry` will stop implementing `MutableTemplateRegistryInterface` in version 4.0. If you are using `setTemplate()` or `setTemplates()` methods, you MUST use `MutableTemplateRegistry` instead. + ### Deprecated `Sonata\AdminBundle\Model\DatagridManagerInterface` interface. This interface has been deprecated without replacement. diff --git a/src/Admin/Pool.php b/src/Admin/Pool.php index edc2720e0b..df0cd3bbc8 100644 --- a/src/Admin/Pool.php +++ b/src/Admin/Pool.php @@ -80,6 +80,8 @@ class Pool protected $propertyAccessor; /** + * NEXT_MAJOR: change to TemplateRegistryInterface. + * * @var MutableTemplateRegistryInterface */ private $templateRegistry; @@ -469,6 +471,9 @@ public function getAdminClasses() return $this->adminClasses; } + /** + * NEXT_MAJOR: change to TemplateRegistryInterface. + */ final public function setTemplateRegistry(MutableTemplateRegistryInterface $templateRegistry): void { $this->templateRegistry = $templateRegistry; diff --git a/src/Resources/config/core.php b/src/Resources/config/core.php index af03976421..5e86ef5d21 100644 --- a/src/Resources/config/core.php +++ b/src/Resources/config/core.php @@ -238,6 +238,7 @@ ->alias(TemplateRegistry::class, 'sonata.admin.global_template_registry') + // NEXT_MAJOR: remove this alias, global template registry SHOULD NOT be mutable ->alias(MutableTemplateRegistryInterface::class, 'sonata.admin.global_template_registry') ; }; diff --git a/src/Templating/AbstractTemplateRegistry.php b/src/Templating/AbstractTemplateRegistry.php new file mode 100644 index 0000000000..5c3bb1024b --- /dev/null +++ b/src/Templating/AbstractTemplateRegistry.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Sonata\AdminBundle\Templating; + +abstract class AbstractTemplateRegistry implements TemplateRegistryInterface +{ + /** + * @var array + */ + protected $templates = []; + + /** + * @param string[] $templates + */ + public function __construct(array $templates = []) + { + $this->templates = $templates; + } + + public function getTemplates(): array + { + return $this->templates; + } + + public function hasTemplate(string $name): bool + { + return isset($this->templates[$name]); + } + + /** + * NEXT_MAJOR: add type hint. + * + * @param string $name + */ + public function getTemplate($name): ?string + { + if ($this->hasTemplate($name)) { + return $this->templates[$name]; + } + + @trigger_error(sprintf( + 'Passing a nonexistent template name as argument 1 to %s() is deprecated since' + .' sonata-project/admin-bundle 3.52 and will throw an exception in 4.0.', + __METHOD__ + ), E_USER_DEPRECATED); + + // NEXT_MAJOR : remove the previous `trigger_error()` call, the `return null` statement, uncomment the following exception and declare string as return type + // throw new \InvalidArgumentException(sprintf( + // 'Template named "%s" doesn\'t exist.', + // $name + // )); + + return null; + } +} diff --git a/src/Templating/MutableTemplateRegistry.php b/src/Templating/MutableTemplateRegistry.php new file mode 100644 index 0000000000..a3e8f9d462 --- /dev/null +++ b/src/Templating/MutableTemplateRegistry.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Sonata\AdminBundle\Templating; + +/** + * @author Wojciech Błoszyk + */ +final class MutableTemplateRegistry extends AbstractTemplateRegistry implements MutableTemplateRegistryInterface +{ + // NEXT_MAJOR: change method declaration for new one + // public function setTemplates(array $templates): void + public function setTemplates(array $templates) + { + $this->templates = $templates; + } + + // NEXT_MAJOR: change method declaration for new one + // public function setTemplate(string $name, string $template): void + public function setTemplate($name, $template) + { + $this->templates[$name] = $template; + } +} diff --git a/src/Templating/MutableTemplateRegistryAwareInterface.php b/src/Templating/MutableTemplateRegistryAwareInterface.php new file mode 100644 index 0000000000..3fba22c62e --- /dev/null +++ b/src/Templating/MutableTemplateRegistryAwareInterface.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Sonata\AdminBundle\Templating; + +/** + * @author Wojciech Błoszyk + * + * @method MutableTemplateRegistryInterface getTemplateRegistry() + * @method bool hasTemplateRegistry() + * @method void setTemplateRegistry(MutableTemplateRegistryInterface $templateRegistry) + */ +interface MutableTemplateRegistryAwareInterface +{ + // NEXT_MAJOR: uncomment this method in 4.0 + //public function getTemplateRegistry(): MutableTemplateRegistryInterface; + + // NEXT_MAJOR: uncomment this method in 4.0 + //public function setTemplateRegistry(MutableTemplateRegistryInterface $templateRegistry): void; +} diff --git a/src/Templating/MutableTemplateRegistryInterface.php b/src/Templating/MutableTemplateRegistryInterface.php index d4005ba6d8..0202b52a95 100644 --- a/src/Templating/MutableTemplateRegistryInterface.php +++ b/src/Templating/MutableTemplateRegistryInterface.php @@ -19,15 +19,26 @@ interface MutableTemplateRegistryInterface extends TemplateRegistryInterface { /** + * NEXT_MAJOR: remove this method declaration with docblock and uncomment code below. + * * @param array $templates 'name' => 'file_path.html.twig' */ public function setTemplates(array $templates); + ///** + // * @param array $templates 'name' => 'file_path.html.twig' + // */ + //public function setTemplates(array $templates): void; + /** + * NEXT_MAJOR: remove this method declaration with docblock and uncomment code below. + * * @param string $name * @param string $template * * @return void */ public function setTemplate($name, $template); + + //public function setTemplate(string $name, string $template): void; } diff --git a/src/Templating/TemplateRegistry.php b/src/Templating/TemplateRegistry.php index 959390c29d..e1395fa376 100644 --- a/src/Templating/TemplateRegistry.php +++ b/src/Templating/TemplateRegistry.php @@ -15,109 +15,38 @@ /** * @author Timo Bakx + * + * NEXT_MAJOR: remove `MutableTemplateRegistryInterface` implementation. */ -final class TemplateRegistry implements MutableTemplateRegistryInterface +final class TemplateRegistry extends AbstractTemplateRegistry implements MutableTemplateRegistryInterface { - public const TYPE_ARRAY = 'array'; - public const TYPE_BOOLEAN = 'boolean'; - public const TYPE_DATE = 'date'; - public const TYPE_TIME = 'time'; - public const TYPE_DATETIME = 'datetime'; - /** - * NEXT_MAJOR: Remove this constant. - * - * @deprecated since sonata-project/admin-bundle 3.68, to be removed in 4.0. Use Sonata\AdminBundle\Templating\TemplateRegistry::TYPE_STRING instead. - */ - public const TYPE_TEXT = 'text'; - public const TYPE_TEXTAREA = 'textarea'; - public const TYPE_EMAIL = 'email'; - public const TYPE_TRANS = 'trans'; - public const TYPE_STRING = 'string'; - /** - * NEXT_MAJOR: Remove this constant. - * - * @deprecated since sonata-project/admin-bundle 3.68, to be removed in 4.0. Use Sonata\AdminBundle\Templating\TemplateRegistry::TYPE_INTEGER instead. - */ - public const TYPE_SMALLINT = 'smallint'; - /** - * NEXT_MAJOR: Remove this constant. - * - * @deprecated since sonata-project/admin-bundle 3.68, to be removed in 4.0. Use Sonata\AdminBundle\Templating\TemplateRegistry::TYPE_INTEGER instead. - */ - public const TYPE_BIGINT = 'bigint'; - public const TYPE_INTEGER = 'integer'; /** - * NEXT_MAJOR: Remove this constant. + * NEXT_MAJOR: remove this method. * - * @deprecated since sonata-project/admin-bundle 3.68, to be removed in 4.0. Use Sonata\AdminBundle\Templating\TemplateRegistry::TYPE_FLOAT instead. + * @deprecated since version sonata-project/admin-bundle 3.39.0 and will be removed in 4.0. Use Sonata\AdminBundle\Templating\MutableTemplateRegistry instead. */ - public const TYPE_DECIMAL = 'decimal'; - public const TYPE_FLOAT = 'float'; - public const TYPE_IDENTIFIER = 'identifier'; - public const TYPE_CURRENCY = 'currency'; - public const TYPE_PERCENT = 'percent'; - public const TYPE_CHOICE = 'choice'; - public const TYPE_URL = 'url'; - public const TYPE_HTML = 'html'; - public const TYPE_MANY_TO_MANY = 'many_to_many'; - public const TYPE_MANY_TO_ONE = 'many_to_one'; - public const TYPE_ONE_TO_MANY = 'one_to_many'; - public const TYPE_ONE_TO_ONE = 'one_to_one'; - - /** - * @var array - */ - private $templates = []; - - /** - * @param string[] $templates - */ - public function __construct(array $templates = []) - { - $this->templates = $templates; - } - - public function getTemplates(): array - { - return $this->templates; - } - public function setTemplates(array $templates) { $this->templates = $templates; - } - public function hasTemplate(string $name): bool - { - return isset($this->templates[$name]); + @trigger_error(sprintf( + 'Method "%s()" is deprecated since sonata-admin/admin-bundle 3.39 and will be removed in 4.0.', + __METHOD__ + ), E_USER_DEPRECATED); } /** - * @param string $name + * NEXT_MAJOR: remove this method. + * + * @deprecated since version sonata-project/admin-bundle 3.39.0 and will be removed in 4.0. Use Sonata\AdminBundle\Templating\MutableTemplateRegistry instead. */ - public function getTemplate($name): ?string + public function setTemplate($name, $template) { - if (isset($this->templates[$name])) { - return $this->templates[$name]; - } + $this->templates[$name] = $template; @trigger_error(sprintf( - 'Passing a nonexistent template name as argument 1 to %s() is deprecated since' - .' sonata-project/admin-bundle 3.52 and will throw an exception in 4.0.', + 'Method "%s()" is deprecated since sonata-admin/admin-bundle 3.39 and will be removed in 4.0.', __METHOD__ ), E_USER_DEPRECATED); - - // NEXT_MAJOR : remove the previous `trigger_error()` call, the `return null` statement, uncomment the following exception and declare string as return type - // throw new \InvalidArgumentException(sprintf( - // 'Template named "%s" doesn\'t exist.', - // $name - // )); - - return null; - } - - public function setTemplate($name, $template) - { - $this->templates[$name] = $template; } } diff --git a/src/Templating/TemplateRegistryAwareInterface.php b/src/Templating/TemplateRegistryAwareInterface.php index 14743c8097..bfacf1b53f 100644 --- a/src/Templating/TemplateRegistryAwareInterface.php +++ b/src/Templating/TemplateRegistryAwareInterface.php @@ -14,21 +14,20 @@ namespace Sonata\AdminBundle\Templating; /** - * /** * @author Wojciech Błoszyk * - * @method MutableTemplateRegistryInterface getTemplateRegistry() - * @method bool hasTemplateRegistry() - * @method void setTemplateRegistry(MutableTemplateRegistryInterface $templateRegistry) + * @method TemplateRegistryInterface getTemplateRegistry() + * @method bool hasTemplateRegistry() + * @method void setTemplateRegistry(TemplateRegistryInterface $templateRegistry) */ interface TemplateRegistryAwareInterface { // NEXT_MAJOR: uncomment this method in 4.0 - //public function getTemplateRegistry(): MutableTemplateRegistryInterface; + //public function getTemplateRegistry(): TemplateRegistryInterface; // NEXT_MAJOR: uncomment this method in 4.0 //public function hasTemplateRegistry(): bool; // NEXT_MAJOR: uncomment this method in 4.0 - //public function setTemplateRegistry(MutableTemplateRegistryInterface $templateRegistry): void; + //public function setTemplateRegistry(TemplateRegistryInterface $templateRegistry): void; } diff --git a/src/Templating/TemplateRegistryInterface.php b/src/Templating/TemplateRegistryInterface.php index 97b5e93b60..e1a10f3eec 100644 --- a/src/Templating/TemplateRegistryInterface.php +++ b/src/Templating/TemplateRegistryInterface.php @@ -20,6 +20,52 @@ */ interface TemplateRegistryInterface { + public const TYPE_ARRAY = 'array'; + public const TYPE_BOOLEAN = 'boolean'; + public const TYPE_DATE = 'date'; + public const TYPE_TIME = 'time'; + public const TYPE_DATETIME = 'datetime'; + /** + * NEXT_MAJOR: Remove this constant. + * + * @deprecated since sonata-project/admin-bundle 3.68, to be removed in 4.0. Use Sonata\AdminBundle\Templating\TemplateRegistry::TYPE_STRING instead. + */ + public const TYPE_TEXT = 'text'; + public const TYPE_TEXTAREA = 'textarea'; + public const TYPE_EMAIL = 'email'; + public const TYPE_TRANS = 'trans'; + public const TYPE_STRING = 'string'; + /** + * NEXT_MAJOR: Remove this constant. + * + * @deprecated since sonata-project/admin-bundle 3.68, to be removed in 4.0. Use Sonata\AdminBundle\Templating\TemplateRegistry::TYPE_INTEGER instead. + */ + public const TYPE_SMALLINT = 'smallint'; + /** + * NEXT_MAJOR: Remove this constant. + * + * @deprecated since sonata-project/admin-bundle 3.68, to be removed in 4.0. Use Sonata\AdminBundle\Templating\TemplateRegistry::TYPE_INTEGER instead. + */ + public const TYPE_BIGINT = 'bigint'; + public const TYPE_INTEGER = 'integer'; + /** + * NEXT_MAJOR: Remove this constant. + * + * @deprecated since sonata-project/admin-bundle 3.68, to be removed in 4.0. Use Sonata\AdminBundle\Templating\TemplateRegistry::TYPE_FLOAT instead. + */ + public const TYPE_DECIMAL = 'decimal'; + public const TYPE_FLOAT = 'float'; + public const TYPE_IDENTIFIER = 'identifier'; + public const TYPE_CURRENCY = 'currency'; + public const TYPE_PERCENT = 'percent'; + public const TYPE_CHOICE = 'choice'; + public const TYPE_URL = 'url'; + public const TYPE_HTML = 'html'; + public const TYPE_MANY_TO_MANY = 'many_to_many'; + public const TYPE_MANY_TO_ONE = 'many_to_one'; + public const TYPE_ONE_TO_MANY = 'one_to_many'; + public const TYPE_ONE_TO_ONE = 'one_to_one'; + /** * @return array 'name' => 'file_path.html.twig' */ diff --git a/tests/Templating/MutableTemplateRegistryTest.php b/tests/Templating/MutableTemplateRegistryTest.php new file mode 100644 index 0000000000..a7b0558416 --- /dev/null +++ b/tests/Templating/MutableTemplateRegistryTest.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Sonata\AdminBundle\Tests\Templating; + +use PHPUnit\Framework\TestCase; +use Sonata\AdminBundle\Templating\MutableTemplateRegistry; +use Sonata\AdminBundle\Templating\MutableTemplateRegistryInterface; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; + +final class MutableTemplateRegistryTest extends TestCase +{ + use ExpectDeprecationTrait; + + /** + * @var MutableTemplateRegistryInterface + */ + private $templateRegistry; + + protected function setUp(): void + { + parent::setUp(); + + $this->templateRegistry = new MutableTemplateRegistry(['list' => '@FooAdmin/CRUD/list.html.twig']); + } + + public function testGetTemplates(): void + { + $this->assertSame(['list' => '@FooAdmin/CRUD/list.html.twig'], $this->templateRegistry->getTemplates()); + + $templates = [ + 'show' => '@FooAdmin/CRUD/show.html.twig', + 'edit' => '@FooAdmin/CRUD/edit.html.twig', + ]; + + $this->templateRegistry->setTemplates($templates); + $this->assertSame($templates, $this->templateRegistry->getTemplates()); + } + + /** + * @group legacy + */ + public function testGetTemplateAfterSetTemplate(): void + { + $this->templateRegistry->setTemplate('edit', '@FooAdmin/CRUD/edit.html.twig'); + + $this->assertTrue($this->templateRegistry->hasTemplate('edit')); + $this->assertSame('@FooAdmin/CRUD/edit.html.twig', $this->templateRegistry->getTemplate('edit')); + + $this->assertFalse($this->templateRegistry->hasTemplate('nonexist_template')); + // NEXT_MAJOR: remove this line + $this->expectDeprecation('Passing a nonexistent template name as argument 1 to Sonata\AdminBundle\Templating\AbstractTemplateRegistry::getTemplate() is deprecated since sonata-project/admin-bundle 3.52 and will throw an exception in 4.0.'); + $this->assertNull($this->templateRegistry->getTemplate('nonexist_template')); + // NEXT_MAJOR: Remove previous assertion, the "@group" annotations and uncomment the following line + // $this->assertFalse($this->templateRegistry->hasTemplate('nonexist_template')); + } + + /** + * @group legacy + */ + public function testGetTemplateAfterSetTemplates(): void + { + $templates = [ + 'show' => '@FooAdmin/CRUD/show.html.twig', + 'edit' => '@FooAdmin/CRUD/edit.html.twig', + ]; + + $this->templateRegistry->setTemplates($templates); + + $this->assertTrue($this->templateRegistry->hasTemplate('edit')); + $this->assertSame('@FooAdmin/CRUD/edit.html.twig', $this->templateRegistry->getTemplate('edit')); + // NEXT_MAJOR: remove this line + $this->expectDeprecation('Passing a nonexistent template name as argument 1 to Sonata\AdminBundle\Templating\AbstractTemplateRegistry::getTemplate() is deprecated since sonata-project/admin-bundle 3.52 and will throw an exception in 4.0.'); + $this->assertNull($this->templateRegistry->getTemplate('nonexist_template')); + $this->assertFalse($this->templateRegistry->hasTemplate('nonexist_template')); + // NEXT_MAJOR: Remove previous assertion, the "@group" annotations and uncomment the following line + // $this->assertFalse($this->templateRegistry->hasTemplate('nonexist_template')); + } +} diff --git a/tests/Templating/TemplateRegistryTest.php b/tests/Templating/TemplateRegistryTest.php index bd62168e21..3d15f34595 100644 --- a/tests/Templating/TemplateRegistryTest.php +++ b/tests/Templating/TemplateRegistryTest.php @@ -15,9 +15,12 @@ use PHPUnit\Framework\TestCase; use Sonata\AdminBundle\Templating\TemplateRegistry; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; class TemplateRegistryTest extends TestCase { + use ExpectDeprecationTrait; + /** * @var TemplateRegistry */ @@ -25,67 +28,37 @@ class TemplateRegistryTest extends TestCase protected function setUp(): void { - $this->templateRegistry = new TemplateRegistry(); + $this->templateRegistry = new TemplateRegistry([ + 'list' => '@FooAdmin/CRUD/list.html.twig', + 'show' => '@FooAdmin/CRUD/show.html.twig', + 'edit' => '@FooAdmin/CRUD/edit.html.twig', + ]); } public function testGetTemplates(): void { - $this->assertSame([], $this->templateRegistry->getTemplates()); - $templates = [ 'list' => '@FooAdmin/CRUD/list.html.twig', 'show' => '@FooAdmin/CRUD/show.html.twig', 'edit' => '@FooAdmin/CRUD/edit.html.twig', ]; - $this->templateRegistry->setTemplates($templates); $this->assertSame($templates, $this->templateRegistry->getTemplates()); } /** * @group legacy - * - * @expectedDeprecation Passing a nonexistent template name as argument 1 to Sonata\AdminBundle\Templating\TemplateRegistry::getTemplate() is deprecated since sonata-project/admin-bundle 3.52 and will throw an exception in 4.0. - */ - public function testGetTemplate1(): void - { - $this->assertFalse($this->templateRegistry->hasTemplate('edit')); - $this->assertNull($this->templateRegistry->getTemplate('edit')); - // NEXT_MAJOR: Remove previous assertion, the "@group" and "@expectedDeprecation" annotations and uncomment the following line - // $this->assertFalse($this->templateRegistry->hasTemplate('edit')); - - $this->templateRegistry->setTemplate('edit', '@FooAdmin/CRUD/edit.html.twig'); - $this->templateRegistry->setTemplate('show', '@FooAdmin/CRUD/show.html.twig'); - - $this->assertTrue($this->templateRegistry->hasTemplate('edit')); - $this->assertSame('@FooAdmin/CRUD/edit.html.twig', $this->templateRegistry->getTemplate('edit')); - $this->assertTrue($this->templateRegistry->hasTemplate('show')); - $this->assertSame('@FooAdmin/CRUD/show.html.twig', $this->templateRegistry->getTemplate('show')); - } - - /** - * @group legacy - * - * @expectedDeprecation Passing a nonexistent template name as argument 1 to Sonata\AdminBundle\Templating\TemplateRegistry::getTemplate() is deprecated since sonata-project/admin-bundle 3.52 and will throw an exception in 4.0. */ - public function testGetTemplate2(): void + public function testGetTemplate(): void { - $this->assertFalse($this->templateRegistry->hasTemplate('edit')); - $this->assertNull($this->templateRegistry->getTemplate('edit')); - // NEXT_MAJOR: Remove previous assertion, the "@group" and "@expectedDeprecation" annotations and uncomment the following line - // $this->assertFalse($this->templateRegistry->hasTemplate('edit')); - - $templates = [ - 'list' => '@FooAdmin/CRUD/list.html.twig', - 'show' => '@FooAdmin/CRUD/show.html.twig', - 'edit' => '@FooAdmin/CRUD/edit.html.twig', - ]; - - $this->templateRegistry->setTemplates($templates); + $this->assertFalse($this->templateRegistry->hasTemplate('nonexist_template')); + // NEXT_MAJOR: remove this line + $this->expectDeprecation('Passing a nonexistent template name as argument 1 to Sonata\AdminBundle\Templating\AbstractTemplateRegistry::getTemplate() is deprecated since sonata-project/admin-bundle 3.52 and will throw an exception in 4.0.'); + $this->assertNull($this->templateRegistry->getTemplate('nonexist_template')); + // NEXT_MAJOR: Remove previous assertion, the "@group" annotations and uncomment the following line + // $this->assertFalse($this->templateRegistry->hasTemplate('nonexist_template')); $this->assertTrue($this->templateRegistry->hasTemplate('edit')); $this->assertSame('@FooAdmin/CRUD/edit.html.twig', $this->templateRegistry->getTemplate('edit')); - $this->assertTrue($this->templateRegistry->hasTemplate('show')); - $this->assertSame('@FooAdmin/CRUD/show.html.twig', $this->templateRegistry->getTemplate('show')); } }