From adde49dff75afcf94183cb9704fbfeefd240b4d8 Mon Sep 17 00:00:00 2001 From: jacobdekeizer Date: Tue, 22 Feb 2022 20:36:01 +0100 Subject: [PATCH 1/6] Add support for validation attributes --- src/Support/Field.php | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Support/Field.php b/src/Support/Field.php index ac84656a..81dbf6d3 100644 --- a/src/Support/Field.php +++ b/src/Support/Field.php @@ -63,6 +63,16 @@ public function validationErrorMessages(array $args = []): array return []; } + /** + * Define custom Laravel Validator attributes as per Laravel 'custom attributes'. + * + * @param array $args submitted arguments + */ + public function validationAttributes(array $args = []): array + { + return []; + } + /** * @param array $args * @return array @@ -119,8 +129,11 @@ public function getValidator(array $args, array $rules): ValidatorContract { // allow our error messages to be customised $messages = $this->validationErrorMessages($args); + + // allow our attributes to be customized + $attributes = $this->validationAttributes($args); - return Validator::make($args, $rules, $messages); + return Validator::make($args, $rules, $messages, $attributes); } /** From 76395badabad3d932f87115a2e9e12de6c47f4f9 Mon Sep 17 00:00:00 2001 From: jacobdekeizer Date: Tue, 22 Feb 2022 20:44:30 +0100 Subject: [PATCH 2/6] Document validation attributes in readme --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index 7b83b7da..74dbc8ef 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,7 @@ The default GraphiQL view makes use of the global `csrf_token()` helper function - [Example using Laravel's validator directly](#example-using-laravels-validator-directly) - [Handling validation errors](#handling-validation-errors) - [Customizing error messages](#customizing-error-messages) + - [Customizing attributes](#customizing-attributes) - [Misc notes](#misc-notes) - [Resolve method](#resolve-method) - [Resolver middleware](#resolver-middleware) @@ -993,6 +994,21 @@ public function validationErrorMessages(array $args = []): array } ``` +#### Customizing attributes + +The validation attributes can be customised by overriding the +`validationAttributes` method. This method should return an array of custom +attributes in the same way documented by Laravel's validation. + +```php +public function validationAttributes(array $args = []): array +{ + return [ + 'email' => 'email address', + ]; +} +``` + #### Misc notes Certain type declarations of GraphQL may cancel our or render certain validations From 6965cdcac0a46485921bed46ab68ff89297bc54c Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 22 Feb 2022 21:15:05 +0100 Subject: [PATCH 3/6] Add tests --- .../UpdateExampleMutationWithInputType.php | 13 ++++++ tests/Unit/MutationTest.php | 42 +++++++++++++++---- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/tests/Support/Objects/UpdateExampleMutationWithInputType.php b/tests/Support/Objects/UpdateExampleMutationWithInputType.php index 5644ba1b..71dd9e75 100644 --- a/tests/Support/Objects/UpdateExampleMutationWithInputType.php +++ b/tests/Support/Objects/UpdateExampleMutationWithInputType.php @@ -62,6 +62,19 @@ public function args(): array 'name' => 'test', 'type' => Type::nonNull(Type::listOf(Type::nonNull(GraphQL::type('ExampleValidationInputObject')))), ], + + 'test_validation_custom_attributes' => [ + 'name' => 'custom validation attributes', + 'type' => Type::string(), + 'rules' => ['required'], + ], + ]; + } + + public function validationAttributes(array $args = []): array + { + return [ + 'test_validation_custom_attributes' => 'custom attribute', ]; } diff --git a/tests/Unit/MutationTest.php b/tests/Unit/MutationTest.php index 1f09743d..ff684dec 100644 --- a/tests/Unit/MutationTest.php +++ b/tests/Unit/MutationTest.php @@ -74,6 +74,7 @@ public function testResolve(): void ['email' => 'test@test.com'], ], ], + 'test_validation_custom_attributes' => 'test', ], [], $this->resolveInfoMock()); } @@ -117,7 +118,8 @@ public function testValidationError(): void self::assertTrue($messages->has('test_with_rules_non_nullable_input_object.otherValue')); self::assertTrue($messages->has('test_with_rules_non_nullable_input_object.nest')); self::assertTrue($messages->has('test_with_rules_non_nullable_input_object.list')); - self::assertCount(6, $messages->all()); + self::assertTrue($messages->has('test_validation_custom_attributes')); + self::assertCount(7, $messages->all()); } public function testWithInput(): void @@ -154,7 +156,8 @@ public function testWithInput(): void self::assertTrue($messages->has('test_with_rules_non_nullable_input_object.otherValue')); self::assertTrue($messages->has('test_with_rules_non_nullable_input_object.nest')); self::assertTrue($messages->has('test_with_rules_non_nullable_input_object.list')); - self::assertCount(6, $messages->all()); + self::assertTrue($messages->has('test_validation_custom_attributes')); + self::assertCount(7, $messages->all()); } public function testWithEmptyInput(): void @@ -182,7 +185,8 @@ public function testWithEmptyInput(): void self::assertTrue($messages->has('test_with_rules')); self::assertTrue($messages->has('test_with_rules_non_nullable_input_object')); self::assertTrue($messages->has('test_with_rules_closure')); - self::assertCount(4, $messages->all()); + self::assertTrue($messages->has('test_validation_custom_attributes')); + self::assertCount(5, $messages->all()); } public function testWithInputDepthOne(): void @@ -212,7 +216,8 @@ public function testWithInputDepthOne(): void self::assertTrue($messages->has('test_with_rules_non_nullable_input_object')); self::assertTrue($messages->has('test_with_rules_closure')); - self::assertCount(3, $messages->all()); + self::assertTrue($messages->has('test_validation_custom_attributes')); + self::assertCount(4, $messages->all()); } public function testWithInputWithEmptyInputObjects(): void @@ -245,6 +250,8 @@ public function testWithInputWithEmptyInputObjects(): void self::assertTrue($messages->has('test_with_rules')); + self::assertTrue($messages->has('test_validation_custom_attributes')); + self::assertTrue($messages->has('test_with_rules_nullable_input_object.otherValue')); self::assertTrue($messages->has('test_with_rules_nullable_input_object.val')); self::assertTrue($messages->has('test_with_rules_nullable_input_object.nest')); @@ -253,7 +260,7 @@ public function testWithInputWithEmptyInputObjects(): void self::assertTrue($messages->has('test_with_rules_non_nullable_input_object.val')); self::assertTrue($messages->has('test_with_rules_non_nullable_input_object.nest')); self::assertTrue($messages->has('test_with_rules_non_nullable_input_object.list')); - self::assertCount(12, $messages->all()); + self::assertCount(13, $messages->all()); } public function testWithEmptyArrayOfInputsObjects(): void @@ -282,7 +289,8 @@ public function testWithEmptyArrayOfInputsObjects(): void self::assertTrue($messages->has('test_with_rules')); self::assertTrue($messages->has('test_with_rules_non_nullable_input_object')); self::assertTrue($messages->has('test_with_rules_closure')); - self::assertCount(4, $messages->all()); + self::assertTrue($messages->has('test_validation_custom_attributes')); + self::assertCount(5, $messages->all()); } public function testWithArrayOfInputsObjects(): void @@ -319,7 +327,8 @@ public function testWithArrayOfInputsObjects(): void self::assertTrue($messages->has('test_with_rules_non_nullable_list_of_non_nullable_input_object.0.otherValue')); self::assertTrue($messages->has('test_with_rules_non_nullable_list_of_non_nullable_input_object.0.nest')); self::assertTrue($messages->has('test_with_rules_non_nullable_list_of_non_nullable_input_object.0.list')); - self::assertCount(7, $messages->all()); + self::assertTrue($messages->has('test_validation_custom_attributes')); + self::assertCount(8, $messages->all()); } public function testCustomValidationErrorMessages(): void @@ -356,6 +365,25 @@ public function testCustomValidationErrorMessages(): void ); } + public function testCustomValidationAttributes(): void + { + $class = $this->getFieldClass(); + $field = new $class(); + $attributes = $field->getAttributes(); + + /** @var ValidationError $exception */ + $exception = null; + + try { + $attributes['resolve'](null, [], [], $this->resolveInfoMock()); + } catch (ValidationError $exception) { + } + + $messages = $exception->getValidatorMessages(); + + self::assertEquals('The custom attribute field is required.', $messages->first('test_validation_custom_attributes')); + } + public function testRuleCallbackArgumentsMatchesTheInput(): void { $this->expectException(ValidationError::class); From 5b61e96111dbf05bcb158498462ecb8faadf5dc8 Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 22 Feb 2022 21:23:44 +0100 Subject: [PATCH 4/6] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92abf70b..412dc040 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ CHANGELOG ### Added - Add support to use array in `controller` param in config [\#906 / viktorruskai](https://github.com/rebing/graphql-laravel/pull/906) +- Add support for laravel validation attributes [\#901 / jacobdekeizer](https://github.com/rebing/graphql-laravel/pull/901) ### Fixed - Allow 'always' to work on object types [\#473 / tinyoverflow \#369 / zjbarg](https://github.com/rebing/graphql-laravel/pull/892) From 3b81b5584def2846fdfca204c0d28032f11f2279 Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 22 Feb 2022 21:26:36 +0100 Subject: [PATCH 5/6] Fix style --- src/Support/Field.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Support/Field.php b/src/Support/Field.php index 81dbf6d3..c813fb8a 100644 --- a/src/Support/Field.php +++ b/src/Support/Field.php @@ -129,7 +129,7 @@ public function getValidator(array $args, array $rules): ValidatorContract { // allow our error messages to be customised $messages = $this->validationErrorMessages($args); - + // allow our attributes to be customized $attributes = $this->validationAttributes($args); From c0a199b36aa311012559ad23c38b1d66e1f16408 Mon Sep 17 00:00:00 2001 From: jacobdekeizer Date: Fri, 20 May 2022 17:54:50 +0200 Subject: [PATCH 6/6] Fix phpstan errors --- phpstan-baseline.neon | 5 +++++ src/Support/Field.php | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 30dd15cb..fc460464 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1395,6 +1395,11 @@ parameters: count: 14 path: tests/Unit/MutationTest.php + - + message: "#^Relation 'test_validation_custom_attributes' is not found in Illuminate\\\\Contracts\\\\Support\\\\MessageBag model\\.$#" + count: 7 + path: tests/Unit/MutationTest.php + - message: "#^Relation 'test_with_rules_non_nullable_list_of_non_nullable_input_object' is not found in Illuminate\\\\Contracts\\\\Support\\\\MessageBag model\\.$#" count: 3 diff --git a/src/Support/Field.php b/src/Support/Field.php index c813fb8a..728be1f6 100644 --- a/src/Support/Field.php +++ b/src/Support/Field.php @@ -66,7 +66,8 @@ public function validationErrorMessages(array $args = []): array /** * Define custom Laravel Validator attributes as per Laravel 'custom attributes'. * - * @param array $args submitted arguments + * @param array $args submitted arguments + * @return array */ public function validationAttributes(array $args = []): array {