Skip to content

Commit

Permalink
Avoid BC-break with symfony/form 5
Browse files Browse the repository at this point in the history
  • Loading branch information
franmomu committed Aug 10, 2020
1 parent 1ec04ff commit 1b7d151
Show file tree
Hide file tree
Showing 6 changed files with 434 additions and 305 deletions.
56 changes: 56 additions & 0 deletions src/Form/Extension/BaseChoiceTypeExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Sonata\AdminBundle\Form\Extension;

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

/**
* NEXT_MAJOR: Copy its methods to ChoiceTypeExtension and remove it.
*
* @internal
*/
abstract class BaseChoiceTypeExtension extends AbstractTypeExtension
{
/**
* NEXT_MAJOR: Remove method, when bumping requirements to SF 2.7+.
*
* {@inheritdoc}
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$this->configureOptions($resolver);
}

public function configureOptions(OptionsResolver $resolver)
{
$optionalOptions = ['sortable'];

$resolver->setDefined($optionalOptions);
}

public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars['sortable'] = \array_key_exists('sortable', $options) && $options['sortable'];
}

public function getExtendedType()
{
return ChoiceType::class;
}
}
58 changes: 22 additions & 36 deletions src/Form/Extension/ChoiceTypeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,49 +13,35 @@

namespace Sonata\AdminBundle\Form\Extension;

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormTypeExtensionInterface;

/**
* @final since sonata-project/admin-bundle 3.52
*
* @author Amine Zaghdoudi <[email protected]>
*/
class ChoiceTypeExtension extends AbstractTypeExtension
{
// NEXT_MAJOR: Remove the "else" part, copy all methods from BaseChoiceTypeExtension in this class and
// extend from AbstractTypeExtension.
if (method_exists(FormTypeExtensionInterface::class, 'getExtendedTypes')) {
/**
* NEXT_MAJOR: Remove method, when bumping requirements to SF 2.7+.
* @final since sonata-project/admin-bundle 3.52
*
* {@inheritdoc}
* @author Amine Zaghdoudi <[email protected]>
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$this->configureOptions($resolver);
}

public function configureOptions(OptionsResolver $resolver)
{
$optionalOptions = ['sortable'];

$resolver->setDefined($optionalOptions);
}

public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars['sortable'] = \array_key_exists('sortable', $options) && $options['sortable'];
}

public function getExtendedType()
class ChoiceTypeExtension extends BaseChoiceTypeExtension
{
return ChoiceType::class;
public static function getExtendedTypes(): iterable
{
return [ChoiceType::class];
}
}

public static function getExtendedTypes(): iterable
} else {
/**
* @final since sonata-project/admin-bundle 3.52
*
* @author Amine Zaghdoudi <[email protected]>
*/
class ChoiceTypeExtension extends BaseChoiceTypeExtension
{
return [ChoiceType::class];
public static function getExtendedTypes()
{
return [ChoiceType::class];
}
}
}
250 changes: 250 additions & 0 deletions src/Form/Extension/Field/Type/BaseFormTypeFieldExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Sonata\AdminBundle\Form\Extension\Field\Type;

use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
use Sonata\AdminBundle\Exception\NoValueException;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

/**
* NEXT_MAJOR: Copy its methods to FormTypeFieldExtension and remove it.
*
* @internal
*/
abstract class BaseFormTypeFieldExtension extends AbstractTypeExtension
{
/**
* @var array
*/
protected $defaultClasses = [];

/**
* @var array
*/
protected $options = [];

public function __construct(array $defaultClasses, array $options)
{
$this->defaultClasses = $defaultClasses;
$this->options = $options;
}

public function buildForm(FormBuilderInterface $builder, array $options)
{
$sonataAdmin = [
'name' => null,
'admin' => null,
'value' => null,
'edit' => 'standard',
'inline' => 'natural',
'field_description' => null,
'block_name' => false,
'options' => $this->options,
];

$builder->setAttribute('sonata_admin_enabled', false);
// NEXT_MAJOR: Remove this line
$builder->setAttribute('sonata_help', false);

if ($options['sonata_field_description'] instanceof FieldDescriptionInterface) {
$fieldDescription = $options['sonata_field_description'];

$sonataAdmin['admin'] = $fieldDescription->getAdmin();
$sonataAdmin['field_description'] = $fieldDescription;
$sonataAdmin['name'] = $fieldDescription->getName();
$sonataAdmin['edit'] = $fieldDescription->getOption('edit', 'standard');
$sonataAdmin['inline'] = $fieldDescription->getOption('inline', 'natural');
$sonataAdmin['block_name'] = $fieldDescription->getOption('block_name', false);
$sonataAdmin['class'] = $this->getClass($builder);

$builder->setAttribute('sonata_admin_enabled', true);
}

$builder->setAttribute('sonata_admin', $sonataAdmin);
}

public function buildView(FormView $view, FormInterface $form, array $options)
{
$sonataAdmin = $form->getConfig()->getAttribute('sonata_admin');
// NEXT_MAJOR: Remove this line
$sonataAdminHelp = $options['sonata_help'] ?? null;

/*
* We have a child, so we need to upgrade block prefix
*/
if ($view->parent && $view->parent->vars['sonata_admin_enabled'] && !$sonataAdmin['admin']) {
$blockPrefixes = $view->vars['block_prefixes'];
$baseName = str_replace('.', '_', $view->parent->vars['sonata_admin_code']);

$baseType = $blockPrefixes[\count($blockPrefixes) - 2];
$blockSuffix = preg_replace('#^_([a-z0-9]{14})_(.++)$#', '$2', end($blockPrefixes));

$blockPrefixes[] = sprintf('%s_%s', $baseName, $baseType);
$blockPrefixes[] = sprintf('%s_%s_%s_%s', $baseName, $baseType, $view->parent->vars['name'], $view->vars['name']);
$blockPrefixes[] = sprintf('%s_%s_%s_%s', $baseName, $baseType, $view->parent->vars['name'], $blockSuffix);

$view->vars['block_prefixes'] = array_unique($blockPrefixes);
$view->vars['sonata_admin_enabled'] = true;
$view->vars['sonata_admin'] = [
'admin' => false,
'field_description' => false,
'name' => false,
'edit' => 'standard',
'inline' => 'natural',
'block_name' => false,
'class' => false,
'options' => $this->options,
];
// NEXT_MAJOR: Remove this line
$view->vars['sonata_help'] = $sonataAdminHelp;
$view->vars['sonata_admin_code'] = $view->parent->vars['sonata_admin_code'];

return;
}

// avoid to add extra information not required by non admin field
if ($sonataAdmin && $form->getConfig()->getAttribute('sonata_admin_enabled', true)) {
$sonataAdmin['value'] = $form->getData();

// add a new block types, so the Admin Form element can be tweaked based on the admin code
$blockPrefixes = $view->vars['block_prefixes'];
$baseName = str_replace('.', '_', $sonataAdmin['admin']->getCode());
$baseType = $blockPrefixes[\count($blockPrefixes) - 2];
$blockSuffix = preg_replace('#^_([a-z0-9]{14})_(.++)$#', '$2', end($blockPrefixes));

$blockPrefixes[] = sprintf('%s_%s', $baseName, $baseType);
$blockPrefixes[] = sprintf('%s_%s_%s', $baseName, $sonataAdmin['name'], $baseType);
$blockPrefixes[] = sprintf('%s_%s_%s_%s', $baseName, $sonataAdmin['name'], $baseType, $blockSuffix);

if (isset($sonataAdmin['block_name']) && false !== $sonataAdmin['block_name']) {
$blockPrefixes[] = $sonataAdmin['block_name'];
}

$view->vars['block_prefixes'] = array_unique($blockPrefixes);
$view->vars['sonata_admin_enabled'] = true;
$view->vars['sonata_admin'] = $sonataAdmin;
$view->vars['sonata_admin_code'] = $sonataAdmin['admin']->getCode();

$attr = $view->vars['attr'];

if (!isset($attr['class']) && isset($sonataAdmin['class'])) {
$attr['class'] = $sonataAdmin['class'];
}

$view->vars['attr'] = $attr;
} else {
$view->vars['sonata_admin_enabled'] = false;
}

// NEXT_MAJOR: Remove this line
$view->vars['sonata_help'] = $sonataAdminHelp;
$view->vars['sonata_admin'] = $sonataAdmin;
}

public function getExtendedType()
{
return FormType::class;
}

/**
* NEXT_MAJOR: Remove method, when bumping requirements to SF 2.7+.
*
* {@inheritdoc}
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$this->configureOptions($resolver);
}

public function configureOptions(OptionsResolver $resolver)
{
$resolver
->setDefaults([
'sonata_admin' => null,
'sonata_field_description' => null,

// be compatible with mopa if not installed, avoid generating an exception for invalid option
'label_render' => true,
// NEXT_MAJOR: Remove this property and the deprecation message
'sonata_help' => null,
])
->setDeprecated(
'sonata_help',
'The "sonata_help" option is deprecated since sonata-project/admin-bundle 3.60, to be removed in 4.0. Use "help" instead.'
);
}

/**
* return the value related to FieldDescription, if the associated object does no
* exists => a temporary one is created.
*
* @param object|null $object
*
* @return mixed
*/
public function getValueFromFieldDescription($object, FieldDescriptionInterface $fieldDescription)
{
$value = null;

if (!$object) {
return null;
}

try {
$value = $fieldDescription->getValue($object);
} catch (NoValueException $e) {
if ($fieldDescription->hasAssociationAdmin()) {
$value = $fieldDescription->getAssociationAdmin()->getNewInstance();
}
}

return $value;
}

/**
* @return string
*/
protected function getClass(FormBuilderInterface $formBuilder)
{
foreach ($this->getTypes($formBuilder) as $type) {
$name = \get_class($type);

if (isset($this->defaultClasses[$name])) {
return $this->defaultClasses[$name];
}
}

return '';
}

/**
* @return array
*/
protected function getTypes(FormBuilderInterface $formBuilder)
{
$types = [];

for ($type = $formBuilder->getType(); null !== $type; $type = $type->getParent()) {
array_unshift($types, $type->getInnerType());
}

return $types;
}
}
Loading

0 comments on commit 1b7d151

Please sign in to comment.