Compare commits

...

85 commits

Author SHA1 Message Date
a0488daa41 update structure of composer.json and update dependencies
All checks were successful
ci/woodpecker/tag/code-style Pipeline was successful
ci/woodpecker/tag/functional-tests/1 Pipeline was successful
ci/woodpecker/tag/functional-tests/2 Pipeline was successful
ci/woodpecker/tag/functional-tests/3 Pipeline was successful
ci/woodpecker/tag/functional-tests/4 Pipeline was successful
2024-10-11 14:30:45 +02:00
230677d289 Merge branch 'release/3.2.0'
All checks were successful
ci/woodpecker/push/code-style Pipeline was successful
ci/woodpecker/push/functional-tests/1 Pipeline was successful
ci/woodpecker/push/functional-tests/2 Pipeline was successful
ci/woodpecker/tag/code-style Pipeline was successful
ci/woodpecker/push/functional-tests/3 Pipeline was successful
ci/woodpecker/push/functional-tests/4 Pipeline was successful
ci/woodpecker/tag/functional-tests/1 Pipeline was successful
ci/woodpecker/tag/functional-tests/2 Pipeline was successful
ci/woodpecker/tag/functional-tests/3 Pipeline was successful
ci/woodpecker/tag/functional-tests/4 Pipeline was successful
2024-09-04 16:05:13 +02:00
ad973f63ed Merge branch 'feature/conditional-validator' into develop
All checks were successful
ci/woodpecker/push/code-style Pipeline was successful
ci/woodpecker/push/functional-tests/2 Pipeline was successful
ci/woodpecker/push/functional-tests/3 Pipeline was successful
ci/woodpecker/push/functional-tests/1 Pipeline was successful
ci/woodpecker/push/functional-tests/4 Pipeline was successful
* feature/conditional-validator:
  add feature comment
  improve tests
  fix handling of validation groups
  add conditional validator to allow more flexible configuration
  rewrite settings validator to support validators on first level ; deprecate "properties" and "self" level
2024-09-04 16:04:29 +02:00
1f5b491d5a add feature comment
All checks were successful
ci/woodpecker/push/code-style Pipeline was successful
ci/woodpecker/push/functional-tests/1 Pipeline was successful
ci/woodpecker/push/functional-tests/2 Pipeline was successful
ci/woodpecker/push/functional-tests/3 Pipeline was successful
ci/woodpecker/push/functional-tests/4 Pipeline was successful
2024-09-04 15:59:15 +02:00
3b64e5b87b improve tests 2024-09-04 15:58:08 +02:00
cf710783d9 fix handling of validation groups 2024-09-04 15:57:55 +02:00
da4f409a8d add conditional validator to allow more flexible configuration
Some checks failed
ci/woodpecker/push/code-style Pipeline was successful
ci/woodpecker/push/functional-tests/1 Pipeline failed
ci/woodpecker/push/functional-tests/2 Pipeline failed
ci/woodpecker/push/functional-tests/3 Pipeline failed
ci/woodpecker/push/functional-tests/4 Pipeline failed
2024-08-30 14:47:28 +02:00
b86110a3b0 rewrite settings validator to support validators on first level ; deprecate "properties" and "self" level 2024-08-30 14:46:49 +02:00
04d1810bb2 Merge tag '3.1.1' into develop
All checks were successful
ci/woodpecker/push/code-style Pipeline was successful
ci/woodpecker/push/functional-tests Pipeline was successful
Tagging 3.1.1
2023-02-19 00:01:04 +01:00
a3209c6976 Merge branch 'release/3.1.1'
All checks were successful
ci/woodpecker/push/code-style Pipeline was successful
ci/woodpecker/push/functional-tests Pipeline was successful
2023-02-19 00:01:00 +01:00
f452efae74 Allow recent flow versions
All checks were successful
ci/woodpecker/push/code-style Pipeline was successful
ci/woodpecker/push/functional-tests Pipeline was successful
2023-02-18 23:55:38 +01:00
a213057567 Merge branch 'version/2.x-dev' into develop
All checks were successful
ci/woodpecker/push/code-style Pipeline was successful
ci/woodpecker/push/test Pipeline was successful
2022-10-27 12:39:50 +02:00
Robin Krahnen
a94e3a3291 Merge branch 'release/3.1.0'
Some checks failed
ci/woodpecker/push/code-style Pipeline failed
ci/woodpecker/push/test Pipeline was successful
2022-05-04 23:41:58 +02:00
Robin Krahnen
09f6aa089b Merge tag '3.1.0' into develop
All checks were successful
ci/woodpecker/push/code-style Pipeline was successful
ci/woodpecker/push/test Pipeline was successful
3.1.0
2022-05-04 23:41:58 +02:00
Robin Krahnen
0e5a09e45a optimized versions in composer.json
All checks were successful
ci/woodpecker/push/code-style Pipeline was successful
ci/woodpecker/push/test Pipeline was successful
2022-05-04 19:01:14 +02:00
Robin Krahnen
0ad084f734 add "declare(strict_types=1);"
All checks were successful
ci/woodpecker/push/code-style Pipeline was successful
ci/woodpecker/push/test Pipeline was successful
2022-05-02 09:56:09 +02:00
7c0c667dd3 Adjusting tests to support only Flow 6.3
Some checks failed
ci/woodpecker/push/code-style Pipeline failed
ci/woodpecker/push/test Pipeline failed
2022-04-30 18:40:25 +02:00
01bb260444 Merge remote-tracking branch 'origin/feature/drone-ci-tests' into feature/drone-ci-tests-develop 2022-04-30 18:38:50 +02:00
6beb9f1997 Merge branch 'feature/drone-ci-tests' into feature/drone-ci-tests-develop 2022-04-29 03:07:45 +02:00
Robin Krahnen
1fd6480cd2 revised code 2022-04-20 17:36:29 +02:00
Robin Krahnen
c09b13c124 optimized code from tests 2022-04-04 22:36:48 +02:00
Robin Krahnen
fb9f31ccee optimized code from code migrations 2022-04-04 22:29:30 +02:00
Robin Krahnen
3087390299 reorder entries in Validation.yaml 2022-03-03 14:25:17 +01:00
Robin Krahnen
d4e095dd54 optimized php requirement 2022-03-03 13:30:50 +01:00
Robin Krahnen
9707c47a1c optimized Package.php 2021-10-06 15:58:48 +02:00
Robin Krahnen
9c4138b4d1 added return type hints for callables 2021-09-23 09:52:07 +02:00
Robin Krahnen
51115825ac add empty line at end of License.txt 2021-09-22 15:00:26 +02:00
Robin Krahnen
26a71d266d update composer.json 2021-09-02 17:50:15 +02:00
Robin Krahnen
c4c3d94fd9 Merge branch 'develop' 2021-04-14 10:57:43 +02:00
Robin Krahnen
ba7e6ce33f code style changes 2021-04-13 08:51:04 +02:00
Robin Krahnen
a1882a2b11 optimized CHANGELOG.md 2021-03-15 19:57:44 +01:00
Robin Krahnen
d03d940f6a optimized CHANGELOG.md 2021-03-15 19:47:22 +01:00
Robin Krahnen
3fab89e54b Merge branch 'develop' 2021-02-17 14:40:53 +01:00
Robin Krahnen
bd7fca349c reorder composer.json 2021-02-17 14:40:35 +01:00
Robin Krahnen
75101c2147 fixed branch alias 2021-02-17 13:56:00 +01:00
Robin Krahnen
f857055059 update required versions 2021-02-17 09:01:00 +01:00
Robin Krahnen
591886bfdf optimized README.md 2021-02-16 12:47:06 +01:00
Robin Krahnen
20cf7bff05 use double quotes in yaml files 2021-02-16 11:19:51 +01:00
Robin Krahnen
9610c2a27e Merge branch 'develop' 2021-01-11 17:07:25 +01:00
Robin Krahnen
b01aa11242 optimized composer.json 2021-01-11 17:00:12 +01:00
Robin Krahnen
e5aed7a587 Merge branch 'develop' 2020-09-09 10:49:33 +02:00
Robin Krahnen
c5e511fecc raise required version of neos/flow to 6.3 2020-09-09 10:47:24 +02:00
Robin Krahnen
eada129ce9 Merge branch 'develop' 2020-08-31 13:50:13 +02:00
Robin Krahnen
3426886a56 Merge branch 'feature/flow_6.x' into develop 2020-08-31 13:44:06 +02:00
Robin Krahnen
849c87ce6f changed date 2020-08-31 13:42:10 +02:00
Robin Krahnen
ba6f572cec added CHANGELOG.md 2020-08-30 21:58:08 +02:00
Robin Krahnen
82a68be97d added empty line at end of composer.json 2020-08-28 14:53:43 +02:00
Robin Krahnen
42cefc7ced added branch aliases 2020-08-28 14:52:30 +02:00
Robin Krahnen
1775021854 TASK: Apply migration Neos.Flow-20190515215000
Adjust "Settings.yaml" to new PSR-3 logging settings (see
https://github.com/neos/flow-development-collection/pull/1574)

Note: This migration did not produce any changes, so the commit simply
marks the migration as applied. This makes sure it will not be applied
again.
2020-08-28 11:22:41 +02:00
Robin Krahnen
5437fb29bd TASK: Apply migration Neos.Flow-20190425144900
Adjusts code to FlashMessageContainer renaming from "\Neos\Flow\Mvc" to
"\Neos\Flow\Mvc\FlashMessage".

Note: This migration did not produce any changes, so the commit simply
marks the migration as applied. This makes sure it will not be applied
again.
2020-08-28 11:22:40 +02:00
Robin Krahnen
5ab1085590 update required version of neos/flow 2020-08-28 11:06:06 +02:00
Robin Krahnen
937e74671c code style 2020-08-19 13:56:55 +02:00
Robin Krahnen
651f5815a4 remove unused import 2020-08-10 13:47:28 +02:00
Robin Krahnen
e311c202bc update to newest standard 2020-07-22 17:22:46 +02:00
Robin Krahnen
efdb8560a1 reorder attributes 2020-05-14 14:47:33 +02:00
Robin Krahnen
8c9790b662 optimized code 2020-05-14 14:43:48 +02:00
Robin Krahnen
0de085c5cf optimized migration 2020-05-14 14:43:25 +02:00
Robin Krahnen
ca1ec5707f added missing @throws 2020-05-14 14:43:09 +02:00
Robin Krahnen
c6e7d549c1 reorder lines 2020-05-13 10:20:20 +02:00
Robin Krahnen
bb8ec70593 added neos package key 2020-05-13 10:19:26 +02:00
Robin Krahnen
8f6fbf9058 use neos/flow ^6.2 and php ~7.4.0 2020-05-13 10:05:30 +02:00
Robin Krahnen
8eea5e9b15 optimize error message 2020-05-13 09:48:43 +02:00
Robin Krahnen
f33647559a optimized condition 2020-05-13 09:47:41 +02:00
Robin Krahnen
a81c1bfe35 update README.md 2020-05-04 23:27:47 +02:00
Robin Krahnen
000c301d25 remove .gitignore 2020-05-04 23:13:06 +02:00
Robin Krahnen
c6e23fdf35 code guideline 2020-05-04 23:07:52 +02:00
Robin Krahnen
272f78f96e optimize code 2020-05-04 23:05:55 +02:00
Robin Krahnen
e4abe5a96c reformat code 2020-05-04 22:26:58 +02:00
Robin Krahnen
72904639a4 reformat code 2020-05-04 22:23:54 +02:00
Robin Krahnen
362b37b6d6 added property types 2020-05-04 22:19:37 +02:00
Robin Krahnen
8d76072227 remove unnecessary reference 2020-05-04 22:10:46 +02:00
Robin Krahnen
e141dbddee replaced static with self 2020-05-04 22:09:37 +02:00
Robin Krahnen
f20c3ba090 added missing visibility to constant 2020-05-04 22:05:16 +02:00
Robin Krahnen
8cc705bd48 remove unnecessary references 2020-05-04 22:04:15 +02:00
Robin Krahnen
743ec61c44 simplify function handleValidationGroups 2020-05-04 22:02:12 +02:00
Robin Krahnen
08e6ad00d4 use existing constant for configuration type 2020-05-04 22:01:48 +02:00
Robin Krahnen
8b0e5640b9 replace use getter instead of directly accessing no longer protected variable 2020-05-04 21:57:03 +02:00
Robin Krahnen
d30ed3310a remove deprecated parts 2020-04-30 08:19:57 +02:00
Robin Krahnen
00f7e385d9 require newer neos/flow 2020-04-29 15:34:23 +02:00
Robin Krahnen
72789243f0 empty line between opening php tag and namespace 2020-03-16 15:44:36 +01:00
Robin Krahnen
c528658f82 optimize code migrations 2020-03-16 15:41:30 +01:00
Robin Krahnen
20e891ac91 removed empty lines between @param and @return/@throws 2020-03-12 14:21:30 +01:00
Robin Krahnen
befaf99d9f removed trailing spaces 2020-03-11 12:09:37 +01:00
Robin Krahnen
e8c94b15a1 replaces tabs with spaces 2020-03-11 12:00:42 +01:00
Robin Krahnen
87544c3976 write strings in yaml files in quotes 2020-03-11 10:39:33 +01:00
18 changed files with 721 additions and 287 deletions

1
.gitignore vendored
View file

@ -1 +0,0 @@
.svn

View file

@ -0,0 +1,32 @@
workspace:
base: /woodpecker
path: package
matrix:
include:
- FLOW_VERSION: 6.3
PHP_VERSION: 7.4
- FLOW_VERSION: 7.3
PHP_VERSION: 7.4
- FLOW_VERSION: 7.3
PHP_VERSION: 8.2
- FLOW_VERSION: 8.2
PHP_VERSION: 8.2
pipeline:
functional-tests:
image: thecodingmachine/php:${PHP_VERSION}-v4-cli
environment:
# Enable the PDO_SQLITE extension
- "PHP_EXTENSION_PDO_SQLITE=1"
- "FLOW_VERSION=${FLOW_VERSION}"
- "NEOS_BUILD_DIR=/woodpecker/Build-${FLOW_VERSION}"
commands:
- "sudo mkdir $NEOS_BUILD_DIR"
- "sudo chown -R docker:docker $NEOS_BUILD_DIR"
- "cd $NEOS_BUILD_DIR"
- "composer create-project --no-install neos/flow-base-distribution:^$FLOW_VERSION ."
- "composer config repositories.repo-name path /woodpecker/package"
- "composer remove --dev --no-update neos/behat || composer remove --no-update neos/behat"
- "composer require digicomp/settingvalidator:@dev"
- "bin/phpunit --configuration Build/BuildEssentials/PhpUnit/FunctionalTests.xml Packages/Application/DigiComp.SettingValidator/Tests/Functional"

View file

@ -1,46 +0,0 @@
workspace:
base: /woodpecker
path: package
matrix:
FLOW_VERSION:
- 4.3
- 5.3
pipeline:
functional-tests:
image: thecodingmachine/php:7.4-v4-cli
environment:
# Enable the PDO_SQLITE extension
- "PHP_EXTENSION_PDO_SQLITE=1"
- "FLOW_VERSION=${FLOW_VERSION}"
- "NEOS_BUILD_DIR=/woodpecker/Build-${FLOW_VERSION}"
commands:
- "sudo mkdir $NEOS_BUILD_DIR"
- "sudo chown -R docker:docker $NEOS_BUILD_DIR"
- "cd $NEOS_BUILD_DIR"
- "if [ \"$FLOW_VERSION\" = \"4.3\" ]; then sudo composer self-update --1; fi"
- "composer create-project --no-install neos/flow-base-distribution:^$FLOW_VERSION ."
- "composer config repositories.repo-name path /woodpecker/package"
- "composer remove --dev neos/behat"
- "if [ \"$FLOW_VERSION\" = \"4.3\" ]; then composer require typo3fluid/fluid:2.4.3; fi"
- "composer require digicomp/settingvalidator:@dev"
- |
if [ "$FLOW_VERSION" = "4.3" ]; then
echo 'Neos:
Flow:
persistence:
backendOptions:
dbname: "flow_functional_testing"
error:
errorHandler:
exceptionalErrors:
0: "%E_USER_ERROR%"
1: "%E_RECOVERABLE_ERROR%"
2: ~
3: "%E_NOTICE%"
4: "%E_USER_WARNING%"
5: "%E_USER_NOTICE%"
6: "%E_STRICT%"' > Configuration/Testing/Settings.yaml
fi
- "bin/phpunit --configuration Build/BuildEssentials/PhpUnit/FunctionalTests.xml Packages/Application/DigiComp.SettingValidator/Tests/Functional"

14
CHANGELOG.md Normal file
View file

@ -0,0 +1,14 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [3.0.1] - 2020-09-09
### Changed
- dependency to Flow ^6.3
## [3.0.0] - 2020-08-31
Start of the changelog.

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace DigiComp\SettingValidator;
/*
@ -14,32 +16,27 @@ namespace DigiComp\SettingValidator;
use Neos\Flow\Configuration\ConfigurationManager;
use Neos\Flow\Core\Bootstrap;
use Neos\Flow\Package\Package as BasePackage;
use Neos\Flow\Package\Package as NeosFlowPackagePackage;
/**
* Package base class of the DigiComp.SettingValidator package.
*/
class Package extends BasePackage
class Package extends NeosFlowPackagePackage
{
const CONFIGURATION_TYPE_VALIDATION = 'Validation';
/**
* @param Bootstrap $bootstrap
* @inheritDoc
*/
public function boot(Bootstrap $bootstrap)
public function boot(Bootstrap $bootstrap): void
{
parent::boot($bootstrap);
$dispatcher = $bootstrap->getSignalSlotDispatcher();
$dispatcher->connect(
ConfigurationManager::class,
'configurationManagerReady',
function (ConfigurationManager $configurationManager) {
$configurationManager->registerConfigurationType(
static::CONFIGURATION_TYPE_VALIDATION,
ConfigurationManager::CONFIGURATION_PROCESSING_TYPE_DEFAULT,
true
);
function (ConfigurationManager $configurationManager): void {
$configurationManager->registerConfigurationType('Validation');
}
);
}

View file

@ -0,0 +1,152 @@
<?php
declare(strict_types=1);
namespace DigiComp\SettingValidator\Validation\Validator;
/*
* This file is part of the DigiComp.SettingValidator package.
*
* (c) digital competence
*
* 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\Eel\EelEvaluatorInterface;
use Neos\Eel\Exception as NeosEelException;
use Neos\Eel\Utility;
use Neos\Flow\Annotations as Flow;
use Neos\Flow\ObjectManagement\DependencyInjection\DependencyProxy;
use Neos\Flow\Validation\Exception\InvalidValidationConfigurationException;
use Neos\Flow\Validation\Exception\NoSuchValidatorException;
use Neos\Flow\Validation\Validator\AbstractValidator;
use Neos\Flow\Validation\ValidatorResolver;
class ConditionalValidator extends AbstractValidator
{
/**
* @Flow\Inject
* @var EelEvaluatorInterface
*/
protected $eelEvaluator;
/**
* @Flow\Inject
* @var ValidatorResolver
*/
protected $validatorResolver;
/**
* @inheritDoc
*/
protected $supportedOptions = [
'conditions' => [[], 'List of entries with "condition" (eel expression) and "validators" (list of validators).', 'array', true],
'fallbackValidators' => [[], 'List of validators that is used if no condition matched.', 'array'],
'validationGroups' => [['Default'], 'Same as "Validation Groups" of Flow Framework', 'array'],
];
/**
* @inheritDoc
* @throws InvalidValidationConfigurationException
* @throws NeosEelException
* @throws NoSuchValidatorException
*/
protected function isValid($value): void
{
$validatorConfigs = [];
$hasMatch = false;
foreach ($this->options['conditions'] as $condition) {
if ($this->eelEvaluator instanceof DependencyProxy) {
$this->eelEvaluator->_activateDependency();
}
if (!Utility::evaluateEelExpression($condition['condition'], $this->eelEvaluator, ['this' => $value])) {
continue;
}
$hasMatch = true;
foreach ($condition['validators'] as $validator => $options) {
if ($options === null) {
continue;
}
$validatorConfigs[] = [
'validator' => $validator,
'options' => $options,
];
}
}
if (!$hasMatch) {
foreach ($this->options['fallbackValidators'] as $validator => $options) {
if ($options === null) {
continue;
}
$validatorConfigs[] = [
'validator' => $validator,
'options' => $options,
];
}
}
foreach ($validatorConfigs as $validatorConfig) {
if (!$this->doesValidationGroupsMatch($validatorConfig)) {
continue;
}
$this->handleValidationGroups($validatorConfig);
$validator = $this->validatorResolver->createValidator(
$validatorConfig['validator'],
$validatorConfig['options']
);
if ($validator === null) {
throw new InvalidValidationConfigurationException(
\sprintf(
'Validator "%s" could not be resolved. Check your Validation.yaml',
$validatorConfig['validator']
),
1402326139
);
}
$this->getResult()->merge($validator->validate($value));
}
}
/**
* Check whether at least one configured group does match, if any is configured.
*
* @param array $validatorConfig
* @return bool
*/
protected function doesValidationGroupsMatch(array $validatorConfig): bool
{
return !isset($validatorConfig['options']['validationGroups'])
|| \array_intersect(
$validatorConfig['options']['validationGroups'],
$this->options['validationGroups']
) !== [];
}
/**
* Add validation groups for recursion if necessary.
*
* @param array $validatorConfig
*/
protected function handleValidationGroups(array &$validatorConfig): void
{
if (\in_array($validatorConfig['validator'], ['DigiComp.SettingValidator:Settings', 'DigiComp.SettingValidator:Conditional', 'DigiComp.SettingValidator:Properties', 'Neos.Flow:Collection'])) {
$validatorConfig['options']['validationGroups'] = $this->options['validationGroups'];
} elseif (isset($validatorConfig['options']['validationGroups'])) {
unset($validatorConfig['options']['validationGroups']);
}
}
}

View file

@ -0,0 +1,119 @@
<?php
declare(strict_types=1);
namespace DigiComp\SettingValidator\Validation\Validator;
/*
* This file is part of the DigiComp.SettingValidator package.
*
* (c) digital competence
*
* 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\Validation\Exception\InvalidValidationConfigurationException;
use Neos\Flow\Validation\Exception\NoSuchValidatorException;
use Neos\Flow\Validation\Validator\AbstractValidator;
use Neos\Flow\Validation\ValidatorResolver;
use Neos\Utility\ObjectAccess;
class PropertiesValidator extends AbstractValidator
{
/**
* @Flow\Inject
* @var ValidatorResolver
*/
protected $validatorResolver;
/**
* @inheritDoc
*/
protected $supportedOptions = [
'validatorsForProperties' => [[], 'List of validators for properties. ', 'array', true],
'validationGroups' => [['Default'], 'Same as "Validation Groups" of Flow Framework', 'array'],
];
/**
* @inheritDoc
* @throws InvalidValidationConfigurationException
* @throws NoSuchValidatorException
*/
protected function isValid($value): void
{
$validatorConfigs = [];
foreach ($this->options['validatorsForProperties'] as $property => $validators) {
foreach ($validators as $validator => $options) {
if ($options === null) {
continue;
}
$validatorConfigs[] = [
'validator' => $validator,
'options' => $options,
'property' => $property,
];
}
}
foreach ($validatorConfigs as $validatorConfig) {
if (!$this->doesValidationGroupsMatch($validatorConfig)) {
continue;
}
$this->handleValidationGroups($validatorConfig);
$validator = $this->validatorResolver->createValidator(
$validatorConfig['validator'],
$validatorConfig['options']
);
if ($validator === null) {
throw new InvalidValidationConfigurationException(
\sprintf(
'Validator "%s" could not be resolved. Check your Validation.yaml',
$validatorConfig['validator']
),
1402326139
);
}
$this->getResult()->forProperty($validatorConfig['property'])->merge(
$validator->validate(ObjectAccess::getPropertyPath($value, $validatorConfig['property']))
);
}
}
/**
* Check whether at least one configured group does match, if any is configured.
*
* @param array $validatorConfig
* @return bool
*/
protected function doesValidationGroupsMatch(array $validatorConfig): bool
{
return !isset($validatorConfig['options']['validationGroups'])
|| \array_intersect(
$validatorConfig['options']['validationGroups'],
$this->options['validationGroups']
) !== [];
}
/**
* Add validation groups for recursion if necessary.
*
* @param array $validatorConfig
*/
protected function handleValidationGroups(array &$validatorConfig): void
{
if (\in_array($validatorConfig['validator'], ['DigiComp.SettingValidator:Settings', 'DigiComp.SettingValidator:Conditional', 'DigiComp.SettingValidator:Properties', 'Neos.Flow:Collection'])) {
$validatorConfig['options']['validationGroups'] = $this->options['validationGroups'];
} elseif (isset($validatorConfig['options']['validationGroups'])) {
unset($validatorConfig['options']['validationGroups']);
}
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace DigiComp\SettingValidator\Validation\Validator;
/*
@ -13,13 +15,11 @@ namespace DigiComp\SettingValidator\Validation\Validator;
*/
use Neos\Flow\Annotations as Flow;
use Neos\Flow\Configuration\ConfigurationManager;
use Neos\Flow\Reflection\ReflectionService;
use Neos\Flow\Validation\Exception\InvalidValidationConfigurationException;
use Neos\Flow\Validation\Exception\InvalidValidationOptionsException;
use Neos\Flow\Validation\Exception\NoSuchValidatorException;
use Neos\Flow\Validation\Validator\AbstractValidator;
use Neos\Flow\Validation\ValidatorResolver;
use Neos\Utility\ObjectAccess;
use Neos\Utility\TypeHandling;
/**
@ -34,66 +34,76 @@ class SettingsValidator extends AbstractValidator
protected $validatorResolver;
/**
* @var ConfigurationManager
*/
protected $configurationManager;
/**
* @Flow\Inject
* @deprecated
* @var ReflectionService
*/
protected $reflectionService;
/**
* @Flow\InjectConfiguration(type="Validation")
* @var array
*/
protected array $validations;
/**
* @inheritDoc
*/
protected $supportedOptions = [
'name' => ['', 'Set the name of the setting-array to use', 'string', false],
'validationGroups' => [
['Default'],
'Same as "Validation Groups" of Flow Framework. Defines the groups to execute.',
'array',
false,
],
'name' => ['', 'Name of the setting array to use', 'string'],
'validationGroups' => [['Default'], 'Same as "Validation Groups" of Flow Framework', 'array'],
];
/**
* @var array
*/
protected $validations;
/**
* @param ConfigurationManager $configurationManager
*/
public function injectConfigurationManager(ConfigurationManager $configurationManager)
{
$this->configurationManager = $configurationManager;
$this->validations = $this->configurationManager->getConfiguration('Validation');
}
/**
* Check if $value is valid. If it is not valid, needs to add an error
* to Result.
*
* @param mixed $value
*
* @inheritDoc
* @throws InvalidValidationOptionsException
* @throws InvalidValidationConfigurationException
* @throws NoSuchValidatorException
*/
protected function isValid($value)
protected function isValid($value): void
{
$name = $this->options['name'] ? $this->options['name'] : TypeHandling::getTypeForValue($value);
if (! isset($this->validations[$name])) {
$validations = $this->validations;
// TODO: feature idea - we could extend the library to automatically be part of the base conjunction validator
$name = $this->options['name'] !== '' ? $this->options['name'] : TypeHandling::getTypeForValue($value);
if (!isset($validations[$name])) {
throw new InvalidValidationOptionsException(
'The name ' . $name . ' has not been defined in Validation.yaml!',
'The name "' . $name . '" has not been defined in Validation.yaml!',
1397821438
);
}
$config = $this->getConfigForName($name);
// @deprecated - converts old "self" to new structure
if (isset($validations[$name]['self'])) {
foreach ($validations[$name]['self'] as $validator => $options) {
if (isset($validations[$name][$validator])) {
throw new \RuntimeException('The validator "' . $validator . '" is already defined on parent level.', 1725000364);
}
$validations[$name][$validator] = $options;
}
foreach ($config as $validatorConfig) {
unset($validations[$name]['self']);
}
// @deprecated - converts old "properties" to new structure
if (isset($validations[$name]['properties'])) {
if (isset($validations[$name]['DigiComp.SettingValidator:Properties'])) {
throw new \RuntimeException('The validator "DigiComp.SettingValidator:Properties" is already defined on parent level.', 1725000396);
}
$validations[$name]['DigiComp.SettingValidator:Properties'] = [
'validatorsForProperties' => $validations[$name]['properties'],
];
unset($validations[$name]['properties']);
}
$validatorConfigs = [];
foreach ($validations[$name] as $validator => $options) {
if ($options === null) {
continue;
}
$validatorConfigs[] = [
'validator' => $validator,
'options' => $options,
];
}
foreach ($validatorConfigs as $validatorConfig) {
if (!$this->doesValidationGroupsMatch($validatorConfig)) {
continue;
}
@ -105,77 +115,33 @@ class SettingsValidator extends AbstractValidator
$validatorConfig['options']
);
if (! $validator) {
if ($validator === null) {
throw new InvalidValidationConfigurationException(
\sprintf(
'Validator could not be resolved: "%s" Check your Validation.yaml',
'Validator "%s" could not be resolved. Check your Validation.yaml',
$validatorConfig['validator']
),
1402326139
);
}
if (isset($validatorConfig['property'])) {
$this->result->forProperty($validatorConfig['property'])->merge(
$validator->validate(ObjectAccess::getPropertyPath($value, $validatorConfig['property']))
);
} else {
$this->result->merge($validator->validate($value));
$this->getResult()->merge($validator->validate($value));
}
}
}
/**
* @param string $name
*
* @return array
*/
protected function getConfigForName($name): array
{
$config = [];
if (isset($this->validations[$name]['self'])) {
foreach ($this->validations[$name]['self'] as $validator => &$validation) {
if ($validation === null) {
continue;
}
$newValidation['options'] = $validation;
$newValidation['validator'] = $validator;
$config[] = $newValidation;
}
}
if (isset($this->validations[$name]['properties'])) {
foreach ($this->validations[$name]['properties'] as $propertyName => &$validation) {
foreach ($validation as $validator => &$options) {
if ($options === null) {
continue;
}
$newValidation['property'] = $propertyName;
$newValidation['validator'] = $validator;
$newValidation['options'] = $options;
$config[] = $newValidation;
}
}
}
return $config;
}
/**
* Check whether at least one configured group does match, if any is configured.
*
* @param array $validatorConfig
*
* @return bool
*/
protected function doesValidationGroupsMatch(array &$validatorConfig)
protected function doesValidationGroupsMatch(array $validatorConfig): bool
{
if (
isset($validatorConfig['options']['validationGroups'])
&& \array_intersect($validatorConfig['options']['validationGroups'], $this->options['validationGroups']) === []
) {
return false;
}
return true;
return !isset($validatorConfig['options']['validationGroups'])
|| \array_intersect(
$validatorConfig['options']['validationGroups'],
$this->options['validationGroups']
) !== [];
}
/**
@ -183,12 +149,12 @@ class SettingsValidator extends AbstractValidator
*
* @param array $validatorConfig
*/
protected function handleValidationGroups(array &$validatorConfig)
protected function handleValidationGroups(array &$validatorConfig): void
{
if (isset($validatorConfig['options']['validationGroups']) && $validatorConfig['validator'] !== 'DigiComp.SettingValidator:Settings') {
unset($validatorConfig['options']['validationGroups']);
} elseif ($validatorConfig['validator'] === 'DigiComp.SettingValidator:Settings') {
if (\in_array($validatorConfig['validator'], ['DigiComp.SettingValidator:Settings', 'DigiComp.SettingValidator:Conditional', 'DigiComp.SettingValidator:Properties', 'Neos.Flow:Collection'])) {
$validatorConfig['options']['validationGroups'] = $this->options['validationGroups'];
} elseif (isset($validatorConfig['options']['validationGroups'])) {
unset($validatorConfig['options']['validationGroups']);
}
}
}

View file

@ -8,20 +8,15 @@ DigiComp\SettingValidator\Tests\Functional\Fixtures\TestObject:
expectedValue: false
Grumble: ~
TrueValidator:
self:
BooleanValue:
expectedValue: true
DigiComp\SettingValidator\Tests\Functional\Fixtures\TestValidationGroupsCustomObject:
self:
DigiComp.SettingValidator:Settings:
name: 'GroupValidatorCustom'
name: "GroupValidatorCustom"
DigiComp\SettingValidator\Tests\Functional\Fixtures\TestValidationGroupsDefaultObject:
self:
DigiComp.SettingValidator:Settings:
name: 'GroupValidatorDefault'
name: "GroupValidatorDefault"
GroupValidatorDefault:
properties:
@ -35,4 +30,9 @@ GroupValidatorCustom:
BooleanValue:
expectedValue: false
validationGroups:
- 'Custom'
- "Custom"
TrueValidator:
self:
BooleanValue:
expectedValue: true

View file

@ -1,37 +1,30 @@
<?php
declare(strict_types=1);
namespace Neos\Flow\Core\Migrations;
/*
* This file is part of the DigiComp.SettingValidator package.
*
* (c) digital competence
*
* 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 DigiComp\SettingValidator\Package;
/**
* Restructures Validation.yamls to new format
* Restructures all Validation.yaml to new format
*/
class Version20170603120900 extends AbstractMigration
{
public function getIdentifier()
/**
* @return string
*/
public function getIdentifier(): string
{
return 'DigiComp.SettingValidator-20170603120900';
}
/**
* @return void
* @inheritDoc
*/
public function up()
public function up(): void
{
$this->processConfiguration(
Package::CONFIGURATION_TYPE_VALIDATION,
function (&$configuration) {
'Validation',
function (array &$configuration): void {
foreach ($configuration as $validatorName => &$validators) {
// guard that protects configuration, which has already the new format:
if (isset($validators['properties']) || isset($validators['self'])) {
@ -39,15 +32,17 @@ class Version20170603120900 extends AbstractMigration
}
$newConfiguration = ['properties' => [], 'self' => []];
foreach ($validators as $key => &$validator) {
foreach ($validators as $key => $validator) {
if (!isset($validator['validator']) || !isset($validator['options'])) {
$this->showWarning('The Validation.yaml files contained no validator or options for ' .
'validation: "' . $validatorName . '.' . $key . '". It was not migrated.');
$this->showWarning(
'The Validation.yaml files contained no validator or options for validation: '
. '"' . $validatorName . '.' . $key . '". It was not migrated.'
);
continue;
}
if (isset($validator['property'])) {
$newConfiguration['properties'][$validator['property']][$validator['validator']]
= $validator['options'];
$newConfiguration['properties'][$validator['property']][$validator['validator']] =
$validator['options'];
} else {
$newConfiguration['self'][$validator['validator']] = $validator['options'];
}

233
README.md
View file

@ -1,46 +1,211 @@
DigiComp.SettingValidator
-------------------------
# DigiComp.SettingValidator
This package allows configuring validators with a new configuration type.
This Package allows to configure Validators for your Action-Arguments or domain model properties to be set by a new
Yaml-File in your Configuration directory.
## Introduction
Lets imagine you had this action-method:
This package provides the `SettingsValidator` which uses the configuration type `Validation` to resolve the validators
that should be applied to the value. It distinguishes between validators that are applied to the value itself and its
properties.
## Resolving the validation configuration
The `SettingsValidator` has an option `name`. If it is set, the name is used to resolve the validation configuration,
otherwise the type of the value is used, which is mainly useful for objects where the FQCN is used.
### Resolving by option `name`
To resolve the validation configuration by name just use the option `name`.
```php
/**
* @param Order $order
* @Flow\Validate(type="DigiComp.SettingValidator:Settings")
* @Flow\Validate(type="DigiComp.SettingValidator:Settings", options={"name"="MyNamedValidator"})
* @var MyObject
*/
public function createOrder($order) {...}
protected MyObject $myObject;
```
Then your Validation.yaml could look like this:
The `SettingsValidator` will search for an entry inside the `Validation.yaml` with that name.
SuperVendor\SuperPackage\Domain\Model\Order:
-
property: price
validator: NumberRange
options:
maximum: 20
minimum: 10
-
validator: SuperVendor.SuperPackage:SomeOtherValidator #validates the complete object
options: []
-
property: customer
validator: DigiComp.SettingValidator:Settings
options:
name: OrderCustomer
```yaml
MyNamedValidator:
...
```
OrderCustomer:
-
property: firstName
validator: StringLength
options:
minimum: 3
maximum: 20
### Resolving by type
To resolve the validation configuration by type just do not set the option `name`.
As you see: Nesting is possible ;) That way you can easily construct flexible structures.
```php
/**
* @Flow\Validate(type="DigiComp.SettingValidator:Settings")
* @var MyObject
*/
protected MyObject $myObject;
```
The SettingsValidator has an optional option: "name" - If you don't give one, it assumes your validation value is an
object and searches in Validation.yaml for the FQCN.
The `SettingsValidator` will search for an entry inside the `Validation.yaml` with the FQCN of `MyObject`.
```yaml
My\Package\Domain\Model\MyObject:
...
```
## The validation configuration
### Difference between `self` and `properties`
`self` contains a map of validators that are applied to the value itself. `properties` contains a map with property
names of the value you would like to validate and each entry contains a map of validators that are applied to that
property.
```yaml
MyNamedValidator:
self:
...
properties:
myProperty1:
...
myProperty2:
...
```
### Configuring a validator
To configure a validator you use the type of the validator as key and the options as entries of that key. If the
validator has no options or all the default values are used, set an empty map as options.
```yaml
MyNamedValidator:
self:
'My.Package:SomeValidator':
myOption: "myOptionValue"
properties:
myProperty1:
'My.Package:SomeOtherValidator': {}
myProperty2:
'My.Package:SomeOtherValidator': {}
```
### Disable a validator
To disable a validator you need to set the options to `null`.
```yaml
MyNamedValidator:
self:
'My.Package:SomeValidator': ~
```
## Using the `SettingsValidator`
The `SettingsValidator` can be used to reduce the number of `@Flow\Validate` annotations and gives you the possibility
of overwriting existing validation configurations in other packages.
### Using on properties
Old PHP code:
```php
/**
* @Flow\Validate(type="My.Package:SomeValidator", options={"myOption"="myOptionValue"})
* @Flow\Validate(type="My.Package:SomeOtherValidator")
* @var MyObject
*/
protected MyObject $myObject;
```
New PHP code:
```php
/**
* @Flow\Validate(type="DigiComp.SettingValidator:Settings", options={"name"="MyNamedValidator"})
* @var MyObject
*/
protected MyObject $myObject;
```
New validation configuration:
```yaml
MyNamedValidator:
self:
'My.Package:SomeValidator':
myOption: "myOptionValue"
'My.Package:SomeOtherValidator': {}
```
### Using on actions
Old PHP code:
```php
/**
* @Flow\Validate(argumentName="myObject", type="My.Package:SomeValidator", options={"myOption"="myOptionValue"})
* @Flow\Validate(argumentName="myObject", type="My.Package:SomeOtherValidator")
* @param MyObject $myObject
*/
public function myAction(MyObject $myObject)
{
...
}
```
New PHP code:
```php
/**
* @Flow\Validate(argumentName="myObject", type="DigiComp.SettingValidator:Settings", options={"name"="MyNamedValidator"})
* @param MyObject $myObject
*/
public function myAction(MyObject $myObject)
{
...
}
```
New validation configuration:
```yaml
MyNamedValidator:
self:
'My.Package:SomeValidator':
myOption: "myOptionValue"
'My.Package:SomeOtherValidator': {}
```
### Using inside validator configurations
You can use the `SettingsValidator` inside the validator configuration to easily construct flexible structures.
```yaml
MyNamedValidator:
properties:
myProperty1:
'DigiComp.SettingValidator:Settings':
name: "MyOtherNamedValidator"
MyOtherNamedValidator:
self:
'My.Package:SomeOtherValidator': {}
```
## Providing an empty validator
It can be useful to provide an empty validator in code that is used by many projects. By doing so you can make sure that
a different validation is possible in any project.
```php
/**
* @Flow\Validate(argumentName="myObject", type="DigiComp.SettingValidator:Settings", options={"name"="MyNamedValidator"})
* @param MyObject $myObject
*/
public function myAction(MyObject $myObject)
{
...
}
```
```yaml
MyNamedValidator: {}
```

View file

@ -1,11 +1,11 @@
type: dictionary
type: "dictionary"
additionalProperties:
type: dictionary
type: "dictionary"
additionalProperties: false
properties:
type: dictionary
type: "dictionary"
additionalProperties: false
properties:
type: dictionary
type: "dictionary"
self:
type: dictionary
type: "dictionary"

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace DigiComp\SettingValidator\Tests\Functional\Fixtures;
use Neos\Flow\Annotations as Flow;
@ -9,18 +11,18 @@ class TestObject
/**
* @var bool
*/
protected $shouldBeTrue = true;
protected bool $shouldBeTrue = true;
/**
* @var bool
*/
protected $shouldBeFalse = true;
protected bool $shouldBeFalse = true;
/**
* @Flow\Validate(type="DigiComp.SettingValidator:Settings", options={"name"="TrueValidator"})
* @var bool
*/
protected $shouldBeTrueAndValidatedByAnnotation = false;
protected bool $shouldBeTrueAndValidatedByAnnotation = false;
/**
* @return bool

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace DigiComp\SettingValidator\Tests\Functional\Fixtures;
class TestValidationGroupsCustomObject
@ -7,12 +9,12 @@ class TestValidationGroupsCustomObject
/**
* @var bool
*/
protected $shouldBeTrue = false;
protected bool $shouldBeTrue = false;
/**
* @var bool
*/
protected $shouldBeFalse = true;
protected bool $shouldBeFalse = true;
/**
* @return bool

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace DigiComp\SettingValidator\Tests\Functional\Fixtures;
class TestValidationGroupsDefaultObject
@ -7,12 +9,12 @@ class TestValidationGroupsDefaultObject
/**
* @var bool
*/
protected $shouldBeTrue = false;
protected bool $shouldBeTrue = false;
/**
* @var bool
*/
protected $shouldBeFalse = true;
protected bool $shouldBeFalse = true;
/**
* @return bool

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace DigiComp\SettingValidator\Tests\Functional;
use DigiComp\SettingValidator\Tests\Functional\Fixtures\TestObject;
@ -7,55 +9,71 @@ use DigiComp\SettingValidator\Tests\Functional\Fixtures\TestValidationGroupsCust
use DigiComp\SettingValidator\Tests\Functional\Fixtures\TestValidationGroupsDefaultObject;
use DigiComp\SettingValidator\Validation\Validator\SettingsValidator;
use Neos\Flow\Tests\FunctionalTestCase;
use Neos\Flow\Validation\Exception\InvalidValidationConfigurationException;
use Neos\Flow\Validation\Exception\InvalidValidationOptionsException;
use Neos\Flow\Validation\Exception\NoSuchValidatorException;
use Neos\Flow\Validation\ValidatorResolver;
class SettingsValidatorTest extends FunctionalTestCase
{
/**
* @test
* @throws InvalidValidationOptionsException
*/
public function ifNoNameIsGivenClassNameIsUsed()
public function ifNoNameIsGivenClassNameIsUsed(): void
{
$validator = $this->objectManager->get(SettingsValidator::class);
$result = $validator->validate(new TestObject());
$this->assertTrue($result->hasErrors());
$this->assertCount(1, $result->getFlattenedErrors());
$this->assertCount(1, $result->forProperty('shouldBeFalse')->getErrors());
$result = $this->objectManager->get(SettingsValidator::class)->validate(new TestObject());
self::assertTrue($result->hasErrors());
self::assertCount(1, $result->getFlattenedErrors());
self::assertCount(1, $result->forProperty('shouldBeFalse')->getErrors());
}
/**
* @test
* @throws InvalidValidationConfigurationException
* @throws InvalidValidationOptionsException
* @throws NoSuchValidatorException
*/
public function conjunctionValidationWorksAsExpected()
public function conjunctionValidationWorksAsExpected(): void
{
$validatorResolver = $this->objectManager->get(ValidatorResolver::class);
$validator = $validatorResolver->getBaseValidatorConjunction(TestObject::class);
$result = $validator->validate(new TestObject());
$this->assertTrue($result->hasErrors());
$this->assertCount(1, $result->getFlattenedErrors());
$result = $this->objectManager
->get(ValidatorResolver::class)
->getBaseValidatorConjunction(TestObject::class)
->validate(new TestObject());
self::assertTrue($result->hasErrors());
self::assertCount(1, $result->getFlattenedErrors());
self::assertCount(1, $result->forProperty('shouldBeTrueAndValidatedByAnnotation')->getErrors());
}
/**
* @test
* @throws InvalidValidationOptionsException
*/
public function defaultValidationGroupWorks()
public function defaultValidationGroupWorks(): void
{
$validator = $this->objectManager->get(SettingsValidator::class, ['validationGroups' => ['Default']]);
$result = $validator->validate(new TestValidationGroupsDefaultObject());
$this->assertTrue($result->hasErrors(), 'No Errors for validation group "Default"');
$this->assertCount(1, $result->getFlattenedErrors(), 'Got a non expected number of errors for group "Default"');
$this->assertCount(1, $result->forProperty('shouldBeTrue')->getErrors(), 'Got no error for property');
$result = $this->objectManager
->get(SettingsValidator::class, ['validationGroups' => ['Default']])
->validate(new TestValidationGroupsDefaultObject());
self::assertTrue($result->hasErrors(), 'No errors for validation group "Default"');
self::assertCount(1, $result->getFlattenedErrors(), 'Got a non expected number of errors for group "Default"');
self::assertCount(1, $result->forProperty('shouldBeTrue')->getErrors(), 'Got no error for property');
}
/**
* @test
* @throws InvalidValidationOptionsException
*/
public function customValidationGroupWorks()
public function customValidationGroupWorks(): void
{
$validator = $this->objectManager->get(SettingsValidator::class, ['validationGroups' => ['Custom']]);
$result = $validator->validate(new TestValidationGroupsCustomObject());
$this->assertTrue($result->hasErrors(), 'No Errors for validation group "Custom"');
$this->assertCount(1, $result->getFlattenedErrors(), 'Got a non expected number of errors for group "Custom"');
$this->assertCount(1, $result->forProperty('shouldBeFalse')->getErrors(), 'Got no error for property');
$result = $this->objectManager
->get(SettingsValidator::class, ['validationGroups' => ['Custom']])
->validate(new TestValidationGroupsCustomObject());
self::assertTrue($result->hasErrors(), 'No errors for validation group "Custom"');
self::assertCount(1, $result->getFlattenedErrors(), 'Got a non expected number of errors for group "Custom"');
self::assertCount(1, $result->forProperty('shouldBeFalse')->getErrors(), 'Got no error for property');
}
}

View file

@ -1,40 +1,55 @@
{
"name": "digicomp/settingvalidator",
"type": "neos-package",
"description": "Just a Neos\\Flow Validator resolving other Validators with Configuration/Validation.yaml",
"authors": [
{
"name": "Ferdinand Kuhl",
"email": "f.kuhl@digital-competence.de",
"homepage": "http://www.digital-competence.de",
"role": "Developer"
}
],
"license": "MIT",
"homepage": "https://github.com/fcool/DigiComp.SettingValidator",
"type": "neos-package",
"keywords": [
"Neos",
"Flow",
"validation"
],
"homepage": "https://github.com/digital-competence/DigiComp.SettingValidator",
"license": "MIT",
"authors": [
{
"name": "Ferdinand Kuhl",
"email": "f.kuhl@digital-competence.de",
"homepage": "https://www.digital-competence.de",
"role": "Developer"
}
],
"require": {
"neos/flow": "~4.1|^5.3"
"php": ">=7.4.0",
"neos/flow": "^6.3.5 || ^7.0 || ^8.0"
},
"require-dev": {
"mikey179/vfsstream": "^1.6.1",
"neos/buildessentials": "^7.0.0",
"phpunit/phpunit": "~8.5",
"vimeo/psalm": "~4.22.0"
},
"autoload": {
"psr-4": {
"DigiComp\\SettingValidator\\": "Classes"
"DigiComp\\SettingValidator\\": "Classes/"
}
},
"autoload-dev": {
"psr-4": {
"DigiComp\\SettingValidator\\Tests\\": "Tests"
"DigiComp\\SettingValidator\\Tests\\": "Tests/"
}
},
"config": {
"sort-packages": true,
"platform-check": true
},
"extra": {
"branch-alias": {
"dev-develop": "2.0.x-dev",
"dev-develop": "3.2.x-dev",
"dev-version/2.x-dev": "2.1.x-dev",
"dev-version/1.x-dev": "1.0.x-dev"
},
"neos": {
"package-key": "DigiComp.SettingValidator"
},
"applied-flow-migrations": [
"Inwebs.Basket-201409170938",
"TYPO3.FLOW3-201201261636",
@ -67,7 +82,9 @@
"Neos.Flow-20170125103800",
"Neos.Flow-20170127183102",
"DigiComp.SettingValidator-20170603120900",
"Neos.Flow-20180415105700"
"Neos.Flow-20180415105700",
"Neos.Flow-20190425144900",
"Neos.Flow-20190515215000"
]
}
}