Compare commits

..

No commits in common. "master" and "3.0.0" have entirely different histories.

17 changed files with 139 additions and 655 deletions

View file

@ -1,8 +0,0 @@
pipeline:
code-style:
image: composer
commands:
- composer global config repositories.repo-name vcs https://git.digital-competence.de/Packages/php-codesniffer
- composer global config --no-plugins allow-plugins.dealerdirect/phpcodesniffer-composer-installer true
- composer global require digicomp/php-codesniffer:@dev
- composer global exec -- phpcs --runtime-set ignore_warnings_on_exit 1 --standard=DigiComp Classes/ Migrations/ Tests/ Resources/Private/

View file

@ -1,32 +0,0 @@
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

@ -4,11 +4,6 @@ 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/), 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). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased] ## 3.0.0 - 2020-08-31
## [3.0.1] - 2020-09-09
### Changed
- dependency to Flow ^6.3
## [3.0.0] - 2020-08-31
Start of the changelog. Start of the changelog.

View file

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace DigiComp\SettingValidator; namespace DigiComp\SettingValidator;
/* /*
@ -24,18 +22,17 @@ use Neos\Flow\Package\Package as NeosFlowPackagePackage;
class Package extends NeosFlowPackagePackage class Package extends NeosFlowPackagePackage
{ {
/** /**
* @inheritDoc * @param Bootstrap $bootstrap
*/ */
public function boot(Bootstrap $bootstrap): void public function boot(Bootstrap $bootstrap): void
{ {
parent::boot($bootstrap); parent::boot($bootstrap);
$dispatcher = $bootstrap->getSignalSlotDispatcher(); $dispatcher = $bootstrap->getSignalSlotDispatcher();
$dispatcher->connect( $dispatcher->connect(
ConfigurationManager::class, ConfigurationManager::class,
'configurationManagerReady', 'configurationManagerReady',
function (ConfigurationManager $configurationManager): void { function (ConfigurationManager $configurationManager) {
$configurationManager->registerConfigurationType('Validation'); $configurationManager->registerConfigurationType('Validation');
} }
); );

View file

@ -1,152 +0,0 @@
<?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

@ -1,119 +0,0 @@
<?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,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace DigiComp\SettingValidator\Validation\Validator; namespace DigiComp\SettingValidator\Validation\Validator;
/* /*
@ -20,6 +18,7 @@ use Neos\Flow\Validation\Exception\InvalidValidationOptionsException;
use Neos\Flow\Validation\Exception\NoSuchValidatorException; use Neos\Flow\Validation\Exception\NoSuchValidatorException;
use Neos\Flow\Validation\Validator\AbstractValidator; use Neos\Flow\Validation\Validator\AbstractValidator;
use Neos\Flow\Validation\ValidatorResolver; use Neos\Flow\Validation\ValidatorResolver;
use Neos\Utility\ObjectAccess;
use Neos\Utility\TypeHandling; use Neos\Utility\TypeHandling;
/** /**
@ -57,7 +56,6 @@ class SettingsValidator extends AbstractValidator
{ {
$validations = $this->validations; $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); $name = $this->options['name'] !== '' ? $this->options['name'] : TypeHandling::getTypeForValue($value);
if (!isset($validations[$name])) { if (!isset($validations[$name])) {
throw new InvalidValidationOptionsException( throw new InvalidValidationOptionsException(
@ -66,44 +64,7 @@ class SettingsValidator extends AbstractValidator
); );
} }
// @deprecated - converts old "self" to new structure foreach ($this->getConfigForValidation($validations[$name]) as $validatorConfig) {
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;
}
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)) { if (!$this->doesValidationGroupsMatch($validatorConfig)) {
continue; continue;
} }
@ -125,10 +86,54 @@ class SettingsValidator extends AbstractValidator
); );
} }
$this->getResult()->merge($validator->validate($value)); if (isset($validatorConfig['property'])) {
$this->getResult()->forProperty($validatorConfig['property'])->merge(
$validator->validate(ObjectAccess::getPropertyPath($value, $validatorConfig['property']))
);
} else {
$this->getResult()->merge($validator->validate($value));
}
} }
} }
/**
* @param array $validation
* @return array
*/
protected function getConfigForValidation(array $validation): array
{
$config = [];
if (isset($validation['self'])) {
foreach ($validation['self'] as $validator => $options) {
if ($options === null) {
continue;
}
$config[] = [
'validator' => $validator,
'options' => $options,
];
}
}
if (isset($validation['properties'])) {
foreach ($validation['properties'] as $property => $propertyValidation) {
foreach ($propertyValidation as $validator => $options) {
if ($options === null) {
continue;
}
$config[] = [
'property' => $property,
'validator' => $validator,
'options' => $options,
];
}
}
}
return $config;
}
/** /**
* Check whether at least one configured group does match, if any is configured. * Check whether at least one configured group does match, if any is configured.
* *
@ -151,7 +156,7 @@ class SettingsValidator extends AbstractValidator
*/ */
protected function handleValidationGroups(array &$validatorConfig): void protected function handleValidationGroups(array &$validatorConfig): void
{ {
if (\in_array($validatorConfig['validator'], ['DigiComp.SettingValidator:Settings', 'DigiComp.SettingValidator:Conditional', 'DigiComp.SettingValidator:Properties', 'Neos.Flow:Collection'])) { if ($validatorConfig['validator'] === 'DigiComp.SettingValidator:Settings') {
$validatorConfig['options']['validationGroups'] = $this->options['validationGroups']; $validatorConfig['options']['validationGroups'] = $this->options['validationGroups'];
} elseif (isset($validatorConfig['options']['validationGroups'])) { } elseif (isset($validatorConfig['options']['validationGroups'])) {
unset($validatorConfig['options']['validationGroups']); unset($validatorConfig['options']['validationGroups']);

View file

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

View file

@ -16,4 +16,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.

View file

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Neos\Flow\Core\Migrations; namespace Neos\Flow\Core\Migrations;
/** /**
@ -17,14 +15,11 @@ class Version20170603120900 extends AbstractMigration
return 'DigiComp.SettingValidator-20170603120900'; return 'DigiComp.SettingValidator-20170603120900';
} }
/**
* @inheritDoc
*/
public function up(): void public function up(): void
{ {
$this->processConfiguration( $this->processConfiguration(
'Validation', 'Validation',
function (array &$configuration): void { function (array &$configuration) {
foreach ($configuration as $validatorName => &$validators) { foreach ($configuration as $validatorName => &$validators) {
// guard that protects configuration, which has already the new format: // guard that protects configuration, which has already the new format:
if (isset($validators['properties']) || isset($validators['self'])) { if (isset($validators['properties']) || isset($validators['self'])) {
@ -35,14 +30,14 @@ class Version20170603120900 extends AbstractMigration
foreach ($validators as $key => $validator) { foreach ($validators as $key => $validator) {
if (!isset($validator['validator']) || !isset($validator['options'])) { if (!isset($validator['validator']) || !isset($validator['options'])) {
$this->showWarning( $this->showWarning(
'The Validation.yaml files contained no validator or options for validation: ' 'The Validation.yaml files contained no validator or options for validation: ' .
. '"' . $validatorName . '.' . $key . '". It was not migrated.' '"' . $validatorName . '.' . $key . '". It was not migrated.'
); );
continue; continue;
} }
if (isset($validator['property'])) { if (isset($validator['property'])) {
$newConfiguration['properties'][$validator['property']][$validator['validator']] = $newConfiguration['properties'][$validator['property']][$validator['validator']]
$validator['options']; = $validator['options'];
} else { } else {
$newConfiguration['self'][$validator['validator']] = $validator['options']; $newConfiguration['self'][$validator['validator']] = $validator['options'];
} }

233
README.md
View file

@ -1,211 +1,40 @@
# DigiComp.SettingValidator # DigiComp.SettingValidator
This package allows configuring validators with a new configuration type. This Package allows configuring Validators for your Action-Arguments or domain model properties to be set by a new
Yaml-File in your Configuration directory.
## Introduction Let's 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 * @Flow\Validate(argumentName="order", type="DigiComp.SettingValidator:Settings")
properties. * @param Order $order
*/
public function createOrder($order) {...}
## Resolving the validation configuration Then your Validation.yaml could look like this:
The `SettingsValidator` has an option `name`. If it is set, the name is used to resolve the validation configuration, Vendor\Package\Domain\Model\Order:
otherwise the type of the value is used, which is mainly useful for objects where the FQCN is used. # validates the complete object
self:
'Vendor.Package:SomeOtherValidator': []
# validates properties of the object
properties:
price:
NumberRange:
maximum: 20
minimum: 10
customer:
'DigiComp.SettingValidator:Settings':
name: 'OrderCustomer'
### Resolving by option `name` OrderCustomer:
properties:
firstName:
StringLength:
minimum: 3
maximum: 20
To resolve the validation configuration by name just use the option `name`. As you see: Nesting is possible ;) That way you can easily construct flexible structures.
```php 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.
* @Flow\Validate(type="DigiComp.SettingValidator:Settings", options={"name"="MyNamedValidator"})
* @var MyObject
*/
protected MyObject $myObject;
```
The `SettingsValidator` will search for an entry inside the `Validation.yaml` with that name.
```yaml
MyNamedValidator:
...
```
### Resolving by type
To resolve the validation configuration by type just do not set the option `name`.
```php
/**
* @Flow\Validate(type="DigiComp.SettingValidator:Settings")
* @var MyObject
*/
protected MyObject $myObject;
```
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: additionalProperties:
type: "dictionary" type: 'dictionary'
additionalProperties: false additionalProperties: false
properties: properties:
type: "dictionary" type: 'dictionary'
additionalProperties: false additionalProperties: false
properties: properties:
type: "dictionary" type: 'dictionary'
self: self:
type: "dictionary" type: 'dictionary'

View file

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace DigiComp\SettingValidator\Tests\Functional\Fixtures; namespace DigiComp\SettingValidator\Tests\Functional\Fixtures;
use Neos\Flow\Annotations as Flow; use Neos\Flow\Annotations as Flow;

View file

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace DigiComp\SettingValidator\Tests\Functional\Fixtures; namespace DigiComp\SettingValidator\Tests\Functional\Fixtures;
class TestValidationGroupsCustomObject class TestValidationGroupsCustomObject

View file

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace DigiComp\SettingValidator\Tests\Functional\Fixtures; namespace DigiComp\SettingValidator\Tests\Functional\Fixtures;
class TestValidationGroupsDefaultObject class TestValidationGroupsDefaultObject

View file

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace DigiComp\SettingValidator\Tests\Functional; namespace DigiComp\SettingValidator\Tests\Functional;
use DigiComp\SettingValidator\Tests\Functional\Fixtures\TestObject; use DigiComp\SettingValidator\Tests\Functional\Fixtures\TestObject;
@ -22,11 +20,11 @@ class SettingsValidatorTest extends FunctionalTestCase
*/ */
public function ifNoNameIsGivenClassNameIsUsed(): void public function ifNoNameIsGivenClassNameIsUsed(): void
{ {
$result = $this->objectManager->get(SettingsValidator::class)->validate(new TestObject()); $validator = $this->objectManager->get(SettingsValidator::class);
$result = $validator->validate(new TestObject());
self::assertTrue($result->hasErrors()); $this->assertTrue($result->hasErrors());
self::assertCount(1, $result->getFlattenedErrors()); $this->assertCount(1, $result->getFlattenedErrors());
self::assertCount(1, $result->forProperty('shouldBeFalse')->getErrors()); $this->assertCount(1, $result->forProperty('shouldBeFalse')->getErrors());
} }
/** /**
@ -37,14 +35,11 @@ class SettingsValidatorTest extends FunctionalTestCase
*/ */
public function conjunctionValidationWorksAsExpected(): void public function conjunctionValidationWorksAsExpected(): void
{ {
$result = $this->objectManager $validatorResolver = $this->objectManager->get(ValidatorResolver::class);
->get(ValidatorResolver::class) $validator = $validatorResolver->getBaseValidatorConjunction(TestObject::class);
->getBaseValidatorConjunction(TestObject::class) $result = $validator->validate(new TestObject());
->validate(new TestObject()); $this->assertTrue($result->hasErrors());
$this->assertCount(1, $result->getFlattenedErrors());
self::assertTrue($result->hasErrors());
self::assertCount(1, $result->getFlattenedErrors());
self::assertCount(1, $result->forProperty('shouldBeTrueAndValidatedByAnnotation')->getErrors());
} }
/** /**
@ -53,13 +48,11 @@ class SettingsValidatorTest extends FunctionalTestCase
*/ */
public function defaultValidationGroupWorks(): void public function defaultValidationGroupWorks(): void
{ {
$result = $this->objectManager $validator = $this->objectManager->get(SettingsValidator::class, ['validationGroups' => ['Default']]);
->get(SettingsValidator::class, ['validationGroups' => ['Default']]) $result = $validator->validate(new TestValidationGroupsDefaultObject());
->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"');
self::assertTrue($result->hasErrors(), 'No errors for validation group "Default"'); $this->assertCount(1, $result->forProperty('shouldBeTrue')->getErrors(), 'Got no error for property');
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');
} }
/** /**
@ -68,12 +61,10 @@ class SettingsValidatorTest extends FunctionalTestCase
*/ */
public function customValidationGroupWorks(): void public function customValidationGroupWorks(): void
{ {
$result = $this->objectManager $validator = $this->objectManager->get(SettingsValidator::class, ['validationGroups' => ['Custom']]);
->get(SettingsValidator::class, ['validationGroups' => ['Custom']]) $result = $validator->validate(new TestValidationGroupsCustomObject());
->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"');
self::assertTrue($result->hasErrors(), 'No errors for validation group "Custom"'); $this->assertCount(1, $result->forProperty('shouldBeFalse')->getErrors(), 'Got no error for property');
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

@ -2,54 +2,43 @@
"name": "digicomp/settingvalidator", "name": "digicomp/settingvalidator",
"description": "Just a Neos\\Flow Validator resolving other Validators with Configuration/Validation.yaml", "description": "Just a Neos\\Flow Validator resolving other Validators with Configuration/Validation.yaml",
"type": "neos-package", "type": "neos-package",
"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",
"keywords": [ "keywords": [
"Neos", "Neos",
"Flow", "Flow",
"validation" "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": { "require": {
"php": ">=7.4.0", "neos/flow": "^6.2.3",
"neos/flow": "^6.3.5 || ^7.0 || ^8.0" "php": "~7.4.0"
},
"require-dev": {
"mikey179/vfsstream": "^1.6.1",
"neos/buildessentials": "^7.0.0",
"phpunit/phpunit": "~8.5",
"vimeo/psalm": "~4.22.0"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"DigiComp\\SettingValidator\\": "Classes/" "DigiComp\\SettingValidator\\": "Classes"
} }
}, },
"autoload-dev": { "autoload-dev": {
"psr-4": { "psr-4": {
"DigiComp\\SettingValidator\\Tests\\": "Tests/" "DigiComp\\SettingValidator\\Tests\\": "Tests"
} }
}, },
"config": {
"sort-packages": true,
"platform-check": true
},
"extra": { "extra": {
"branch-alias": {
"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": { "neos": {
"package-key": "DigiComp.SettingValidator" "package-key": "DigiComp.SettingValidator"
}, },
"branch-alias": {
"dev-develop": "3.0.x-dev",
"dev-version/1.x-dev": "1.1.x-dev"
},
"applied-flow-migrations": [ "applied-flow-migrations": [
"Inwebs.Basket-201409170938", "Inwebs.Basket-201409170938",
"TYPO3.FLOW3-201201261636", "TYPO3.FLOW3-201201261636",