diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 90ec22b..0000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.svn diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..ab59148 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,9 @@ +# 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). + +## 3.0.0 - 2020-08-31 + +Start of the changelog. diff --git a/Classes/Package.php b/Classes/Package.php index 7f7f1b8..cd71a3c 100644 --- a/Classes/Package.php +++ b/Classes/Package.php @@ -14,19 +14,17 @@ 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 */ - public function boot(Bootstrap $bootstrap) + public function boot(Bootstrap $bootstrap): void { parent::boot($bootstrap); @@ -35,11 +33,7 @@ class Package extends BasePackage ConfigurationManager::class, 'configurationManagerReady', function (ConfigurationManager $configurationManager) { - $configurationManager->registerConfigurationType( - static::CONFIGURATION_TYPE_VALIDATION, - ConfigurationManager::CONFIGURATION_PROCESSING_TYPE_DEFAULT, - true - ); + $configurationManager->registerConfigurationType('Validation'); } ); } diff --git a/Classes/Validation/Validator/SettingsValidator.php b/Classes/Validation/Validator/SettingsValidator.php index c79103d..8b825d8 100644 --- a/Classes/Validation/Validator/SettingsValidator.php +++ b/Classes/Validation/Validator/SettingsValidator.php @@ -13,10 +13,9 @@ 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; @@ -28,72 +27,45 @@ use Neos\Utility\TypeHandling; class SettingsValidator extends AbstractValidator { /** - * @var ValidatorResolver * @Flow\Inject + * @var ValidatorResolver */ protected $validatorResolver; /** - * @var ConfigurationManager - */ - protected $configurationManager; - - /** - * @var ReflectionService - * @Flow\Inject - * @deprecated - */ - 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; + + $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); - - foreach ($config as $validatorConfig) { - if (! $this->doesValidationGroupsMatch($validatorConfig)) { + foreach ($this->getConfigForValidation($validations[$name]) as $validatorConfig) { + if (!$this->doesValidationGroupsMatch($validatorConfig)) { continue; } @@ -104,10 +76,10 @@ 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', + \sprintf( + 'Validator "%s" could not be resolved. Check your Validation.yaml', $validatorConfig['validator'] ), 1402326139 @@ -115,45 +87,50 @@ class SettingsValidator extends AbstractValidator } if (isset($validatorConfig['property'])) { - $this->result->forProperty($validatorConfig['property'])->merge( + $this->getResult()->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 + * @param array $validation * @return array */ - protected function getConfigForName($name): array + protected function getConfigForValidation(array $validation): array { $config = []; - if (isset($this->validations[$name]['self'])) { - foreach ($this->validations[$name]['self'] as $validator => &$validation) { - if (is_null($validation)) { + + if (isset($validation['self'])) { + foreach ($validation['self'] as $validator => $options) { + if ($options === null) { continue; } - $newValidation['options'] = $validation; - $newValidation['validator'] = $validator; - $config[] = $newValidation; + $config[] = [ + 'validator' => $validator, + 'options' => $options, + ]; } } - if (isset($this->validations[$name]['properties'])) { - foreach ($this->validations[$name]['properties'] as $propertyName => &$validation) { - foreach ($validation as $validator => &$options) { - if (is_null($options)) { + + if (isset($validation['properties'])) { + foreach ($validation['properties'] as $property => $propertyValidation) { + foreach ($propertyValidation as $validator => $options) { + if ($options === null) { continue; } - $newValidation['property'] = $propertyName; - $newValidation['validator'] = $validator; - $newValidation['options'] = $options; - $config[] = $newValidation; + $config[] = [ + 'property' => $property, + 'validator' => $validator, + 'options' => $options, + ]; } } } + return $config; } @@ -163,13 +140,13 @@ class SettingsValidator extends AbstractValidator * @param array $validatorConfig * @return bool */ - protected function doesValidationGroupsMatch(array &$validatorConfig) + protected function doesValidationGroupsMatch(array $validatorConfig): bool { - if (isset($validatorConfig['options']['validationGroups']) && empty(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'] + ) !== []; } /** @@ -177,12 +154,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 ($validatorConfig['validator'] === 'DigiComp.SettingValidator:Settings') { $validatorConfig['options']['validationGroups'] = $this->options['validationGroups']; + } elseif (isset($validatorConfig['options']['validationGroups'])) { + unset($validatorConfig['options']['validationGroups']); } } } diff --git a/Migrations/Code/Version20170603120900.php b/Migrations/Code/Version20170603120900.php index 4df7e83..ff218d9 100644 --- a/Migrations/Code/Version20170603120900.php +++ b/Migrations/Code/Version20170603120900.php @@ -2,29 +2,24 @@ namespace Neos\Flow\Core\Migrations; -use DigiComp\SettingValidator\Package; - /** - * Restructures Validation.yamls to new format + * Restructures all Validation.yaml to new format */ class Version20170603120900 extends AbstractMigration { /** * @return string */ - public function getIdentifier() + public function getIdentifier(): string { return 'DigiComp.SettingValidator-20170603120900'; } - /** - * @return void - */ - public function up() + public function up(): void { $this->processConfiguration( - Package::CONFIGURATION_TYPE_VALIDATION, - function (&$configuration) { + 'Validation', + function (array &$configuration) { foreach ($configuration as $validatorName => &$validators) { // guard that protects configuration, which has already the new format: if (isset($validators['properties']) || isset($validators['self'])) { @@ -32,10 +27,12 @@ class Version20170603120900 extends AbstractMigration } $newConfiguration = ['properties' => [], 'self' => []]; - 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.'); + 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.' + ); continue; } if (isset($validator['property'])) { diff --git a/README.md b/README.md index d4274f4..fc438b7 100644 --- a/README.md +++ b/README.md @@ -1,44 +1,38 @@ -DigiComp.SettingValidator -------------------------- +# DigiComp.SettingValidator - -This Package allows to configure Validators for your Action-Arguments or domain model properties to be set by a new +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. -Lets imagine you had this action-method: +Let's imagine you had this action-method: /** + * @Flow\Validate(argumentName="order", type="DigiComp.SettingValidator:Settings") * @param Order $order - * @Flow\Validate(type="DigiComp.SettingValidator:Settings") */ public function createOrder($order) {...} Then your Validation.yaml could look like this: - 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 + Vendor\Package\Domain\Model\Order: + # 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' OrderCustomer: - - - property: firstName - validator: StringLength - options: - minimum: 3 - maximum: 20 - + properties: + firstName: + StringLength: + minimum: 3 + maximum: 20 As you see: Nesting is possible ;) That way you can easily construct flexible structures. diff --git a/Tests/Functional/Fixtures/TestObject.php b/Tests/Functional/Fixtures/TestObject.php index 8686bbd..6f8e667 100644 --- a/Tests/Functional/Fixtures/TestObject.php +++ b/Tests/Functional/Fixtures/TestObject.php @@ -9,18 +9,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 diff --git a/Tests/Functional/Fixtures/TestValidationGroupsCustomObject.php b/Tests/Functional/Fixtures/TestValidationGroupsCustomObject.php index 82101ab..b671e00 100644 --- a/Tests/Functional/Fixtures/TestValidationGroupsCustomObject.php +++ b/Tests/Functional/Fixtures/TestValidationGroupsCustomObject.php @@ -7,12 +7,12 @@ class TestValidationGroupsCustomObject /** * @var bool */ - protected $shouldBeTrue = false; + protected bool $shouldBeTrue = false; /** * @var bool */ - protected $shouldBeFalse = true; + protected bool $shouldBeFalse = true; /** * @return bool diff --git a/Tests/Functional/Fixtures/TestValidationGroupsDefaultObject.php b/Tests/Functional/Fixtures/TestValidationGroupsDefaultObject.php index ef9f909..30261b2 100644 --- a/Tests/Functional/Fixtures/TestValidationGroupsDefaultObject.php +++ b/Tests/Functional/Fixtures/TestValidationGroupsDefaultObject.php @@ -7,12 +7,12 @@ class TestValidationGroupsDefaultObject /** * @var bool */ - protected $shouldBeTrue = false; + protected bool $shouldBeTrue = false; /** * @var bool */ - protected $shouldBeFalse = true; + protected bool $shouldBeFalse = true; /** * @return bool diff --git a/Tests/Functional/SettingsValidatorTest.php b/Tests/Functional/SettingsValidatorTest.php index c16a48b..305b515 100644 --- a/Tests/Functional/SettingsValidatorTest.php +++ b/Tests/Functional/SettingsValidatorTest.php @@ -7,14 +7,18 @@ 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()); @@ -25,8 +29,11 @@ class SettingsValidatorTest extends FunctionalTestCase /** * @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); @@ -37,8 +44,9 @@ class SettingsValidatorTest extends FunctionalTestCase /** * @test + * @throws InvalidValidationOptionsException */ - public function defaultValidationGroupWorks() + public function defaultValidationGroupWorks(): void { $validator = $this->objectManager->get(SettingsValidator::class, ['validationGroups' => ['Default']]); $result = $validator->validate(new TestValidationGroupsDefaultObject()); @@ -49,8 +57,9 @@ class SettingsValidatorTest extends FunctionalTestCase /** * @test + * @throws InvalidValidationOptionsException */ - public function customValidationGroupWorks() + public function customValidationGroupWorks(): void { $validator = $this->objectManager->get(SettingsValidator::class, ['validationGroups' => ['Custom']]); $result = $validator->validate(new TestValidationGroupsCustomObject()); diff --git a/composer.json b/composer.json index 4651bb7..62b81e5 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "digicomp/settingvalidator", - "type": "neos-package", "description": "Just a Neos\\Flow Validator resolving other Validators with Configuration/Validation.yaml", + "type": "neos-package", "authors": [ { "name": "Ferdinand Kuhl", @@ -18,7 +18,8 @@ "validation" ], "require": { - "neos/flow": "~4.1|^5.3" + "neos/flow": "^6.2.3", + "php": "~7.4.0" }, "autoload": { "psr-4": { @@ -31,9 +32,12 @@ } }, "extra": { + "neos": { + "package-key": "DigiComp.SettingValidator" + }, "branch-alias": { - "dev-develop": "2.0.x-dev", - "dev-version/1.x-dev": "1.0.x-dev" + "dev-develop": "3.0.x-dev", + "dev-version/1.x-dev": "1.1.x-dev" }, "applied-flow-migrations": [ "Inwebs.Basket-201409170938", @@ -67,7 +71,9 @@ "Neos.Flow-20170125103800", "Neos.Flow-20170127183102", "DigiComp.SettingValidator-20170603120900", - "Neos.Flow-20180415105700" + "Neos.Flow-20180415105700", + "Neos.Flow-20190425144900", + "Neos.Flow-20190515215000" ] } -} \ No newline at end of file +}