Skip to content

Commit

Permalink
added PreviousStepInvalidEvent and PreviousStepInvalidEventListener
Browse files Browse the repository at this point in the history
  • Loading branch information
craue committed Aug 1, 2014
1 parent 17c1c05 commit 2d6cbde
Show file tree
Hide file tree
Showing 9 changed files with 172 additions and 42 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
- [#104]: removed options from method `createForm`
- removed the step field template
- renamed property `step` to `stepNumber` and method `getStep` to `getStepNumber` within event classes
- [#98]: add a validation error to the current form if a form of a previous step became invalid
- [#98]+[#143]: add a validation error to the current form if a form of a previous step became invalid
- [#107]: added Czech translation
- [#112]: improved Dutch translation
- [#117]: method `getFormOptions` returns an array for the `validation_groups` option
Expand All @@ -27,6 +27,7 @@
[#126]: https://github.com/craue/CraueFormFlowBundle/issues/126
[#133]: https://github.com/craue/CraueFormFlowBundle/issues/133
[#134]: https://github.com/craue/CraueFormFlowBundle/issues/134
[#143]: https://github.com/craue/CraueFormFlowBundle/issues/143

## 2.1.5 (2014-06-13)

Expand Down
52 changes: 52 additions & 0 deletions Event/PreviousStepInvalidEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

namespace Craue\FormFlowBundle\Event;

use Craue\FormFlowBundle\Form\FormFlowInterface;
use Symfony\Component\Form\FormInterface;

/**
* Is called once if revalidating previous steps failed.
*
* @author Christian Raue <christian.raue@gmail.com>
* @copyright 2011-2014 Christian Raue
* @license http://opensource.org/licenses/mit-license.php MIT License
*/
class PreviousStepInvalidEvent extends FormFlowEvent {

/**
* @var integer
*/
protected $invalidStepNumber;

/**
* @var FormInterface
*/
protected $currentStepForm;

/**
* @param FormFlowInterface $flow
* @param FormInterface $currentStepForm
* @param integer $invalidStepNumber
*/
public function __construct(FormFlowInterface $flow, FormInterface $currentStepForm, $invalidStepNumber) {
$this->flow = $flow;
$this->currentStepForm = $currentStepForm;
$this->invalidStepNumber = $invalidStepNumber;
}

/**
* @return FormInterface
*/
public function getCurrentStepForm() {
return $this->currentStepForm;
}

/**
* @return integer
*/
public function getInvalidStepNumber() {
return $this->invalidStepNumber;
}

}
48 changes: 48 additions & 0 deletions EventListener/PreviousStepInvalidEventListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

namespace Craue\FormFlowBundle\EventListener;

use Craue\FormFlowBundle\Event\PreviousStepInvalidEvent;
use Symfony\Component\Form\FormError;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Translation\TranslatorInterface;

/**
* Adds a validation error to the current step's form if revalidating previous steps failed.
*
* @author Christian Raue <christian.raue@gmail.com>
* @copyright 2011-2014 Christian Raue
* @license http://opensource.org/licenses/mit-license.php MIT License
*/
class PreviousStepInvalidEventListener {

/**
* @var TranslatorInterface
*/
protected $translator;

public function setTranslator(TranslatorInterface $translator) {
$this->translator = $translator;
}

public function onPreviousStepInvalid(PreviousStepInvalidEvent $event) {
$event->getCurrentStepForm()->addError($this->getPreviousStepInvalidFormError($event->getInvalidStepNumber()));
}

/**
* @param integer $stepNumber
* @return FormError
*/
protected function getPreviousStepInvalidFormError($stepNumber) {
$messageId = 'craueFormFlow.previousStepInvalid';
$messageParameters = array('%stepNumber%' => $stepNumber);

if (version_compare(Kernel::VERSION, '2.2', '>=')) {
return new FormError($this->translator->trans($messageId, $messageParameters, 'validators'));
}

// TODO remove as soon as Symfony >= 2.2 is required
return new FormError($messageId, $messageParameters);
}

}
36 changes: 5 additions & 31 deletions Form/FormFlow.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,15 @@
use Craue\FormFlowBundle\Event\PostBindSavedDataEvent;
use Craue\FormFlowBundle\Event\PostValidateEvent;
use Craue\FormFlowBundle\Event\PreBindEvent;
use Craue\FormFlowBundle\Event\PreviousStepInvalidEvent;
use Craue\FormFlowBundle\Exception\InvalidTypeException;
use Craue\FormFlowBundle\Storage\StorageInterface;
use Craue\FormFlowBundle\Util\StringUtil;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Translation\TranslatorInterface;

/**
* @author Christian Raue <christian.raue@gmail.com>
Expand Down Expand Up @@ -46,11 +45,6 @@ abstract class FormFlow implements FormFlowInterface {
*/
protected $eventDispatcher = null;

/**
* @var TranslatorInterface
*/
protected $translator;

/**
* @var string
*/
Expand Down Expand Up @@ -199,13 +193,6 @@ public function setEventDispatcher(EventDispatcherInterface $eventDispatcher) {
$this->eventDispatcher = $eventDispatcher;
}

/**
* {@inheritDoc}
*/
public function setTranslator(TranslatorInterface $translator) {
$this->translator = $translator;
}

public function setId($id) {
$this->id = $id;
}
Expand Down Expand Up @@ -801,7 +788,10 @@ public function isValid(FormInterface $form) {
}

if (!$stepForm->isValid()) {
$form->addError($this->getPreviousStepInvalidFormError($stepNumber));
if ($this->hasListeners(FormFlowEvents::PREVIOUS_STEP_INVALID)) {
$event = new PreviousStepInvalidEvent($this, $form, $stepNumber);
$this->eventDispatcher->dispatch(FormFlowEvents::PREVIOUS_STEP_INVALID, $event);
}

return false;
}
Expand Down Expand Up @@ -876,22 +866,6 @@ protected function hasListeners($eventName) {
return $this->eventDispatcher !== null && $this->eventDispatcher->hasListeners($eventName);
}

/**
* @param integer $stepNumber
* @return FormError
*/
protected function getPreviousStepInvalidFormError($stepNumber) {
$messageId = 'craueFormFlow.previousStepInvalid';
$messageParameters = array('%stepNumber%' => $stepNumber);

if (version_compare(Kernel::VERSION, '2.2', '>=')) {
return new FormError($this->translator->trans($messageId, $messageParameters, 'validators'));
}

// TODO remove as soon as Symfony >= 2.2 is required
return new FormError($messageId, $messageParameters);
}

// methods for BC with third-party templates (e.g. MopaBootstrapBundle)

public function getCurrentStep() {
Expand Down
2 changes: 2 additions & 0 deletions Form/FormFlowEvents.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class FormFlowEvents {

const POST_BIND_REQUEST = 'flow.post_bind_request';

const PREVIOUS_STEP_INVALID = 'flow.previous_step_invalid';

const POST_VALIDATE = 'flow.post_validate';

}
6 changes: 0 additions & 6 deletions Form/FormFlowInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Translation\TranslatorInterface;

/**
* @author Christian Raue <christian.raue@gmail.com>
Expand Down Expand Up @@ -47,11 +46,6 @@ function getStorage();
*/
function setEventDispatcher(EventDispatcherInterface $eventDispatcher);

/**
* @param TranslatorInterface $translator
*/
function setTranslator(TranslatorInterface $translator);

/**
* @return boolean
*/
Expand Down
10 changes: 7 additions & 3 deletions Resources/config/form_flow.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@
<call method="setEventDispatcher">
<argument type="service" id="event_dispatcher" on-invalid="ignore" />
</call>
<call method="setTranslator">
<argument type="service" id="translator" />
</call>
</service>

<service id="craue.form.flow.form_extension" class="Craue\FormFlowBundle\Form\Extension\FormFlowFormExtension">
Expand All @@ -46,5 +43,12 @@
<service id="craue.form.flow.hidden_field_extension" class="Craue\FormFlowBundle\Form\Extension\FormFlowHiddenFieldExtension">
<tag name="form.type_extension" alias="hidden" />
</service>

<service id="craue.form.flow.event_listener.previous_step_invalid" class="Craue\FormFlowBundle\EventListener\PreviousStepInvalidEventListener">
<tag name="kernel.event_listener" event="flow.previous_step_invalid" method="onPreviousStepInvalid" />
<call method="setTranslator">
<argument type="service" id="translator" />
</call>
</service>
</services>
</container>
45 changes: 44 additions & 1 deletion Tests/IntegrationTestBundle/Form/RevalidatePreviousStepsFlow.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@

namespace Craue\FormFlowBundle\Tests\IntegrationTestBundle\Form;

use Craue\FormFlowBundle\Event\PreviousStepInvalidEvent;
use Craue\FormFlowBundle\Form\FormFlow;
use Craue\FormFlowBundle\Form\FormFlowEvents;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
* @author Christian Raue <christian.raue@gmail.com>
* @copyright 2011-2014 Christian Raue
* @license http://opensource.org/licenses/mit-license.php MIT License
*/
class RevalidatePreviousStepsFlow extends FormFlow {
class RevalidatePreviousStepsFlow extends FormFlow implements EventSubscriberInterface {

/**
* {@inheritDoc}
Expand All @@ -18,6 +22,23 @@ public function getName() {
return 'revalidatePreviousSteps';
}

/**
* {@inheritDoc}
*/
public function setEventDispatcher(EventDispatcherInterface $dispatcher) {
parent::setEventDispatcher($dispatcher);
$dispatcher->addSubscriber($this);
}

/**
* {@inheritDoc}
*/
public static function getSubscribedEvents() {
return array(
FormFlowEvents::PREVIOUS_STEP_INVALID => 'onPreviousStepInvalid',
);
}

/**
* {@inheritDoc}
*/
Expand All @@ -35,4 +56,26 @@ protected function loadStepsConfig() {
);
}

/**
* {@inheritDoc}
*/
public function bind($formData) {
$this->storage->set($this->getCalledEventsSessionKey(), array());
parent::bind($formData);
}

public function getCalledEventsSessionKey() {
return $this->getId() . '_debug_events_called';
}

protected function logEventCall($name) {
$calledEvents = $this->storage->get($this->getCalledEventsSessionKey());
$calledEvents[] = $name;
$this->storage->set($this->getCalledEventsSessionKey(), $calledEvents);
}

public function onPreviousStepInvalid(PreviousStepInvalidEvent $event) {
$this->logEventCall('onPreviousStepInvalid #' . $event->getInvalidStepNumber());
}

}
12 changes: 12 additions & 0 deletions Tests/RevalidatePreviousStepsFlowTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public function testRevalidatePreviousSteps_enabled() {
$crawler = $this->client->submit($form);
$this->assertCurrentStepNumber(2, $crawler);
$this->assertContainsFormError('The form for step 1 is invalid. Please go back and try to submit it again.', $crawler);
$this->assertEquals(array('onPreviousStepInvalid #1'), $this->getCalledEvents());

// back -> step 1
$form = $crawler->selectButton('back')->form();
Expand Down Expand Up @@ -68,4 +69,15 @@ public function testRevalidatePreviousSteps_disabled() {
// die;
}

protected function getCalledEvents() {
$container = static::$kernel->getContainer();
$container->enterScope('request');
$container->set('request', $this->client->getRequest(), 'request');

$flow = $container->get('integrationTestBundle.form.flow.revalidatePreviousSteps');
$storage = $container->get('craue.form.flow.storage');

return $storage->get($flow->getCalledEventsSessionKey());
}

}

0 comments on commit 2d6cbde

Please sign in to comment.