Skip to content

Commit

Permalink
Add a form handling service
Browse files Browse the repository at this point in the history
  • Loading branch information
stefk committed Feb 26, 2016
1 parent 88829f8 commit b23f78e
Show file tree
Hide file tree
Showing 2 changed files with 185 additions and 0 deletions.
93 changes: 93 additions & 0 deletions Form/Handler/FormHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

namespace Claroline\CoreBundle\Form\Handler;

use JMS\DiExtraBundle\Annotation as DI;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\Request;

/**
* Utility class for handling forms defined as services.
*
* @DI\Service("claroline.form_handler")
*/
class FormHandler
{
private $factory;
private $currentForm;

/**
* @DI\InjectParams({
* "factory" = @DI\Inject("form.factory")
* })
*
* @param FormFactoryInterface $factory
*/
public function __construct(FormFactoryInterface $factory)
{
$this->factory = $factory;
$this->currentForm = null;
}

/**
* Returns whether a form is valid and stores it internally for future use.
*
* @param string $formReference The form type name
* @param Request $request The request to be bound
* @param mixed $data An entity or array to be bound
* @param array $options The options to be passed to the form builder
* @return bool
*/
public function isValid($formReference, Request $request, $data = null, array $options = [])
{
$form = $this->getForm($formReference, $data, $options);
$form->handleRequest($request);

return $form->isValid();
}

/**
* Returns the data associated to the current form.
*
* @return mixed
* @throws \LogicException if no form has been handled yet
*/
public function getData()
{
return $this->getCurrentForm()->getData();
}

/**
* Creates and returns a form view either from the current form
* or from a new form type reference passed as argument.
*
* @param string $formReference The form type name
* @param mixed $data An entity or array to be bound
* @param array $options The options to be passed to the form builder
* @return mixed
* @throws \LogicException if no reference is passed and
* no form has been handled yet
*/
public function getView($formReference = null, $data = null, array $options = [])
{
if ($formReference) {
$this->getForm($formReference, $data, $options);
}

return $this->getCurrentForm()->createView();
}

private function getForm($reference, $data = null, array $options = [])
{
return $this->currentForm = $this->factory->create($reference, $data, $options);
}

private function getCurrentForm()
{
if (!$this->currentForm) {
throw new \LogicException('No form has been handled yet');
}

return $this->currentForm;
}
}
92 changes: 92 additions & 0 deletions Tests/Unit/Form/Handler/FormHandlerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php

namespace Claroline\CoreBundle\Form\Handler;

use HeVinci\CompetencyBundle\Util\UnitTestCase;
use Symfony\Component\HttpFoundation\Request;

class FormHandlerTest extends UnitTestCase
{
private $factory;
private $handler;

protected function setUp()
{
$this->factory = $this->mock('Symfony\Component\Form\FormFactoryInterface');
$this->handler = new FormHandler($this->factory);
}

/**
* @expectedException \LogicException
* @dataProvider currentFormMethodProvider
* @param string $method
*/
public function testAccessToCurrentFormRequiresPreviousFetch($method)
{
$this->handler->{$method}();
}

public function testValidateAndRetrieveDataAndView()
{
$form = $this->mock('Symfony\Component\Form\Form');
$request = new Request();

// validation
$this->factory->expects($this->exactly(2))
->method('create')
->withConsecutive(
['form.ref'],
['form.ref', 'DATA', ['options']]
)
->willReturn($form);
$form->expects($this->exactly(2))
->method('isValid')
->willReturnOnConsecutiveCalls(true, false);
$this->assertTrue($this->handler->isValid('form.ref', $request));
$this->assertFalse($this->handler->isValid('form.ref', $request, 'DATA', ['options']));

// retrieval
$form->expects($this->once())
->method('getData')
->willReturn('DATA');
$form->expects($this->once())
->method('createView')
->willReturn('VIEW');

$this->assertEquals('DATA', $this->handler->getData());
$this->assertEquals('VIEW', $this->handler->getView());
}

public function testGetViewAndRetrieveData()
{
$form = $this->mock('Symfony\Component\Form\Form');
$this->factory->expects($this->once())
->method('create')
->with('form.ref')
->willReturn($form);
$form->expects($this->once())
->method('createView')
->willReturn('VIEW');
$form->expects($this->once())
->method('getData')
->willReturn('DATA');

$this->assertEquals('VIEW', $this->handler->getView('form.ref'));
$this->assertEquals('DATA', $this->handler->getData());
}

public function currentFormMethodProvider()
{
return [
['getData'],
['getView']
];
}

protected function mock($class)
{
return $this->getMockBuilder($class)
->disableOriginalConstructor()
->getMock();
}
}

0 comments on commit b23f78e

Please sign in to comment.