merged branch bschussek/issue5038 (PR #5044)
Commits -------eeb66dd
[Form] Renamed the internal FormView variables "types" and "full_block_name"6b17640
[Form] Fixed caching of block names when types of forms with the same unique block ID differ Discussion ---------- [Form] Fixed caching of block names when types of forms with the same unique block ID differ Bug fix: yes Feature addition: no Backwards compatibility break: no Symfony2 tests pass: yes Fixes the following tickets: #5038 Todo: -
This commit is contained in:
commit
c6f0987771
@ -21,7 +21,7 @@ abstract class AbstractRendererEngine implements FormRendererEngineInterface
|
||||
/**
|
||||
* The variable in {@link FormView} used as cache key.
|
||||
*/
|
||||
const CACHE_KEY_VAR = 'full_block_name';
|
||||
const CACHE_KEY_VAR = 'cache_key';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
|
@ -71,11 +71,11 @@ class FormType extends AbstractType
|
||||
if ('' !== ($parentFullName = $view->parent->vars['full_name'])) {
|
||||
$id = sprintf('%s_%s', $view->parent->vars['id'], $name);
|
||||
$fullName = sprintf('%s[%s]', $parentFullName, $name);
|
||||
$fullBlockName = sprintf('%s_%s', $view->parent->vars['full_block_name'], $blockName);
|
||||
$uniqueBlockPrefix = sprintf('%s_%s', $view->parent->vars['unique_block_prefix'], $blockName);
|
||||
} else {
|
||||
$id = $name;
|
||||
$fullName = $name;
|
||||
$fullBlockName = '_' . $blockName;
|
||||
$uniqueBlockPrefix = '_' . $blockName;
|
||||
}
|
||||
|
||||
// Complex fields are read-only if they themselves or their parents are.
|
||||
@ -89,7 +89,7 @@ class FormType extends AbstractType
|
||||
} else {
|
||||
$id = $name;
|
||||
$fullName = $name;
|
||||
$fullBlockName = '_' . $blockName;
|
||||
$uniqueBlockPrefix = '_' . $blockName;
|
||||
|
||||
// Strip leading underscores and digits. These are allowed in
|
||||
// form names, but not in HTML4 ID attributes.
|
||||
@ -97,10 +97,11 @@ class FormType extends AbstractType
|
||||
$id = ltrim($id, '_0123456789');
|
||||
}
|
||||
|
||||
$types = array();
|
||||
$blockPrefixes = array();
|
||||
for ($type = $form->getConfig()->getType(); null !== $type; $type = $type->getParent()) {
|
||||
array_unshift($types, $type->getName());
|
||||
array_unshift($blockPrefixes, $type->getName());
|
||||
}
|
||||
$blockPrefixes[] = $uniqueBlockPrefix;
|
||||
|
||||
if (!$translationDomain) {
|
||||
$translationDomain = 'messages';
|
||||
@ -111,7 +112,6 @@ class FormType extends AbstractType
|
||||
'id' => $id,
|
||||
'name' => $name,
|
||||
'full_name' => $fullName,
|
||||
'full_block_name' => $fullBlockName,
|
||||
'read_only' => $readOnly,
|
||||
'errors' => $form->getErrors(),
|
||||
'valid' => $form->isBound() ? $form->isValid() : true,
|
||||
@ -127,8 +127,16 @@ class FormType extends AbstractType
|
||||
'attr' => $options['attr'],
|
||||
'label_attr' => $options['label_attr'],
|
||||
'compound' => $form->getConfig()->getCompound(),
|
||||
'types' => $types,
|
||||
'block_prefixes' => $blockPrefixes,
|
||||
'unique_block_prefix' => $uniqueBlockPrefix,
|
||||
'translation_domain' => $translationDomain,
|
||||
// Using the block name here speeds up performance in collection
|
||||
// forms, where each entry has the same full block name.
|
||||
// Including the type is important too, because if rows of a
|
||||
// collection form have different types (dynamically), they should
|
||||
// be rendered differently.
|
||||
// https://github.com/symfony/symfony/issues/5038
|
||||
'cache_key' => $uniqueBlockPrefix . '_' . $form->getConfig()->getType()->getName(),
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
|
||||
*/
|
||||
class FormRenderer implements FormRendererInterface
|
||||
{
|
||||
const CACHE_KEY_VAR = 'full_block_name';
|
||||
const CACHE_KEY_VAR = 'unique_block_prefix';
|
||||
|
||||
/**
|
||||
* @var FormRendererEngineInterface
|
||||
@ -173,10 +173,9 @@ class FormRenderer implements FormRendererInterface
|
||||
// Calculate the hierarchy of template blocks and start on
|
||||
// the bottom level of the hierarchy (= "_<id>_<section>" block)
|
||||
$blockNameHierarchy = array();
|
||||
foreach ($view->vars['types'] as $type) {
|
||||
$blockNameHierarchy[] = $type . '_' . $blockNameSuffix;
|
||||
foreach ($view->vars['block_prefixes'] as $blockNamePrefix) {
|
||||
$blockNameHierarchy[] = $blockNamePrefix . '_' . $blockNameSuffix;
|
||||
}
|
||||
$blockNameHierarchy[] = $view->vars['full_block_name'] . '_' . $blockNameSuffix;
|
||||
$hierarchyLevel = count($blockNameHierarchy) - 1;
|
||||
|
||||
$hierarchyInit = true;
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace Symfony\Component\Form\Tests;
|
||||
|
||||
use Symfony\Component\Form\FormError;
|
||||
use Symfony\Component\Form\Tests\Fixtures\AlternatingRowType;
|
||||
|
||||
abstract class AbstractDivLayoutTest extends AbstractLayoutTest
|
||||
{
|
||||
@ -283,6 +284,29 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest
|
||||
);
|
||||
}
|
||||
|
||||
// https://github.com/symfony/symfony/issues/5038
|
||||
public function testCollectionWithAlternatingRowTypes()
|
||||
{
|
||||
$data = array(
|
||||
array('title' => 'a'),
|
||||
array('title' => 'b'),
|
||||
);
|
||||
$form = $this->factory->createNamed('name', 'collection', $data, array(
|
||||
'type' => new AlternatingRowType(),
|
||||
));
|
||||
|
||||
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||
'/div
|
||||
[
|
||||
./div[./div/div/input[@type="text"][@value="a"]]
|
||||
/following-sibling::div[./div/div/textarea[.="b"]]
|
||||
]
|
||||
[count(./div[./div/div/input])=1]
|
||||
[count(./div[./div/div/textarea])=1]
|
||||
'
|
||||
);
|
||||
}
|
||||
|
||||
public function testEmptyCollection()
|
||||
{
|
||||
$form = $this->factory->createNamed('name', 'collection', array(), array(
|
||||
|
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Form\Tests\Fixtures;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class AlternatingRowType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$formFactory = $builder->getFormFactory();
|
||||
|
||||
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($formFactory) {
|
||||
$form = $event->getForm();
|
||||
$type = $form->getName() % 2 === 0 ? 'text' : 'textarea';
|
||||
$form->add($formFactory->createNamed('title', $type));
|
||||
});
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return 'alternating_row';
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user