diff --git a/Classes/Middleware/Item/Begin/BeginMiddleware.php b/Classes/Middleware/Item/Begin/BeginMiddleware.php index 80f7034..83c0e55 100644 --- a/Classes/Middleware/Item/Begin/BeginMiddleware.php +++ b/Classes/Middleware/Item/Begin/BeginMiddleware.php @@ -20,6 +20,7 @@ use Romm\Formz\Middleware\Processor\MiddlewareProcessor; use Romm\Formz\Middleware\Signal\After; use Romm\Formz\Middleware\Signal\SignalObject; +use Romm\Formz\ViewHelpers\Step\PreviousLinkViewHelper; final class BeginMiddleware implements BasicMiddlewareInterface { @@ -89,8 +90,10 @@ protected function checkFormSubmission() $formzData = $request->getArgument('formzData'); $formObject->getRequestData()->fillFromHash($formzData); - $proxy = FormObjectFactory::get()->getProxy($form); - $proxy->markFormAsSubmitted(); + if (!$request->hasArgument(PreviousLinkViewHelper::PREVIOUS_LINK_PARAMETER)) { + $proxy = FormObjectFactory::get()->getProxy($form); + $proxy->markFormAsSubmitted(); + } $this->injectFormHashInProxy(); } diff --git a/Classes/Middleware/Item/Field/Focus/FieldFocusMiddleware.php b/Classes/Middleware/Item/Field/Focus/FieldFocusMiddleware.php index eab1038..5d7e2e3 100644 --- a/Classes/Middleware/Item/Field/Focus/FieldFocusMiddleware.php +++ b/Classes/Middleware/Item/Field/Focus/FieldFocusMiddleware.php @@ -18,6 +18,7 @@ use Romm\Formz\Form\Definition\Step\Step\Substep\SubstepDefinition; use Romm\Formz\Form\FormObject\FormObjectFactory; use Romm\Formz\Middleware\Item\OnBeginMiddleware; +use Romm\Formz\Middleware\Item\Step\Service\StepMiddlewareService; use Romm\Formz\Middleware\Processor\PresetMiddlewareInterface; /** @@ -37,6 +38,19 @@ class FieldFocusMiddleware extends OnBeginMiddleware implements PresetMiddleware */ protected $field; + /** + * @var StepMiddlewareService + */ + protected $service; + + /** + * Inject the step service. + */ + public function initializeMiddleware() + { + $this->service = StepMiddlewareService::get(); + } + /** * @todo */ @@ -62,8 +76,7 @@ protected function process() return; } - $firstSubstepDefinition = $this->step->getSubsteps()->getFirstSubstepDefinition(); - $substepDefinition = $this->fetchFieldSubstep($firstSubstepDefinition); + $substepDefinition = $this->fetchFieldSubstep(); if ($substepDefinition) { $stepService = FormObjectFactory::get()->getStepService($this->getFormObject()); @@ -72,20 +85,16 @@ protected function process() } /** - * @param SubstepDefinition $substepDefinition * @return SubstepDefinition|null */ - protected function fetchFieldSubstep(SubstepDefinition $substepDefinition) + protected function fetchFieldSubstep() { - if ($substepDefinition->getSubstep()->supportsField($this->field)) { - return $substepDefinition; - } - - if ($substepDefinition->hasNextSubstep()) { - return $this->fetchFieldSubstep($substepDefinition->getNextSubstep()); - } - - return null; + return $this->service->findSubstepDefinition( + $this->step, + function (SubstepDefinition $substepDefinition) { + return $substepDefinition->getSubstep()->supportsField($this->field); + } + ); } protected function fetchField() diff --git a/Classes/Middleware/Item/Step/PreviousStepMiddleware.php b/Classes/Middleware/Item/Step/PreviousStepMiddleware.php index 95b90c2..a6cf434 100644 --- a/Classes/Middleware/Item/Step/PreviousStepMiddleware.php +++ b/Classes/Middleware/Item/Step/PreviousStepMiddleware.php @@ -13,24 +13,26 @@ namespace Romm\Formz\Middleware\Item\Step; +use Romm\Formz\Form\FormObject\FormObjectFactory; use Romm\Formz\Middleware\Argument\Arguments; use Romm\Formz\Middleware\Item\AbstractMiddleware; -use Romm\Formz\Middleware\Item\FormValidation\FormValidationSignal; +use Romm\Formz\Middleware\Item\FormInjection\FormInjectionSignal; use Romm\Formz\Middleware\Item\Step\Service\StepMiddlewareService; +use Romm\Formz\Middleware\Processor\PresetMiddlewareInterface; use Romm\Formz\Middleware\Scope\FieldValidationScope; use Romm\Formz\Middleware\Scope\ReadScope; -use Romm\Formz\Middleware\Signal\Before; +use Romm\Formz\Middleware\Signal\After; use Romm\Formz\ViewHelpers\Step\PreviousLinkViewHelper; /** * @todo */ -class PreviousStepMiddleware extends AbstractMiddleware implements Before, FormValidationSignal +class PreviousStepMiddleware extends AbstractMiddleware implements After, FormInjectionSignal, PresetMiddlewareInterface { /** * @var int */ - protected $priority = self::PRIORITY_STEP + 100; + protected $priority = self::PRIORITY_STEP_FETCHING + 100; /** * @var StepMiddlewareService @@ -51,11 +53,11 @@ public function initializeMiddleware() } /** - * @see StepFetchingMiddleware + * @see PreviousStepMiddleware * * @param Arguments $arguments */ - public function before(Arguments $arguments) + public function after(Arguments $arguments) { $formObject = $this->getFormObject(); $this->service->reset($formObject, $this->getRequest()); @@ -73,6 +75,39 @@ public function before(Arguments $arguments) if ($currentStep) { $stepDefinition = $this->service->getStepDefinition($currentStep); + if ($currentStep->hasSubsteps()) { + $stepService = FormObjectFactory::get()->getStepService($this->getFormObject()); + $substepsLevel = $stepService->getSubstepsLevel(); + + if ($substepsLevel > 1) { + $substepDefinition = $currentStep->getSubsteps()->getFirstSubstepDefinition(); + + while ($substepDefinition) { + $nextSubstepDefinition = $this->service->getNextSubstepDefinition($substepDefinition); + + if (!$nextSubstepDefinition + || $nextSubstepDefinition->getLevel() >= $substepsLevel - 1 + ) { + break; + } + + $substepDefinition = $nextSubstepDefinition; + } + + $stepService->setCurrentSubstepDefinition($substepDefinition); + $stepService->setCurrentStep($currentStep); + $stepService->setSubstepsLevel($substepDefinition->getLevel()); +// \TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($substepDefinition, __CLASS__ . ':' . __LINE__ . ' $substepDefinition'); +// \TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($substepDefinition->getLevel(), __CLASS__ . ':' . __LINE__ . ' $substepDefinition->getLevel()'); +// \TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($currentStep, __CLASS__ . ':' . __LINE__ . ' $currentStep'); +// \TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($stepService, __CLASS__ . ':' . __LINE__ . ' $stepService'); +// die(); + + return; + } + } + + if ($stepDefinition->hasPreviousDefinition()) { $this->service->redirectToStep($stepDefinition->getPreviousDefinition()->getStep(), $this->redirect()); } diff --git a/Classes/Middleware/Item/Step/Service/StepMiddlewareService.php b/Classes/Middleware/Item/Step/Service/StepMiddlewareService.php index 96e1962..e4d6816 100644 --- a/Classes/Middleware/Item/Step/Service/StepMiddlewareService.php +++ b/Classes/Middleware/Item/Step/Service/StepMiddlewareService.php @@ -18,6 +18,7 @@ use Romm\Formz\Error\FormResult; use Romm\Formz\Form\Definition\Step\Step\Step; use Romm\Formz\Form\Definition\Step\Step\StepDefinition; +use Romm\Formz\Form\Definition\Step\Step\Substep\SubstepDefinition; use Romm\Formz\Form\FormObject\FormObject; use Romm\Formz\Form\FormObject\FormObjectFactory; use Romm\Formz\Form\FormObject\Service\Step\FormStepPersistence; @@ -91,7 +92,7 @@ public function getNextStep(Step $currentStep) $nextStep = null; if ($currentStepDefinition->hasNextStep()) { - $nextStep = $this->getNextStepDefinition($currentStepDefinition, true); + $nextStep = $this->getNextStepDefinition($currentStepDefinition); } return $nextStep; @@ -178,10 +179,9 @@ public function getFirstInvalidStep(Step $step) /** * @param StepDefinition $step - * @param bool $removeConditionalSteps * @return StepDefinition */ - public function getNextStepDefinition(StepDefinition $step, $removeConditionalSteps = false) + public function getNextStepDefinition(StepDefinition $step) { $nextStep = null; @@ -204,7 +204,7 @@ public function getNextStepDefinition(StepDefinition $step, $removeConditionalSt if (true === $this->getStepDefinitionConditionResult($step)) { $nextStep = $step; break; - } elseif (true === $removeConditionalSteps) { + } else { $this->persistence->removeStep($step); } } else { @@ -217,6 +217,60 @@ public function getNextStepDefinition(StepDefinition $step, $removeConditionalSt return $nextStep; } + public function getNextSubstepDefinition(SubstepDefinition $substepDefinition) + { + $nextSubstep = null; + + if ($substepDefinition->hasDivergence()) { + $divergenceSteps = $substepDefinition->getDivergenceSubsteps(); + + foreach ($divergenceSteps as $divergenceStep) { + if (true === $this->getSubstepDefinitionConditionResult($divergenceStep)) { + $nextSubstep = $divergenceStep; + break; + } + } + } + + if (null === $nextSubstep) { + while ($substepDefinition->hasNextSubstep()) { + $substepDefinition = $substepDefinition->getNextSubstep(); + + if ($substepDefinition->hasActivation()) { + if (true === $this->getSubstepDefinitionConditionResult($substepDefinition)) { + $nextSubstep = $substepDefinition; + break; + } + } else { + $nextSubstep = $substepDefinition; + break; + } + } + } + + return $nextSubstep; + } + + public function findSubstepDefinition(Step $step, callable $callback) + { + return $this->findSubstepDefinitionRecursive($step->getSubsteps()->getFirstSubstepDefinition(), $callback); + } + + protected function findSubstepDefinitionRecursive(SubstepDefinition $substepDefinition, callable $callback) + { + $result = $callback($substepDefinition); + + if (true === $result) { + return $substepDefinition; + } + + $substepDefinition = $this->getNextSubstepDefinition($substepDefinition); + + return $substepDefinition + ? $this->findSubstepDefinitionRecursive($substepDefinition, $callback) + : null; + } + /** * @param StepDefinition $stepDefinition * @param Redirect $redirect @@ -261,6 +315,20 @@ public function getStepDefinitionConditionResult(StepDefinition $stepDefinition) return $tree->getPhpResult($dataObject); } + /** + * @param SubstepDefinition $substepDefinition + * @return bool + */ + public function getSubstepDefinitionConditionResult(SubstepDefinition $substepDefinition) + { + $conditionProcessor = ConditionProcessorFactory::getInstance()->get($this->getFormObject()); + $tree = $conditionProcessor->getActivationConditionTreeForSubstep($substepDefinition); + $todo = new FormValidatorExecutor(new FormValidatorDataObject($this->getFormObject(), new FormResult(), true)); // @todo + $dataObject = new PhpConditionDataObject($this->getFormObject()->getForm(), $todo); + + return $tree->getPhpResult($dataObject); + } + /** * @param Step $step * @return StepDefinition|null diff --git a/Classes/Middleware/Item/Step/StepDispatchingMiddleware.php b/Classes/Middleware/Item/Step/StepDispatchingMiddleware.php index 66161ac..8fedf34 100644 --- a/Classes/Middleware/Item/Step/StepDispatchingMiddleware.php +++ b/Classes/Middleware/Item/Step/StepDispatchingMiddleware.php @@ -31,7 +31,7 @@ class StepDispatchingMiddleware extends DefaultMiddleware implements PresetMiddl /** * @var int */ - protected $priority = self::PRIORITY_STEP; + protected $priority = self::PRIORITY_STEP_DISPATCHING; /** * @var StepMiddlewareService diff --git a/Classes/Middleware/Item/Step/StepFetchingMiddleware.php b/Classes/Middleware/Item/Step/StepFetchingMiddleware.php index 6c29955..54e87c0 100644 --- a/Classes/Middleware/Item/Step/StepFetchingMiddleware.php +++ b/Classes/Middleware/Item/Step/StepFetchingMiddleware.php @@ -16,11 +16,12 @@ use Romm\Formz\Form\Definition\Step\Step\StepDefinition; use Romm\Formz\Middleware\Argument\Arguments; use Romm\Formz\Middleware\Item\AbstractMiddleware; -use Romm\Formz\Middleware\Item\FormValidation\FormValidationSignal; +use Romm\Formz\Middleware\Item\FormInjection\FormInjectionSignal; use Romm\Formz\Middleware\Item\Step\Service\StepMiddlewareService; +use Romm\Formz\Middleware\Processor\PresetMiddlewareInterface; use Romm\Formz\Middleware\Scope\FieldValidationScope; use Romm\Formz\Middleware\Scope\ReadScope; -use Romm\Formz\Middleware\Signal\Before; +use Romm\Formz\Middleware\Signal\After; /** * This middleware will fetch the current step in the form, based on the request @@ -30,12 +31,12 @@ * on all previous steps is done to determine the first valid step: the request * is then redirected to this step. */ -class StepFetchingMiddleware extends AbstractMiddleware implements Before, FormValidationSignal +class StepFetchingMiddleware extends AbstractMiddleware implements After, FormInjectionSignal, PresetMiddlewareInterface { /** * @var int */ - protected $priority = self::PRIORITY_STEP; + protected $priority = self::PRIORITY_STEP_FETCHING; /** * @var StepMiddlewareService @@ -60,7 +61,7 @@ public function initializeMiddleware() * * @param Arguments $arguments */ - public function before(Arguments $arguments) + public function after(Arguments $arguments) { $formObject = $this->getFormObject(); diff --git a/Classes/Middleware/MiddlewareInterface.php b/Classes/Middleware/MiddlewareInterface.php index 6dd5e06..cc55e1d 100644 --- a/Classes/Middleware/MiddlewareInterface.php +++ b/Classes/Middleware/MiddlewareInterface.php @@ -21,7 +21,8 @@ interface MiddlewareInterface extends BasicMiddlewareInterface { const PRIORITY_INJECT_FORM = 1000; const PRIORITY_BEHAVIOURS = 100; - const PRIORITY_STEP = -1000000; + const PRIORITY_STEP_FETCHING = 1000000; + const PRIORITY_STEP_DISPATCHING = -1000000; /** * @param OptionInterface $options diff --git a/Classes/ViewHelpers/FormViewHelper.php b/Classes/ViewHelpers/FormViewHelper.php index d41be4d..45e12db 100644 --- a/Classes/ViewHelpers/FormViewHelper.php +++ b/Classes/ViewHelpers/FormViewHelper.php @@ -30,6 +30,7 @@ use Romm\Formz\Service\StringService; use Romm\Formz\Service\TimeTrackerService; use Romm\Formz\Service\ViewHelper\Form\FormViewHelperService; +use Romm\Formz\ViewHelpers\Step\PreviousLinkViewHelper; use TYPO3\CMS\Core\Page\PageRenderer; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Error\Result; @@ -296,6 +297,7 @@ protected function renderHiddenReferrerFields() ->getLevel(); $result .= '' . LF; + $result .= '' . LF; } } diff --git a/Classes/ViewHelpers/Step/PreviousLinkViewHelper.php b/Classes/ViewHelpers/Step/PreviousLinkViewHelper.php index e6ce37c..aa8e648 100644 --- a/Classes/ViewHelpers/Step/PreviousLinkViewHelper.php +++ b/Classes/ViewHelpers/Step/PreviousLinkViewHelper.php @@ -13,20 +13,19 @@ namespace Romm\Formz\ViewHelpers\Step; -use Romm\Formz\Form\FormObject\FormObjectFactory; use Romm\Formz\Middleware\Item\Step\Service\StepMiddlewareService; use Romm\Formz\Service\ViewHelper\Form\FormViewHelperService; use TYPO3\CMS\Extbase\Mvc\Web\Request; -use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractTagBasedViewHelper; +use TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper; -class PreviousLinkViewHelper extends AbstractTagBasedViewHelper +class PreviousLinkViewHelper extends AbstractFormFieldViewHelper { - const PREVIOUS_LINK_PARAMETER = 'fz-previous-step'; + const PREVIOUS_LINK_PARAMETER = 'substepsPrevious'; /** * @var string */ - protected $tagName = 'a'; + protected $tagName = 'input'; /** * @var FormViewHelperService @@ -69,17 +68,22 @@ public function render() return null; } - $stepService = FormObjectFactory::get()->getStepService($formObject); - $level = $stepService->getSubstepsLevel(); +// $stepService = FormObjectFactory::get()->getStepService($formObject); +// $level = $stepService->getSubstepsLevel(); - $uriBuilder = $this->controllerContext->getUriBuilder(); - $uri = $uriBuilder - ->reset() - ->uriFor(null, [self::PREVIOUS_LINK_PARAMETER => $level]); +// $uriBuilder = $this->controllerContext->getUriBuilder(); +// $uri = $uriBuilder +// ->reset() +// ->uriFor(null, [self::PREVIOUS_LINK_PARAMETER => $level]); - $this->tag->addAttribute('href', $uri); - $this->tag->setContent($this->renderChildren()); - $this->tag->forceClosingTag(true); + $this->tag->addAttribute('type', 'submit'); + $this->tag->addAttribute('value', $this->getValueAttribute()); + $this->tag->addAttribute('name', $this->prefixFieldName(PreviousLinkViewHelper::PREVIOUS_LINK_PARAMETER)); + +// $this->tag->addAttribute('href', $uri); + $this->tag->addAttribute('fz-previous-link', true); +// $this->tag->setContent($this->renderChildren()); +// $this->tag->forceClosingTag(true); return $this->tag->render(); }