Skip to content

Commit

Permalink
[Form] moved csrf listener to its own class
Browse files Browse the repository at this point in the history
  • Loading branch information
kriswallsmith committed Jun 10, 2011
1 parent cb53414 commit fe4382e
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 23 deletions.
@@ -0,0 +1,66 @@
<?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\Component\Form\Extension\Csrf\EventListener;

use Symfony\Component\Form\Event\DataEvent;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
use Symfony\Component\Form\FormFactoryInterface;

/**
* Ensures the CSRF field.
*
* @author Bulat Shakirzyanov <mallluhuct@gmail.com>
* @author Kris Wallsmith <kris@symfony.com>
*/
class EnsureCsrfFieldListener
{
private $factory;
private $name;
private $intention;
private $provider;

/**
* Constructor.
*
* @param FormFactoryInterface $factory The form factory
* @param string $name A name for the CSRF field
* @param string $intention The intention string
* @param CsrfProviderInterface $provider The CSRF provider
*/
public function __construct(FormFactoryInterface $factory, $name, $intention = null, CsrfProviderInterface $provider = null)
{
$this->factory = $factory;
$this->name = $name;
$this->intention = $intention;
$this->provider = $provider;
}

/**
* Ensures a root form has a CSRF field.
*
* This method should be connected to both form.pre_set_data and form.pre_bind.
*/
public function ensureCsrfField(DataEvent $event)
{
$form = $event->getForm();

$options = array();
if ($this->intention) {
$options['intention'] = $this->intention;
}
if ($this->provider) {
$options['csrf_provider'] = $this->provider;
}

$form->add($this->factory->createNamed('csrf', $this->name, null, $options));
}
}
Expand Up @@ -12,9 +12,10 @@
namespace Symfony\Component\Form\Extension\Csrf\Type;

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Event\DataEvent;
use Symfony\Component\Form\Extension\Csrf\EventListener\EnsureCsrfFieldListener;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormInterface;

class FormTypeCsrfExtension extends AbstractTypeExtension
Expand All @@ -40,30 +41,18 @@ public function buildForm(FormBuilder $builder, array $options)
return;
}

$listener = function(DataEvent $event) use ($options, $builder)
{
$form = $event->getForm();

if (!$form->isRoot()) {
return;
}

$csrfOptions = array('intention' => $options['intention']);

if ($options['csrf_provider']) {
$csrfOptions['csrf_provider'] = $options['csrf_provider'];
}

$form->add(
$builder
->create($options['csrf_field_name'], 'csrf', $csrfOptions)
->getForm()
);
};
$listener = new EnsureCsrfFieldListener(
$builder->getFormFactory(),
$options['csrf_field_name'],
$options['intention'],
$options['csrf_provider']
);

// use a low priority so higher priority listeners don't remove the field
$builder
->addEventListener('form.pre_set_data', $listener, -10)
->addEventListener('form.pre_bind', $listener, -10)
->setAttribute('csrf_field_name', $options['csrf_field_name'])
->addEventListener(FormEvents::PRE_SET_DATA, array($listener, 'ensureCsrfField'), -10)
->addEventListener(FormEvents::PRE_BIND, array($listener, 'ensureCsrfField'), -10)
;
}

Expand Down
@@ -0,0 +1,73 @@
<?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\EventListener;

use Symfony\Component\Form\Event\DataEvent;
use Symfony\Component\Form\Extension\Csrf\EventListener\EnsureCsrfFieldListener;

class EnsureCsrfFieldListenerTest extends \PHPUnit_Framework_TestCase
{
private $form;
private $formFactory;

protected function setUp()
{
$this->formFactory = $this->getMock('Symfony\\Component\\Form\\FormFactoryInterface');
$this->form = $this->getMock('Symfony\\Tests\\Component\\Form\\FormInterface');
$this->field = $this->getMock('Symfony\\Tests\\Component\\Form\\FormInterface');
$this->event = new DataEvent($this->form, array());
}

public function testAddField()
{
$this->formFactory->expects($this->once())
->method('createNamed')
->with('csrf', '_token', null, array())
->will($this->returnValue($this->field));
$this->form->expects($this->once())
->method('add')
->with($this->isInstanceOf('Symfony\\Tests\\Component\\Form\\FormInterface'));

$listener = new EnsureCsrfFieldListener($this->formFactory, '_token');
$listener->ensureCsrfField($this->event);
}

public function testIntention()
{
$this->formFactory->expects($this->once())
->method('createNamed')
->with('csrf', '_token', null, array('intention' => 'something'))
->will($this->returnValue($this->field));
$this->form->expects($this->once())
->method('add')
->with($this->isInstanceOf('Symfony\\Tests\\Component\\Form\\FormInterface'));

$listener = new EnsureCsrfFieldListener($this->formFactory, '_token', 'something');
$listener->ensureCsrfField($this->event);
}

public function testProvider()
{
$provider = $this->getMock('Symfony\\Component\\Form\\Extension\\Csrf\\CsrfProvider\\CsrfProviderInterface');

$this->formFactory->expects($this->once())
->method('createNamed')
->with('csrf', '_token', null, array('csrf_provider' => $provider))
->will($this->returnValue($this->field));
$this->form->expects($this->once())
->method('add')
->with($this->isInstanceOf('Symfony\\Tests\\Component\\Form\\FormInterface'));

$listener = new EnsureCsrfFieldListener($this->formFactory, '_token', null, $provider);
$listener->ensureCsrfField($this->event);
}
}

0 comments on commit fe4382e

Please sign in to comment.