From be445e1668007b8230d539d60bb9c768fd000ead Mon Sep 17 00:00:00 2001 From: wbloszyk Date: Fri, 19 Jun 2020 14:42:10 +0200 Subject: [PATCH] Fix BC after drop twig/extensions (#6145) This commit replace using TextExtension from `twig/extensions` by copy truncate function to `DeprecatedTextExtension` method. Update src/DependencyInjection/Configuration.php Co-authored-by: Vincent Langlet Co-authored-by: Vincent Langlet --- src/DependencyInjection/Configuration.php | 13 ++-- .../SonataAdminExtension.php | 17 +++--- src/Resources/config/twig_string.xml | 4 ++ .../Extension/DeprecatedTextExtension.php | 61 +++++++++++++++++++ src/Twig/Extension/StringExtension.php | 21 +++++-- .../SonataAdminExtensionTest.php | 10 ++- 6 files changed, 95 insertions(+), 31 deletions(-) create mode 100644 src/Twig/Extension/DeprecatedTextExtension.php diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index b2167e64ca..b67412a81b 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -34,13 +34,7 @@ class Configuration implements ConfigurationInterface public function getConfigTreeBuilder() { $treeBuilder = new TreeBuilder('sonata_admin'); - - // Keep compatibility with symfony/config < 4.2 - if (!method_exists($treeBuilder, 'getRootNode')) { - $rootNode = $treeBuilder->root('sonata_admin'); - } else { - $rootNode = $treeBuilder->getRootNode(); - } + $rootNode = $treeBuilder->getRootNode(); $caseSensitiveInfo = <<<'CASESENSITIVE' Whether the global search should behave case sensitive or not. @@ -176,6 +170,7 @@ public function getConfigTreeBuilder() // NEXT_MAJOR : remove this option ->booleanNode('legacy_twig_text_extension') ->info('Use text filters from "twig/extensions" instead of those provided by "twig/string-extra".') + ->setDeprecated('The child node "%node%" at path "%path%" is deprecated since sonata-project/admin-bundle 3.x and will be remove in 4.0.') ->defaultValue(static function (): bool { @trigger_error( 'Using `true` as value for "sonata_admin.options.legacy_twig_text_extension" option is deprecated since sonata-project/admin-bundle 3.64. '. @@ -188,8 +183,8 @@ public function getConfigTreeBuilder() ->ifTrue() ->then(static function (bool $v): bool { @trigger_error( - 'Using `true` as value for "sonata_admin.options.legacy_twig_text_extension" option is deprecated since sonata-project/admin-bundle 3.64. '. - 'You should set it to `false`, which will be the default value since version 4.0.' + 'Using `true` as value for "sonata_admin.options.legacy_twig_text_extension" option is deprecated since sonata-project/admin-bundle 3.64 and will be remove in 4.0'. + 'You should set it to `false` before upgrade process.' ); return $v; diff --git a/src/DependencyInjection/SonataAdminExtension.php b/src/DependencyInjection/SonataAdminExtension.php index 80a4dcd3b5..b1d8502192 100644 --- a/src/DependencyInjection/SonataAdminExtension.php +++ b/src/DependencyInjection/SonataAdminExtension.php @@ -323,21 +323,18 @@ private function replacePropertyAccessor(ContainerBuilder $container): void $modelChoice->replaceArgument(0, new Reference('form.property_accessor')); } + /** + * NEXT_MAJOR: remove this method. + */ private function configureTwigTextExtension(ContainerBuilder $container, XmlFileLoader $loader, array $config): void { - $bundles = $container->getParameter('kernel.bundles'); - $container->setParameter('sonata.admin.configuration.legacy_twig_text_extension', $config['options']['legacy_twig_text_extension']); $loader->load('twig_string.xml'); - if (isset($bundles['SonataCoreBundle']) && false !== $config['options']['legacy_twig_text_extension']) { - $stringExtension = $container->getDefinition('sonata.string.twig.extension'); - $stringExtension->replaceArgument(0, new Reference('sonata.core.twig.extension.text')); - } elseif (isset($bundles['SonataTwigBundle']) && false !== $config['options']['legacy_twig_text_extension']) { - if ($container->getDefinition('sonata.twig.extension.deprecated_text_extension')) { - $stringExtension = $container->getDefinition('sonata.string.twig.extension'); - $stringExtension->replaceArgument(0, new Reference('sonata.twig.extension.deprecated_text_extension')); - } + if (false !== $config['options']['legacy_twig_text_extension']) { + $container + ->getDefinition('sonata.string.twig.extension') + ->replaceArgument(0, new Reference('sonata.deprecated_text.twig.extension')); } } } diff --git a/src/Resources/config/twig_string.xml b/src/Resources/config/twig_string.xml index 64241ad37d..3136aaa936 100644 --- a/src/Resources/config/twig_string.xml +++ b/src/Resources/config/twig_string.xml @@ -5,5 +5,9 @@ null + + + + diff --git a/src/Twig/Extension/DeprecatedTextExtension.php b/src/Twig/Extension/DeprecatedTextExtension.php new file mode 100644 index 0000000000..ae0a7aba94 --- /dev/null +++ b/src/Twig/Extension/DeprecatedTextExtension.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Sonata\AdminBundle\Twig\Extension; + +use Twig\Environment; +use Twig\Extension\AbstractExtension; + +/** + * NEXT_MAJOR: Remove this class. + * + * @internal + * + * @deprecated since sonata-project/admin-bundle 3.x, to be removed in 4.0. + * + * This class is used to support `Sonata\AdminBundle\Twig\Extension\StringExtensions` when `sonata_admin.options.legacy_twig_text_extension` + * is set to true and deprecated `twig/extensions` is not installed. It is copy of required function, which keep BC for `sonata_truncate` + * twig filter until sonata-project/admin-bundle 4.0 where this filter will be dropped. + */ +final class DeprecatedTextExtension extends AbstractExtension +{ + public function twigTruncateFilter(Environment $env, ?string $value, int $length = 30, bool $preserve = false, $separator = '...') + { + if (\function_exists('mb_get_info')) { + if (mb_strlen($value, $env->getCharset()) > $length) { + if ($preserve) { + // If breakpoint is on the last word, return the value without separator. + if (false === ($breakpoint = mb_strpos($value, ' ', $length, $env->getCharset()))) { + return $value; + } + + $length = $breakpoint; + } + + return rtrim(mb_substr($value, 0, $length, $env->getCharset())).$separator; + } + } else { + if (\strlen($value) > $length) { + if ($preserve) { + if (false !== ($breakpoint = strpos($value, ' ', $length))) { + $length = $breakpoint; + } + } + + return rtrim(substr($value, 0, $length)).$separator; + } + } + + return $value; + } +} diff --git a/src/Twig/Extension/StringExtension.php b/src/Twig/Extension/StringExtension.php index 130f93a691..0d5a0dc771 100644 --- a/src/Twig/Extension/StringExtension.php +++ b/src/Twig/Extension/StringExtension.php @@ -29,18 +29,28 @@ * @internal * * @see https://github.com/symfony/symfony/pull/35649 + * @deprecated since sonata-project/admin-bundle 3.69, to be removed in 4.0. * * @author Javier Spagnoletti */ final class StringExtension extends AbstractExtension { /** - * @var TextExtension + * @var AbstractExtension */ private $legacyExtension; - public function __construct(?TextExtension $legacyExtension = null) + public function __construct(?AbstractExtension $legacyExtension = null) { + if (!$legacyExtension instanceof TextExtension && !$legacyExtension instanceof DeprecatedTextExtension) { + throw new \TypeError(sprintf( + 'Argument 1 passed to %s::__construct() must be instance of %s or %s', + self::class, + TextExtension::class, + DeprecatedTextExtension::class + )); + } + $this->legacyExtension = $legacyExtension; } @@ -65,16 +75,15 @@ public function deprecatedTruncate(Environment $env, ?string $text, int $length E_USER_DEPRECATED ); - if (null !== $this->legacyExtension) { + if ($this->legacyExtension instanceof TextExtension) { return twig_truncate_filter($env, $text, $length, $preserve, $ellipsis); + } elseif ($this->legacyExtension instanceof DeprecatedTextExtension) { + return $this->legacyExtension->twigTruncateFilter($env, $text, $length, $preserve, $ellipsis); } return $this->legacyTruncteWithUnicodeString($text, $length, $preserve, $ellipsis); } - /** - * NEXT_MAJOR: Fix the arguments in order to respect the signature at `UnicodeString::truncate()`. - */ public function legacyTruncteWithUnicodeString(?string $text, int $length = 30, bool $preserve = false, string $ellipsis = '...'): SymfonyUnicodeString { return (new SymfonyUnicodeString($text ?? ''))->truncate($length, $ellipsis, $preserve); diff --git a/tests/DependencyInjection/SonataAdminExtensionTest.php b/tests/DependencyInjection/SonataAdminExtensionTest.php index 00156c593b..ebd29e8ced 100644 --- a/tests/DependencyInjection/SonataAdminExtensionTest.php +++ b/tests/DependencyInjection/SonataAdminExtensionTest.php @@ -342,15 +342,13 @@ public function testLegacyTextExtensionConfiguration(): void { $this->load(); - $bundles = $this->container->getParameter('kernel.bundles'); $this->assertTrue($this->container->getParameter('sonata.admin.configuration.legacy_twig_text_extension')); $this->assertContainerBuilderHasService('sonata.string.twig.extension'); - if (isset($bundles['SonataCoreBundle'])) { - $this->assertSame('sonata.core.twig.extension.text', (string) $this->container->getDefinition('sonata.string.twig.extension')->getArgument(0)); - } else { - $this->assertNull($this->container->getDefinition('sonata.string.twig.extension')->getArgument(0)); - } + $this->assertSame( + 'sonata.deprecated_text.twig.extension', + (string) $this->container->getDefinition('sonata.string.twig.extension')->getArgument(0) + ); $this->load([ 'options' => [