diff --git a/app/code/Magento/ContactGraphQl/Model/ContactUsValidator.php b/app/code/Magento/ContactGraphQl/Model/ContactUsValidator.php new file mode 100644 index 0000000000000..e608df9db8b2d --- /dev/null +++ b/app/code/Magento/ContactGraphQl/Model/ContactUsValidator.php @@ -0,0 +1,52 @@ +emailValidator = $emailValidator; + } + + /** + * Validate input data + * + * @param string[] $input + * @return void + * @throws GraphQlInputException + */ + public function execute(array $input): void + { + if (!$this->emailValidator->isValid($input['email'])) { + throw new GraphQlInputException( + __('The email address is invalid. Verify the email address and try again.') + ); + } + + if ($input['name'] === '') { + throw new GraphQlInputException(__('Name field is required.')); + } + + if ($input['comment'] === '') { + throw new GraphQlInputException(__('Comment field is required.')); + } + } +} diff --git a/app/code/Magento/ContactGraphQl/Model/Resolver/ContactUs.php b/app/code/Magento/ContactGraphQl/Model/Resolver/ContactUs.php new file mode 100644 index 0000000000000..eb6e852358579 --- /dev/null +++ b/app/code/Magento/ContactGraphQl/Model/Resolver/ContactUs.php @@ -0,0 +1,95 @@ +mail = $mail; + $this->contactConfig = $contactConfig; + $this->logger = $logger; + $this->validator = $validator; + } + + /** + * @inheritDoc + */ + public function resolve( + Field $field, + $context, + ResolveInfo $info, + array $value = null, + array $args = null + ) { + if (!$this->contactConfig->isEnabled()) { + throw new GraphQlInputException( + __('The contact form is unavailable.') + ); + } + + $input = array_map(function ($field) { + return $field === null ? '' : trim($field); + }, $args['input']); + $this->validator->execute($input); + + try { + $this->mail->send($input['email'], ['data' => $input]); + } catch (\Exception $e) { + $this->logger->critical($e); + throw new GraphQlInputException( + __('An error occurred while processing your form. Please try again later.') + ); + } + + return [ + 'status' => true + ]; + } +} diff --git a/app/code/Magento/ContactGraphQl/README.md b/app/code/Magento/ContactGraphQl/README.md new file mode 100644 index 0000000000000..0d983ddf4a4e4 --- /dev/null +++ b/app/code/Magento/ContactGraphQl/README.md @@ -0,0 +1,3 @@ +# ContactGraphQlPwa + +**ContactGraphQlPwa** provides GraphQL support for `magento/module-contact`. diff --git a/app/code/Magento/ContactGraphQl/composer.json b/app/code/Magento/ContactGraphQl/composer.json new file mode 100644 index 0000000000000..9c08ecbb16758 --- /dev/null +++ b/app/code/Magento/ContactGraphQl/composer.json @@ -0,0 +1,28 @@ +{ + "name": "magento/module-contact-graph-ql", + "description": "N/A", + "type": "magento2-module", + "config": { + "sort-packages": true + }, + "require": { + "php": "~8.1.0||~8.2.0", + "magento/framework": "*", + "magento/module-contact": "*" + }, + "suggest": { + "magento/module-graph-ql": "*" + }, + "license": [ + "OSL-3.0", + "AFL-3.0" + ], + "autoload": { + "files": [ + "registration.php" + ], + "psr-4": { + "Magento\\ContactGraphQl\\": "" + } + } +} diff --git a/app/code/Magento/ContactGraphQl/etc/graphql/di.xml b/app/code/Magento/ContactGraphQl/etc/graphql/di.xml new file mode 100644 index 0000000000000..b46225b07eede --- /dev/null +++ b/app/code/Magento/ContactGraphQl/etc/graphql/di.xml @@ -0,0 +1,16 @@ + + + + + + + contact/contact/enabled + + + + diff --git a/app/code/Magento/ContactGraphQl/etc/module.xml b/app/code/Magento/ContactGraphQl/etc/module.xml new file mode 100644 index 0000000000000..801683ba43618 --- /dev/null +++ b/app/code/Magento/ContactGraphQl/etc/module.xml @@ -0,0 +1,10 @@ + + + + + diff --git a/app/code/Magento/ContactGraphQl/etc/schema.graphqls b/app/code/Magento/ContactGraphQl/etc/schema.graphqls new file mode 100644 index 0000000000000..400c5471d942f --- /dev/null +++ b/app/code/Magento/ContactGraphQl/etc/schema.graphqls @@ -0,0 +1,23 @@ +# Copyright © Magento, Inc. All rights reserved. +# See COPYING.txt for license details. + +type Mutation { + contactUs( + input: ContactUsInput! @doc(description: "An input object that defines shopper information.") + ): ContactUsOutput @doc(description: "Send a 'Contact Us' email to the merchant.") @resolver(class: "Magento\\ContactGraphQl\\Model\\Resolver\\ContactUs") +} + +input ContactUsInput { + email: String! @doc(description: "The email address of the shopper.") + name: String! @doc(description: "The full name of the shopper.") + telephone: String @doc(description: "The shopper's telephone number.") + comment: String! @doc(description: "The shopper's comment to the merchant.") +} + +type ContactUsOutput @doc(description: "Contains the status of the request."){ + status: Boolean! @doc(description: "Indicates whether the request was successful.") +} + +type StoreConfig { + contact_enabled: Boolean! @doc(description: "Indicates whether the Contact Us form in enabled.") +} diff --git a/app/code/Magento/ContactGraphQl/registration.php b/app/code/Magento/ContactGraphQl/registration.php new file mode 100644 index 0000000000000..27782c62d7966 --- /dev/null +++ b/app/code/Magento/ContactGraphQl/registration.php @@ -0,0 +1,10 @@ + [ + "status" => true + ] + ]; + $response = $this->graphQlMutation($query, [], '', []); + $this->assertEquals($expected, $response, "Contact Us form can not be send"); + } + + /** + * Failed send contact us form - missing email + */ + public function testContactUsBadEmail() + { + $query = <<expectException(ResponseContainsErrorsException::class); + $this->expectExceptionMessage( + 'GraphQL response contains errors: The email address is invalid. Verify the email address and try again.' + ); + $this->graphQlMutation($query, [], '', []); + } + + /** + * Failed send contact us form - missing name + */ + public function testContactUsMissingName() + { + $query = <<expectException(ResponseContainsErrorsException::class); + $this->expectExceptionMessage( + 'GraphQL response contains errors: Field ContactUsInput.name of required type String! was not provided.' + ); + $this->graphQlMutation($query, [], '', []); + } + + /** + * Failed send contact us form - missing name + */ + public function testContactUsMissingComment() + { + $query = <<expectException(ResponseContainsErrorsException::class); + $this->expectExceptionMessage( + 'GraphQL response contains errors: Field ContactUsInput.comment of required type String! was not provided.' + ); + $this->graphQlMutation($query, [], '', []); + } + + /** + * Failed send contact us form - missing name + */ + #[ + Config("contact/contact/enabled", "0") + ] + public function testContactUsDisabled() + { + $query = <<expectException(ResponseContainsErrorsException::class); + $this->expectExceptionMessage('GraphQL response contains errors: The contact form is unavailable.'); + $this->graphQlMutation($query, [], '', []); + } +}