Skip to content

Optimize validator #815

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 1, 2021
Merged

Conversation

murtukov
Copy link
Contributor

@murtukov murtukov commented Jan 27, 2021

Q A
Bug fix? no
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes

Change the way the validation rules are generated. As result the generated classes and the TypeBuilder class reduced in size.

Before

Before the change all validation rules were genereted inside the resolver closure and passed to the InputValidator:

public function __construct(ConfigProcessor $configProcessor, GraphQLServices $services)
{
    $config = [
        'name' => self::NAME,
        'fields' => fn() => [
            'linkedConstraintsValidation' => [
                'type' => Type::boolean(),
                'resolve' => function ($value, $args, $context, $info) use ($services) {
                    $validator = new InputValidator(
                        \func_get_args(),
                        $services->get('container')->get('validator'),
                        $services->get('validatorFactory'),
                        [
                            'string1' => [
                                'link' => ['App\Models\User', 'string1', 'property'],
                            ],
                            'string2' => [
                                'link' => ['App\Models\User', 'string2', 'getter'],
                            ],
                            'string3' => [
                                'link' => ['App\Models\User', 'string3', 'member'],
                            ],
                        ],
                    );
                    return $services->mutation("mutation_mock", $args, $validator);
                },
                'args' => [
                    [
                        'name' => 'string1',
                        'type' => Type::nonNull(Type::string()),
                    ],
                    [
                        'name' => 'string2',
                        'type' => Type::nonNull(Type::string()),
                    ],
                    [
                        'name' => 'string3',
                        'type' => Type::nonNull(Type::string()),
                    ],
                ],
            ],
            'cascadeValidationWithGroups' => [
                'type' => Type::boolean(),
                'resolve' => function ($value, $args, $context, $info) use ($services) {
                    $validator = new InputValidator(
                        \func_get_args(),
                        $services->get('container')->get('validator'),
                        $services->get('validatorFactory'),
                        [
                            'address' => [
                                'cascade' => [
                                    'isCollection' => false,
                                    'referenceType' => $services->getType('Address'),
                                ],
                            ],
                            'birthdate' => [
                                'cascade' => [
                                    'groups' => ['group2'],
                                    'isCollection' => false,
                                    'referenceType' => $services->getType('Birthdate'),
                                ],
                            ],
                        ],
                    );
                    return $services->mutation("mutation_mock", $args, $validator);
                },
                'args' => [
                    [
                        'name' => 'groups',
                        'type' => Type::nonNull(Type::listOf(Type::string())),
                    ],
                    [
                        'name' => 'address',
                        'type' => fn() => Type::nonNull($services->getType('Address')),
                    ],
                    [
                        'name' => 'birthdate',
                        'type' => fn() => $services->getType('Birthdate'),
                    ],
                ],
            ],
        ],
    ];

    parent::__construct($configProcessor->process($config));
}

After

Now validation rules are generated each in the corresponding entry under the args key and the resolver closure doesn't contain much logic:

public function __construct(ConfigProcessor $configProcessor, GraphQLServices $services)
{
    $config = [
        'name' => self::NAME,
        'fields' => fn() => [
            'linkedConstraintsValidation' => [
                'type' => Type::boolean(),
                'resolve' => function ($value, $args, $context, $info) use ($services) {
                    $validator = $services->createInputValidator(func_get_args());
                    return $services->mutation("mutation_mock", $args, $validator);
                },
                'args' => [
                    [
                        'name' => 'string1',
                        'type' => Type::nonNull(Type::string()),
                        'validation' => [
                            'link' => ['App\Models\User', 'string1', 'property'],
                        ],
                    ],
                    [
                        'name' => 'string2',
                        'type' => Type::nonNull(Type::string()),
                        'validation' => [
                            'link' => ['App\Models\User', 'string2', 'getter'],
                        ],
                    ],
                    [
                        'name' => 'string3',
                        'type' => Type::nonNull(Type::string()),
                        'validation' => [
                            'link' => ['App\Models\User', 'string3', 'member'],
                        ],
                    ],
                ],
            ],
            'cascadeValidationWithGroups' => [
                'type' => Type::boolean(),
                'resolve' => function ($value, $args, $context, $info) use ($services) {
                    $validator = $services->createInputValidator(func_get_args());
                    return $services->mutation("mutation_mock", $args, $validator);
                },
                'args' => [
                    [
                        'name' => 'groups',
                        'type' => Type::nonNull(Type::listOf(Type::string())),
                    ],
                    [
                        'name' => 'address',
                        'type' => fn() => Type::nonNull($services->getType('Address')),
                        'validation' => InputValidator::CASCADE,
                    ],
                    [
                        'name' => 'birthdate',
                        'type' => fn() => $services->getType('Birthdate'),
                        'validation' => [
                            InputValidator::CASCADE => ['group2'],
                        ],
                    ],
                ],
            ],
        ],
    ];

    parent::__construct($configProcessor->process($config));
}

Additionally

  • The 'cascade' literal is replaced with the constant InputValidator::CASCADE
  • The creation of the InputValidator instances isn't hardcoded inside the resolver closure, but fetched from a service:
    Before:
     $validator = new InputValidator(
         \func_get_args(),
         $services->get('container')->get('validator'),
         $services->get('validatorFactory'),
         [ /* property constraints */ ],
         [ /* class constraints */]
     );
    After:
    $validator = $services->createInputValidator(func_get_args());
  • The keys isCollection and referenceType are removed as unnecessary, because this information is read directly from the type classes.

@murtukov murtukov added the wip label Jan 27, 2021
* Update docblocks
* Remove dead code and annotations
* Fix tests
* Fix service definitions
* Increase coverage
* Update GraphQLServices
* Refactor methods in TypeBuilder related to validation
* Refactor InputValidator
* Throw in InputValidatorFactory if no validator defined
* Add extra checks in tests related to validator
* Update isListOfType method
* Refactor class ValidatorFactory into InputValidatorFactory
* Move InputValidator instantiation into the InputValidatorFactory service
@murtukov murtukov force-pushed the refactor/input-validator branch from 7924e1d to af9fd3b Compare January 27, 2021 18:31
@murtukov murtukov changed the title [WIP] Optimize validator Optimize validator Jan 27, 2021
@murtukov murtukov added enhancement and removed wip labels Jan 27, 2021
@murtukov murtukov requested review from mcg-web, ste93cry and Vincz and removed request for ste93cry January 27, 2021 18:54
Copy link
Member

@mcg-web mcg-web left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also can you provide an example of generation without no validation present please?

@murtukov
Copy link
Contributor Author

Also can you provide an example of generation without no validation present please?

If no validation is present, then types are generated as usual, so there is nothing to provide

@murtukov murtukov requested a review from mcg-web January 31, 2021 01:24
@murtukov murtukov force-pushed the refactor/input-validator branch from d2993b8 to 779caea Compare January 31, 2021 01:26
@murtukov murtukov changed the title Optimize validator [WIP] Optimize validator Feb 1, 2021
@murtukov murtukov changed the title [WIP] Optimize validator Optimize validator Feb 1, 2021
@murtukov murtukov merged commit 244ff31 into overblog:master Feb 1, 2021
@murtukov murtukov deleted the refactor/input-validator branch February 1, 2021 14:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants