I have a fairly ugly controller method I would like to refactor / extract. I can only test this in an integration-type test which kind of signals a code smell.
The method processes the form and needs to do one of 5 things, depending on which button was pressed
- if submitted and valid (button 1) => update some values on the entity and re-render the form
- if submitted and valid (button 2) => perform another controller action that shows a .pdf print of the entity
- if submitted and valid (button 3) => save entity and redirect
- if not submitted or not valid => render form (plus errors)
In code it looks kind of like this:
protected function processForm(Request $request, MyEntity $entity)
{
$form = $this->createForm(new MyEntityType, $entity);
if ($form->handleRequest($request)->isValid()) {
$alteredEntity = SomeClass:performStuffOnEntity($entity);
if ($form->get('button1')->isClicked()) {
$form = $this->createForm(
new MyEntityType, $alteredEntity
);
}
else if ($form->get('button2')->isClicked()) {
return $this->pdfPreview($alteredEntity);
}
else if ($form->get('button3')->isClicked()) {
return $this->persistAndRedirectToEntity(
$alteredEntity
);
}
}
return $this->render(
'MyBundle:MyEntity:new.html.twig', array(
'form' => $form->createView(),
));
}
There are actually two buttons like button1
; I left one out for brevity of the example.
Ideas:
I have tried to extract this into a
EntityFormWizard
of some sort but this ended up as a cluttered Object with too many dependencies (Router, Templating, Form) which was also a pain to test.Using
FormEvents
I wanted to extract at least the altering of the entity depending on which button was pressed into aFormEventListener
, but the only place where I can alter theEntity
is theFormEvents::PRE_SET_DATA
event, but in there I have problems figuring out which button was clicked.
Do I have to live with my integration test for this behavior or is there a way to extract it and test it with a unit test?