From 4b3ce7fead270e99e6c2239c022af459e774136a Mon Sep 17 00:00:00 2001 From: Fran Moreno Date: Sat, 11 Apr 2020 13:42:05 +0200 Subject: [PATCH] Add AdminExtractor --- .../SonataAdminExtension.php | 2 +- src/Resources/config/core.xml | 7 + src/Translator/Extractor/AdminExtractor.php | 123 +++++++++++++++++ .../JMSTranslatorBundle/AdminExtractor.php | 4 + .../SonataAdminExtensionTest.php | 2 + .../Extractor/AdminExtractorTest.php | 124 ++++++++++++++++++ .../AdminExtractorTest.php | 4 + 7 files changed, 265 insertions(+), 1 deletion(-) create mode 100644 src/Translator/Extractor/AdminExtractor.php create mode 100644 tests/Translator/Extractor/AdminExtractorTest.php diff --git a/src/DependencyInjection/SonataAdminExtension.php b/src/DependencyInjection/SonataAdminExtension.php index cc638d36f2..6d7c2ce272 100644 --- a/src/DependencyInjection/SonataAdminExtension.php +++ b/src/DependencyInjection/SonataAdminExtension.php @@ -178,7 +178,7 @@ public function load(array $configs, ContainerBuilder $container) ->replaceArgument(0, $classes) ->replaceArgument(1, $config['options']); - // remove non used service + // NEXT_MAJOR: Remove this block if (!isset($bundles['JMSTranslationBundle'])) { $container->removeDefinition('sonata.admin.translator.extractor.jms_translator_bundle'); } diff --git a/src/Resources/config/core.xml b/src/Resources/config/core.xml index dc6c29ca38..a538ffb2b0 100644 --- a/src/Resources/config/core.xml +++ b/src/Resources/config/core.xml @@ -47,7 +47,9 @@ + + The service "%service_id%" is deprecated in favor of the "Sonata\AdminBundle\Translator\Extractor\AdminExtractor" service since version 3.x and will be removed in 4.0. @@ -55,6 +57,11 @@ + + + + + The controller service "%service_id%" is deprecated in favor of several action services since version 3.38.0 and will be removed in 4.0. diff --git a/src/Translator/Extractor/AdminExtractor.php b/src/Translator/Extractor/AdminExtractor.php new file mode 100644 index 0000000000..25f00c762d --- /dev/null +++ b/src/Translator/Extractor/AdminExtractor.php @@ -0,0 +1,123 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Sonata\AdminBundle\Translator\Extractor; + +use Sonata\AdminBundle\Admin\BreadcrumbsBuilderInterface; +use Sonata\AdminBundle\Admin\Pool; +use Sonata\AdminBundle\Translator\LabelTranslatorStrategyInterface; +use Symfony\Component\Translation\Extractor\ExtractorInterface; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * @internal + */ +final class AdminExtractor implements ExtractorInterface, LabelTranslatorStrategyInterface +{ + private const PUBLIC_ADMIN_METHODS = [ + 'getShow', + 'getDatagrid', + 'getList', + 'getForm', + ]; + + private const BREADCRUMB_ACTIONS = [ + 'list', + 'edit', + 'create', + 'update', + 'batch', + 'delete', + ]; + + /** + * @var string + */ + private $prefix = ''; + + /** + * @var MessageCatalogue|null + */ + private $catalogue; + + /** + * @var Pool + */ + private $adminPool; + + /** + * @var LabelTranslatorStrategyInterface|null + */ + private $labelStrategy; + + /** + * @var string|null + */ + private $domain; + + /** + * @var BreadcrumbsBuilderInterface + */ + private $breadcrumbsBuilder; + + public function __construct(Pool $adminPool, BreadcrumbsBuilderInterface $breadcrumbsBuilder) + { + $this->adminPool = $adminPool; + $this->breadcrumbsBuilder = $breadcrumbsBuilder; + } + + public function extract($resource, MessageCatalogue $catalogue) + { + $this->catalogue = $catalogue; + + foreach ($this->adminPool->getAdminGroups() as $name => $group) { + $catalogue->set($name, $this->prefix.$name, $group['label_catalogue']); + } + + foreach ($this->adminPool->getAdminServiceIds() as $id) { + $admin = $this->adminPool->getInstance($id); + + $this->labelStrategy = $admin->getLabelTranslatorStrategy(); + $this->domain = $admin->getTranslationDomain(); + + $label = $admin->getLabel(); + if (!empty($label)) { + $catalogue->set($label, $this->prefix.$label, $admin->getTranslationDomain()); + } + + $admin->setLabelTranslatorStrategy($this); + + foreach (self::PUBLIC_ADMIN_METHODS as $method) { + $admin->$method(); + } + + foreach (self::BREADCRUMB_ACTIONS as $action) { + $this->breadcrumbsBuilder->getBreadcrumbs($admin, $action); + } + } + } + + public function setPrefix($prefix): void + { + $this->prefix = $prefix; + } + + public function getLabel($label, $context = '', $type = ''): string + { + $label = $this->labelStrategy->getLabel($label, $context, $type); + + $this->catalogue->set($label, $this->prefix.$label, $this->domain); + + return $label; + } +} diff --git a/src/Translator/Extractor/JMSTranslatorBundle/AdminExtractor.php b/src/Translator/Extractor/JMSTranslatorBundle/AdminExtractor.php index 4b66c34b8e..8fde6606b3 100644 --- a/src/Translator/Extractor/JMSTranslatorBundle/AdminExtractor.php +++ b/src/Translator/Extractor/JMSTranslatorBundle/AdminExtractor.php @@ -26,6 +26,10 @@ use Symfony\Component\Translation\TranslatorInterface; /** + * NEXT_MAJOR: Remove this class and the jms/translation-bundle dev dependency. + * + * @deprecated since sonata-project/admin-bundle 3.x. Use `translation:update` Symfony command instead. + * * @final since sonata-project/admin-bundle 3.52 */ class AdminExtractor implements ExtractorInterface, TranslatorInterface, SecurityHandlerInterface, LabelTranslatorStrategyInterface diff --git a/tests/DependencyInjection/SonataAdminExtensionTest.php b/tests/DependencyInjection/SonataAdminExtensionTest.php index efe791a8ad..fec2734734 100644 --- a/tests/DependencyInjection/SonataAdminExtensionTest.php +++ b/tests/DependencyInjection/SonataAdminExtensionTest.php @@ -33,6 +33,7 @@ use Sonata\AdminBundle\Templating\MutableTemplateRegistryInterface; use Sonata\AdminBundle\Templating\TemplateRegistry; use Sonata\AdminBundle\Translator\BCLabelTranslatorStrategy; +use Sonata\AdminBundle\Translator\Extractor\AdminExtractor; use Sonata\AdminBundle\Translator\FormLabelTranslatorStrategy; use Sonata\AdminBundle\Translator\LabelTranslatorStrategyInterface; use Sonata\AdminBundle\Translator\NativeLabelTranslatorStrategy; @@ -97,6 +98,7 @@ public function testHasCoreServicesAlias(): void MutableTemplateRegistryInterface::class, TemplateRegistry::class ); + $this->assertContainerBuilderHasService(AdminExtractor::class); } /** diff --git a/tests/Translator/Extractor/AdminExtractorTest.php b/tests/Translator/Extractor/AdminExtractorTest.php new file mode 100644 index 0000000000..fba8b4a314 --- /dev/null +++ b/tests/Translator/Extractor/AdminExtractorTest.php @@ -0,0 +1,124 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Sonata\AdminBundle\Tests\Translator\Extractor; + +use PHPUnit\Framework\TestCase; +use Sonata\AdminBundle\Admin\AdminInterface; +use Sonata\AdminBundle\Admin\BreadcrumbsBuilderInterface; +use Sonata\AdminBundle\Admin\Pool; +use Sonata\AdminBundle\Translator\Extractor\AdminExtractor; +use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\Translation\MessageCatalogue; + +final class AdminExtractorTest extends TestCase +{ + /** + * @var AdminExtractor + */ + private $adminExtractor; + + /** + * @var Pool + */ + private $pool; + + /** + * @var AdminInterface + */ + private $fooAdmin; + + /** + * @var AdminInterface + */ + private $barAdmin; + + /** + * @var BreadcrumbsBuilderInterface + */ + private $breadcrumbsBuilder; + + protected function setUp(): void + { + $this->fooAdmin = $this->createStub(AdminInterface::class); + $this->barAdmin = $this->createStub(AdminInterface::class); + + $container = new Container(); + $container->set('foo_admin', $this->fooAdmin); + $container->set('bar_admin', $this->barAdmin); + + $this->pool = new Pool($container, 'title', 'logo_title'); + $this->pool->setAdminServiceIds(['foo_admin', 'bar_admin']); + $this->pool->setAdminGroups(['group' => [ + 'label_catalogue' => 'admin_domain', + ]]); + + $this->breadcrumbsBuilder = $this->createMock(BreadcrumbsBuilderInterface::class); + $this->adminExtractor = new AdminExtractor($this->pool, $this->breadcrumbsBuilder); + } + + public function testExtractEmpty(): void + { + $catalogue = new MessageCatalogue('en'); + + $this->adminExtractor->extract([], $catalogue); + $this->assertFalse($catalogue->has('foo', 'foo_admin_domain')); + } + + public function testExtract(): void + { + $this->fooAdmin + ->method('getLabel') + ->willReturn('foo_label'); + $this->fooAdmin + ->method('getTranslationDomain') + ->willReturn('foo_admin_domain'); + + $catalogue = new MessageCatalogue('en'); + + $this->adminExtractor->extract([], $catalogue); + + $this->assertCount(2, $catalogue->getDomains()); + $message = $catalogue->get('foo', 'foo_admin_domain'); + $this->assertSame('foo', $message); + + $this->assertTrue($catalogue->has('group', 'admin_domain')); + $this->assertTrue($catalogue->has('foo_label', 'foo_admin_domain')); + } + + public function testExtractWithException(): void + { + $this->fooAdmin + ->method('getShow') + ->willThrowException(new \RuntimeException('Foo throws exception')); + + $catalogue = new MessageCatalogue('en'); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Foo throws exception'); + + $this->adminExtractor->extract([], $catalogue); + } + + public function testExtractCallsBreadcrumbs(): void + { + $numberOfAdmins = \count($this->pool->getAdminServiceIds()); + $numberOfActionsToCheck = 6; + + $this->breadcrumbsBuilder->expects($this->exactly($numberOfAdmins * $numberOfActionsToCheck)) + ->method('getBreadcrumbs'); + $catalogue = new MessageCatalogue('en'); + + $this->adminExtractor->extract([], $catalogue); + } +} diff --git a/tests/Translator/Extractor/JMSTranslatorBundle/AdminExtractorTest.php b/tests/Translator/Extractor/JMSTranslatorBundle/AdminExtractorTest.php index 97c412aadd..9dd79546e9 100644 --- a/tests/Translator/Extractor/JMSTranslatorBundle/AdminExtractorTest.php +++ b/tests/Translator/Extractor/JMSTranslatorBundle/AdminExtractorTest.php @@ -27,6 +27,10 @@ /** * Test for AdminExtractor. * + * NEXT_MAJOR: Remove this class. + * + * @group legacy + * * @author Andrej Hudec */ class AdminExtractorTest extends TestCase