rewrite controller to add form validation

The controller handle form validation. Each step is now responsible for validating his own form and, if valid, redirect to next step. The last step gather data from previous step and generate a redirection to an HTTP GET query to generate the report.
This commit is contained in:
Julien Fastré 2016-01-12 22:16:48 +01:00
parent fa1be795ec
commit cf255cd0a2

View File

@ -32,9 +32,16 @@ use Symfony\Component\Form\Extension\Core\Type\FormType;
/**
* ExportController is the controller use for exporting data.
*
*
*/
class ExportController extends Controller
{
/**
* Render the list of available exports
*
* @param Request $request
* @return \Symfony\Component\HttpFoundation\Response
*/
public function indexAction(Request $request)
{
$exportManager = $this->get('chill.main.export_manager');
@ -47,15 +54,19 @@ class ExportController extends Controller
}
/**
* Render the form required to generate data for the export.
* handle the step to build a query for an export
*
* This action has two steps :
* This action has three steps :
*
* - 'export', for the export form
* - 'formatter', for the formatter form
* 1.'export', the export form. When the form is posted, the data is stored
* in the session (if valid), and then a redirection is done to next step.
* 2. 'formatter', the formatter form. When the form is posted, the data is
* stored in the session (if valid), and then a redirection is done to next step.
* 3. 'generate': gather data from session from the previous steps, and
* make a redirection to the "generate" action with data in query (HTTP GET)
*
* @param string $alias
* @param Request $request
* @param string $request
* @param Request $alias
* @return \Symfony\Component\HttpFoundation\Response
*/
public function newAction(Request $request, $alias)
@ -64,7 +75,7 @@ class ExportController extends Controller
switch ($step) {
case 'export':
return $this->exportFormStep($alias);
return $this->exportFormStep($request, $alias);
break;
case 'formatter':
return $this->formatterFormStep($request, $alias);
@ -80,10 +91,13 @@ class ExportController extends Controller
/**
* Render the export form
*
* When the method is POST, the form is stored if valid, and a redirection
* is done to next step.
*
* @param string $alias
* @return \Symfony\Component\HttpFoundation\Response
*/
protected function exportFormStep($alias)
protected function exportFormStep(Request $request, $alias)
{
$exportManager = $this->get('chill.main.export_manager');
@ -91,6 +105,31 @@ class ExportController extends Controller
$form = $this->createCreateFormExport($alias, 'export');
if ($request->getMethod() === 'POST') {
$form->handleRequest($request);
if ($form->isValid()) {
$this->get('logger')->debug('form export is valid', array(
'location' => __METHOD__));
// store data for reusing in next steps
$data = $form->getData();
$this->get('session')->set('export_step_raw',
$request->request->all());
$this->get('session')->set('export_step', $data);
//redirect to next step
return $this->redirect(
$this->generateUrl('chill_main_export_new', array(
'step' => $this->getNextStep('export'),
'alias' => $alias
)));
} else {
$this->get('logger')->debug('form export is invalid', array(
'location' => __METHOD__));
}
}
return $this->render('ChillMainBundle:Export:new.html.twig', array(
'form' => $form->createView(),
'export_alias' => $alias,
@ -99,31 +138,32 @@ class ExportController extends Controller
}
/**
* create a form to show on different steps.
*
* @param string $alias
* @param string $step, can either be 'export', 'formatter', 'generate_export' or 'generate_formatter' (last two are used by generate action)
* @param array $data the data from previous step. Required for steps 'formatter' and 'generate_formatter'
* @return \Symfony\Component\Form\Form
*/
protected function createCreateFormExport($alias, $step, $data = array())
{
/* @var $exportManager \Chill\MainBundle\Export\ExportManager */
$exportManager = $this->get('chill.main.export_manager');
$isGenerate = strpos($step, 'generate_') === 0;
$builder = $this->get('form.factory')
->createNamedBuilder(null, FormType::class, array(), array(
'method' => 'GET',
'csrf_protection' => false,
'action' => $this->generateUrl($this->getNextRoute($step), array(
'alias' => $alias
))
'method' => $isGenerate ? 'GET' : 'POST',
'csrf_protection' => $isGenerate ? false : true,
));
if ($step === 'export') {
if ($step === 'export' or $step === 'generate_export') {
$builder->add('export', ExportType::class, array(
'export_alias' => $alias,
));
}
if ($step === 'formatter') {
if ($step === 'formatter' or $step === 'generate_formatter') {
$builder->add('formatter', FormatterType::class, array(
'formatter_alias' => $exportManager
->getFormatterAlias($data['export']),
@ -133,96 +173,155 @@ class ExportController extends Controller
));
}
$builder->add('submit', 'submit', array(
'label' => 'Generate'
));
$builder->add('step', 'hidden', array(
'data' => $this->getNextStep($step)
));
//if (strpos($step, 'generate_') !== false) {
$builder->add('submit', 'submit', array(
'label' => 'Generate'
));
//}
return $builder->getForm();
}
private function getNextStep($step)
/**
* get the next step. If $reverse === true, the previous step is returned.
*
* This method provides a centralized way of handling next/previous step.
*
* @param string $step the current step
* @param boolean $reverse set to true to get the previous step
* @return string the next/current step
* @throws \LogicException if there is no step before or after the given step
*/
private function getNextStep($step, $reverse = false)
{
switch($step) {
case 'export': return 'formatter';
case 'formatter' : return 'generate';
case 'export':
if ($reverse !== false) {
throw new \LogicException("there is no step before 'export'");
}
return $reverse ? 'export' : 'formatter';
case 'formatter' :
return $reverse ? 'export' : 'generate';
case 'generate' :
if ($reverse === false) {
throw new \LogicException("there is no step after 'generate'");
}
return 'formatter';
default:
throw new \LogicException("the step $step is not defined.");
}
}
private function getNextRoute($step)
{
switch($step) {
case 'generate':
return 'chill_main_export_generate';
default:
return 'chill_main_export_new';
}
}
/**
* Render the form for formatter.
*
* If the form is posted and valid, store the data in session and
* redirect to the next step.
*
* @param Request $request
* @param string $alias
* @return \Symfony\Component\HttpFoundation\Response
*/
protected function formatterFormStep(Request $request, $alias)
{
$export = $this->get('chill.main.export_manager')->getExport($alias);
$exportForm = $this->createCreateFormExport($alias, 'export');
$exportForm->handleRequest($request);
// check we have data from the previous step (export step)
$data = $this->get('session')->get('export_step', null);
if ($exportForm->isValid()) {
$data = $exportForm->getData();
$this->get('session')->set('export_step_raw', $request->query->all());
if ($data === null) {
return $this->redirectToRoute('chill_main_export_new', array(
'step' => $this->getNextStep('formatter', true),
'alias' => $alias
));
}
$form = $this->createCreateFormExport($alias,
'formatter', $data);
$form = $this->createCreateFormExport($alias, 'formatter', $data);
if ($request->getMethod() === 'POST') {
$form->handleRequest($request);
if ($form->isValid()) {
$dataFormatter = $form->getData();
$this->get('session')->set('formatter_step', $dataFormatter);
$this->get('session')->set('formatter_step_raw',
$request->request->all());
//redirect to next step
return $this->redirect($this->generateUrl('chill_main_export_new',
array(
'alias' => $alias,
'step' => $this->getNextStep('formatter')
)));
}
}
return $this->render('ChillMainBundle:Export:new_formatter_step.html.twig',
array(
'form' => $form->createView(),
'export' => $export
));
} else {
throw new \LogicException("The form contains invalid data. Currently"
. " we do not handle invalid data in forms");
}
}
/**
* Gather data stored in session from previous steps, and redirect
* to the `generate` action, compiling data from previous step in the URL
* (to obtain a GET HTTP query).
*
* The data from previous steps is removed from session.
*
* @param Request $request
* @param string $alias
* @return \Symfony\Component\HttpFoundation\RedirectResponse
*/
protected function forwardToGenerate(Request $request, $alias)
{
$data = $this->get('session')->get('export_step');
$dataFormatter = $this->get('session')->get('formatter_step_raw', null);
$dataExport = $this->get('session')->get('export_step_raw', null);
$form = $this->createCreateFormExport($alias,
'formatter', $data);
$form->handleRequest($request);
if ($form->isValid()) {
$dataFormatter = $form->getData();
$this->get('session')->set('formatter_step', $dataFormatter);
if ($dataFormatter === NULL) {
return $this->redirectToRoute('chill_main_export_new', array(
'alias' => $alias, 'step' => $this->getNextStep('generate', true)
));
}
// remove data from session
$this->get('session')->remove('export_step_raw');
$this->get('session')->remove('export_step');
$this->get('session')->remove('formatter_step_raw');
$this->get('session')->remove('formatter_step');
$redirectParameters = array_merge(
$this->get('session')->get('export_step_raw'),
$request->query->all(),
$dataFormatter,
$dataExport,
array('alias' => $alias)
);
unset($redirectParameters['_token']);
return $this->redirect($this->generateUrl(
'chill_main_export_generate', $redirectParameters));
return $this->redirectToRoute('chill_main_export_generate',
$redirectParameters);
}
/**
* Generate a report.
*
* This action must work with GET queries.
*
* @param Request $request
* @param string $alias
* @return \Symfony\Component\HttpFoundation\Response
*/
public function generateAction(Request $request, $alias)
{
$exportManager = $this->get('chill.main.export_manager');
$formExport = $this->createCreateFormExport($alias, 'export');
$formExport = $this->createCreateFormExport($alias, 'generate_export');
$formExport->handleRequest($request);
$dataExport = $formExport->getData();
$formFormatter = $this->createCreateFormExport($alias, 'formatter',
$formFormatter = $this->createCreateFormExport($alias, 'generate_formatter',
$dataExport);
$formFormatter->handleRequest($request);
$dataFormatter = $formFormatter->getData();