diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..ca3d04b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,18 @@ +; This file is for unifying the coding style for different editors and IDEs. +; More information at http://editorconfig.org + +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.yml] +indent_size = 2 + +[*.json] +charset = utf-8 +indent_size = 2 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..e16b4b4 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,42 @@ +# Define the line ending behavior of the different file extensions +# Set default behaviour, in case users don't have core.autocrlf set. +* text=auto +* text eol=lf + +# Explicitly declare text files we want to always be normalized and converted +# to native line endings on checkout. +*.php text +*.default text +*.ctp text +*.sql text +*.md text +*.po text +*.js text +*.css text +*.ini text +*.properties text +*.txt text +*.xml text +*.svg text +*.yml text +.htaccess text + +# Declare files that will always have CRLF line endings on checkout. +*.bat eol=crlf + +# Declare files that will always have LF line endings on checkout. +*.pem eol=lf + +# Denote all files that are truly binary and should not be modified. +*.png binary +*.jpg binary +*.gif binary +*.ico binary +*.mo binary +*.pdf binary +*.phar binary +*.woff binary +*.woff2 binary +*.ttf binary +*.otf binary +*.eot binary diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a3e9703 --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +/config/app.php + +/.htpasswd +/vendor/* +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +Icon? +ehthumbs.db +ehthumbs_vista.db +Thumbs.db +Desktop.ini +$RECYCLE.BIN/ +*.stackdump +/.well-known/* +*~ +*.swp +*.swo +*.sublime-* +*.stTheme.cache +*.tmlanguage.cache +*.tmPreferences.cache +.settings/* +.idea/* +nbproject/* +.vscode +.sass-cache/ +*.php_cs.cache +/.scannerwork/* +/.settings/* +/.tests/* \ No newline at end of file diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..325546b --- /dev/null +++ b/.htaccess @@ -0,0 +1,24 @@ + + RequestHeader unset Proxy + + + RewriteEngine on + RewriteBase / + + RewriteCond %{REQUEST_URI} !^/webroot/ + RewriteCond %{REQUEST_URI} !^(\.well-known/.*)$ + RewriteRule ^(.*)$ /webroot/$1 [QSA,L] + + RewriteRule ^(\.well-known/.*)$ $1 [L] + + RewriteCond %{HTTP:Authorization} ^(.*) + RewriteRule .* - [e=HTTP_AUTHORIZATION:%1] + + +SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 + + + Header set Access-Control-Allow-Origin: "*" + Header set Access-Control-Allow-Methods: "POST" + Header set Access-Control-Allow-Headers: "Authorization, Access-Control-Allow-Origin, Content-Type" + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..41bf941 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Pittica S.r.l.s. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +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 THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..6b4fb60 --- /dev/null +++ b/README.md @@ -0,0 +1,56 @@ +# Post SendGrid + +[![LICENSE](https://img.shields.io/github/license/pittica/post-sendgrid.svg)](LICENSE) +[![packagist](https://img.shields.io/badge/packagist-pittica%2Fpost--sendgrid-brightgreen.svg)](https://packagist.org/packages/pittica/post-sendgrid) +![PHP from Packagist](https://img.shields.io/packagist/php-v/pittica/post-sendgrid) + +This project uses SendGrid to send data from contact forms. + +## Installation + +You can install _post-sendgrid_ using [Composer](https://getcomposer.org). + +``` bash +composer create-project --prefer-dist pittica/post-sendgrid +``` + +## Configuration + +Create and edit a **config/app.php** file. + +### Example + +``` php + [ + 'whitelisted' => [ + 'message' + ], + 'email' => 'email', + 'subject' => 'subject', + 'name' => 'name', + 'labels' => [ + 'message' => 'Message', + 'email' => 'E-Mail', + 'subject' => 'Subject' + ] + ], + 'sender' => [ + 'address' => 'YOUR@EMAIL.ADDRESS', + 'name' => 'YOUR NAME' + ], + 'api' => [ + 'key' => 'SendGrid API KEY' + ], + 'recaptcha' => [ + 'key' => 'RECAPTCHA KEY', + 'field' => 'g-recaptcha' + ] +]; +``` + +## Copyright + +© 2020 [Pittica S.r.l.s.](https://pittica.com) \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..af133eb --- /dev/null +++ b/composer.json @@ -0,0 +1,38 @@ +{ + "name": "pittica/post-sendgrid", + "homepage": "https://github.com/pittica/post-sendgrid", + "description": "Send e-mails using SendGrid from HTTP POST", + "type": "project", + "license": "MIT", + "keywords": [ + "email", + "sendgrid", + "post" + ], + "authors": [ + { + "name": "Lucio Benini", + "email": "info@pittica.com", + "homepage": "https://pittica.com", + "role": "Web Developer" + } + ], + "autoload": { + "psr-4": { + "Pittica\\PostSendGrid\\": "src" + } + }, + "minimum-stability": "stable", + "require": { + "ext-curl": "*", + "ext-json": "*", + "php": "^7.1", + "sendgrid/sendgrid": "^7.0", + "guzzlehttp/guzzle": "^6.5.2", + "google/recaptcha": "^1.2" + }, + "prefer-stable": true, + "config": { + "sort-packages": true + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..93fb948 --- /dev/null +++ b/composer.lock @@ -0,0 +1,457 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "content-hash": "a98692bcf162b8ed1acff17d7eeb4ba5", + "packages": [ + { + "name": "google/recaptcha", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/google/recaptcha.git", + "reference": "98c4a6573b27e8b0990ea8789c74ea378795134c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/google/recaptcha/zipball/98c4a6573b27e8b0990ea8789c74ea378795134c", + "reference": "98c4a6573b27e8b0990ea8789c74ea378795134c", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.2.20|^2.15", + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^4.8.36|^5.7.27|^6.59|^7.5.11" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "ReCaptcha\\": "src/ReCaptcha" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Client library for reCAPTCHA, a free service that protects websites from spam and abuse.", + "homepage": "https://www.google.com/recaptcha/", + "keywords": [ + "Abuse", + "captcha", + "recaptcha", + "spam" + ], + "time": "2019-08-16T15:48:25+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "6.5.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "43ece0e75098b7ecd8d13918293029e555a50f82" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/43ece0e75098b7ecd8d13918293029e555a50f82", + "reference": "43ece0e75098b7ecd8d13918293029e555a50f82", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.6.1", + "php": ">=5.5" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", + "psr/log": "^1.1" + }, + "suggest": { + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.5-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2019-12-23T11:57:10+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "v1.3.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "time": "2016-12-20T10:07:11+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "1.6.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "239400de7a173fe9901b9ac7c06497751f00727a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/239400de7a173fe9901b9ac7c06497751f00727a", + "reference": "239400de7a173fe9901b9ac7c06497751f00727a", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0", + "ralouphie/getallheaders": "^2.0.5 || ^3.0.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "ext-zlib": "*", + "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8" + }, + "suggest": { + "zendframework/zend-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "time": "2019-07-01T23:21:34+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2016-08-06T14:39:51+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "sendgrid/php-http-client", + "version": "3.10.2", + "source": { + "type": "git", + "url": "https://github.com/sendgrid/php-http-client.git", + "reference": "a3891dfe1130014e46b59e3c76be0c1c9d4fd540" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sendgrid/php-http-client/zipball/a3891dfe1130014e46b59e3c76be0c1c9d4fd540", + "reference": "a3891dfe1130014e46b59e3c76be0c1c9d4fd540", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "phpunit/phpunit": "~4.4", + "squizlabs/php_codesniffer": "~2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "SendGrid\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matt Bernier", + "email": "dx@sendgrid.com" + }, + { + "name": "Elmer Thomas", + "email": "ethomas@twilio.com" + } + ], + "description": "HTTP REST client, simplified for PHP", + "homepage": "http://github.com/sendgrid/php-http-client", + "keywords": [ + "api", + "fluent", + "http", + "rest", + "sendgrid" + ], + "time": "2020-01-22T20:51:56+00:00" + }, + { + "name": "sendgrid/sendgrid", + "version": "7.4.2", + "source": { + "type": "git", + "url": "https://github.com/sendgrid/sendgrid-php.git", + "reference": "d697c9e1677516314c28d2b946cc3062ee9537ff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sendgrid/sendgrid-php/zipball/d697c9e1677516314c28d2b946cc3062ee9537ff", + "reference": "d697c9e1677516314c28d2b946cc3062ee9537ff", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "ext-mbstring": "*", + "ext-openssl": "*", + "php": ">=5.6", + "sendgrid/php-http-client": "~3.10" + }, + "replace": { + "sendgrid/sendgrid-php": "*" + }, + "require-dev": { + "phpunit/phpunit": "^5.7.9 || ^6.4.3", + "squizlabs/php_codesniffer": "3.*", + "swaggest/json-diff": "^3.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "SendGrid\\": "lib/", + "SendGrid\\Mail\\": "lib/mail/", + "SendGrid\\Contacts\\": "lib/contacts/", + "SendGrid\\Stats\\": "lib/stats/" + }, + "files": [ + "lib/SendGrid.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "This library allows you to quickly and easily send emails through Twilio SendGrid using PHP.", + "homepage": "http://github.com/sendgrid/sendgrid-php", + "keywords": [ + "email", + "grid", + "send", + "sendgrid", + "twilio sendgrid" + ], + "time": "2020-01-22T20:59:57+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": true, + "prefer-lowest": false, + "platform": { + "ext-curl": "*", + "ext-json": "*", + "php": "^7.1" + }, + "platform-dev": [] +} diff --git a/config/empty b/config/empty new file mode 100644 index 0000000..e69de29 diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..406bec0 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,12 @@ +sonar.projectKey=post-sendgrid +sonar.projectName=Post SendGrid +sonar.projectVersion=1.0 +sonar.sources=src +sonar.language=php +sonar.sourceEncoding=UTF-8 +sonar.issue.ignore.multicriteria=e1 +sonar.issue.ignore.multicriteria.e1.ruleKey=php:S1192 +sonar.issue.ignore.multicriteria.e1.resourceKey=**/*.php +#sonar.tests=tests +sonar.php.tests.reportPath=.tests/junit.xml +sonar.php.coverage.reportPath=.tests/coverage-clover.xml \ No newline at end of file diff --git a/src/Application.php b/src/Application.php new file mode 100644 index 0000000..04fd96a --- /dev/null +++ b/src/Application.php @@ -0,0 +1,117 @@ + + * @copyright 2020 Pittica S.r.l.s. (https://pittica.com) + * @license https://opensource.org/licenses/mit-license.php MIT License + * @link https://pittica.com Pittica S.r.l.s. + * @since 1.0.0 + */ + +namespace Pittica\PostSendGrid; + +use SendGrid\Mail\Mail; + +/** + * Application main class. + * @package Pittica\PostSendGrid + * @author Lucio Benini + * @since 1.0.0 + */ +class Application +{ + /** + * The configuration. + * @var array + * @author Lucio Benini + * @since 1.0.0 + */ + private $_config = []; + + /** + * Application constructor. + * @throws \Exception Method is not POST. + * @author Lucio Benini + * @since 1.0.0 + */ + public function __construct() + { + $server = new Server; + + if (!$server->isPost()) { + http_response_code(200); + + header('Access-Control-Allow-Methods: GET, POST, OPTIONS'); + header('Access-Control-Allow-Headers: Authorization, Content-Type, Accept, Origin'); + + exit(0); + } + + $config = new Configuration; + $this->_config = $config->get(); + } + + /** + * Runs the application. + * @return void + * @throws \SendGrid\Mail\TypeException + * @author Lucio Benini + * @since 1.0.0 + */ + public function run(): void + { + $recaptha = new ReCaptcha; + + if ($recaptha->validate()) { + $vars = new BodyParts(); + $message = new Mail(); + $email = $vars->getAddress(); + $subject = $vars->getSubject(); + $name = $vars->getName(); + + if (!$name) { + $name = $email; + } + + $message->setFrom($email, $name); + $message->setSubject($subject ? $subject : ('Message from: ' . $name)); + $message->addTo($this->_config['sender']['address'], $this->_config['sender']['name']); + $message->addContent("text/plain", $vars->toString()); + $message->addContent("text/html", $vars->toHTML()); + $client = new \SendGrid($this->_config['api']['key']); + + header('Content-type:application/json;charset=utf-8'); + + try { + $this->_respond($client->send($message)->statusCode()); + } catch (\Exception $e) { + $this->_respond(500); + } + } + + $this->_respond(403); + } + + /** + * Prepares and output the JSON response. + * @param int $code HTTP code. + * @author Lucio Benini + * @since 1.0.0 + */ + protected function _respond(int $code): void + { + http_response_code($code); + + die(json_encode([ + 'error' => $code < 200 || $code >= 300 + ])); + } +} diff --git a/src/BodyParts.php b/src/BodyParts.php new file mode 100644 index 0000000..502e05c --- /dev/null +++ b/src/BodyParts.php @@ -0,0 +1,203 @@ + + * @copyright 2020 Pittica S.r.l.s. (https://pittica.com) + * @license https://opensource.org/licenses/mit-license.php MIT License + * @link https://pittica.com Pittica S.r.l.s. + * @since 1.0.0 + */ + +namespace Pittica\PostSendGrid; + +/** + * Represents the form variables and message body parts. + * @package Pittica\PostSendGrid + * @author Lucio Benini + * @since 1.0.0 + */ +class BodyParts +{ + /** + * The configuration. + * @var array + * @author Lucio Benini + * @since 1.0.0 + */ + private $_config = []; + + /** + * The variables. + * @var array + * @author Lucio Benini + * @since 1.0.0 + */ + private $_vars = []; + + /** + * The formatted variables. + * @var array + * @author Lucio Benini + * @since 1.0.0 + */ + private $_parts = []; + + /** + * BodyParts constructor. + * @author Lucio Benini + * @since 1.0.0 + */ + public function __construct() + { + $config = new Configuration; + + $this->_config = $config->get('fields'); + $this->_vars = $this->_processFields(); + $this->_parts = $this->_formatFields(); + } + + /** + * Gets the e-mail address. + * @return string The e-mail address. + * @author Lucio Benini + * @since 1.0.0 + */ + public function getAddress(): string + { + return $this->_getValue('email'); + } + + /** + * Gets the sender's name. + * @return string The sender's name. + * @author Lucio Benini + * @since 1.0.0 + */ + public function getName(): string + { + return $this->_getValue('name'); + } + + /** + * Gets the subject. + * @return string The subject. + * @author Lucio Benini + * @since 1.0.0 + */ + public function getSubject(): string + { + return $this->_getValue('subject'); + } + + /** + * Gets a value from the raw variables. + * @param string $key The key of the associated value. + * @return string A value from the raw variables. + * @author Lucio Benini + * @since 1.0.0 + */ + protected function _getValue(string $key): string + { + return !empty($this->_vars[$this->_config[$key]]) ? $this->_vars[$this->_config[$key]] : ''; + } + + /** + * Returns an HTML representation of the current object. + * @return string An HTML representation of the current object. + * @author Lucio Benini + * @since 1.0.0 + */ + public function toHTML(): string + { + $out = ''; + + foreach ($this->_vars as $label => $var) { + $out .= '
  • ' . $label . '

    ' . $var . '
  • '; + } + + return $out; + } + + /** + * Returns a string representation of the current object. + * @return string A string representation of the current object. + * @author Lucio Benini + * @since 1.0.0 + */ + public function toString(): string + { + $out = ''; + + foreach ($this->_vars as $label => $var) { + $out .= $label . ':' . PHP_EOL . $var . PHP_EOL . PHP_EOL; + } + + return $out; + } + + /** + * Returns a string representation of the current object. + * @return string A string representation of the current object. + * @author Lucio Benini + * @since 1.0.0 + */ + public function __toString(): string + { + return $this->toString(); + } + + /** + * Formats an array of form variables in an array of label/value. + * @return array An array of label/value. + * @author Lucio Benini + * @since 1.0.0 + */ + protected function _formatFields(): array + { + if (!empty($this->_config['labels'])) { + $res = []; + + foreach ($this->_vars as $key => $value) { + if (!empty($this->_config['labels'][$key])) { + $res[$this->_config['labels'][$key]] = $value; + } + } + + return $res; + } + + return $this->_vars; + } + + /** + * Processes an array of form variables. + * @return array An array of variables. + * @author Lucio Benini + * @since 1.0.0 + */ + protected function _processFields(): array + { + $res = []; + $fields = array_merge([$this->_config['email'], $this->_config['subject'], $this->_config['name']], $this->_config['whitelisted']); + + if (!empty($fields)) { + $server = new Server; + + foreach ($server->getFields() as $key => $var) { + if (in_array($key, $fields)) { + $res[$key] = $var; + } + } + } + + return $res; + } +} diff --git a/src/Configuration.php b/src/Configuration.php new file mode 100644 index 0000000..140ff71 --- /dev/null +++ b/src/Configuration.php @@ -0,0 +1,62 @@ + + * @copyright 2020 Pittica S.r.l.s. (https://pittica.com) + * @license https://opensource.org/licenses/mit-license.php MIT License + * @link https://pittica.com Pittica S.r.l.s. + * @since 1.0.0 + */ + +namespace Pittica\PostSendGrid; + +/** + * Configuration reader. + * @package Pittica\PostSendGrid + * @author Lucio Benini + * @since 1.0.0 + */ +class Configuration +{ + /** + * The configuration data. + * @var array + * @author Lucio Benini + * @since 1.0.0 + */ + private $_data = []; + + /** + * Configuration constructor. + * @author Lucio Benini + * @since 1.0.0 + */ + public function __construct() + { + $this->_data = include '..' . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'app.php'; + } + + /** + * Gets configuration data. + * @param $key string Configuration key. + * @return array|string|null The configuration data. + * @author Lucio Benini + * @since 1.0.0 + */ + public function get(string $key = '') + { + if (empty($key)) { + return $this->_data; + } + + return !empty($this->_data[$key]) ? $this->_data[$key] : null; + } +} \ No newline at end of file diff --git a/src/ReCaptcha.php b/src/ReCaptcha.php new file mode 100644 index 0000000..5bf0689 --- /dev/null +++ b/src/ReCaptcha.php @@ -0,0 +1,71 @@ + + * @copyright 2020 Pittica S.r.l.s. (https://pittica.com) + * @license https://opensource.org/licenses/mit-license.php MIT License + * @link https://pittica.com Pittica S.r.l.s. + * @since 1.0.0 + */ + +namespace Pittica\PostSendGrid; + +/** + * ReCaptcha client. + * @package Pittica\PostSendGrid + * @author Lucio Benini + * @since 1.0.0 + */ +class ReCaptcha +{ + /** + * The configuration. + * @var array + * @author Lucio Benini + * @since 1.0.0 + */ + private $_config = []; + + /** + * Application constructor. + * @author Lucio Benini + * @since 1.0.0 + */ + public function __construct() + { + $config = new Configuration; + $this->_config = $config->get('recaptcha'); + } + + /** + * Validates the captcha input. + * @return bool A value indicating whether the request has been validated. + * @author Lucio Benini + * @since 1.0.0 + */ + public function validate(): bool + { + if (!empty($this->_config)) { + $server = new Server; + $response = $server->getField($this->_config['field']); + + if ($response) { + $recaptcha = new \ReCaptcha\ReCaptcha($this->_config['key']); + + return $recaptcha->verify($response, $server->getRemoteAddress())->isSuccess(); + } + + return false; + } + + return true; + } +} diff --git a/src/Server.php b/src/Server.php new file mode 100644 index 0000000..2cf9f0a --- /dev/null +++ b/src/Server.php @@ -0,0 +1,94 @@ + + * @copyright 2020 Pittica S.r.l.s. (https://pittica.com) + * @license https://opensource.org/licenses/mit-license.php MIT License + * @link https://pittica.com Pittica S.r.l.s. + * @since 1.0.0 + */ + +namespace Pittica\PostSendGrid; + +use GuzzleHttp\Psr7\ServerRequest; + +/** + * Server. + * @package Pittica\PostSendGrid + * @author Lucio Benini + * @since 1.0.0 + */ +class Server +{ + /** + * Gets the address of the request. + * @return string The address of the request. + * @author Lucio Benini + * @since 1.0.0 + */ + public function getRemoteAddress(): string + { + $request = ServerRequest::fromGlobals(); + $params = $request->getServerParams(); + + return $params['REMOTE_ADDR']; + } + + /** + * Determines whether the request is POST. + * @return bool A value indicating whether the request is POST. + * @author Lucio Benini + * @since 1.0.0 + */ + public function isPost(): bool + { + $request = ServerRequest::fromGlobals(); + $params = $request->getServerParams(); + + return $params['REQUEST_METHOD'] === 'POST'; + } + + /** + * Gets fields from request. + * @return array The fields from the current request. + * @author Lucio Benini + * @since 1.0.0 + */ + public function getFields(): array + { + $request = ServerRequest::fromGlobals(); + $body = $request->getParsedBody(); + + if (is_array($body)) { + return $body; + } + + return []; + } + + /** + * Gets a field from request. + * @param $key string The key of the field. + * @return string A field from the current request. + * @author Lucio Benini + * @since 1.0.0 + */ + public function getField(string $key): string + { + $body = $this->getFields(); + + if (!empty($body[$key])) { + return $body[$key]; + } + + return ''; + } +} diff --git a/web.config b/web.config new file mode 100644 index 0000000..398285c --- /dev/null +++ b/web.config @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/webroot/index.php b/webroot/index.php new file mode 100644 index 0000000..629e819 --- /dev/null +++ b/webroot/index.php @@ -0,0 +1,24 @@ + + * @copyright 2020 Pittica S.r.l.s. (https://pittica.com) + * @license https://opensource.org/licenses/mit-license.php MIT License + * @link https://pittica.com Pittica S.r.l.s. + * @since 1.0.0 + */ + +require dirname(__DIR__) . '/vendor/autoload.php'; + +use Pittica\PostSendGrid\Application; + +$application = new Application(); +$application->run(); \ No newline at end of file