[Form] Added FormTypeExtensionInterface
With implementations of this interface, existing types can be amended. The Csrf extension, for example, now contains a class FormTypeCsrfExtension that adds CSRF capabilities to the "form" type. To register new type extensions in the DIC, tag them with "form.type_extension" and the name of the extended type as alias.
This commit is contained in:
parent
54e66c518f
commit
1ce2db87e2
@ -42,9 +42,25 @@ class FormPass implements CompilerPassInterface
|
||||
|
||||
$container->getDefinition('form.extension')->replaceArgument(1, $types);
|
||||
|
||||
$typeExtensions = array();
|
||||
|
||||
foreach ($container->findTaggedServiceIds('form.type_extension') as $serviceId => $tag) {
|
||||
$alias = isset($tag[0]['alias'])
|
||||
? $tag[0]['alias']
|
||||
: $serviceId;
|
||||
|
||||
if (!isset($typeExtensions[$alias])) {
|
||||
$typeExtensions[$alias] = array();
|
||||
}
|
||||
|
||||
$typeExtensions[$alias][] = $serviceId;
|
||||
}
|
||||
|
||||
$container->getDefinition('form.extension')->replaceArgument(2, $typeExtensions);
|
||||
|
||||
// Find all services annotated with "form.type_guesser"
|
||||
$guessers = array_keys($container->findTaggedServiceIds('form.type_guesser'));
|
||||
|
||||
$container->getDefinition('form.extension')->replaceArgument(2, $guessers);
|
||||
$container->getDefinition('form.extension')->replaceArgument(3, $guessers);
|
||||
}
|
||||
}
|
@ -42,6 +42,11 @@
|
||||
-->
|
||||
<argument type="collection" />
|
||||
<!--
|
||||
All services with tag "form.type_extension" are inserted here by
|
||||
InitFormsPass
|
||||
-->
|
||||
<argument type="collection" />
|
||||
<!--
|
||||
All services with tag "form.type_guesser" are inserted here by
|
||||
InitFormsPass
|
||||
-->
|
||||
@ -68,7 +73,7 @@
|
||||
<argument>%file.temporary_storage.directory%</argument>
|
||||
</service>
|
||||
|
||||
<!-- FieldTypes -->
|
||||
<!-- CoreExtension -->
|
||||
<service id="form.type.field" class="Symfony\Component\Form\Extension\Core\Type\FieldType">
|
||||
<tag name="form.type" alias="field" />
|
||||
<argument type="service" id="validator" />
|
||||
@ -91,10 +96,6 @@
|
||||
<service id="form.type.country" class="Symfony\Component\Form\Extension\Core\Type\CountryType">
|
||||
<tag name="form.type" alias="country" />
|
||||
</service>
|
||||
<service id="form.type.csrf" class="Symfony\Component\Form\Extension\Csrf\Type\CsrfType">
|
||||
<tag name="form.type" alias="csrf" />
|
||||
<argument type="service" id="form.csrf_provider" />
|
||||
</service>
|
||||
<service id="form.type.date" class="Symfony\Component\Form\Extension\Core\Type\DateType">
|
||||
<tag name="form.type" alias="date" />
|
||||
</service>
|
||||
@ -153,6 +154,15 @@
|
||||
<service id="form.type.url" class="Symfony\Component\Form\Extension\Core\Type\UrlType">
|
||||
<tag name="form.type" alias="url" />
|
||||
</service>
|
||||
|
||||
<!-- CsrfExtension -->
|
||||
<service id="form.type.csrf" class="Symfony\Component\Form\Extension\Csrf\Type\CsrfType">
|
||||
<tag name="form.type" alias="csrf" />
|
||||
<argument type="service" id="form.csrf_provider" />
|
||||
</service>
|
||||
<service id="form.type_extension.csrf" class="Symfony\Component\Form\Extension\Csrf\Type\FormTypeCsrfExtension">
|
||||
<tag name="form.type_extension" alias="form" />
|
||||
</service>
|
||||
|
||||
</services>
|
||||
</container>
|
||||
|
@ -25,9 +25,9 @@ abstract class AbstractExtension implements FormExtensionInterface
|
||||
private $types;
|
||||
|
||||
/**
|
||||
* @var Boolean
|
||||
* @var array
|
||||
*/
|
||||
private $typesLoaded = false;
|
||||
private $typeExtensions;
|
||||
|
||||
/**
|
||||
* @var FormTypeGuesserInterface
|
||||
@ -39,14 +39,23 @@ abstract class AbstractExtension implements FormExtensionInterface
|
||||
*/
|
||||
private $typeGuesserLoaded = false;
|
||||
|
||||
abstract protected function loadTypes();
|
||||
protected function loadTypes()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
abstract protected function loadTypeGuesser();
|
||||
protected function loadTypeExtensions()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
protected function loadTypeGuesser()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
private function initTypes()
|
||||
{
|
||||
$this->typesLoaded = true;
|
||||
|
||||
$types = $this->loadTypes();
|
||||
$typesByName = array();
|
||||
|
||||
@ -61,6 +70,28 @@ abstract class AbstractExtension implements FormExtensionInterface
|
||||
$this->types = $typesByName;
|
||||
}
|
||||
|
||||
private function initTypeExtensions()
|
||||
{
|
||||
$extensions = $this->loadTypeExtensions();
|
||||
$extensionsByType = array();
|
||||
|
||||
foreach ($extensions as $extension) {
|
||||
if (!$extension instanceof FormTypeExtensionInterface) {
|
||||
throw new UnexpectedTypeException($extension, 'Symfony\Component\Form\FormTypeExtensionInterface');
|
||||
}
|
||||
|
||||
$type = $extension->getExtendedType();
|
||||
|
||||
if (!isset($extensionsByType[$type])) {
|
||||
$extensionsByType[$type] = array();
|
||||
}
|
||||
|
||||
$extensionsByType[$type][] = $extension;
|
||||
}
|
||||
|
||||
$this->typeExtensions = $extensionsByType;
|
||||
}
|
||||
|
||||
private function initTypeGuesser()
|
||||
{
|
||||
$this->typeGuesserLoaded = true;
|
||||
@ -76,12 +107,12 @@ abstract class AbstractExtension implements FormExtensionInterface
|
||||
|
||||
public function getType($name)
|
||||
{
|
||||
if (!$this->typesLoaded) {
|
||||
if (null === $this->types) {
|
||||
$this->initTypes();
|
||||
}
|
||||
|
||||
if (!isset($this->types[$name])) {
|
||||
throw new FormException(sprintf('The type "%s" can not be typesLoaded by this extension', $name));
|
||||
throw new FormException(sprintf('The type "%s" can not be loaded by this extension', $name));
|
||||
}
|
||||
|
||||
return $this->types[$name];
|
||||
@ -89,13 +120,33 @@ abstract class AbstractExtension implements FormExtensionInterface
|
||||
|
||||
public function hasType($name)
|
||||
{
|
||||
if (!$this->typesLoaded) {
|
||||
if (null === $this->types) {
|
||||
$this->initTypes();
|
||||
}
|
||||
|
||||
return isset($this->types[$name]);
|
||||
}
|
||||
|
||||
function getTypeExtensions($name)
|
||||
{
|
||||
if (null === $this->typeExtensions) {
|
||||
$this->initTypeExtensions();
|
||||
}
|
||||
|
||||
return isset($this->typeExtensions[$name])
|
||||
? $this->typeExtensions[$name]
|
||||
: array();
|
||||
}
|
||||
|
||||
function hasTypeExtensions($name)
|
||||
{
|
||||
if (null === $this->typeExtensions) {
|
||||
$this->initTypeExtensions();
|
||||
}
|
||||
|
||||
return isset($this->typeExtensions[$name]) && count($this->typeExtensions[$name]) > 0;
|
||||
}
|
||||
|
||||
public function getTypeGuesser()
|
||||
{
|
||||
if (!$this->typeGuesserLoaded) {
|
||||
|
@ -13,6 +13,8 @@ namespace Symfony\Component\Form;
|
||||
|
||||
abstract class AbstractType implements FormTypeInterface
|
||||
{
|
||||
private $extensions = array();
|
||||
|
||||
public function buildForm(FormBuilder $builder, array $options)
|
||||
{
|
||||
}
|
||||
@ -46,4 +48,20 @@ abstract class AbstractType implements FormTypeInterface
|
||||
|
||||
return strtolower($matches[1]);
|
||||
}
|
||||
|
||||
public function setExtensions(array $extensions)
|
||||
{
|
||||
foreach ($extensions as $extension) {
|
||||
if (!$extension instanceof FormTypeExtensionInterface) {
|
||||
throw new UnexpectedTypeException($extension, 'Symfony\Component\Form\FormTypeExtensionInterface');
|
||||
}
|
||||
}
|
||||
|
||||
$this->extensions = $extensions;
|
||||
}
|
||||
|
||||
public function getExtensions()
|
||||
{
|
||||
return $this->extensions;
|
||||
}
|
||||
}
|
||||
|
32
src/Symfony/Component/Form/AbstractTypeExtension.php
Normal file
32
src/Symfony/Component/Form/AbstractTypeExtension.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form;
|
||||
|
||||
abstract class AbstractTypeExtension implements FormTypeExtensionInterface
|
||||
{
|
||||
public function buildForm(FormBuilder $builder, array $options)
|
||||
{
|
||||
}
|
||||
|
||||
public function buildView(FormView $view, FormInterface $form)
|
||||
{
|
||||
}
|
||||
|
||||
public function buildViewBottomUp(FormView $view, FormInterface $form)
|
||||
{
|
||||
}
|
||||
|
||||
public function getDefaultOptions(array $options)
|
||||
{
|
||||
return array();
|
||||
}
|
||||
}
|
@ -25,16 +25,6 @@ class FormType extends AbstractType
|
||||
{
|
||||
$builder->setAttribute('virtual', $options['virtual'])
|
||||
->setDataMapper(new PropertyPathMapper($options['data_class']));
|
||||
|
||||
if ($options['csrf_protection']) {
|
||||
$csrfOptions = array('page_id' => $options['csrf_page_id']);
|
||||
|
||||
if ($options['csrf_provider']) {
|
||||
$csrfOptions['csrf_provider'] = $options['csrf_provider'];
|
||||
}
|
||||
|
||||
$builder->add($options['csrf_field_name'], 'csrf', $csrfOptions);
|
||||
}
|
||||
}
|
||||
|
||||
public function buildViewBottomUp(FormView $view, FormInterface $form)
|
||||
@ -54,10 +44,6 @@ class FormType extends AbstractType
|
||||
public function getDefaultOptions(array $options)
|
||||
{
|
||||
$defaultOptions = array(
|
||||
'csrf_protection' => true,
|
||||
'csrf_field_name' => '_token',
|
||||
'csrf_provider' => null,
|
||||
'csrf_page_id' => get_class($this),
|
||||
'virtual' => false,
|
||||
// Errors in forms bubble by default, so that form errors will
|
||||
// end up as global errors in the root form
|
||||
|
@ -31,7 +31,10 @@ class CsrfExtension extends AbstractExtension
|
||||
);
|
||||
}
|
||||
|
||||
protected function loadTypeGuesser()
|
||||
protected function loadTypeExtensions()
|
||||
{
|
||||
return array(
|
||||
new Type\FormTypeCsrfExtension(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Extension\Csrf\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractTypeExtension;
|
||||
use Symfony\Component\Form\FormBuilder;
|
||||
|
||||
class FormTypeCsrfExtension extends AbstractTypeExtension
|
||||
{
|
||||
public function buildForm(FormBuilder $builder, array $options)
|
||||
{
|
||||
if ($options['csrf_protection']) {
|
||||
$csrfOptions = array('page_id' => $options['csrf_page_id']);
|
||||
|
||||
if ($options['csrf_provider']) {
|
||||
$csrfOptions['csrf_provider'] = $options['csrf_provider'];
|
||||
}
|
||||
|
||||
$builder->add($options['csrf_field_name'], 'csrf', $csrfOptions);
|
||||
}
|
||||
}
|
||||
|
||||
public function getDefaultOptions(array $options)
|
||||
{
|
||||
return array(
|
||||
'csrf_protection' => true,
|
||||
'csrf_field_name' => '_token',
|
||||
'csrf_provider' => null,
|
||||
'csrf_page_id' => get_class($this),
|
||||
);
|
||||
}
|
||||
|
||||
public function getExtendedType()
|
||||
{
|
||||
return 'form';
|
||||
}
|
||||
}
|
@ -28,25 +28,45 @@ class DependencyInjectionExtension implements FormExtensionInterface
|
||||
private $guesserLoaded = false;
|
||||
|
||||
public function __construct(ContainerInterface $container,
|
||||
array $typeServiceIds, array $guesserServiceIds)
|
||||
array $typeServiceIds, array $typeExtensionServiceIds,
|
||||
array $guesserServiceIds)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->typeServiceIds = $typeServiceIds;
|
||||
$this->typeExtensionServiceIds = $typeExtensionServiceIds;
|
||||
$this->guesserServiceIds = $guesserServiceIds;
|
||||
}
|
||||
|
||||
public function getType($identifier)
|
||||
public function getType($name)
|
||||
{
|
||||
if (!isset($this->typeServiceIds[$identifier])) {
|
||||
throw new \InvalidArgumentException(sprintf('The field type "%s" is not registered with the service container.', $identifier));
|
||||
if (!isset($this->typeServiceIds[$name])) {
|
||||
throw new \InvalidArgumentException(sprintf('The field type "%s" is not registered with the service container.', $name));
|
||||
}
|
||||
|
||||
return $this->container->get($this->typeServiceIds[$identifier]);
|
||||
return $this->container->get($this->typeServiceIds[$name]);
|
||||
}
|
||||
|
||||
public function hasType($identifier)
|
||||
public function hasType($name)
|
||||
{
|
||||
return isset($this->typeServiceIds[$identifier]);
|
||||
return isset($this->typeServiceIds[$name]);
|
||||
}
|
||||
|
||||
public function getTypeExtensions($name)
|
||||
{
|
||||
$extensions = array();
|
||||
|
||||
if (isset($this->typeExtensionServiceIds[$name])) {
|
||||
foreach ($this->typeExtensionServiceIds[$name] as $serviceId) {
|
||||
$extensions[] = $this->container->get($serviceId);
|
||||
}
|
||||
}
|
||||
|
||||
return $extensions;
|
||||
}
|
||||
|
||||
public function hasTypeExtensions($name)
|
||||
{
|
||||
return isset($this->typeExtensionServiceIds[$name]);
|
||||
}
|
||||
|
||||
public function getTypeGuesser()
|
||||
|
@ -844,6 +844,10 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
|
||||
foreach ($types as $type) {
|
||||
$type->buildView($view, $this);
|
||||
|
||||
foreach ($type->getExtensions() as $typeExtension) {
|
||||
$typeExtension->buildView($view, $this);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->children as $key => $child) {
|
||||
@ -854,6 +858,10 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
|
||||
foreach ($types as $type) {
|
||||
$type->buildViewBottomUp($view, $this);
|
||||
|
||||
foreach ($type->getExtensions() as $typeExtension) {
|
||||
$typeExtension->buildViewBottomUp($view, $this);
|
||||
}
|
||||
}
|
||||
|
||||
return $view;
|
||||
|
@ -17,5 +17,9 @@ interface FormExtensionInterface
|
||||
|
||||
function hasType($name);
|
||||
|
||||
function getTypeExtensions($name);
|
||||
|
||||
function hasTypeExtensions($name);
|
||||
|
||||
function getTypeGuesser();
|
||||
}
|
||||
|
@ -20,6 +20,8 @@ class FormFactory implements FormFactoryInterface
|
||||
{
|
||||
private $extensions = array();
|
||||
|
||||
private $types = array();
|
||||
|
||||
private $guesser;
|
||||
|
||||
public function __construct(array $extensions)
|
||||
@ -48,6 +50,46 @@ class FormFactory implements FormFactoryInterface
|
||||
$this->guesser = new FormTypeGuesserChain($guessers);
|
||||
}
|
||||
|
||||
public function getType($name)
|
||||
{
|
||||
$type = null;
|
||||
|
||||
if ($name instanceof FormTypeInterface) {
|
||||
$type = $name;
|
||||
$name = $type->getName();
|
||||
}
|
||||
|
||||
if (!isset($this->types[$name])) {
|
||||
if (!$type) {
|
||||
foreach ($this->extensions as $extension) {
|
||||
if ($extension->hasType($name)) {
|
||||
$type = $extension->getType($name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$type) {
|
||||
throw new FormException(sprintf('Could not load type "%s"', $name));
|
||||
}
|
||||
}
|
||||
|
||||
$typeExtensions = array();
|
||||
|
||||
foreach ($this->extensions as $extension) {
|
||||
$typeExtensions = array_merge(
|
||||
$typeExtensions,
|
||||
$extension->getTypeExtensions($name)
|
||||
);
|
||||
}
|
||||
|
||||
$type->setExtensions($typeExtensions);
|
||||
|
||||
$this->types[$name] = $type;
|
||||
}
|
||||
|
||||
return $this->types[$name];
|
||||
}
|
||||
|
||||
public function create($type, $data = null, array $options = array())
|
||||
{
|
||||
return $this->createBuilder($type, $data, $options)->getForm();
|
||||
@ -77,27 +119,22 @@ class FormFactory implements FormFactoryInterface
|
||||
{
|
||||
$builder = null;
|
||||
$types = array();
|
||||
$typeExtensions = array();
|
||||
$knownOptions = array();
|
||||
$passedOptions = array_keys($options);
|
||||
|
||||
while (null !== $type) {
|
||||
if (!$type instanceof FormTypeInterface) {
|
||||
foreach ($this->extensions as $extension) {
|
||||
if ($extension->hasType($type)) {
|
||||
$type = $extension->getType($type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
$type = $this->getType($type);
|
||||
|
||||
if (!$type) {
|
||||
throw new FormException(sprintf('Could not load type "%s"', $type));
|
||||
}
|
||||
$defaultOptions = $type->getDefaultOptions($options);
|
||||
|
||||
foreach ($type->getExtensions() as $typeExtension) {
|
||||
$defaultOptions = array_merge($defaultOptions, $typeExtension->getDefaultOptions($options));
|
||||
}
|
||||
|
||||
array_unshift($types, $type);
|
||||
$defaultOptions = $type->getDefaultOptions($options);
|
||||
$options = array_merge($defaultOptions, $options);
|
||||
$knownOptions = array_merge($knownOptions, array_keys($defaultOptions));
|
||||
array_unshift($types, $type);
|
||||
$type = $type->getParent($options);
|
||||
}
|
||||
|
||||
@ -117,6 +154,10 @@ class FormFactory implements FormFactoryInterface
|
||||
|
||||
foreach ($types as $type) {
|
||||
$type->buildForm($builder, $options);
|
||||
|
||||
foreach ($type->getExtensions() as $typeExtension) {
|
||||
$typeExtension->buildForm($builder, $options);
|
||||
}
|
||||
}
|
||||
|
||||
if (null !== $data) {
|
||||
|
25
src/Symfony/Component/Form/FormTypeExtensionInterface.php
Normal file
25
src/Symfony/Component/Form/FormTypeExtensionInterface.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form;
|
||||
|
||||
interface FormTypeExtensionInterface
|
||||
{
|
||||
function buildForm(FormBuilder $builder, array $options);
|
||||
|
||||
function buildView(FormView $view, FormInterface $form);
|
||||
|
||||
function buildViewBottomUp(FormView $view, FormInterface $form);
|
||||
|
||||
function getDefaultOptions(array $options);
|
||||
|
||||
function getExtendedType();
|
||||
}
|
@ -26,4 +26,8 @@ interface FormTypeInterface
|
||||
function getParent(array $options);
|
||||
|
||||
function getName();
|
||||
|
||||
function setExtensions(array $extensions);
|
||||
|
||||
function getExtensions();
|
||||
}
|
@ -53,6 +53,10 @@ class TestType implements FormTypeInterface
|
||||
function getDefaultOptions(array $options) {}
|
||||
|
||||
function getParent(array $options) {}
|
||||
|
||||
function setExtensions(array $extensions) {}
|
||||
|
||||
function getExtensions() {}
|
||||
}
|
||||
|
||||
class TestExtension extends AbstractExtension
|
||||
|
@ -16,15 +16,13 @@ use Symfony\Component\Form\Form;
|
||||
|
||||
class CollectionFormTest extends TypeTestCase
|
||||
{
|
||||
public function testContainsOnlyCsrfTokenByDefault()
|
||||
public function testContainsNoFieldByDefault()
|
||||
{
|
||||
$form = $this->factory->create('collection', null, array(
|
||||
'type' => 'field',
|
||||
'csrf_field_name' => 'abc',
|
||||
));
|
||||
|
||||
$this->assertTrue($form->has('abc'));
|
||||
$this->assertEquals(1, count($form));
|
||||
$this->assertEquals(0, count($form));
|
||||
}
|
||||
|
||||
public function testSetDataAdjustsSize()
|
||||
|
@ -63,24 +63,6 @@ class FormTest_AuthorWithoutRefSetter
|
||||
|
||||
class FormTypeTest extends TypeTestCase
|
||||
{
|
||||
public function testCsrfProtectionByDefault()
|
||||
{
|
||||
$form = $this->factory->create('form', null, array(
|
||||
'csrf_field_name' => 'csrf',
|
||||
));
|
||||
|
||||
$this->assertTrue($form->has('csrf'));
|
||||
}
|
||||
|
||||
public function testCsrfProtectionCanBeDisabled()
|
||||
{
|
||||
$form = $this->factory->create('form', null, array(
|
||||
'csrf_protection' => false,
|
||||
));
|
||||
|
||||
$this->assertEquals(0, count($form));
|
||||
}
|
||||
|
||||
public function testValidationGroupNullByDefault()
|
||||
{
|
||||
$form = $this->factory->create('form');
|
||||
|
@ -14,13 +14,10 @@ namespace Symfony\Tests\Component\Form\Extension\Core\Type;
|
||||
use Symfony\Component\Form\FormBuilder;
|
||||
use Symfony\Component\Form\FormFactory;
|
||||
use Symfony\Component\Form\Extension\Core\CoreExtension;
|
||||
use Symfony\Component\Form\Extension\Csrf\CsrfExtension;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
|
||||
abstract class TypeTestCase extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $csrfProvider;
|
||||
|
||||
protected $validator;
|
||||
|
||||
protected $storage;
|
||||
@ -35,7 +32,6 @@ abstract class TypeTestCase extends \PHPUnit_Framework_TestCase
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->csrfProvider = $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface');
|
||||
$this->validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface');
|
||||
$this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
|
||||
$this->storage = $this->getMockBuilder('Symfony\Component\HttpFoundation\File\TemporaryStorage')
|
||||
@ -49,7 +45,6 @@ abstract class TypeTestCase extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
return array(
|
||||
new CoreExtension($this->validator, $this->storage),
|
||||
new CsrfExtension($this->csrfProvider),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -11,8 +11,6 @@
|
||||
|
||||
namespace Symfony\Tests\Component\Form\Extension\Csrf\Type;
|
||||
|
||||
use Symfony\Tests\Component\Form\Extension\Core\Type\TypeTestCase;
|
||||
|
||||
class CsrfTypeTest extends TypeTestCase
|
||||
{
|
||||
protected $provider;
|
||||
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Tests\Component\Form\Extension\Csrf\Type;
|
||||
|
||||
class FormTypeCsrfExtensionTest extends TypeTestCase
|
||||
{
|
||||
public function testCsrfProtectionByDefault()
|
||||
{
|
||||
$form = $this->factory->create('form', null, array(
|
||||
'csrf_field_name' => 'csrf',
|
||||
));
|
||||
|
||||
$this->assertTrue($form->has('csrf'));
|
||||
}
|
||||
|
||||
public function testCsrfProtectionCanBeDisabled()
|
||||
{
|
||||
$form = $this->factory->create('form', null, array(
|
||||
'csrf_protection' => false,
|
||||
));
|
||||
|
||||
$this->assertEquals(0, count($form));
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Tests\Component\Form\Extension\Csrf\Type;
|
||||
|
||||
use Symfony\Tests\Component\Form\Extension\Core\Type\TypeTestCase as BaseTestCase;
|
||||
use Symfony\Component\Form\Extension\Csrf\CsrfExtension;
|
||||
|
||||
abstract class TypeTestCase extends BaseTestCase
|
||||
{
|
||||
protected $csrfProvider;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->csrfProvider = $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface');
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
protected function getExtensions()
|
||||
{
|
||||
return array_merge(parent::getExtensions(), array(
|
||||
new CsrfExtension($this->csrfProvider),
|
||||
));
|
||||
}
|
||||
}
|
@ -869,7 +869,15 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
$test = $this;
|
||||
$type1 = $this->getMock('Symfony\Component\Form\FormTypeInterface');
|
||||
$type1Extension = $this->getMock('Symfony\Component\Form\FormTypeExtensionInterface');
|
||||
$type1->expects($this->any())
|
||||
->method('getExtensions')
|
||||
->will($this->returnValue(array($type1Extension)));
|
||||
$type2 = $this->getMock('Symfony\Component\Form\FormTypeInterface');
|
||||
$type2Extension = $this->getMock('Symfony\Component\Form\FormTypeExtensionInterface');
|
||||
$type2->expects($this->any())
|
||||
->method('getExtensions')
|
||||
->will($this->returnValue(array($type2Extension)));
|
||||
$calls = array();
|
||||
|
||||
$type1->expects($this->once())
|
||||
@ -880,6 +888,14 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
$test->assertFalse($view->hasChildren());
|
||||
}));
|
||||
|
||||
$type1Extension->expects($this->once())
|
||||
->method('buildView')
|
||||
->will($this->returnCallback(function (FormView $view, Form $form) use ($test, &$calls) {
|
||||
$calls[] = 'type1ext::buildView';
|
||||
$test->assertTrue($view->hasParent());
|
||||
$test->assertFalse($view->hasChildren());
|
||||
}));
|
||||
|
||||
$type2->expects($this->once())
|
||||
->method('buildView')
|
||||
->will($this->returnCallback(function (FormView $view, Form $form) use ($test, &$calls) {
|
||||
@ -888,6 +904,14 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
$test->assertFalse($view->hasChildren());
|
||||
}));
|
||||
|
||||
$type2Extension->expects($this->once())
|
||||
->method('buildView')
|
||||
->will($this->returnCallback(function (FormView $view, Form $form) use ($test, &$calls) {
|
||||
$calls[] = 'type2ext::buildView';
|
||||
$test->assertTrue($view->hasParent());
|
||||
$test->assertFalse($view->hasChildren());
|
||||
}));
|
||||
|
||||
$type1->expects($this->once())
|
||||
->method('buildViewBottomUp')
|
||||
->will($this->returnCallback(function (FormView $view, Form $form) use ($test, &$calls) {
|
||||
@ -895,6 +919,13 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
$test->assertTrue($view->hasChildren());
|
||||
}));
|
||||
|
||||
$type1Extension->expects($this->once())
|
||||
->method('buildViewBottomUp')
|
||||
->will($this->returnCallback(function (FormView $view, Form $form) use ($test, &$calls) {
|
||||
$calls[] = 'type1ext::buildViewBottomUp';
|
||||
$test->assertTrue($view->hasChildren());
|
||||
}));
|
||||
|
||||
$type2->expects($this->once())
|
||||
->method('buildViewBottomUp')
|
||||
->will($this->returnCallback(function (FormView $view, Form $form) use ($test, &$calls) {
|
||||
@ -902,6 +933,13 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
$test->assertTrue($view->hasChildren());
|
||||
}));
|
||||
|
||||
$type2Extension->expects($this->once())
|
||||
->method('buildViewBottomUp')
|
||||
->will($this->returnCallback(function (FormView $view, Form $form) use ($test, &$calls) {
|
||||
$calls[] = 'type2ext::buildViewBottomUp';
|
||||
$test->assertTrue($view->hasChildren());
|
||||
}));
|
||||
|
||||
$form = $this->getBuilder()->setTypes(array($type1, $type2))->getForm();
|
||||
$form->setParent($this->getBuilder()->getForm());
|
||||
$form->add($this->getBuilder()->getForm());
|
||||
@ -910,9 +948,13 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$this->assertEquals(array(
|
||||
0 => 'type1::buildView',
|
||||
1 => 'type2::buildView',
|
||||
2 => 'type1::buildViewBottomUp',
|
||||
3 => 'type2::buildViewBottomUp',
|
||||
1 => 'type1ext::buildView',
|
||||
2 => 'type2::buildView',
|
||||
3 => 'type2ext::buildView',
|
||||
4 => 'type1::buildViewBottomUp',
|
||||
5 => 'type1ext::buildViewBottomUp',
|
||||
6 => 'type2::buildViewBottomUp',
|
||||
7 => 'type2ext::buildViewBottomUp',
|
||||
), $calls);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user