Skip to content
This repository has been archived by the owner on Mar 1, 2023. It is now read-only.

Commit

Permalink
[FEATURE] Skip step/substep
Browse files Browse the repository at this point in the history
  • Loading branch information
romm committed Jun 26, 2019
1 parent c05a563 commit a944ff7
Show file tree
Hide file tree
Showing 9 changed files with 281 additions and 3 deletions.
2 changes: 1 addition & 1 deletion Classes/AssetHandler/Css/SubstepCssAssetHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ protected function aze(Substeps $substeps)
$substepIdentifier = $substep->getIdentifier();

$cssBlocks[] = <<<CSS
form[name="$formName"]:not([fz-substep="$substepIdentifier"]) div[fz-substep="$substepIdentifier"] {
form[name="$formName"]:not([fz-substep="$substepIdentifier"]) [fz-substep="$substepIdentifier"] {
display: none;
}
CSS;
Expand Down
19 changes: 18 additions & 1 deletion Classes/Exceptions/ContextNotFoundException.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
use Romm\Formz\ViewHelpers\Slot\HasViewHelper;
use Romm\Formz\ViewHelpers\Slot\RenderViewHelper;
use Romm\Formz\ViewHelpers\SlotViewHelper;
use Romm\Formz\ViewHelpers\SubstepViewHelper;
use Romm\Formz\ViewHelpers\Step\SkipViewHelper;
use Romm\Formz\ViewHelpers\Step\SubstepViewHelper;

class ContextNotFoundException extends FormzException
{
Expand Down Expand Up @@ -61,6 +62,22 @@ final public static function substepViewHelperFormContextNotFound()
return $exception;
}

/**
* @code 1561020379
*
* @return self
*/
final public static function skipViewHelperFormContextNotFound()
{
/** @var self $exception */
$exception = self::getNewExceptionInstance(
self::FORM_CONTEXT_NOT_FOUND,
[SkipViewHelper::class, FormViewHelper::class]
);

return $exception;
}

/**
* @code 1465243287
*
Expand Down
14 changes: 14 additions & 0 deletions Classes/Form/Definition/Middleware/PresetMiddlewares.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use Romm\Formz\Middleware\Item\FormValidation\FormValidationMiddleware;
use Romm\Formz\Middleware\Item\Persistence\PersistenceFetchingMiddleware;
use Romm\Formz\Middleware\Item\Step\PreviousStepMiddleware;
use Romm\Formz\Middleware\Item\Step\SkipMiddleware;
use Romm\Formz\Middleware\Item\Step\StepDispatchingMiddleware;
use Romm\Formz\Middleware\Item\Step\StepFetchingMiddleware;
use Romm\Formz\Middleware\Item\Step\SubstepFetchingMiddleware;
Expand Down Expand Up @@ -70,6 +71,11 @@ class PresetMiddlewares implements DataPreProcessorInterface
*/
protected $fieldFocusMiddleware;

/**
* @var \Romm\Formz\Middleware\Item\Step\SkipMiddleware
*/
protected $skipMiddleware;

/**
* Returns the full list of preset middlewares.
*
Expand Down Expand Up @@ -161,4 +167,12 @@ public function getFieldFocusMiddleware()
{
return $this->fieldFocusMiddleware;
}

/**
* @return SkipMiddleware
*/
public function getSkipMiddleware()
{
return $this->skipMiddleware;
}
}
4 changes: 4 additions & 0 deletions Classes/Middleware/Item/Begin/BeginMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use Romm\Formz\Middleware\Item\Begin\Service\FormService;
use Romm\Formz\Middleware\Processor\MiddlewareProcessor;
use Romm\Formz\Middleware\Signal\After;
use Romm\Formz\Middleware\Signal\Before;
use Romm\Formz\Middleware\Signal\SignalObject;
use Romm\Formz\ViewHelpers\Step\PreviousLinkViewHelper;
use TYPO3\CMS\Extbase\Service\ExtensionService;
Expand All @@ -42,6 +43,9 @@ public function initialize()
{
$this->formService = Core::instantiate(FormService::class, $this->processor->getRequest(), $this->processor->getRequestArguments());

$signalObject = new SignalObject($this->processor, BeginSignal::class, Before::class);
$signalObject->dispatch();

$this->checkFormSubmission();
$this->fetchCurrentStep();
$this->fetchSubstepsLevel();
Expand Down
77 changes: 77 additions & 0 deletions Classes/Middleware/Item/Step/SkipMiddleware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php
declare(strict_types=1);

namespace Romm\Formz\Middleware\Item\Step;

use Romm\Formz\Middleware\Argument\Arguments;
use Romm\Formz\Middleware\Item\AbstractMiddleware;
use Romm\Formz\Middleware\Item\Begin\BeginSignal;
use Romm\Formz\Middleware\Signal\Before;
use TYPO3\CMS\Core\Utility\GeneralUtility;

class SkipMiddleware extends AbstractMiddleware implements Before, BeginSignal
{
/**
* @param Arguments $arguments
*/
public function before(Arguments $arguments)
{
$request = $this->getRequest();

if (!$request->hasArgument('skip')
|| !$request->getArgument('skip')
) {
return;
}

$formName = $this->getFormObject()->getName();

if (!$request->hasArgument($formName)) {
return;
}

if (!$request->hasArgument('step')) {
return;
}

$step = $request->getArgument('step');
$definition = $this->getFormObject()->getDefinition();

if (!$definition->hasSteps()
|| !$definition->getSteps()->hasEntry($step)
) {
return;
}

$currentStep = $definition->getSteps()->getEntry($step);

/** @var array $formArray */
$formArray = $request->getArgument($formName);

$skipSubsteps = [];

if ($request->hasArgument('skipSubsteps')) {
$skipSubsteps = GeneralUtility::trimExplode(',', $request->getArgument('skipSubsteps'));
}

if (empty($skipSubsteps)) {
foreach ($currentStep->getSupportedFields() as $field) {
unset($formArray[$field->getField()->getName()]);
}
} elseif ($currentStep->hasSubsteps()) {
$substeps = $currentStep->getSubsteps();

foreach ($skipSubsteps as $substep) {
if (!$substeps->hasEntry($substep)) {
continue;
}

foreach ($substeps->getEntry($substep)->getSupportedFields() as $field) {
unset($formArray[$field->getField()->getName()]);
}
}
}

$request->setArgument($formName, $formArray);
}
}
6 changes: 5 additions & 1 deletion Classes/Middleware/Processor/MiddlewareProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,14 @@ public function run()
/** @var BeginMiddleware $beginMiddleware */
$beginMiddleware = Core::instantiate(BeginMiddleware::class);
$beginMiddleware->bindMiddlewareProcessor($this);
$beginMiddleware->initialize();

foreach ($this->formObject->getDefinition()->getAllMiddlewares() as $middleware) {
$middleware->bindMiddlewareProcessor($this);
}

$beginMiddleware->initialize();

foreach ($this->formObject->getDefinition()->getAllMiddlewares() as $middleware) {
$middleware->initialize();
}

Expand Down
5 changes: 5 additions & 0 deletions Classes/ViewHelpers/FormViewHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,8 @@ public function initializeArguments()
*/
protected function renderViewHelper()
{
$this->viewHelperVariableContainer->add(self::class, 'arguments', $this->arguments);

if (false === $this->typoScriptIncluded) {
return (ExtensionService::get()->isInDebugMode())
? ContextService::get()->translate('form.typoscript_not_included.error_message')
Expand Down Expand Up @@ -342,8 +344,11 @@ protected function renderHiddenReferrerFields()
->getLevel();

$result .= '<input type="hidden" fz-substeps-level="1" name="' . $this->prefixFieldName('substepsLevel') . '" value="' . $substepsLevel . '" />' . LF;
$result .= '<input type="hidden" fz-skip="1" name="' . $this->prefixFieldName('skip') . '" />' . LF;
$result .= '<input type="hidden" fz-substeps-skip="1" name="' . $this->prefixFieldName('skipSubsteps') . '" />' . LF;
}

$result .= '<input type="hidden" name="' . $this->prefixFieldName('step') . '" value="' . $currentStep->getIdentifier() . '" />' . LF;
$result .= '<input type="hidden" fz-substeps-previous="1" name="' . $this->prefixFieldName(PreviousLinkViewHelper::PREVIOUS_LINK_PARAMETER) . '" disabled="1" value="1" />' . LF;
$result .= '<input type="submit" style="position: absolute; left: -9999px" />' . LF;
}
Expand Down
143 changes: 143 additions & 0 deletions Classes/ViewHelpers/Step/SkipViewHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
<?php
/*
* 2017 Romain CANON <romain.hydrocanon@gmail.com>
*
* This file is part of the TYPO3 FormZ project.
* It is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License, either
* version 3 of the License, or any later version.
*
* For the full copyright and license information, see:
* http://www.gnu.org/licenses/gpl-3.0.html
*/

namespace Romm\Formz\ViewHelpers\Step;

use Exception;
use Romm\Formz\Exceptions\ContextNotFoundException;
use Romm\Formz\Form\Definition\Step\Step\Step;
use Romm\Formz\Service\ViewHelper\Form\FormViewHelperService;
use Romm\Formz\ViewHelpers\FormViewHelper;
use TYPO3\CMS\Extbase\Mvc\Web\Request;
use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder;
use TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper;

class SkipViewHelper extends AbstractFormFieldViewHelper
{
/**
* @var string
*/
protected $tagName = 'input';

/**
* @var FormViewHelperService
*/
protected $formService;

/**
* @inheritDoc
*/
public function initializeArguments()
{
parent::initializeArguments();

$this->registerUniversalTagAttributes();

$this->registerArgument('substep', 'string', 'Identifier of the optional substep to be skipped.');
}

/**
* @return string
*/
public function render(): string
{
/*
* First, we check if this view helper is called from within the
* `FormViewHelper`, because it would not make sense anywhere else.
*/
if (false === $this->formService->formContextExists()) {
throw ContextNotFoundException::skipViewHelperFormContextNotFound();
}

$formObject = $this->formService->getFormObject();
$formDefinition = $formObject->getDefinition();

if (false === $formDefinition->hasSteps()) {
throw new Exception('No stop for this form.');
}

/** @var Request $request */
$request = $this->controllerContext->getRequest();
$currentStep = $formObject->fetchCurrentStep($request)->getCurrentStep();

if ($substep = $this->arguments['substep'] ?? null) {
if (false === $currentStep->hasSubsteps()) {
throw new Exception('No substeps for this form.');
}

$substeps = $currentStep->getSubsteps();

if (false === $substeps->hasEntry($substep)) {
throw new Exception("No substep `$substep` for this form.");
}

$this->tag->addAttribute('fz-substep', $substep);
}

$this->tag->addAttribute('type', 'submit');
$this->tag->addAttribute('value', $this->getValueAttribute());
$this->tag->addAttribute('formaction', $this->formAction($currentStep));

return $this->tag->render();
}

private function formAction(Step $step): string
{
$formArguments = $this->viewHelperVariableContainer->get(FormViewHelper::class, 'arguments');

$pageUid = (int)$formArguments['pageUid'] > 0 ? (int)$formArguments['pageUid'] : null;

/** @var UriBuilder $uriBuilder */
$uriBuilder = $this->renderingContext->getControllerContext()->getUriBuilder();

$arguments = (array)$formArguments['arguments'];

$arguments['skip'] = true;
$arguments['step'] = $step->getIdentifier();

$substep = $this->arguments['substep'] ?? null;

if ($substep) {
$arguments['skipSubsteps'] = $substep;
}

return $uriBuilder
->reset()
->setTargetPageUid($pageUid)
->setTargetPageType($formArguments['pageType'])
->setNoCache($formArguments['noCache'])
->setUseCacheHash(!$formArguments['noCacheHash'])
->setSection($formArguments['section'])
->setCreateAbsoluteUri($formArguments['absolute'])
->setArguments((array)$formArguments['additionalParams'])
->setAddQueryString($formArguments['addQueryString'])
->setAddQueryStringMethod($formArguments['addQueryStringMethod'])
->setArgumentsToBeExcludedFromQueryString((array)$formArguments['argumentsToBeExcludedFromQueryString'])
->setFormat($formArguments['format'])
->uriFor(
$formArguments['action'],
$arguments,
$formArguments['controller'],
$formArguments['extensionName'],
$formArguments['pluginName']
);
}

/**
* @param FormViewHelperService $service
*/
public function injectFormService(FormViewHelperService $service)
{
$this->formService = $service;
}
}
14 changes: 14 additions & 0 deletions Resources/Public/JavaScript/Form/Formz.Form.SubmissionService.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ Fz.Form.SubmissionService = (function () {
*/
var onSubmitCallBacks = [];

/**
* @type {Array<function>}
*/
var onSubmitBeginCallBacks = [];

/**
* Callback function called when the form was submitted. The submission
* is cancelled and a check is done on every field to know if the
Expand Down Expand Up @@ -137,6 +142,10 @@ Fz.Form.SubmissionService = (function () {
endProcess();
};

for (var i = 0; i < onSubmitBeginCallBacks.length; i++) {
onSubmitBeginCallBacks[i]();
}

var fields = form.getFields();
for (var fieldName in fields) {
if (fields.hasOwnProperty(fieldName)) {
Expand Down Expand Up @@ -277,6 +286,11 @@ Fz.Form.SubmissionService = (function () {
onSubmitCallBacks.push(callback);
}
},
onSubmitBegin: function (callback) {
if (typeof callback === 'function') {
onSubmitBeginCallBacks.push(callback);
}
},
submit: function() {
Fz.Form.get(formName, function(form) {
handleFormSubmission(form);
Expand Down

0 comments on commit a944ff7

Please sign in to comment.