Skip to content

Commit

Permalink
Merge pull request #154 from neos/feature/simple-form-initializer
Browse files Browse the repository at this point in the history
FEATURE: Make formState initialization extendable
  • Loading branch information
daniellienert authored Jun 7, 2022
2 parents 800b0f5 + a659196 commit b88f8d2
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 24 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ jobs:
strategy:
fail-fast: false
matrix:
php-versions: ['7.3', '7.4']
flow-versions: ['7.0']
php-versions: ['7.4', '8.1']
flow-versions: ['7.3']
dependencies: ['highest']

defaults:
Expand Down Expand Up @@ -90,7 +90,7 @@ jobs:
EOF
- name: Run Unit tests
run: |
run: |
bin/phpunit --colors -c Build/BuildEssentials/PhpUnit/UnitTests.xml Packages/Application/${PACKAGE_NAME}/Tests/Unit
- name: Run Functional tests
Expand Down
25 changes: 22 additions & 3 deletions Classes/Core/Model/FormDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
use Neos\Form\Exception;
use Neos\Form\Exception\IdentifierNotValidException;
use Neos\Form\Exception\TypeDefinitionNotFoundException;
use Neos\Form\FormState\DefaultFormStateInitializer;
use Neos\Form\FormState\FormStateInitializerInterface;
use Neos\Form\Utility\Arrays as FormArrays;
use Neos\Form\Utility\SupertypeResolver;
use Neos\Utility\Arrays;
Expand Down Expand Up @@ -318,6 +320,8 @@ class FormDefinition extends Renderable\AbstractCompositeRenderable
*/
protected $finisherPresets;

protected FormStateInitializerInterface $formStateInitializer;

/**
* Constructor. Creates a new FormDefinition with the given identifier.
*
Expand All @@ -329,13 +333,20 @@ class FormDefinition extends Renderable\AbstractCompositeRenderable
*/
public function __construct($identifier, $formDefaults = [], $type = 'Neos.Form:Form')
{
$this->formFieldTypeManager = new SupertypeResolver(isset($formDefaults['formElementTypes']) ? $formDefaults['formElementTypes'] : []);
$this->validatorPresets = isset($formDefaults['validatorPresets']) ? $formDefaults['validatorPresets'] : [];
$this->finisherPresets = isset($formDefaults['finisherPresets']) ? $formDefaults['finisherPresets'] : [];
$this->formFieldTypeManager = new SupertypeResolver($formDefaults['formElementTypes'] ?? []);
$this->validatorPresets = $formDefaults['validatorPresets'] ?? [];
$this->finisherPresets = $formDefaults['finisherPresets'] ?? [];

if (!is_string($identifier) || strlen($identifier) === 0) {
throw new IdentifierNotValidException('The given identifier was not a string or the string was empty.', 1325574803);
}

$formStateInitializerClass = $formDefaults['formStateInitializer'] ?? DefaultFormStateInitializer::class;
if (!is_a($formStateInitializerClass, FormStateInitializerInterface::class, true)) {
throw new \RuntimeException(sprintf('The given class "%s" does not implement the interface %s', $formStateInitializerClass, FormStateInitializerInterface::class), 1648204540);
}
$this->formStateInitializer = new $formStateInitializerClass();

$this->identifier = $identifier;
$this->type = $type;

Expand Down Expand Up @@ -703,4 +714,12 @@ public function getValidatorPresets()
{
return $this->validatorPresets;
}

/**
* @internal
*/
public function getFormStateInitializer(): FormStateInitializerInterface
{
return $this->formStateInitializer;
}
}
18 changes: 1 addition & 17 deletions Classes/Core/Runtime/FormRuntime.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,30 +162,14 @@ public function __construct(FormDefinition $formDefinition, ActionRequest $reque
*/
public function initializeObject()
{
$this->initializeFormStateFromRequest();
$this->formState = $this->formDefinition->getFormStateInitializer()->initializeFormState($this->formDefinition, $this->request);
$this->initializeCurrentPageFromRequest();

if (!$this->isFirstRequest()) {
$this->processSubmittedFormValues();
}
}

/**
* @return void
* @internal
*/
protected function initializeFormStateFromRequest()
{
$serializedFormStateWithHmac = $this->request->getInternalArgument('__state');
if ($serializedFormStateWithHmac === null) {
$this->formState = new FormState();
} else {
$serializedFormState = $this->hashService->validateAndStripHmac($serializedFormStateWithHmac);
/** @noinspection UnserializeExploitsInspection The unserialize call is safe because of the HMAC check above */
$this->formState = unserialize(base64_decode($serializedFormState));
}
}

/**
* @return void
* @internal
Expand Down
41 changes: 41 additions & 0 deletions Classes/FormState/DefaultFormStateInitializer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php
declare(strict_types=1);

namespace Neos\Form\FormState;

/*
* This file is part of the Neos.Form package.
*
* (c) Contributors of the Neos Project - www.neos.io
*
* This package is Open Source Software. For the full copyright and license
* information, please view the LICENSE file which was distributed with this
* source code.
*/

use Neos\Flow\Annotations as Flow;
use Neos\Flow\Mvc\ActionRequest;
use Neos\Flow\Security\Cryptography\HashService;
use Neos\Form\Core\Model\FormDefinition;
use Neos\Form\Core\Runtime\FormState;

class DefaultFormStateInitializer implements FormStateInitializerInterface
{
/**
* @Flow\Inject
* @var HashService
*/
protected $hashService;

public function initializeFormState(FormDefinition $formDefinition, ActionRequest $actionRequest): FormState
{
$serializedFormStateWithHmac = $actionRequest->getInternalArgument('__state');
if ($serializedFormStateWithHmac !== null) {
$serializedFormState = $this->hashService->validateAndStripHmac($serializedFormStateWithHmac);
/** @noinspection UnserializeExploitsInspection The unserialize call is safe because of the HMAC check above */
return unserialize(base64_decode($serializedFormState));
}

return new FormState();
}
}
23 changes: 23 additions & 0 deletions Classes/FormState/FormStateInitializerInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php
declare(strict_types=1);

namespace Neos\Form\FormState;

/*
* This file is part of the Neos.Form package.
*
* (c) Contributors of the Neos Project - www.neos.io
*
* This package is Open Source Software. For the full copyright and license
* information, please view the LICENSE file which was distributed with this
* source code.
*/

use Neos\Flow\Mvc\ActionRequest;
use Neos\Form\Core\Model\FormDefinition;
use Neos\Form\Core\Runtime\FormState;

interface FormStateInitializerInterface
{
public function initializeFormState(FormDefinition $formDefinition, ActionRequest $actionRequest): FormState;
}
1 change: 1 addition & 0 deletions Configuration/Settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Neos:
title: Default
stylesheets: { }
javaScripts: { }
formStateInitializer: Neos\Form\FormState\DefaultFormStateInitializer
formElementTypes:
'Neos.Form:Base':
renderingOptions:
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"license": "MIT",
"description": "Extensible and flexible API for building web forms",
"require": {
"php": ">=7.1.0",
"php": ">=7.4.0",
"neos/flow": ">=6.0 || dev-master"
},
"replace": {
Expand Down

0 comments on commit b88f8d2

Please sign in to comment.