-
Notifications
You must be signed in to change notification settings - Fork 118
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #98 from craue/revalidate-previous-steps
add a validation error to the current form if a form of a previous step became invalid
- Loading branch information
Showing
20 changed files
with
288 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,10 +12,12 @@ | |
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 <[email protected]> | ||
|
@@ -44,11 +46,21 @@ abstract class FormFlow implements FormFlowInterface { | |
*/ | ||
protected $eventDispatcher = null; | ||
|
||
/** | ||
* @var TranslatorInterface | ||
*/ | ||
protected $translator; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
protected $transition; | ||
|
||
/** | ||
* @var boolean | ||
*/ | ||
protected $revalidatePreviousSteps = true; | ||
|
||
/** | ||
* @var boolean | ||
*/ | ||
|
@@ -129,6 +141,11 @@ abstract class FormFlow implements FormFlowInterface { | |
*/ | ||
private $currentStepNumber = null; | ||
|
||
/** | ||
* @var FormInterface[] | ||
*/ | ||
private $stepForms = array(); | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
|
@@ -176,6 +193,13 @@ public function setEventDispatcher(EventDispatcherInterface $eventDispatcher) { | |
$this->eventDispatcher = $eventDispatcher; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function setTranslator(TranslatorInterface $translator) { | ||
$this->translator = $translator; | ||
} | ||
|
||
public function setId($id) { | ||
$this->id = $id; | ||
} | ||
|
@@ -296,6 +320,17 @@ public function getCurrentStepNumber() { | |
return $this->currentStepNumber; | ||
} | ||
|
||
public function setRevalidatePreviousSteps($revalidatePreviousSteps) { | ||
$this->revalidatePreviousSteps = (boolean) $revalidatePreviousSteps; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function isRevalidatePreviousSteps() { | ||
return $this->revalidatePreviousSteps; | ||
} | ||
|
||
public function setAllowDynamicStepNavigation($allowDynamicStepNavigation) { | ||
$this->allowDynamicStepNavigation = (boolean) $allowDynamicStepNavigation; | ||
} | ||
|
@@ -597,12 +632,23 @@ public function invalidateStepData($fromStepNumber) { | |
protected function applyDataFromSavedSteps() { | ||
$stepData = $this->retrieveStepData(); | ||
|
||
$this->stepForms = array(); | ||
|
||
$options = array(); | ||
if (!$this->revalidatePreviousSteps) { | ||
$options['validation_groups'] = array(); // disable validation | ||
} | ||
|
||
foreach ($this->getSteps() as $step) { | ||
$stepNumber = $step->getNumber(); | ||
|
||
if (array_key_exists($stepNumber, $stepData)) { | ||
$stepForm = $this->createFormForStep($stepNumber); | ||
$stepForm->bind($stepData[$stepNumber]); | ||
$stepForm = $this->createFormForStep($stepNumber, $options); | ||
$stepForm->bind($stepData[$stepNumber]); // the form is validated here | ||
|
||
if ($this->revalidatePreviousSteps) { | ||
$this->stepForms[$stepNumber] = $stepForm; | ||
} | ||
|
||
if ($this->hasListeners(FormFlowEvents::POST_BIND_SAVED_DATA)) { | ||
$event = new PostBindSavedDataEvent($this, $this->formData, $stepNumber); | ||
|
@@ -722,6 +768,27 @@ public function isValid(FormInterface $form) { | |
$this->eventDispatcher->dispatch(FormFlowEvents::POST_BIND_REQUEST, $event); | ||
} | ||
|
||
if ($this->revalidatePreviousSteps) { | ||
// check if forms of previous steps are still valid | ||
foreach ($this->stepForms as $stepNumber => $stepForm) { | ||
// ignore form of the current step | ||
if ($this->currentStepNumber === $stepNumber) { | ||
break; | ||
} | ||
|
||
// ignore forms of skipped steps | ||
if ($this->isStepSkipped($stepNumber)) { | ||
break; | ||
} | ||
|
||
if (!$stepForm->isValid()) { | ||
$form->addError($this->getPreviousStepInvalidFormError($stepNumber)); | ||
|
||
return false; | ||
} | ||
} | ||
} | ||
|
||
if ($form->isValid()) { | ||
if ($this->hasListeners(FormFlowEvents::POST_VALIDATE)) { | ||
$event = new PostValidateEvent($this, $form->getData()); | ||
|
@@ -790,6 +857,23 @@ 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', '>=')) { | ||
$message = $this->translator->trans($messageId, $messageParameters, 'validators'); | ||
return new FormError($message, $messageId, $messageParameters); | ||
} | ||
|
||
// 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() { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
use Symfony\Component\Form\FormFactoryInterface; | ||
use Symfony\Component\Form\FormInterface; | ||
use Symfony\Component\HttpFoundation\Request; | ||
use Symfony\Component\Translation\TranslatorInterface; | ||
|
||
/** | ||
* @author Christian Raue <[email protected]> | ||
|
@@ -46,6 +47,16 @@ function getStorage(); | |
*/ | ||
function setEventDispatcher(EventDispatcherInterface $eventDispatcher); | ||
|
||
/** | ||
* @param TranslatorInterface $translator | ||
*/ | ||
function setTranslator(TranslatorInterface $translator); | ||
|
||
/** | ||
* @return boolean | ||
*/ | ||
function isRevalidatePreviousSteps(); | ||
|
||
/** | ||
* @return boolean | ||
*/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
craueFormFlow.previousStepInvalid: Das Formular für Schritt %stepNumber% ist ungültig. Gehen Sie bitte zurück und versuchen das Formular erneut zu senden. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
craueFormFlow.previousStepInvalid: The form for step %stepNumber% is invalid. Please go back and try to submit it again. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
craueFormFlow.previousStepInvalid: El formulario del paso %stepNumber% está inválido. Por favor, utilice el botón de atrás y pruebe de enviar el formulario de nuevo. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
craueFormFlow.previousStepInvalid: Le formulaire pour l'étape %stepNumber% est invalide. Veuillez retourner et essayez de le renvoyer. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
craueFormFlow.previousStepInvalid: Het formulier voor stap %stepNumber% is ongeldig. Ga terug en probeer het opnieuw te versturen. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
craueFormFlow.previousStepInvalid: Formularz dla kroku %stepNumber% został wypełniony nieprawidłowo. Proszę cofnąć się i wypełnić go ponownie. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
craueFormFlow.previousStepInvalid: Форма для шага %stepNumber% имеет недопустимое значение. Пожалуйста, вернитесь назад и попробуйте повторить отправку. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
craueFormFlow.previousStepInvalid: Форма для кроку %stepNumber% є недопустимою. Будь ласка, поверніться та спробуйте повторно відправити форму. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
craueFormFlow.previousStepInvalid: 步驟%stepNumber%的表格無效,請回到上一個步驟並重新提交。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
Tests/IntegrationTestBundle/Entity/RevalidatePreviousStepsData.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<?php | ||
|
||
namespace Craue\FormFlowBundle\Tests\IntegrationTestBundle\Entity; | ||
|
||
use Symfony\Component\Validator\Constraints as Assert; | ||
use Symfony\Component\Validator\ExecutionContext; | ||
|
||
/** | ||
* @author Christian Raue <[email protected]> | ||
* @copyright 2011-2013 Christian Raue | ||
* @license http://opensource.org/licenses/mit-license.php MIT License | ||
* | ||
* @Assert\Callback(methods={"isDataValid"}, groups={"flow_revalidatePreviousSteps_step1"}) | ||
*/ | ||
class RevalidatePreviousStepsData { | ||
|
||
private static $validationCalls; | ||
|
||
public static function resetValidationCalls() { | ||
self::$validationCalls = 0; | ||
} | ||
|
||
// TODO replace with ExecutionContextInterface as soon as Symfony >= 2.2 is required | ||
public function isDataValid(ExecutionContext $context) { | ||
// valid only on first call | ||
if (++self::$validationCalls > 1) { | ||
$context->addViolation('Take this!'); | ||
} | ||
} | ||
|
||
} |
38 changes: 38 additions & 0 deletions
38
Tests/IntegrationTestBundle/Form/RevalidatePreviousStepsFlow.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
<?php | ||
|
||
namespace Craue\FormFlowBundle\Tests\IntegrationTestBundle\Form; | ||
|
||
use Craue\FormFlowBundle\Form\FormFlow; | ||
|
||
/** | ||
* @author Christian Raue <[email protected]> | ||
* @copyright 2011-2013 Christian Raue | ||
* @license http://opensource.org/licenses/mit-license.php MIT License | ||
*/ | ||
class RevalidatePreviousStepsFlow extends FormFlow { | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function getName() { | ||
return 'revalidatePreviousSteps'; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
protected function loadStepsConfig() { | ||
return array( | ||
array( | ||
'label' => 'step1', | ||
), | ||
array( | ||
'label' => 'step2', | ||
), | ||
array( | ||
'label' => 'step3', | ||
), | ||
); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
Tests/IntegrationTestBundle/Resources/views/FormFlow/revalidatePreviousSteps.html.twig
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{% extends 'IntegrationTestBundle::layout_flow.html.twig' %} |
Oops, something went wrong.