diff --git a/composer.json b/composer.json index 9c2d607d..3cc1c731 100644 --- a/composer.json +++ b/composer.json @@ -24,29 +24,31 @@ "jms/metadata": "^2.1", "jms/serializer": "^2.0 || ^3.0", "sonata-project/doctrine-extensions": "^1.1", - "symfony/event-dispatcher": "^3.4 || ^4.3 || ^5.0", - "symfony/form": "^3.4.24 || ^4.3 || ^5.0", - "symfony/options-resolver": "^3.4 || ^4.3 || ^5.0", - "symfony/property-access": "^3.4 || ^4.3 || ^5.0", - "symfony/security-csrf": "^3.4 || ^4.3 || ^5.0", - "symfony/translation": "^3.4 || ^4.3 || ^5.0", - "symfony/validator": "^3.4 || ^4.3 || ^5.0", - "twig/twig": "^2.0 || ^3.0" + "symfony/event-dispatcher": "^4.3", + "symfony/form": "^4.3", + "symfony/options-resolver": "^4.3", + "symfony/property-access": "^4.3", + "symfony/security-csrf": "^4.3", + "symfony/translation": "^4.3", + "symfony/validator": "^4.3", + "twig/twig": "^2.12.1" }, "conflict": { - "sonata-project/core-bundle": "<3.19" + "sonata-project/core-bundle": "<3.20" }, "require-dev": { "doctrine/persistence": "^1.1", - "matthiasnoback/symfony-config-test": "^4.0", - "matthiasnoback/symfony-dependency-injection-test": "^4.0", - "symfony/config": "^3.4 || ^4.3 || ^5.0", - "symfony/dependency-injection": "^3.4 || ^4.3 || ^5.0", - "symfony/framework-bundle": "^3.4 || ^4.3 || ^5.0", - "symfony/http-foundation": "^3.4 || ^4.3 || ^5.0", - "symfony/http-kernel": "^3.4 || ^4.3 || ^5.0", + "matthiasnoback/symfony-config-test": "^4.2", + "matthiasnoback/symfony-dependency-injection-test": "^4.1", + "symfony/browser-kit": "^4.3", + "symfony/config": "^4.3", + "symfony/dependency-injection": "^4.3", + "symfony/framework-bundle": "^4.3", + "symfony/http-foundation": "^4.3", + "symfony/http-kernel": "^4.3", "symfony/phpunit-bridge": "^5.0", - "symfony/twig-bridge": "^3.4 || ^4.3 || ^5.0" + "symfony/twig-bridge": "^4.3", + "symfony/twig-bundle": "^4.3" }, "suggest": { "doctrine/persistence": "If you want to use BaseDoctrineORMSerializationType" diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 0ba1bc6d..1fcadb4b 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -15,4 +15,3 @@ parameters: ignoreErrors: - '#Class Sonata\\Form\\Validator\\LegacyExecutionContextInterface not found.#' - - '#Class Symfony\\Component\\Translation\\TranslatorInterface not found.#' diff --git a/src/Bridge/Symfony/Resources/config/form_types.xml b/src/Bridge/Symfony/Resources/config/form_types.xml index 234ff37d..d3d6606d 100644 --- a/src/Bridge/Symfony/Resources/config/form_types.xml +++ b/src/Bridge/Symfony/Resources/config/form_types.xml @@ -22,13 +22,11 @@ - - diff --git a/src/Bridge/Symfony/Resources/translations/SonataFormBundle.ru.xliff b/src/Bridge/Symfony/Resources/translations/SonataFormBundle.ru.xliff index 3d38cf1e..dd7c36bd 100644 --- a/src/Bridge/Symfony/Resources/translations/SonataFormBundle.ru.xliff +++ b/src/Bridge/Symfony/Resources/translations/SonataFormBundle.ru.xliff @@ -14,6 +14,10 @@ label_type_no нет + + sonata_form_template_box_file_found_in + Этот файл можно найти в + label_type_equals равен diff --git a/src/Bridge/Symfony/Bundle/SonataFormBundle.php b/src/Bridge/Symfony/SonataFormBundle.php similarity index 79% rename from src/Bridge/Symfony/Bundle/SonataFormBundle.php rename to src/Bridge/Symfony/SonataFormBundle.php index cbea288d..f20dbbbe 100644 --- a/src/Bridge/Symfony/Bundle/SonataFormBundle.php +++ b/src/Bridge/Symfony/SonataFormBundle.php @@ -11,21 +11,13 @@ * file that was distributed with this source code. */ -namespace Sonata\Form\Bridge\Symfony\Bundle; +namespace Sonata\Form\Bridge\Symfony; use Sonata\Form\Bridge\Symfony\DependencyInjection\SonataFormExtension; use Symfony\Component\HttpKernel\Bundle\Bundle; final class SonataFormBundle extends Bundle { - /** - * @return string - */ - public function getPath() - { - return __DIR__.'/..'; - } - /** * @return string */ diff --git a/src/Date/MomentFormatConverter.php b/src/Date/MomentFormatConverter.php index bd811b6e..71915853 100644 --- a/src/Date/MomentFormatConverter.php +++ b/src/Date/MomentFormatConverter.php @@ -59,7 +59,6 @@ class MomentFormatConverter public function convert($format) { $size = \strlen($format); - $output = ''; //process the format string letter by letter for ($i = 0; $i < $size; ++$i) { diff --git a/src/EventListener/FixCheckboxDataListener.php b/src/EventListener/FixCheckboxDataListener.php index 9f0ceb7c..747de1ff 100644 --- a/src/EventListener/FixCheckboxDataListener.php +++ b/src/EventListener/FixCheckboxDataListener.php @@ -34,7 +34,20 @@ class FixCheckboxDataListener implements EventSubscriberInterface */ public static function getSubscribedEvents() { - return [FormEvents::PRE_SUBMIT => 'preSubmit']; + /* + * NEXT_MAJOR: change preBind to preSubmit + */ + return [FormEvents::PRE_SUBMIT => 'preBind']; + } + + /** + * NEXT_MAJOR: remove this method. + * + * @deprecated since sonata-project/form-extensions 0.x, to be removed in 1.0. Use Use {@link preSubmit} instead. + */ + public function preBind(FormEvent $event) + { + $this->preSubmit($event); } public function preSubmit(FormEvent $event) diff --git a/src/EventListener/ResizeFormListener.php b/src/EventListener/ResizeFormListener.php index 28966bbc..ee2bef98 100644 --- a/src/EventListener/ResizeFormListener.php +++ b/src/EventListener/ResizeFormListener.php @@ -73,11 +73,31 @@ public static function getSubscribedEvents() { return [ FormEvents::PRE_SET_DATA => 'preSetData', - FormEvents::PRE_SUBMIT => 'preSubmit', - FormEvents::SUBMIT => 'onSubmit', + FormEvents::PRE_SUBMIT => 'preBind', + FormEvents::SUBMIT => 'onBind', ]; } + /** + * NEXT_MAJOR: remove this method. + * + * @deprecated since sonata-project/form-extensions 0.x, to be renamed in 1.0. Use {@link preSubmit} instead. + */ + public function preBind(FormEvent $event) + { + $this->preSubmit($event); + } + + /** + * NEXT_MAJOR: remove this method. + * + * @deprecated since sonata-project/form-extensions 0.x, to be renamed in 1.0. Use {@link onSubmit} instead. + */ + public function onBind(FormEvent $event) + { + $this->onSubmit($event); + } + /** * @throws UnexpectedTypeException */ diff --git a/src/Serializer/BaseSerializerHandler.php b/src/Serializer/BaseSerializerHandler.php index a511215e..8c409a51 100644 --- a/src/Serializer/BaseSerializerHandler.php +++ b/src/Serializer/BaseSerializerHandler.php @@ -59,6 +59,16 @@ final public static function addFormat($format) */ public static function getSubscribingMethods() { + // NEXT_MAJOR : remove this block + if (null === static::$formats) { + static::$formats = ['json', 'xml', 'yml']; + @trigger_error(sprintf( + '%s::$formats has been set by default to array("json", "xml", "yml"). Ability to set them to a + different value is deprecated since sonata-project/form-bundle 0.x and will be removed in version 1.0. Use "sonata_form.serializer.formats" configuration instead.', + __CLASS__ + ), E_USER_DEPRECATED); + } + $type = static::getType(); $methods = []; @@ -88,7 +98,7 @@ public static function getSubscribingMethods() * * @return int|null */ - public function serializeObjectToId(VisitorInterface $visitor, $data, $type, Context $context) + public function serializeObjectToId(VisitorInterface $visitor, $data, array $type, Context $context) { $className = $this->manager->getClass(); diff --git a/src/Test/AbstractWidgetTestCase.php b/src/Test/AbstractWidgetTestCase.php index b1183cf0..3a9b0be6 100644 --- a/src/Test/AbstractWidgetTestCase.php +++ b/src/Test/AbstractWidgetTestCase.php @@ -13,16 +13,20 @@ namespace Sonata\Form\Test; +use Sonata\Form\Fixtures\StubFilesystemLoader; use Sonata\Form\Fixtures\StubTranslator; +use Symfony\Bridge\Twig\AppVariable; use Symfony\Bridge\Twig\Extension\FormExtension; use Symfony\Bridge\Twig\Extension\TranslationExtension; +use Symfony\Bridge\Twig\Form\TwigRenderer; use Symfony\Bridge\Twig\Form\TwigRendererEngine; +use Symfony\Component\Form\FormExtensionInterface; use Symfony\Component\Form\FormRenderer; use Symfony\Component\Form\FormView; use Symfony\Component\Form\Test\TypeTestCase; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Twig\Environment; -use Twig\Loader\FilesystemLoader; +use Twig\Extension\InitRuntimeInterface; use Twig\RuntimeLoader\FactoryRuntimeLoader; /** @@ -32,6 +36,11 @@ */ abstract class AbstractWidgetTestCase extends TypeTestCase { + /** + * @var FormExtensionInterface + */ + private $extension; + /** * @var FormRenderer */ @@ -41,34 +50,44 @@ protected function setUp(): void { parent::setUp(); + $this->extension = new FormExtension(); $environment = $this->getEnvironment(); - $this->renderer = new FormRenderer( $this->getRenderingEngine($environment), $this->createMock(CsrfTokenManagerInterface::class) ); + $runtimeLoader = new FactoryRuntimeLoader([ + FormRenderer::class => [$this, 'getRenderer'], + TwigRenderer::class => [$this, 'getRenderer'], + ]); + + $environment->addRuntimeLoader($runtimeLoader); - $environment->addRuntimeLoader(new FactoryRuntimeLoader([ - FormRenderer::class => function () { - return $this->renderer; - }, - ])); - $environment->addExtension(new FormExtension()); + if ($this->extension instanceof InitRuntimeInterface) { + $this->extension->initRuntime($environment); + } } - final public function getRenderer(): FormRenderer + /** + * @return FormRenderer + */ + final public function getRenderer() { return $this->renderer; } - protected function getEnvironment(): Environment + /** + * @return Environment + */ + protected function getEnvironment() { - $loader = new FilesystemLoader($this->getTemplatePaths()); + $loader = new StubFilesystemLoader($this->getTemplatePaths()); $environment = new Environment($loader, [ 'strict_variables' => true, ]); $environment->addExtension(new TranslationExtension(new StubTranslator())); + $environment->addExtension($this->extension); return $environment; } @@ -97,8 +116,22 @@ protected function getTemplatePaths() return $twigPaths; } - protected function getRenderingEngine(Environment $environment) + /** + * NEXT_MAJOR: uncomment and use the $environment argument. + * + * @return TwigRendererEngine + */ + protected function getRenderingEngine(/* \Twig_Environment $environment = null */) { + $environment = current(\func_get_args()); + if (null === $environment && method_exists(AppVariable::class, 'getToken')) { + @trigger_error( + 'Not passing a \Twig_Environment instance to '.__METHOD__. + ' is deprecated since 0.x and will not be possible in 1.0', + E_USER_DEPRECATED + ); + } + return new TwigRendererEngine(['form_div_layout.html.twig'], $environment); } diff --git a/src/Type/BasePickerType.php b/src/Type/BasePickerType.php index 38ea6d5b..d8df485c 100644 --- a/src/Type/BasePickerType.php +++ b/src/Type/BasePickerType.php @@ -18,7 +18,6 @@ use Symfony\Component\Form\Extension\Core\Type\DateTimeType; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface; @@ -32,7 +31,7 @@ abstract class BasePickerType extends AbstractType { /** - * @var TranslatorInterface|LegacyTranslatorInterface|null + * @var LegacyTranslatorInterface|TranslatorInterface|null */ protected $translator; @@ -47,11 +46,15 @@ abstract class BasePickerType extends AbstractType private $formatConverter; /** - * @param LegacyTranslatorInterface|TranslatorInterface|null $translator + * NEXT_MAJOR: TranslatorInterface needs to be mandatory. */ - public function __construct(MomentFormatConverter $formatConverter, $translator = null, ?RequestStack $requestStack = null) + public function __construct(MomentFormatConverter $formatConverter, $translator = null) { - if (!$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface && null !== $translator) { + if ( + !$translator instanceof LegacyTranslatorInterface && + !$translator instanceof TranslatorInterface && + null !== $translator + ) { throw new \InvalidArgumentException(sprintf( 'Argument 2 should be an instance of %s or %s or %s', LegacyTranslatorInterface::class, @@ -60,39 +63,24 @@ public function __construct(MomentFormatConverter $formatConverter, $translator )); } - if (null === $requestStack) { - if ($translator instanceof TranslatorInterface) { - throw new \InvalidArgumentException(sprintf( - 'Argument 3 should be an instance of %s', - RequestStack::class - )); - } - - @trigger_error(sprintf( - 'Not passing the request stack as argument 3 to %s() is deprecated since sonata-project/form-extensions 0.x and will be mandatory in 2.0.', - __METHOD__ - ), E_USER_DEPRECATED); - } - $this->formatConverter = $formatConverter; $this->translator = $translator; - if ($translator instanceof LegacyTranslatorInterface) { - $this->locale = $this->translator->getLocale(); - } elseif ($translator instanceof TranslatorInterface) { - $this->locale = $this->getLocale($requestStack); - } else { - /* - * NEXT_MAJOR: remove this check - */ + /* + * NEXT_MAJOR: remove this check + */ + if (null === $this->translator) { @trigger_error( 'Initializing '.__CLASS__.' without TranslatorInterface is deprecated since 0.x and will be removed in 1.0.', E_USER_DEPRECATED ); - $this->locale = \Locale::getDefault(); + + return; } + + $this->locale = $this->translator->getLocale() ?? \Locale::getDefault(); } public function configureOptions(OptionsResolver $resolver) @@ -124,7 +112,7 @@ public function configureOptions(OptionsResolver $resolver) }); } - public function finishView(FormView $view, FormInterface $form, array $options) + public function finishView(FormView $view, FormInterface $form, array $options): void { $format = $options['format']; @@ -195,15 +183,6 @@ protected function getCommonDefaults() ]; } - private function getLocale(RequestStack $requestStack): string - { - if (!$request = $requestStack->getCurrentRequest()) { - throw new \LogicException('A Request must be available.'); - } - - return $request->getLocale(); - } - private function formatObject(\DateTime $dateTime, $format): string { $formatter = new \IntlDateFormatter($this->locale, \IntlDateFormatter::NONE, \IntlDateFormatter::NONE); diff --git a/src/Type/BaseStatusType.php b/src/Type/BaseStatusType.php index 8c281fe8..520c574a 100644 --- a/src/Type/BaseStatusType.php +++ b/src/Type/BaseStatusType.php @@ -92,7 +92,7 @@ public function configureOptions(OptionsResolver $resolver) { $choices = \call_user_func([$this->class, $this->getter]); - // NEXT_MAJOR: remove this block + // NEXT_MAJOR: remove this property if ($this->flip) { $count = \count($choices); diff --git a/src/Type/BooleanType.php b/src/Type/BooleanType.php index b6a70503..81840610 100644 --- a/src/Type/BooleanType.php +++ b/src/Type/BooleanType.php @@ -35,7 +35,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) $builder->addModelTransformer(new BooleanTypeToBooleanTransformer()); } - if ('SonataCoreBundle' !== $options['catalogue']) { + if ('SonataFormBundle' !== $options['catalogue']) { @trigger_error( 'Option "catalogue" is deprecated since sonata-project/form-extensions 0.x and will be removed in 1.0.' .' Use option "translation_domain" instead.', @@ -46,26 +46,29 @@ public function buildForm(FormBuilderInterface $builder, array $options) public function configureOptions(OptionsResolver $resolver) { - $resolver->setDefaults([ + $defaultOptions = [ 'transform' => false, /* - * NEXT_MAJOR: remove 'catalogue' => 'SonataCoreBundle', - * @deprecated since 0.x, to be removed in 1.0. Use 'translation_domain' => 'SonataCoreBundle' instead. + * NEXT_MAJOR: remove this block. + * @deprecated since sonata-project/form-extensions 0.x, to be removed in 1.0. */ - 'catalogue' => 'SonataCoreBundle', - 'choice_translation_domain' => 'SonataCoreBundle', + 'catalogue' => 'SonataFormBundle', + 'choice_translation_domain' => 'SonataFormBundle', 'choices' => [ 'label_type_yes' => self::TYPE_YES, 'label_type_no' => self::TYPE_NO, ], - 'translation_domain' => static function (Options $options): string { + // Use directly translation_domain + 'translation_domain' => static function (Options $options) { if ($options['catalogue']) { return $options['catalogue']; } return $options['translation_domain']; }, - ]); + ]; + + $resolver->setDefaults($defaultOptions); } /** diff --git a/src/Type/CollectionType.php b/src/Type/CollectionType.php index d442b7dc..8f0f2a16 100644 --- a/src/Type/CollectionType.php +++ b/src/Type/CollectionType.php @@ -28,12 +28,14 @@ class CollectionType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { - $builder->addEventSubscriber(new ResizeFormListener( + $listener = new ResizeFormListener( $options['type'], $options['type_options'], $options['modifiable'], $options['pre_bind_data_callback'] - )); + ); + + $builder->addEventSubscriber($listener); } public function buildView(FormView $view, FormInterface $form, array $options) @@ -50,7 +52,7 @@ public function configureOptions(OptionsResolver $resolver) 'type_options' => [], 'pre_bind_data_callback' => null, 'btn_add' => 'link_add', - 'btn_catalogue' => 'SonataCoreBundle', + 'btn_catalogue' => 'SonataFormBundle', ]); } diff --git a/src/Type/DateRangeType.php b/src/Type/DateRangeType.php index b6b8056b..91329a48 100644 --- a/src/Type/DateRangeType.php +++ b/src/Type/DateRangeType.php @@ -35,29 +35,26 @@ class DateRangeType extends AbstractType * NEXT_MAJOR: remove this method. * * @deprecated translator dependency is deprecated since sonata-project/form-extensions 0.x, to be removed in 1.0 - * - * @param LegacyTranslatorInterface|TranslatorInterface|null $translator */ public function __construct($translator = null) { - if (!$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface && null !== $translator) { + if ( + !$translator instanceof LegacyTranslatorInterface && + !$translator instanceof TranslatorInterface && + null !== $translator + ) { throw new \InvalidArgumentException(sprintf( - 'Argument 1 should be an instance of %s or %s or %s', + 'Argument 2 should be an instance of %s or %s', LegacyTranslatorInterface::class, - TranslatorInterface::class, - 'null' + TranslatorInterface::class )); } + // check if class is overloaded and notify about removing deprecated translator if (null !== $translator && __CLASS__ !== static::class && DateRangePickerType::class !== static::class) { @trigger_error( - sprintf( - 'The translator dependency in %s is deprecated since 0.x and will be removed in 1.0. '. - 'Please do not call %s with translator argument in %s.', - __CLASS__, - __METHOD__, - static::class - ), + 'The translator dependency in '.__CLASS__.' is deprecated since 0.x and will be removed in 1.0. '. + 'Please prepare your dependencies for this change.', E_USER_DEPRECATED ); } @@ -70,7 +67,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) $options['field_options_start'] = array_merge( [ 'label' => 'date_range_start', - 'translation_domain' => 'SonataCoreBundle', + 'translation_domain' => 'SonataFormBundle', ], $options['field_options_start'] ); @@ -78,21 +75,13 @@ public function buildForm(FormBuilderInterface $builder, array $options) $options['field_options_end'] = array_merge( [ 'label' => 'date_range_end', - 'translation_domain' => 'SonataCoreBundle', + 'translation_domain' => 'SonataFormBundle', ], $options['field_options_end'] ); - $builder->add( - 'start', - $options['field_type'], - array_merge(['required' => false], $options['field_options'], $options['field_options_start']) - ); - $builder->add( - 'end', - $options['field_type'], - array_merge(['required' => false], $options['field_options'], $options['field_options_end']) - ); + $builder->add('start', $options['field_type'], array_merge(['required' => false], $options['field_options'], $options['field_options_start'])); + $builder->add('end', $options['field_type'], array_merge(['required' => false], $options['field_options'], $options['field_options_end'])); } /** diff --git a/src/Type/DateTimeRangePickerType.php b/src/Type/DateTimeRangePickerType.php index 35ed1665..d0d2b911 100644 --- a/src/Type/DateTimeRangePickerType.php +++ b/src/Type/DateTimeRangePickerType.php @@ -14,8 +14,6 @@ namespace Sonata\Form\Type; use Symfony\Component\OptionsResolver\OptionsResolver; -use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface; -use Symfony\Contracts\Translation\TranslatorInterface; /** * DateTimeRangePickerType. @@ -24,49 +22,6 @@ */ class DateTimeRangePickerType extends DateTimeRangeType { - /** - * NEXT_MAJOR: remove this property. - * - * @var LegacyTranslatorInterface|TranslatorInterface|null - * - * @deprecated translator property is deprecated since sonata-project/form-extensions 0.x, to be removed in 1.0 - */ - protected $translator; - - /** - * NEXT_MAJOR: remove this method. - * - * @deprecated translator dependency is deprecated since sonata-project/form-extensions 0.x, to be removed in 1.0 - * - * @param LegacyTranslatorInterface|TranslatorInterface|null $translator - */ - public function __construct($translator = null) - { - if (!$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface && null !== $translator) { - throw new \InvalidArgumentException(sprintf( - 'Argument 1 should be an instance of %s or %s or %s', - LegacyTranslatorInterface::class, - TranslatorInterface::class, - 'null' - )); - } - - if (null !== $translator && __CLASS__ !== static::class && DateRangePickerType::class !== static::class) { - @trigger_error( - sprintf( - 'The translator dependency in %s is deprecated since 0.x and will be removed in 1.0. '. - 'Please do not call %s with translator argument in %s.', - __CLASS__, - __METHOD__, - static::class - ), - E_USER_DEPRECATED - ); - } - - $this->translator = $translator; - } - public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ diff --git a/src/Type/DateTimeRangeType.php b/src/Type/DateTimeRangeType.php index dce65dc1..5f267838 100644 --- a/src/Type/DateTimeRangeType.php +++ b/src/Type/DateTimeRangeType.php @@ -17,15 +17,57 @@ use Symfony\Component\Form\Extension\Core\Type\DateTimeType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class DateTimeRangeType extends AbstractType { + /** + * NEXT_MAJOR: remove this property. + * + * @var LegacyTranslatorInterface|TranslatorInterface|null + * + * @deprecated translator property is deprecated since sonata-project/form-bundle 0.x, to be removed in 1.0 + */ + protected $translator; + + /** + * NEXT_MAJOR: remove this method. + * + * @deprecated translator dependency is deprecated since sonata-project/core-bundle 0.x, to be removed in 1.0 + */ + public function __construct($translator = null) + { + if ( + !$translator instanceof LegacyTranslatorInterface && + !$translator instanceof TranslatorInterface && + null !== $translator + ) { + throw new \InvalidArgumentException(sprintf( + 'Argument 2 should be an instance of %s or %s', + LegacyTranslatorInterface::class, + TranslatorInterface::class + )); + } + + // check if class is overloaded and notify about removing deprecated translator + if (null !== $translator && __CLASS__ !== static::class && DateTimeRangePickerType::class !== static::class) { + @trigger_error( + 'The translator dependency in '.__CLASS__.' is deprecated since 0.x and will be removed in 1.0. '. + 'Please prepare your dependencies for this change.', + E_USER_DEPRECATED + ); + } + + $this->translator = $translator; + } + public function buildForm(FormBuilderInterface $builder, array $options) { $options['field_options_start'] = array_merge( [ 'label' => 'date_range_start', - 'translation_domain' => 'SonataCoreBundle', + 'translation_domain' => 'SonataFormBundle', ], $options['field_options_start'] ); @@ -33,21 +75,13 @@ public function buildForm(FormBuilderInterface $builder, array $options) $options['field_options_end'] = array_merge( [ 'label' => 'date_range_end', - 'translation_domain' => 'SonataCoreBundle', + 'translation_domain' => 'SonataFormBundle', ], $options['field_options_end'] ); - $builder->add( - 'start', - $options['field_type'], - array_merge(['required' => false], $options['field_options'], $options['field_options_start']) - ); - $builder->add( - 'end', - $options['field_type'], - array_merge(['required' => false], $options['field_options'], $options['field_options_end']) - ); + $builder->add('start', $options['field_type'], array_merge(['required' => false], $options['field_options'], $options['field_options_start'])); + $builder->add('end', $options['field_type'], array_merge(['required' => false], $options['field_options'], $options['field_options_end'])); } /** diff --git a/src/Type/EqualType.php b/src/Type/EqualType.php index bf04e6be..7a446ab3 100644 --- a/src/Type/EqualType.php +++ b/src/Type/EqualType.php @@ -20,7 +20,7 @@ use Symfony\Contracts\Translation\TranslatorInterface; @trigger_error( - 'The '.__NAMESPACE__.'\EqualType class is deprecated since version 1.2 and will be removed in 2.0.' + 'The '.__NAMESPACE__.'\EqualType class is deprecated since version 0.x and will be removed in 2.0.' .' Use Sonata\AdminBundle\Form\Type\Operator\EqualOperatorType instead.', E_USER_DEPRECATED ); @@ -28,7 +28,7 @@ /** * NEXT_MAJOR: remove this class. * - * @deprecated since sonata-project/form-extensions 1.2, to be removed with 2.0 + * @deprecated since sonata-project/form-extensions 0.x, to be removed with 2.0 * * @final since sonata-project/form-extensions 0.x */ @@ -37,6 +37,7 @@ class EqualType extends AbstractType public const TYPE_IS_EQUAL = 1; public const TYPE_IS_NOT_EQUAL = 2; + /** * NEXT_MAJOR: remove this property. * @@ -50,29 +51,26 @@ class EqualType extends AbstractType * NEXT_MAJOR: remove this method. * * @deprecated translator dependency is deprecated since sonata-project/form-extensions 0.x, to be removed in 1.0 - * - * @param LegacyTranslatorInterface|TranslatorInterface|null $translator */ public function __construct($translator = null) { - if (!$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface && null !== $translator) { + if ( + !$translator instanceof LegacyTranslatorInterface && + !$translator instanceof TranslatorInterface && + null !== $translator + ) { throw new \InvalidArgumentException(sprintf( - 'Argument 1 should be an instance of %s or %s or %s', + 'Argument 2 should be an instance of %s or %s', LegacyTranslatorInterface::class, - TranslatorInterface::class, - 'null' + TranslatorInterface::class )); } - if (null !== $translator && __CLASS__ !== static::class && DateRangePickerType::class !== static::class) { + // check if class is overloaded and notify about removing deprecated translator + if (null !== $translator && __CLASS__ !== static::class) { @trigger_error( - sprintf( - 'The translator dependency in %s is deprecated since 0.x and will be removed in 1.0. '. - 'Please do not call %s with translator argument in %s.', - __CLASS__, - __METHOD__, - static::class - ), + 'The translator dependency in '.__CLASS__.' is deprecated since 0.x and will be removed in 1.0. '. + 'Please prepare your dependencies for this change.', E_USER_DEPRECATED ); } @@ -82,13 +80,15 @@ public function __construct($translator = null) public function configureOptions(OptionsResolver $resolver) { - $resolver->setDefaults([ - 'choice_translation_domain' => 'SonataCoreBundle', + $defaultOptions = [ + 'choice_translation_domain' => 'SonataFormBundle', 'choices' => [ 'label_type_equals' => self::TYPE_IS_EQUAL, 'label_type_not_equals' => self::TYPE_IS_NOT_EQUAL, ], - ]); + ]; + + $resolver->setDefaults($defaultOptions); } /** diff --git a/src/Validator/Constraints/InlineConstraint.php b/src/Validator/Constraints/InlineConstraint.php index 729cccca..ddadb1ca 100755 --- a/src/Validator/Constraints/InlineConstraint.php +++ b/src/Validator/Constraints/InlineConstraint.php @@ -116,7 +116,7 @@ public function getRequiredOptions() } /** - * @return mixed string|callable + * @return string */ public function getMethod() { diff --git a/src/Validator/ErrorElement.php b/src/Validator/ErrorElement.php index 8b7fa51c..d8bb27e9 100755 --- a/src/Validator/ErrorElement.php +++ b/src/Validator/ErrorElement.php @@ -47,7 +47,7 @@ class ErrorElement protected $stack = []; /** - * @var PropertyPath[] + * @var string[] */ protected $propertyPaths = []; @@ -175,7 +175,7 @@ public function getSubject() * * @return ErrorElement */ - public function addViolation($message, $parameters = [], $value = null, string $translationDomain = self::DEFAULT_TRANSLATION_DOMAIN) + public function addViolation($message, $parameters = [], $value = null) { if (\is_array($message)) { $value = $message[2] ?? $value; @@ -184,6 +184,15 @@ public function addViolation($message, $parameters = [], $value = null, string $ } $subPath = (string) $this->getCurrentPropertyPath(); + $translationDomain = self::DEFAULT_TRANSLATION_DOMAIN; + + // NEXT_MAJOR: Remove this hack + if (\func_num_args() >= 4) { + $arg = func_get_arg(3); + if ((\is_string($arg))) { + $translationDomain = $arg; + } + } if ($this->context instanceof LegacyExecutionContextInterface) { $this->context->addViolationAt($subPath, $message, $parameters, $value); @@ -211,10 +220,15 @@ public function getErrors() protected function validate(Constraint $constraint) { - $this->context->getValidator() - ->inContext($this->context) - ->atPath((string) $this->getCurrentPropertyPath()) - ->validate($this->getValue(), $constraint, [$this->group]); + $subPath = (string) $this->getCurrentPropertyPath(); + if ($this->context instanceof LegacyExecutionContextInterface) { + $this->context->validateValue($this->getValue(), $constraint, $subPath, $this->group); + } else { + $this->context->getValidator() + ->inContext($this->context) + ->atPath($subPath) + ->validate($this->getValue(), $constraint, [$this->group]); + } } /** @@ -255,7 +269,7 @@ protected function newConstraint($name, array $options = []) protected function getCurrentPropertyPath() { if (!isset($this->propertyPaths[$this->current])) { - return null; //global error + return; //global error } return $this->propertyPaths[$this->current]; diff --git a/tests/DataTransformer/BooleanTypeToBooleanTransformerTest.php b/tests/DataTransformer/BooleanTypeToBooleanTransformerTest.php index 6e8370d0..8cb6a9ce 100644 --- a/tests/DataTransformer/BooleanTypeToBooleanTransformerTest.php +++ b/tests/DataTransformer/BooleanTypeToBooleanTransformerTest.php @@ -22,14 +22,14 @@ class BooleanTypeToBooleanTransformerTest extends TestCase /** * @dataProvider getReverseTransformData */ - public function testReverseTransform($value, $expected): void + public function testReverseTransform($value, $expected) { $transformer = new BooleanTypeToBooleanTransformer(); $this->assertSame($expected, $transformer->transform($value)); } - public function testTransform(): void + public function testTransform() { $transformer = new BooleanTypeToBooleanTransformer(); $this->assertTrue($transformer->reverseTransform(BooleanType::TYPE_YES)); diff --git a/tests/Date/MomentFormatConverterTest.php b/tests/Date/MomentFormatConverterTest.php index ddf7e9b8..52e40bf6 100644 --- a/tests/Date/MomentFormatConverterTest.php +++ b/tests/Date/MomentFormatConverterTest.php @@ -23,7 +23,7 @@ */ class MomentFormatConverterTest extends TestCase { - public function testPhpToMoment(): void + public function testPhpToMoment() { $mfc = new MomentFormatConverter(); diff --git a/tests/EventListener/FixCheckboxDataListenerTest.php b/tests/EventListener/FixCheckboxDataListenerTest.php index 5798894d..40739e16 100644 --- a/tests/EventListener/FixCheckboxDataListenerTest.php +++ b/tests/EventListener/FixCheckboxDataListenerTest.php @@ -25,7 +25,7 @@ class FixCheckboxDataListenerTest extends TestCase /** * @dataProvider valuesProvider */ - public function testFixCheckbox($data, $expected, $suscriber, $transformer): void + public function testFixCheckbox($data, $expected, $suscriber, $transformer) { $dispatcher = new EventDispatcher(); diff --git a/tests/EventListener/ResizeFormListenerTest.php b/tests/EventListener/ResizeFormListenerTest.php index eb4fad2a..195148dc 100644 --- a/tests/EventListener/ResizeFormListenerTest.php +++ b/tests/EventListener/ResizeFormListenerTest.php @@ -25,23 +25,23 @@ */ class ResizeFormListenerTest extends TestCase { - public function testGetSubscribedEvents(): void + public function testGetSubscribedEvents() { $events = ResizeFormListener::getSubscribedEvents(); $this->assertArrayHasKey(FormEvents::PRE_SET_DATA, $events); $this->assertSame('preSetData', $events[FormEvents::PRE_SET_DATA]); $this->assertArrayHasKey(FormEvents::PRE_SUBMIT, $events); - $this->assertSame('preSubmit', $events[FormEvents::PRE_SUBMIT]); + $this->assertSame('preBind', $events[FormEvents::PRE_SUBMIT]); $this->assertArrayHasKey(FormEvents::SUBMIT, $events); - $this->assertSame('onSubmit', $events[FormEvents::SUBMIT]); + $this->assertSame('onBind', $events[FormEvents::SUBMIT]); } - public function testPreSetDataWithNullData(): void + public function testPreSetDataWithNullData() { $listener = new ResizeFormListener('form', [], false, null); - $form = $this->createMock(Form::class); + $form = $this->getMockBuilder(Form::class)->disableOriginalConstructor()->getMock(); $form->expects($this->once()) ->method('getIterator') ->willReturn(new \ArrayIterator()); @@ -53,11 +53,11 @@ public function testPreSetDataWithNullData(): void $listener->preSetData($event); } - public function testPreSetDataThrowsExceptionWithStringEventData(): void + public function testPreSetDataThrowsExceptionWithStringEventData() { $listener = new ResizeFormListener('form', [], false, null); - $form = $this->createMock(Form::class); + $form = $this->getMockBuilder(Form::class)->disableOriginalConstructor()->getMock(); $event = new FormEvent($form, ''); @@ -66,7 +66,7 @@ public function testPreSetDataThrowsExceptionWithStringEventData(): void $listener->preSetData($event); } - public function testPreSetData(): void + public function testPreSetData() { $typeOptions = [ 'default' => 'option', @@ -80,7 +80,7 @@ public function testPreSetData(): void 'default' => 'option', ]; - $form = $this->createMock(Form::class); + $form = $this->getMockBuilder(Form::class)->disableOriginalConstructor()->getMock(); $form->expects($this->once()) ->method('getIterator') ->willReturn(new \ArrayIterator(['foo' => 'bar'])); @@ -98,22 +98,22 @@ public function testPreSetData(): void $listener->preSetData($event); } - public function testPreSubmitWithResizeOnBindFalse(): void + public function testPreSubmitWithResizeOnBindFalse() { $listener = new ResizeFormListener('form', [], false, null); - $event = $this->createMock(FormEvent::class); + $event = $this->getMockBuilder(FormEvent::class)->disableOriginalConstructor()->getMock(); $event->expects($this->never()) ->method('getForm'); $listener->preSubmit($event); } - public function testPreSubmitDataWithNullData(): void + public function testPreSubmitDataWithNullData() { $listener = new ResizeFormListener('form', [], true, null); - $form = $this->createMock(Form::class); + $form = $this->getMockBuilder(Form::class)->disableOriginalConstructor()->getMock(); $form->expects($this->once()) ->method('getIterator') ->willReturn(new \ArrayIterator(['foo' => 'bar'])); @@ -125,11 +125,12 @@ public function testPreSubmitDataWithNullData(): void $listener->preSubmit($event); } - public function testPreSubmitThrowsExceptionWithIntEventData(): void + public function testPreSubmitThrowsExceptionWithIntEventData() { $listener = new ResizeFormListener('form', [], true, null); - $form = $this->createMock(Form::class); + $form = $this->getMockBuilder(Form::class)->disableOriginalConstructor()->getMock(); + $event = new FormEvent($form, 123); $this->expectException(UnexpectedTypeException::class); @@ -137,7 +138,7 @@ public function testPreSubmitThrowsExceptionWithIntEventData(): void $listener->preSubmit($event); } - public function testPreSubmitData(): void + public function testPreSubmitData() { $typeOptions = [ 'default' => 'option', @@ -150,7 +151,7 @@ public function testPreSubmitData(): void 'default' => 'option', ]; - $form = $this->createMock(Form::class); + $form = $this->getMockBuilder(Form::class)->disableOriginalConstructor()->getMock(); $form->expects($this->once()) ->method('getIterator') ->willReturn(new \ArrayIterator(['foo' => 'bar'])); @@ -168,7 +169,7 @@ public function testPreSubmitData(): void $listener->preSubmit($event); } - public function testPreSubmitDataWithClosure(): void + public function testPreSubmitDataWithClosure() { $typeOptions = [ 'default' => 'option', @@ -188,7 +189,7 @@ public function testPreSubmitDataWithClosure(): void 'data' => 'caz', ]; - $form = $this->createMock(Form::class); + $form = $this->getMockBuilder(Form::class)->disableOriginalConstructor()->getMock(); $form->expects($this->once()) ->method('getIterator') ->willReturn(new \ArrayIterator(['foo' => 'bar'])); @@ -204,22 +205,22 @@ public function testPreSubmitDataWithClosure(): void $listener->preSubmit($event); } - public function testOnSubmitWithResizeOnBindFalse(): void + public function testOnSubmitWithResizeOnBindFalse() { $listener = new ResizeFormListener('form', [], false, null); - $event = $this->createMock(FormEvent::class); + $event = $this->getMockBuilder(FormEvent::class)->disableOriginalConstructor()->getMock(); $event->expects($this->never()) ->method('getForm'); $listener->onSubmit($event); } - public function testOnSubmitDataWithNullData(): void + public function testOnSubmitDataWithNullData() { $listener = new ResizeFormListener('form', [], true, null); - $form = $this->createMock(Form::class); + $form = $this->getMockBuilder(Form::class)->disableOriginalConstructor()->getMock(); $form->expects($this->never()) ->method('has'); @@ -228,11 +229,11 @@ public function testOnSubmitDataWithNullData(): void $listener->onSubmit($event); } - public function testOnSubmitThrowsExceptionWithIntEventData(): void + public function testOnSubmitThrowsExceptionWithIntEventData() { $listener = new ResizeFormListener('form', [], true, null); - $form = $this->createMock(Form::class); + $form = $this->getMockBuilder(Form::class)->disableOriginalConstructor()->getMock(); $event = new FormEvent($form, 123); @@ -241,7 +242,7 @@ public function testOnSubmitThrowsExceptionWithIntEventData(): void $listener->onSubmit($event); } - public function testOnSubmit(): void + public function testOnSubmit() { $listener = new ResizeFormListener('form', [], true, null); @@ -250,7 +251,7 @@ public function testOnSubmit(): void $reflectedMethod->setAccessible(true); $reflectedMethod->setValue($listener, ['foo']); - $form = $this->createMock(Form::class); + $form = $this->getMockBuilder(Form::class)->disableOriginalConstructor()->getMock(); $form->expects($this->at(2)) ->method('has') ->with('baz') @@ -266,7 +267,7 @@ public function testOnSubmit(): void 'baz' => 'baz-value', ]; - $event = $this->createMock(FormEvent::class); + $event = $this->getMockBuilder(FormEvent::class)->disableOriginalConstructor()->getMock(); $event->expects($this->once()) ->method('getForm') ->willReturn($form); diff --git a/tests/Fixtures/Bundle/Entity/Foo.php b/tests/Fixtures/Bundle/Entity/Foo.php index 1159f026..c042ee83 100644 --- a/tests/Fixtures/Bundle/Entity/Foo.php +++ b/tests/Fixtures/Bundle/Entity/Foo.php @@ -29,7 +29,7 @@ public function getBar() return $this->bar; } - public function setBar($bar): void + public function setBar($bar) { $this->bar = $bar; } @@ -39,7 +39,7 @@ public function getBaz() return $this->baz; } - public function setBaz($baz): void + public function setBaz($baz) { $this->baz = $baz; } diff --git a/tests/Fixtures/Bundle/Validator/FooValidatorService.php b/tests/Fixtures/Bundle/Validator/FooValidatorService.php index 84f643d4..1d54fc4d 100644 --- a/tests/Fixtures/Bundle/Validator/FooValidatorService.php +++ b/tests/Fixtures/Bundle/Validator/FooValidatorService.php @@ -24,12 +24,11 @@ final class FooValidatorService { /** - * @param ErrorElement $errorElement - * @param string $value + * @param string $value * * @throws ValidatorException */ - public function fooValidatorMethod(ErrorElement $errorElement, $value): void + public function fooValidatorMethod(ErrorElement $errorElement, $value) { throw new ValidatorException($errorElement->getSubject().' is equal to '.$value); } diff --git a/tests/Type/BasePickerTypeTest.php b/tests/Type/BasePickerTypeTest.php index eeb3dd5d..2ff76edb 100644 --- a/tests/Type/BasePickerTypeTest.php +++ b/tests/Type/BasePickerTypeTest.php @@ -13,7 +13,6 @@ namespace Sonata\Form\Tests\Type; -use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Sonata\Form\Date\MomentFormatConverter; use Sonata\Form\Type\BasePickerType; @@ -21,10 +20,7 @@ use Symfony\Component\Form\Form; use Symfony\Component\Form\FormConfigInterface; use Symfony\Component\Form\FormView; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface; -use Symfony\Contracts\Translation\TranslatorInterface; +use Symfony\Component\Translation\TranslatorInterface; class BasePickerTest extends BasePickerType { @@ -33,11 +29,6 @@ public function getName() return 'base_picker_test'; } - public function getLocale(): string - { - return $this->locale; - } - protected function getDefaultFormat() { return DateTimeType::HTML5_FORMAT; @@ -49,19 +40,17 @@ protected function getDefaultFormat() */ class BasePickerTypeTest extends TestCase { - public function testFinishView(): void + public function testFinishView() { $type = new BasePickerTest( new MomentFormatConverter(), - $this->getTranslatorMock(), - $this->getRequestStack() + $this->createMock(TranslatorInterface::class) ); $view = new FormView(); $form = new Form($this->createMock(FormConfigInterface::class)); $type->finishView($view, $form, [ - 'html5' => false, 'format' => 'yyyy-MM-dd', 'dp_min_date' => '1/1/1900', 'dp_max_date' => new \DateTime('1/1/2001'), @@ -83,13 +72,12 @@ public function testFinishView(): void $this->assertSame('text', $view->vars['type']); } - public function testTimePickerIntlFormater(): void + public function testTimePickerIntlFormater() { - $type = new BasePickerTest( - new MomentFormatConverter(), - $this->getTranslatorMock(), - $this->getRequestStack() - ); + $translator = $this->createMock(TranslatorInterface::class); + $translator->method('getLocale')->willReturn('ru'); + + $type = new BasePickerTest(new MomentFormatConverter(), $translator); $view = new FormView(); $form = new Form($this->createMock(FormConfigInterface::class)); @@ -106,48 +94,4 @@ public function testTimePickerIntlFormater(): void $this->assertSame('H:mm', $view->vars['moment_format']); $this->assertSame('0:00', $view->vars['dp_options']['maxDate']); } - - /** - * @group legacy - */ - public function testConstructWithTwoArguments(): void - { - if (interface_exists(TranslatorInterface::class)) { - $this->markTestSkipped('Test only available for Symfony < 5'); - } - - $type = new BasePickerTest( - new MomentFormatConverter(), - $this->getTranslatorMock('en') - ); - - $this->assertSame('en', $type->getLocale()); - } - - /** - * @return MockObject|TranslatorInterface|LegacyTranslatorInterface - */ - private function getTranslatorMock(string $locale = 'ru'): MockObject - { - if (interface_exists(TranslatorInterface::class)) { - return $this->createMock(TranslatorInterface::class); - } - - $translator = $this->createMock(LegacyTranslatorInterface::class); - $translator->method('getLocale')->willReturn($locale); - - return $translator; - } - - private function getRequestStack(): RequestStack - { - $requestStack = new RequestStack(); - $request = $this->createMock(Request::class); - $request - ->method('getLocale') - ->willReturn('ru'); - $requestStack->push($request); - - return $requestStack; - } } diff --git a/tests/Type/BooleanTypeTest.php b/tests/Type/BooleanTypeTest.php index eaacfdc5..6c3af409 100644 --- a/tests/Type/BooleanTypeTest.php +++ b/tests/Type/BooleanTypeTest.php @@ -15,23 +15,66 @@ use Sonata\Form\Type\BooleanType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; +use Symfony\Component\Form\FormBuilder; +use Symfony\Component\Form\FormTypeInterface; use Symfony\Component\Form\Test\FormBuilderInterface; use Symfony\Component\Form\Test\TypeTestCase; +use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolver; class BooleanTypeTest extends TypeTestCase { - public function testParentIsChoiceType(): void + /** + * @doesNotPerformAssertions + */ + public function testBuildForm() + { + $formBuilder = $this->createMock(FormBuilder::class); + $formBuilder + ->expects($this->any()) + ->method('add') + ->willReturnCallback(function ($name, $type = null) { + if (null !== $type) { + $this->assertTrue(class_exists($type), sprintf('Unable to ensure %s is a FQCN', $type)); + } + }); + + $type = new BooleanType(); + + $type->buildForm($formBuilder, [ + 'transform' => false, + + /* + * NEXT_MAJOR: remove catalogue. + */ + 'catalogue' => 'SonataFormBundle', + + // Use directly translation_domain + 'translation_domain' => static function (Options $options) { + if ($options['catalogue']) { + return $options['catalogue']; + } + + return $options['translation_domain']; + }, + ]); + } + + public function testGetParent() { $form = new BooleanType(); - $this->assertSame(ChoiceType::class, $form->getParent()); + $parentRef = $form->getParent(); + + $this->assertTrue(class_exists($parentRef), sprintf('Unable to ensure %s is a FQCN', $parentRef)); } public function testGetDefaultOptions(): void { $type = new BooleanType(); + $this->assertSame(ChoiceType::class, $type->getParent()); + $type->configureOptions($optionResolver = new OptionsResolver()); $options = $optionResolver->resolve(); @@ -39,7 +82,7 @@ public function testGetDefaultOptions(): void $this->assertCount(2, $options['choices']); } - public function testAddTransformerCall(): void + public function testAddTransformerCall() { $type = new BooleanType(); @@ -56,7 +99,7 @@ public function testAddTransformerCall(): void /** * The default behavior is not to transform to real boolean value .... don't ask. */ - public function testDefaultBehavior(): void + public function testDefaultBehavior() { $type = new BooleanType(); @@ -68,7 +111,7 @@ public function testDefaultBehavior(): void $type->buildForm($builder, $optionResolver->resolve([])); } - public function testOptions(): void + public function testOptions() { $type = new BooleanType(); @@ -86,12 +129,59 @@ public function testOptions(): void $expectedOptions = [ 'transform' => false, - 'catalogue' => 'SonataCoreBundle', - 'choice_translation_domain' => 'SonataCoreBundle', + 'catalogue' => 'SonataFormBundle', + 'choice_translation_domain' => 'SonataFormBundle', + 'choices_as_values' => true, 'choices' => [1 => 'foo_yes', 2 => 'foo_no'], 'translation_domain' => 'fooTrans', ]; + if (!method_exists(FormTypeInterface::class, 'setDefaultOptions')) { + unset($expectedOptions['choices_as_values']); + } + $this->assertSame($expectedOptions, $resolvedOptions); } + + /** + * @group legacy + */ + public function testDeprecatedCatalogueOptionLegacy() + { + $type = new BooleanType(); + + $type->configureOptions($optionResolver = new OptionsResolver()); + + $builder = $this->createMock(FormBuilderInterface::class); + $builder->expects($this->never())->method('addModelTransformer'); + + $resolvedOptions = $optionResolver->resolve([ + 'catalogue' => 'fooTrans', + 'choices' => [1 => 'foo_yes', 2 => 'foo_no'], + ]); + + $type->buildForm($builder, $resolvedOptions); + + $expectedOptions = [ + 'transform' => false, + 'choice_translation_domain' => 'SonataFormBundle', + 'choices_as_values' => true, + 'catalogue' => 'fooTrans', + 'choices' => [1 => 'foo_yes', 2 => 'foo_no'], + 'translation_domain' => 'fooTrans', + ]; + + if (!method_exists(FormTypeInterface::class, 'setDefaultOptions')) { + unset($expectedOptions['choices_as_values']); + } + + $this->assertSame($expectedOptions, $resolvedOptions); + } + + public function testParentIsChoiceType(): void + { + $form = new BooleanType(); + + $this->assertSame(ChoiceType::class, $form->getParent()); + } } diff --git a/tests/Type/CollectionTypeTest.php b/tests/Type/CollectionTypeTest.php index 61362854..f93ecd6f 100644 --- a/tests/Type/CollectionTypeTest.php +++ b/tests/Type/CollectionTypeTest.php @@ -15,12 +15,49 @@ use Sonata\Form\Type\CollectionType; use Symfony\Component\Form\Extension\Core\Type\TextType; +use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\Test\TypeTestCase; use Symfony\Component\OptionsResolver\OptionsResolver; class CollectionTypeTest extends TypeTestCase { - public function testGetDefaultOptions(): void + /** + * @doesNotPerformAssertions + */ + public function testBuildForm() + { + $formBuilder = $this->createMock(FormBuilder::class); + $formBuilder + ->expects($this->any()) + ->method('add') + ->willReturnCallback(function ($name, $type = null) { + if (null !== $type) { + $this->assertTrue(class_exists($type), sprintf('Unable to ensure %s is a FQCN', $type)); + } + }); + + $type = new CollectionType(); + + $type->buildForm($formBuilder, [ + 'modifiable' => false, + 'type' => TextType::class, + 'type_options' => [], + 'pre_bind_data_callback' => null, + 'btn_add' => 'link_add', + 'btn_catalogue' => 'SonataFormBundle', + ]); + } + + public function testGetParent() + { + $form = new CollectionType(); + + $parentRef = $form->getParent(); + + $this->assertTrue(class_exists($parentRef), sprintf('Unable to ensure %s is a FQCN', $parentRef)); + } + + public function testGetDefaultOptions() { $type = new CollectionType(); @@ -32,7 +69,7 @@ public function testGetDefaultOptions(): void $this->assertSame(TextType::class, $options['type']); $this->assertCount(0, $options['type_options']); $this->assertSame('link_add', $options['btn_add']); - $this->assertSame('SonataCoreBundle', $options['btn_catalogue']); + $this->assertSame('SonataFormBundle', $options['btn_catalogue']); $this->assertNull($options['pre_bind_data_callback']); } } diff --git a/tests/Type/DatePickerTypeTest.php b/tests/Type/DatePickerTypeTest.php index 525041f4..cd47f1a0 100644 --- a/tests/Type/DatePickerTypeTest.php +++ b/tests/Type/DatePickerTypeTest.php @@ -13,46 +13,88 @@ namespace Sonata\Form\Tests\Type; -use PHPUnit\Framework\MockObject\MockObject; use Sonata\Form\Date\MomentFormatConverter; use Sonata\Form\Type\DatePickerType; use Symfony\Component\Form\Extension\Core\Type\DateType; +use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\PreloadedExtension; use Symfony\Component\Form\Test\TypeTestCase; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface; -use Symfony\Contracts\Translation\TranslatorInterface; +use Symfony\Component\Translation\TranslatorInterface; /** * @author Hugo Briand */ class DatePickerTypeTest extends TypeTestCase { + /** + * @doesNotPerformAssertions + */ + public function testBuildForm() + { + $formBuilder = $this->createMock(FormBuilder::class); + $formBuilder + ->expects($this->any()) + ->method('add') + ->willReturnCallback(function ($name, $type = null) { + if (null !== $type) { + $this->assertTrue(class_exists($type), sprintf('Unable to ensure %s is a FQCN', $type)); + } + }); + + $type = new DatePickerType( + $this->createMock(MomentFormatConverter::class), + $this->createMock(TranslatorInterface::class) + ); + $type->buildForm($formBuilder, [ + 'dp_pick_time' => false, + 'format' => DateType::DEFAULT_FORMAT, + ]); + } + public function testParentIsDateType(): void { $form = new DatePickerType( $this->createMock(MomentFormatConverter::class), - $this->getTranslatorMock(), - $this->getRequestStack() + $this->createMock(TranslatorInterface::class) ); $this->assertSame(DateType::class, $form->getParent()); } - public function testGetName(): void + public function testGetParent() + { + $form = new DatePickerType( + $this->createMock(MomentFormatConverter::class), + $this->createMock(TranslatorInterface::class) + ); + + $parentRef = $form->getParent(); + + $this->assertTrue(class_exists($parentRef), sprintf('Unable to ensure %s is a FQCN', $parentRef)); + } + + public function testGetName() { - $type = new DatePickerType(new MomentFormatConverter(), $this->getTranslatorMock(), $this->getRequestStack()); + $type = new DatePickerType(new MomentFormatConverter(), $this->createMock(TranslatorInterface::class)); - $this->assertSame('sonata_type_date_picker', $type->getBlockPrefix()); + $this->assertSame('sonata_type_date_picker', $type->getName()); } - public function testSubmitValidData(): void + /** + * @group legacy + */ + public function testConstructorLegacy() + { + $type = new DatePickerType(new MomentFormatConverter()); + + $this->assertSame('sonata_type_date_picker', $type->getName()); + } + + public function testSubmitValidData() { \Locale::setDefault('en'); $form = $this->factory->create(DatePickerType::class, new \DateTime('2018-06-03'), [ 'format' => \IntlDateFormatter::LONG, - 'html5' => false, ]); $this->assertSame('June 3, 2018', $form->getViewData()); @@ -63,37 +105,13 @@ public function testSubmitValidData(): void protected function getExtensions() { - $type = new DatePickerType(new MomentFormatConverter(), $this->getTranslatorMock(), $this->getRequestStack()); + $translator = $this->createMock(TranslatorInterface::class); + $translator->method('getLocale')->willReturn('en'); + + $type = new DatePickerType(new MomentFormatConverter(), $translator); return [ new PreloadedExtension([$type], []), ]; } - - /** - * @return MockObject|TranslatorInterface|LegacyTranslatorInterface\ - */ - private function getTranslatorMock(): MockObject - { - if (interface_exists(TranslatorInterface::class)) { - return $this->createMock(TranslatorInterface::class); - } - - $translator = $this->createMock(LegacyTranslatorInterface::class); - $translator->method('getLocale')->willReturn('en'); - - return $translator; - } - - private function getRequestStack(): RequestStack - { - $requestStack = new RequestStack(); - $request = $this->createMock(Request::class); - $request - ->method('getLocale') - ->willReturn('en'); - $requestStack->push($request); - - return $requestStack; - } } diff --git a/tests/Type/DateRangePickerTypeTest.php b/tests/Type/DateRangePickerTypeTest.php index 8923d176..29a2b85b 100644 --- a/tests/Type/DateRangePickerTypeTest.php +++ b/tests/Type/DateRangePickerTypeTest.php @@ -15,16 +15,48 @@ use Sonata\Form\Type\DatePickerType; use Sonata\Form\Type\DateRangePickerType; +use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\Test\TypeTestCase; use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\Translation\TranslatorInterface; class DateRangePickerTypeTest extends TypeTestCase { - public function testGetDefaultOptions(): void + public function testBuildForm() { - $type = new DateRangePickerType(); + $formBuilder = $this->createMock(FormBuilder::class); + $formBuilder + ->expects($this->any()) + ->method('add') + ->willReturnCallback(function ($name, $type = null) { + if (null !== $type) { + $this->assertTrue(class_exists($type), sprintf('Unable to ensure %s is a FQCN', $type)); + } + }); - $this->assertSame('sonata_type_date_range_picker', $type->getBlockPrefix()); + $type = new DateRangePickerType($this->createMock(TranslatorInterface::class)); + $type->buildForm($formBuilder, [ + 'field_options' => [], + 'field_options_start' => [], + 'field_options_end' => [], + 'field_type' => DatePickerType::class, + ]); + } + + public function testGetParent() + { + $form = new DateRangePickerType($this->createMock(TranslatorInterface::class)); + + $parentRef = $form->getParent(); + + $this->assertTrue(class_exists($parentRef), sprintf('Unable to ensure %s is a FQCN', $parentRef)); + } + + public function testGetDefaultOptions() + { + $type = new DateRangePickerType($this->createMock(TranslatorInterface::class)); + + $this->assertSame('sonata_type_date_range_picker', $type->getName()); $type->configureOptions($resolver = new OptionsResolver()); diff --git a/tests/Type/DateRangeTypeTest.php b/tests/Type/DateRangeTypeTest.php index f08a5a59..d50c3304 100644 --- a/tests/Type/DateRangeTypeTest.php +++ b/tests/Type/DateRangeTypeTest.php @@ -15,16 +15,48 @@ use Sonata\Form\Type\DateRangeType; use Symfony\Component\Form\Extension\Core\Type\DateType; +use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\Test\TypeTestCase; use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\Translation\TranslatorInterface; class DateRangeTypeTest extends TypeTestCase { - public function testGetDefaultOptions(): void + public function testBuildForm() { - $type = new DateRangeType(); + $formBuilder = $this->getMockBuilder(FormBuilder::class)->disableOriginalConstructor()->getMock(); + $formBuilder + ->expects($this->any()) + ->method('add') + ->willReturnCallback(function ($name, $type = null) { + if (null !== $type) { + $this->assertTrue(class_exists($type), sprintf('Unable to ensure %s is a FQCN', $type)); + } + }); - $this->assertSame('sonata_type_date_range', $type->getBlockPrefix()); + $type = new DateRangeType($this->createMock(TranslatorInterface::class)); + $type->buildForm($formBuilder, [ + 'field_options' => [], + 'field_options_start' => [], + 'field_options_end' => [], + 'field_type' => DateType::class, + ]); + } + + public function testGetParent() + { + $form = new DateRangeType($this->createMock(TranslatorInterface::class)); + + $parentRef = $form->getParent(); + + $this->assertTrue(class_exists($parentRef), sprintf('Unable to ensure %s is a FQCN', $parentRef)); + } + + public function testGetDefaultOptions() + { + $type = new DateRangeType($this->createMock(TranslatorInterface::class)); + + $this->assertSame('sonata_type_date_range', $type->getName()); $type->configureOptions($resolver = new OptionsResolver()); diff --git a/tests/Type/DateTimePickerTypeTest.php b/tests/Type/DateTimePickerTypeTest.php index 67b73b0f..cab2025c 100644 --- a/tests/Type/DateTimePickerTypeTest.php +++ b/tests/Type/DateTimePickerTypeTest.php @@ -13,66 +13,107 @@ namespace Sonata\Form\Tests\Type; -use PHPUnit\Framework\MockObject\MockObject; use Sonata\Form\Date\MomentFormatConverter; use Sonata\Form\Type\DateTimePickerType; use Symfony\Component\Form\Extension\Core\Type\DateTimeType; +use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\PreloadedExtension; use Symfony\Component\Form\Test\TypeTestCase; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface; -use Symfony\Contracts\Translation\TranslatorInterface; +use Symfony\Component\Translation\TranslatorInterface; /** * @author Hugo Briand */ class DateTimePickerTypeTest extends TypeTestCase { + /** + * @doesNotPerformAssertions + */ + public function testBuildForm() + { + $formBuilder = $this->createMock(FormBuilder::class); + $formBuilder + ->expects($this->any()) + ->method('add') + ->willReturnCallback(function ($name, $type = null) { + if (null !== $type) { + $this->assertTrue(class_exists($type), sprintf('Unable to ensure %s is a FQCN', $type)); + } + }); + + $type = new DateTimePickerType( + $this->createMock(MomentFormatConverter::class), + $this->createMock(TranslatorInterface::class) + ); + + $type->buildForm($formBuilder, [ + 'dp_use_minutes' => true, + 'dp_use_seconds' => true, + 'dp_minute_stepping' => 1, + 'format' => DateTimeType::DEFAULT_DATE_FORMAT, + 'date_format' => null, + ]); + } + public function testParentIsDateTimeType(): void { $form = new DateTimePickerType( $this->createMock(MomentFormatConverter::class), - $this->getTranslatorMock(), - $this->getRequestStack() + $this->createMock(TranslatorInterface::class) ); $this->assertSame(DateTimeType::class, $form->getParent()); } - public function testGetName(): void + public function testGetParent() { - $type = new DateTimePickerType( - new MomentFormatConverter(), - $this->getTranslatorMock(), - $this->getRequestStack() + $form = new DateTimePickerType( + $this->createMock(MomentFormatConverter::class), + $this->createMock(TranslatorInterface::class) ); - $this->assertSame('sonata_type_datetime_picker', $type->getBlockPrefix()); + $parentRef = $form->getParent(); + + $this->assertTrue(class_exists($parentRef), sprintf('Unable to ensure %s is a FQCN', $parentRef)); + } + + public function testGetName() + { + $type = new DateTimePickerType(new MomentFormatConverter(), $this->createMock(TranslatorInterface::class)); + + $this->assertSame('sonata_type_datetime_picker', $type->getName()); + } + + /** + * @group legacy + */ + public function testConstructorLegacy() + { + $type = new DateTimePickerType(new MomentFormatConverter()); + + $this->assertSame('sonata_type_datetime_picker', $type->getName()); } - public function testSubmitUnmatchingDateFormat(): void + public function testSubmitUnmatchingDateFormat() { \Locale::setDefault('en'); $form = $this->factory->create(DateTimePickerType::class, new \DateTime('2018-06-03 20:02:03'), [ 'format' => \IntlDateFormatter::NONE, 'dp_pick_date' => false, 'dp_use_seconds' => false, - 'html5' => false, ]); $form->submit('05:23'); $this->assertFalse($form->isSynchronized()); } - public function testSubmitMatchingDateFormat(): void + public function testSubmitMatchingDateFormat() { \Locale::setDefault('en'); $form = $this->factory->create(DateTimePickerType::class, new \DateTime('2018-06-03 20:02:03'), [ 'format' => \IntlDateFormatter::NONE, 'dp_pick_date' => false, 'dp_use_seconds' => false, - 'html5' => false, ]); $this->assertSame('8:02 PM', $form->getViewData()); @@ -84,41 +125,13 @@ public function testSubmitMatchingDateFormat(): void protected function getExtensions() { - $type = new DateTimePickerType( - new MomentFormatConverter(), - $this->getTranslatorMock(), - $this->getRequestStack() - ); + $translator = $this->createMock(TranslatorInterface::class); + $translator->method('getLocale')->willReturn('en'); + + $type = new DateTimePickerType(new MomentFormatConverter(), $translator); return [ new PreloadedExtension([$type], []), ]; } - - /** - * @return MockObject|TranslatorInterface|LegacyTranslatorInterface\ - */ - private function getTranslatorMock(): MockObject - { - if (interface_exists(TranslatorInterface::class)) { - return $this->createMock(TranslatorInterface::class); - } - - $translator = $this->createMock(LegacyTranslatorInterface::class); - $translator->method('getLocale')->willReturn('en'); - - return $translator; - } - - private function getRequestStack(): RequestStack - { - $requestStack = new RequestStack(); - $request = $this->createMock(Request::class); - $request - ->method('getLocale') - ->willReturn('en'); - $requestStack->push($request); - - return $requestStack; - } } diff --git a/tests/Type/DateTimeRangePickerTypeTest.php b/tests/Type/DateTimeRangePickerTypeTest.php index dc34a670..d603aae5 100644 --- a/tests/Type/DateTimeRangePickerTypeTest.php +++ b/tests/Type/DateTimeRangePickerTypeTest.php @@ -15,16 +15,48 @@ use Sonata\Form\Type\DateTimePickerType; use Sonata\Form\Type\DateTimeRangePickerType; +use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\Test\TypeTestCase; use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\Translation\TranslatorInterface; class DateTimeRangePickerTypeTest extends TypeTestCase { - public function testGetDefaultOptions(): void + public function testBuildForm() { - $type = new DateTimeRangePickerType(); + $formBuilder = $this->createMock(FormBuilder::class); + $formBuilder + ->expects($this->any()) + ->method('add') + ->willReturnCallback(function ($name, $type = null) { + if (null !== $type) { + $this->assertTrue(class_exists($type), sprintf('Unable to ensure %s is a FQCN', $type)); + } + }); - $this->assertSame('sonata_type_datetime_range_picker', $type->getBlockPrefix()); + $type = new DateTimeRangePickerType($this->createMock(TranslatorInterface::class)); + $type->buildForm($formBuilder, [ + 'field_options' => [], + 'field_options_start' => [], + 'field_options_end' => [], + 'field_type' => DateTimePickerType::class, + ]); + } + + public function testGetParent() + { + $form = new DateTimeRangePickerType($this->createMock(TranslatorInterface::class)); + + $parentRef = $form->getParent(); + + $this->assertTrue(class_exists($parentRef), sprintf('Unable to ensure %s is a FQCN', $parentRef)); + } + + public function testGetDefaultOptions() + { + $type = new DateTimeRangePickerType($this->createMock(TranslatorInterface::class)); + + $this->assertSame('sonata_type_datetime_range_picker', $type->getName()); $type->configureOptions($resolver = new OptionsResolver()); diff --git a/tests/Type/EqualTypeTest.php b/tests/Type/EqualTypeTest.php index 9b9eac82..d1abf3ad 100644 --- a/tests/Type/EqualTypeTest.php +++ b/tests/Type/EqualTypeTest.php @@ -15,8 +15,10 @@ use Sonata\Form\Type\EqualType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; +use Symfony\Component\Form\FormTypeInterface; use Symfony\Component\Form\Test\TypeTestCase; use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\Translation\TranslatorInterface; class EqualTypeTest extends TypeTestCase { @@ -30,14 +32,30 @@ public function testParentIsChoiceType(): void $this->assertSame(ChoiceType::class, $form->getParent()); } - /** - * @group legacy - */ - public function testGetDefaultOptions(): void + public function testGetParent() { - $type = new EqualType(); + $form = new EqualType($this->createMock(TranslatorInterface::class)); + + $parentRef = $form->getParent(); + + $this->assertTrue(class_exists($parentRef), sprintf('Unable to ensure %s is a FQCN', $parentRef)); + } - $this->assertSame('sonata_type_equal', $type->getBlockPrefix()); + public function testGetDefaultOptions() + { + $mock = $this->createMock(TranslatorInterface::class); + + $mock->expects($this->exactly(0)) + ->method('trans') + ->willReturnCallback( + static function ($arg) { + return $arg; + } + ); + + $type = new EqualType($mock); + + $this->assertSame('sonata_type_equal', $type->getName()); $this->assertSame(ChoiceType::class, $type->getParent()); $type->configureOptions($resolver = new OptionsResolver()); @@ -45,10 +63,15 @@ public function testGetDefaultOptions(): void $options = $resolver->resolve(); $expected = [ - 'choice_translation_domain' => 'SonataCoreBundle', + 'choice_translation_domain' => 'SonataFormBundle', 'choices' => ['label_type_equals' => 1, 'label_type_not_equals' => 2], + 'choices_as_values' => true, ]; + if (!method_exists(FormTypeInterface::class, 'setDefaultOptions')) { + unset($expected['choices_as_values']); + } + $this->assertSame($expected, $options); } } diff --git a/tests/Type/FormChoiceWidgetTest.php b/tests/Type/FormChoiceWidgetTest.php index aa48733b..1546f82a 100644 --- a/tests/Type/FormChoiceWidgetTest.php +++ b/tests/Type/FormChoiceWidgetTest.php @@ -15,6 +15,7 @@ use Sonata\Form\Test\AbstractWidgetTestCase; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; +use Symfony\Component\Form\FormTypeInterface; /** * @author Christian Gripp @@ -23,7 +24,10 @@ class FormChoiceWidgetTest extends AbstractWidgetTestCase { public function testLabelRendering() { - $choices = ['some' => 0, 'choices' => 1]; + $choices = ['some', 'choices']; + if (!method_exists(FormTypeInterface::class, 'setDefaultOptions')) { + $choices = array_flip($choices); + } $choice = $this->factory->create( $this->getChoiceClass(), @@ -37,21 +41,12 @@ public function testLabelRendering() $html = $this->renderWidget($choice->createView()); $this->assertStringContainsString( - $this->cleanHtmlWhitespace( - <<<'HTML' -
- - - - -
-HTML - ), + '
', $this->cleanHtmlWhitespace($html) ); } - public function testDefaultValueRendering(): void + public function testDefaultValueRendering() { $choice = $this->factory->create( $this->getChoiceClass(), @@ -67,7 +62,7 @@ public function testDefaultValueRendering(): void ); } - public function testRequiredIsDisabledForEmptyPlaceholder(): void + public function testRequiredIsDisabledForEmptyPlaceholder() { $choice = $this->factory->create( $this->getChoiceClass(), @@ -83,7 +78,7 @@ public function testRequiredIsDisabledForEmptyPlaceholder(): void ); } - public function testRequiredIsEnabledIfPlaceholderIsSet(): void + public function testRequiredIsEnabledIfPlaceholderIsSet() { $choice = $this->factory->create( $this->getChoiceClass(), diff --git a/tests/Type/ImmutableArrayTypeTest.php b/tests/Type/ImmutableArrayTypeTest.php index f572eb4a..c0b082dd 100644 --- a/tests/Type/ImmutableArrayTypeTest.php +++ b/tests/Type/ImmutableArrayTypeTest.php @@ -16,21 +16,53 @@ use Sonata\Form\Type\ImmutableArrayType; use Symfony\Component\Form\Extension\Core\Type\FormType; use Symfony\Component\Form\Extension\Core\Type\TextType; +use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Test\FormBuilderInterface as TestFormBuilderInterface; use Symfony\Component\Form\Test\TypeTestCase; +use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; use Symfony\Component\OptionsResolver\OptionsResolver; class ImmutableArrayTypeTest extends TypeTestCase { - public function testGetDefaultOptions(): void + /** + * @doesNotPerformAssertions + */ + public function testBuildForm() + { + $formBuilder = $this->createMock(FormBuilder::class); + $formBuilder + ->expects($this->any()) + ->method('add') + ->willReturnCallback(function ($name, $type = null) { + if (null !== $type) { + $this->assertTrue(class_exists($type), sprintf('Unable to ensure %s is a FQCN', $type)); + } + }); + + $type = new ImmutableArrayType(); + $type->buildForm($formBuilder, [ + 'keys' => [], + ]); + } + + public function testGetParent() + { + $form = new ImmutableArrayType(); + + $parentRef = $form->getParent(); + + $this->assertTrue(class_exists($parentRef), sprintf('Unable to ensure %s is a FQCN', $parentRef)); + } + + public function testGetDefaultOptions() { $type = new ImmutableArrayType(); - $this->assertSame('sonata_type_immutable_array', $type->getBlockPrefix()); + $this->assertSame('sonata_type_immutable_array', $type->getName()); - $this->assertSame(FormType::class, $type->getParent()); + $this->assertSame(version_compare(Kernel::VERSION, '2.8', '<') ? 'form' : FormType::class, $type->getParent()); $type->configureOptions($resolver = new OptionsResolver()); @@ -43,7 +75,7 @@ public function testGetDefaultOptions(): void $this->assertSame($expected, $options); } - public function testCallback(): void + public function testCallback() { $type = new ImmutableArrayType(); @@ -79,7 +111,7 @@ public function testCallback(): void $type->buildForm($builder, $options); } - public function testWithIncompleteOptions(): void + public function testWithIncompleteOptions() { $optionsResolver = new OptionsResolver(); @@ -94,7 +126,7 @@ public function testWithIncompleteOptions(): void $optionsResolver->resolve(['keys' => [['test']]]); } - public function testFormBuilderIsAValidElement(): void + public function testFormBuilderIsAValidElement() { $optionsResolver = new OptionsResolver(); @@ -103,9 +135,9 @@ public function testFormBuilderIsAValidElement(): void $this->assertArrayHasKey( 'keys', - $optionsResolver->resolve(['keys' => [$this->createMock( + $optionsResolver->resolve(['keys' => [$this->getMockBuilder( FormBuilderInterface::class - )]]) + )->getMock()]]) ); } } diff --git a/tests/Validator/Constraints/InlineConstraintTest.php b/tests/Validator/Constraints/InlineConstraintTest.php index cf0ca8e5..313abad7 100755 --- a/tests/Validator/Constraints/InlineConstraintTest.php +++ b/tests/Validator/Constraints/InlineConstraintTest.php @@ -21,13 +21,13 @@ */ class InlineConstraintTest extends TestCase { - public function testValidatedBy(): void + public function testValidatedBy() { $constraint = new InlineConstraint(['service' => 'foo', 'method' => 'bar']); $this->assertSame('sonata.form.validator.inline', $constraint->validatedBy()); } - public function testIsClosure(): void + public function testIsClosure() { $constraint = new InlineConstraint(['service' => 'foo', 'method' => 'bar']); $this->assertFalse($constraint->isClosure()); @@ -37,7 +37,7 @@ public function testIsClosure(): void $this->assertTrue($constraint->isClosure()); } - public function testGetClosure(): void + public function testGetClosure() { $closure = static function () { return 'FOO'; @@ -47,31 +47,31 @@ public function testGetClosure(): void $this->assertSame($closure, $constraint->getClosure()); } - public function testGetTargets(): void + public function testGetTargets() { $constraint = new InlineConstraint(['service' => 'foo', 'method' => 'bar']); $this->assertSame(InlineConstraint::CLASS_CONSTRAINT, $constraint->getTargets()); } - public function testGetRequiredOptions(): void + public function testGetRequiredOptions() { $constraint = new InlineConstraint(['service' => 'foo', 'method' => 'bar']); $this->assertSame(['service', 'method'], $constraint->getRequiredOptions()); } - public function testGetMethod(): void + public function testGetMethod() { $constraint = new InlineConstraint(['service' => 'foo', 'method' => 'bar']); $this->assertSame('bar', $constraint->getMethod()); } - public function testGetService(): void + public function testGetService() { $constraint = new InlineConstraint(['service' => 'foo', 'method' => 'bar']); $this->assertSame('foo', $constraint->getService()); } - public function testClosureSerialization(): void + public function testClosureSerialization() { $constraint = new InlineConstraint(['service' => 'foo', 'method' => static function (): void { }, 'serializingWarning' => true]); @@ -87,7 +87,7 @@ public function testClosureSerialization(): void $this->assertTrue($constraint->getSerializingWarning()); } - public function testStandardSerialization(): void + public function testStandardSerialization() { $constraint = new InlineConstraint(['service' => 'foo', 'method' => 'bar']); @@ -100,7 +100,7 @@ public function testStandardSerialization(): void $this->assertNull($constraint->getSerializingWarning()); } - public function testSerializingWarningIsFalseWithServiceIsNotString(): void + public function testSerializingWarningIsFalseWithServiceIsNotString() { $this->expectException( 'RuntimeException' @@ -114,7 +114,7 @@ public function testSerializingWarningIsFalseWithServiceIsNotString(): void new InlineConstraint(['service' => 1, 'method' => 'foo', 'serializingWarning' => false]); } - public function testSerializingWarningIsFalseWithMethodIsNotString(): void + public function testSerializingWarningIsFalseWithMethodIsNotString() { $this->expectException( 'RuntimeException' diff --git a/tests/Validator/ErrorElementTest.php b/tests/Validator/ErrorElementTest.php index b94484ee..1c849278 100755 --- a/tests/Validator/ErrorElementTest.php +++ b/tests/Validator/ErrorElementTest.php @@ -45,25 +45,25 @@ protected function setUp(): void if ($this->context instanceof ExecutionContextInterface) { $builder = $this->createMock(ConstraintViolationBuilderInterface::class); - $builder + $builder->expects($this->any()) ->method($this->anything()) ->willReturnSelf(); - $this->context + $this->context->expects($this->any()) ->method('buildViolation') ->willReturn($builder); $validator = $this->createMock(ValidatorInterface::class); $this->contextualValidator = $this->createMock(ContextualValidatorInterface::class); - $this->contextualValidator + $this->contextualValidator->expects($this->any()) ->method($this->anything()) ->willReturnSelf(); - $validator + $validator->expects($this->any()) ->method('inContext') ->willReturn($this->contextualValidator); - $this->context + $this->context->expects($this->any()) ->method('getValidator') ->willReturn($validator); } @@ -73,12 +73,12 @@ protected function setUp(): void $this->errorElement = new ErrorElement($this->subject, $constraintValidatorFactory, $this->context, 'foo_core'); } - public function testGetSubject(): void + public function testGetSubject() { $this->assertSame($this->subject, $this->errorElement->getSubject()); } - public function testGetErrorsEmpty(): void + public function testGetErrorsEmpty() { $this->assertSame([], $this->errorElement->getErrors()); } @@ -86,7 +86,7 @@ public function testGetErrorsEmpty(): void /** * @group legacy */ - public function testGetErrors(): void + public function testGetErrors() { $this->errorElement->addViolation('Foo error message', ['bar_param' => 'bar_param_lvalue'], 'BAR'); $this->assertSame([['Foo error message', ['bar_param' => 'bar_param_lvalue'], 'BAR']], $this->errorElement->getErrors()); @@ -95,7 +95,7 @@ public function testGetErrors(): void /** * @group legacy */ - public function testAddViolation(): void + public function testAddViolation() { $this->errorElement->addViolation(['Foo error message', ['bar_param' => 'bar_param_lvalue'], 'BAR']); $this->assertSame([['Foo error message', ['bar_param' => 'bar_param_lvalue'], 'BAR']], $this->errorElement->getErrors()); @@ -104,7 +104,7 @@ public function testAddViolation(): void /** * @group legacy */ - public function testAddViolationWithTranslationDomain(): void + public function testAddViolationWithTranslationDomain() { $this->errorElement->addViolation(['Foo error message', ['bar_param' => 'bar_param_lvalue'], 'BAR'], [], null, 'translation_domain'); $this->assertSame([['Foo error message', ['bar_param' => 'bar_param_lvalue'], 'BAR']], $this->errorElement->getErrors()); @@ -113,7 +113,7 @@ public function testAddViolationWithTranslationDomain(): void /** * @group legacy */ - public function testAddConstraint(): void + public function testAddConstraint() { $constraint = new NotNull(); if ($this->context instanceof LegacyExecutionContextInterface) { @@ -136,7 +136,7 @@ public function testAddConstraint(): void /** * @group legacy */ - public function testWith(): void + public function testWith() { $constraint = new NotNull(); @@ -162,7 +162,7 @@ public function testWith(): void /** * @group legacy */ - public function testCall(): void + public function testCall() { $constraint = new NotNull(); @@ -185,7 +185,7 @@ public function testCall(): void $this->errorElement->end(); } - public function testCallException(): void + public function testCallException() { $this->expectException('RuntimeException'); $this->expectExceptionMessage('Unable to recognize the command'); @@ -194,7 +194,7 @@ public function testCallException(): void $this->errorElement->baz(); } - public function testGetFullPropertyPath(): void + public function testGetFullPropertyPath() { $this->errorElement->with('baz'); $this->assertSame('bar.baz', $this->errorElement->getFullPropertyPath()); @@ -206,20 +206,20 @@ public function testGetFullPropertyPath(): void /** * @group legacy */ - public function testFluidInterface(): void + public function testFluidInterface() { $constraint = new NotNull(); if ($this->context instanceof LegacyExecutionContextInterface) { - $this->context + $this->context->expects($this->any()) ->method('validateValue') ->with($this->equalTo($this->subject), $this->equalTo($constraint), $this->equalTo(''), $this->equalTo('foo_core')) ->willReturn(null); } else { - $this->contextualValidator + $this->contextualValidator->expects($this->any()) ->method('atPath') ->with(''); - $this->contextualValidator + $this->contextualValidator->expects($this->any()) ->method('validate') ->with($this->subject, $constraint, ['foo_core']); } @@ -230,4 +230,15 @@ public function testFluidInterface(): void $this->assertSame($this->errorElement, $this->errorElement->addConstraint($constraint)); $this->assertSame($this->errorElement, $this->errorElement->assertNotNull()); } + + public function testExceptionIsThrownWhenContextIsString() + { + $constraintValidatorFactory = $this->createMock(ConstraintValidatorFactoryInterface::class); + + $this->expectException( + \TypeError::class + ); + + $this->errorElement = new ErrorElement($this->subject, $constraintValidatorFactory, 'foo', 'foo_core'); + } }