From 0b325bc3c7f19f21887386f864371efab47c470b Mon Sep 17 00:00:00 2001 From: mohith2883 <88938356+mohith2883@users.noreply.github.com> Date: Thu, 27 Oct 2022 19:08:35 +0530 Subject: [PATCH 001/106] remove authors --- README.md | 7 -- composer.json | 7 +- composer.lock | 289 +++++--------------------------------------------- 3 files changed, 30 insertions(+), 273 deletions(-) diff --git a/README.md b/README.md index 3baa3047..445406d1 100644 --- a/README.md +++ b/README.md @@ -135,13 +135,6 @@ To run static code analysis, use the following Psalm command: composer lint ``` -## Authors - -**Jake Barnby** - -+ [https://github.com/abnegate](https://github.com/abnegate) -+ [https://nz.linkedin.com/in/jakebarnby](https://nz.linkedin.com/in/jakebarnby) - ## Copyright and license The MIT License (MIT) [http://www.opensource.org/licenses/mit-license.php](http://www.opensource.org/licenses/mit-license.php) diff --git a/composer.json b/composer.json index e94220b3..9d7ea922 100644 --- a/composer.json +++ b/composer.json @@ -10,12 +10,7 @@ "lint": "vendor/bin/phpcs", "format": "vendor/bin/phpcbf" }, - "authors": [ - { - "name": "Jake Barnby", - "email": "jake@appwrite.io" - } - ], + "autoload": { "psr-4": { "Utopia\\Messaging\\": "src/Utopia/Messaging" diff --git a/composer.lock b/composer.lock index 88f16b81..5048a18e 100644 --- a/composer.lock +++ b/composer.lock @@ -44,13 +44,7 @@ "license": [ "MIT" ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" - } - ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", "homepage": "https://www.doctrine-project.org/projects/instantiator.html", "keywords": [ @@ -176,11 +170,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Nikita Popov" - } - ], + "description": "A PHP parser written in PHP", "keywords": [ "parser", @@ -228,23 +218,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", "support": { "issues": "https://github.com/phar-io/manifest/issues", @@ -279,23 +253,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], + "description": "Library for handling version information and constraints", "support": { "issues": "https://github.com/phar-io/version/issues", @@ -351,23 +309,7 @@ "license": [ "LGPL-2.1-only" ], - "authors": [ - { - "name": "Marcus Bointon", - "email": "phpmailer@synchromedia.co.uk" - }, - { - "name": "Jim Jagielski", - "email": "jimjag@gmail.com" - }, - { - "name": "Andy Prevost", - "email": "codeworxtech@users.sourceforge.net" - }, - { - "name": "Brent R. Matzelle" - } - ], + "description": "PHPMailer is a full-featured email creation and transfer class for PHP", "support": { "issues": "https://github.com/PHPMailer/PHPMailer/issues", @@ -432,13 +374,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", "homepage": "https://github.com/sebastianbergmann/php-code-coverage", "keywords": [ @@ -493,13 +429,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", "keywords": [ @@ -557,13 +487,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], + "description": "Invoke callables with a timeout", "homepage": "https://github.com/sebastianbergmann/php-invoker/", "keywords": [ @@ -616,13 +540,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], + "description": "Simple template engine.", "homepage": "https://github.com/sebastianbergmann/php-text-template/", "keywords": [ @@ -675,13 +593,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], + "description": "Utility class for timing", "homepage": "https://github.com/sebastianbergmann/php-timer/", "keywords": [ @@ -767,13 +679,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], + "description": "The PHP Unit Testing framework.", "homepage": "https://phpunit.de/", "keywords": [ @@ -836,13 +742,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], + "description": "Library for parsing CLI options", "homepage": "https://github.com/sebastianbergmann/cli-parser", "support": { @@ -892,13 +792,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], + "description": "Collection of value objects that represent the PHP code units", "homepage": "https://github.com/sebastianbergmann/code-unit", "support": { @@ -948,12 +842,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], + "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { @@ -1005,24 +894,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - } - ], + "description": "Provides the functionality to compare PHP values for equality", "homepage": "https://github.com/sebastianbergmann/comparator", "keywords": [ @@ -1078,13 +950,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], + "description": "Library for calculating the complexity of PHP code units", "homepage": "https://github.com/sebastianbergmann/complexity", "support": { @@ -1135,16 +1001,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], + "description": "Diff implementation", "homepage": "https://github.com/sebastianbergmann/diff", "keywords": [ @@ -1203,12 +1060,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], + "description": "Provides functionality to handle HHVM/PHP environments", "homepage": "http://www.github.com/sebastianbergmann/environment", "keywords": [ @@ -1265,28 +1117,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], + "description": "Provides the functionality to export PHP variables for visualization", "homepage": "https://www.github.com/sebastianbergmann/exporter", "keywords": [ @@ -1346,12 +1177,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], + "description": "Snapshotting of global state", "homepage": "http://www.github.com/sebastianbergmann/global-state", "keywords": [ @@ -1405,13 +1231,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], + "description": "Library for counting the lines of code in PHP source code", "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { @@ -1463,12 +1283,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { @@ -1518,12 +1333,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { @@ -1573,20 +1383,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], + "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", "support": { @@ -1636,12 +1433,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], + "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", "support": { @@ -1691,13 +1483,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], + "description": "Collection of value objects that represent the types of the PHP type system", "homepage": "https://github.com/sebastianbergmann/type", "support": { @@ -1744,13 +1530,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", "support": { @@ -1802,12 +1582,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Greg Sherwood", - "role": "lead" - } - ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", "keywords": [ @@ -1851,13 +1626,7 @@ "license": [ "BSD-3-Clause" ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - } - ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", From 599866b5972bf0a842fa21966e21714d5cabda45 Mon Sep 17 00:00:00 2001 From: mohith2883 <88938356+mohith2883@users.noreply.github.com> Date: Sat, 29 Oct 2022 10:32:56 +0530 Subject: [PATCH 002/106] Resolved changes Reverted composer.lock file and removed the new line in composer.json --- composer.json | 1 - composer.lock | 289 +++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 260 insertions(+), 30 deletions(-) diff --git a/composer.json b/composer.json index 9d7ea922..2b351516 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,6 @@ "lint": "vendor/bin/phpcs", "format": "vendor/bin/phpcbf" }, - "autoload": { "psr-4": { "Utopia\\Messaging\\": "src/Utopia/Messaging" diff --git a/composer.lock b/composer.lock index 5048a18e..88f16b81 100644 --- a/composer.lock +++ b/composer.lock @@ -44,7 +44,13 @@ "license": [ "MIT" ], - + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" + } + ], "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", "homepage": "https://www.doctrine-project.org/projects/instantiator.html", "keywords": [ @@ -170,7 +176,11 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Nikita Popov" + } + ], "description": "A PHP parser written in PHP", "keywords": [ "parser", @@ -218,7 +228,23 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", "support": { "issues": "https://github.com/phar-io/manifest/issues", @@ -253,7 +279,23 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], "description": "Library for handling version information and constraints", "support": { "issues": "https://github.com/phar-io/version/issues", @@ -309,7 +351,23 @@ "license": [ "LGPL-2.1-only" ], - + "authors": [ + { + "name": "Marcus Bointon", + "email": "phpmailer@synchromedia.co.uk" + }, + { + "name": "Jim Jagielski", + "email": "jimjag@gmail.com" + }, + { + "name": "Andy Prevost", + "email": "codeworxtech@users.sourceforge.net" + }, + { + "name": "Brent R. Matzelle" + } + ], "description": "PHPMailer is a full-featured email creation and transfer class for PHP", "support": { "issues": "https://github.com/PHPMailer/PHPMailer/issues", @@ -374,7 +432,13 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", "homepage": "https://github.com/sebastianbergmann/php-code-coverage", "keywords": [ @@ -429,7 +493,13 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], "description": "FilterIterator implementation that filters files based on a list of suffixes.", "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", "keywords": [ @@ -487,7 +557,13 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], "description": "Invoke callables with a timeout", "homepage": "https://github.com/sebastianbergmann/php-invoker/", "keywords": [ @@ -540,7 +616,13 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], "description": "Simple template engine.", "homepage": "https://github.com/sebastianbergmann/php-text-template/", "keywords": [ @@ -593,7 +675,13 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], "description": "Utility class for timing", "homepage": "https://github.com/sebastianbergmann/php-timer/", "keywords": [ @@ -679,7 +767,13 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], "description": "The PHP Unit Testing framework.", "homepage": "https://phpunit.de/", "keywords": [ @@ -742,7 +836,13 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], "description": "Library for parsing CLI options", "homepage": "https://github.com/sebastianbergmann/cli-parser", "support": { @@ -792,7 +892,13 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], "description": "Collection of value objects that represent the PHP code units", "homepage": "https://github.com/sebastianbergmann/code-unit", "support": { @@ -842,7 +948,12 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { @@ -894,7 +1005,24 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], "description": "Provides the functionality to compare PHP values for equality", "homepage": "https://github.com/sebastianbergmann/comparator", "keywords": [ @@ -950,7 +1078,13 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], "description": "Library for calculating the complexity of PHP code units", "homepage": "https://github.com/sebastianbergmann/complexity", "support": { @@ -1001,7 +1135,16 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], "description": "Diff implementation", "homepage": "https://github.com/sebastianbergmann/diff", "keywords": [ @@ -1060,7 +1203,12 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], "description": "Provides functionality to handle HHVM/PHP environments", "homepage": "http://www.github.com/sebastianbergmann/environment", "keywords": [ @@ -1117,7 +1265,28 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], "description": "Provides the functionality to export PHP variables for visualization", "homepage": "https://www.github.com/sebastianbergmann/exporter", "keywords": [ @@ -1177,7 +1346,12 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], "description": "Snapshotting of global state", "homepage": "http://www.github.com/sebastianbergmann/global-state", "keywords": [ @@ -1231,7 +1405,13 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], "description": "Library for counting the lines of code in PHP source code", "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { @@ -1283,7 +1463,12 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { @@ -1333,7 +1518,12 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], "description": "Allows reflection of object attributes, including inherited and non-public ones", "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { @@ -1383,7 +1573,20 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", "support": { @@ -1433,7 +1636,12 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", "support": { @@ -1483,7 +1691,13 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], "description": "Collection of value objects that represent the types of the PHP type system", "homepage": "https://github.com/sebastianbergmann/type", "support": { @@ -1530,7 +1744,13 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", "support": { @@ -1582,7 +1802,12 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", "keywords": [ @@ -1626,7 +1851,13 @@ "license": [ "BSD-3-Clause" ], - + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", From 8387f7f838ec64db314cdb93b53667566ea2d54a Mon Sep 17 00:00:00 2001 From: Rutam21 Date: Sun, 30 Oct 2022 21:55:48 +0530 Subject: [PATCH 003/106] Issue-4358: Add Code Linter To utopia-php/messaging --- .github/workflows/linter.yml | 2 + composer.json | 6 +- composer.lock | 124 ++++++++++-------- src/Utopia/Messaging/Adapter.php | 17 +-- src/Utopia/Messaging/Adapters/Email.php | 8 +- .../Messaging/Adapters/Email/Mailgun.php | 11 +- src/Utopia/Messaging/Adapters/Email/Mock.php | 7 +- .../Messaging/Adapters/Email/Sendgrid.php | 6 +- src/Utopia/Messaging/Adapters/Push.php | 8 +- src/Utopia/Messaging/Adapters/Push/FCM.php | 9 +- src/Utopia/Messaging/Adapters/SMS.php | 8 +- src/Utopia/Messaging/Adapters/SMS/Mock.php | 11 +- src/Utopia/Messaging/Adapters/SMS/Msg91.php | 15 ++- .../Messaging/Adapters/SMS/Telesign.php | 15 ++- .../Messaging/Adapters/SMS/TextMagic.php | 11 +- src/Utopia/Messaging/Adapters/SMS/Twilio.php | 13 +- .../Messaging/Adapters/SMS/TwilioNotify.php | 13 +- src/Utopia/Messaging/Adapters/SMS/Vonage.php | 13 +- src/Utopia/Messaging/Messages/Email.php | 12 +- src/Utopia/Messaging/Messages/Push.php | 20 +-- 20 files changed, 179 insertions(+), 150 deletions(-) diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index 4ee16844..ffb8a097 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -11,7 +11,9 @@ jobs: uses: actions/checkout@v3 with: fetch-depth: 2 + - run: git checkout HEAD^2 + - name: Run Linter run: | docker run --rm -v $PWD:/app composer sh -c \ diff --git a/composer.json b/composer.json index e94220b3..4025264c 100644 --- a/composer.json +++ b/composer.json @@ -7,8 +7,8 @@ "minimum-stability": "stable", "scripts": { "test": "vendor/bin/phpunit", - "lint": "vendor/bin/phpcs", - "format": "vendor/bin/phpcbf" + "lint": "./vendor/bin/pint --test", + "format": "./vendor/bin/pint" }, "authors": [ { @@ -34,7 +34,7 @@ "require-dev": { "phpunit/phpunit": "9.5.*", "phpmailer/phpmailer": "6.6.*", - "squizlabs/php_codesniffer": "^3.6" + "laravel/pint": "^1.2" }, "config": { "platform": { diff --git a/composer.lock b/composer.lock index 88f16b81..c2118454 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e33a07c2dd4a4d32669369f3e04a7a21", + "content-hash": "1ca9da311c804e40032e90c09ad04d76", "packages": [], "packages-dev": [ { @@ -77,6 +77,72 @@ ], "time": "2022-03-03T08:28:38+00:00" }, + { + "name": "laravel/pint", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/pint.git", + "reference": "1d276e4c803397a26cc337df908f55c2a4e90d86" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/pint/zipball/1d276e4c803397a26cc337df908f55c2a4e90d86", + "reference": "1d276e4c803397a26cc337df908f55c2a4e90d86", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "ext-tokenizer": "*", + "ext-xml": "*", + "php": "^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.11.0", + "illuminate/view": "^9.27", + "laravel-zero/framework": "^9.1.3", + "mockery/mockery": "^1.5.0", + "nunomaduro/larastan": "^2.2", + "nunomaduro/termwind": "^1.14.0", + "pestphp/pest": "^1.22.1" + }, + "bin": [ + "builds/pint" + ], + "type": "project", + "autoload": { + "psr-4": { + "App\\": "app/", + "Database\\Seeders\\": "database/seeders/", + "Database\\Factories\\": "database/factories/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "An opinionated code formatter for PHP.", + "homepage": "https://laravel.com", + "keywords": [ + "format", + "formatter", + "lint", + "linter", + "php" + ], + "support": { + "issues": "https://github.com/laravel/pint/issues", + "source": "https://github.com/laravel/pint" + }, + "time": "2022-09-13T15:07:15+00:00" + }, { "name": "myclabs/deep-copy", "version": "1.11.0", @@ -1765,62 +1831,6 @@ ], "time": "2020-09-28T06:39:44+00:00" }, - { - "name": "squizlabs/php_codesniffer", - "version": "3.7.1", - "source": { - "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619", - "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619", - "shasum": "" - }, - "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" - }, - "bin": [ - "bin/phpcs", - "bin/phpcbf" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Greg Sherwood", - "role": "lead" - } - ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", - "keywords": [ - "phpcs", - "standards" - ], - "support": { - "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", - "source": "https://github.com/squizlabs/PHP_CodeSniffer", - "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" - }, - "time": "2022-06-18T07:21:10+00:00" - }, { "name": "theseer/tokenizer", "version": "1.2.1", diff --git a/src/Utopia/Messaging/Adapter.php b/src/Utopia/Messaging/Adapter.php index 83422709..38ae9496 100644 --- a/src/Utopia/Messaging/Adapter.php +++ b/src/Utopia/Messaging/Adapter.php @@ -35,7 +35,7 @@ abstract public function getMaxMessagesPerRequest(): int; /** * Send a message. * - * @param Message $message The message to send. + * @param Message $message The message to send. * @return string The response body. */ abstract public function send(Message $message): string; @@ -43,11 +43,12 @@ abstract public function send(Message $message): string; /** * Send an HTTP request. * - * @param string $method The HTTP method to use. - * @param string $url The URL to send the request to. - * @param array $headers An array of headers to send with the request. - * @param string|null $body The body of the request. + * @param string $method The HTTP method to use. + * @param string $url The URL to send the request to. + * @param array $headers An array of headers to send with the request. + * @param string|null $body The body of the request. * @return string The response body. + * * @throws \Exception If the request fails. */ protected function request( @@ -56,7 +57,7 @@ protected function request( array $headers = [], mixed $body = null, ): string { - $headers[] = 'Content-length: ' . \strlen($body); + $headers[] = 'Content-length: '.\strlen($body); $ch = \curl_init(); @@ -66,14 +67,14 @@ protected function request( \curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); \curl_setopt($ch, CURLOPT_USERAGENT, "Appwrite {$this->getName()} Message Sender"); - if (!is_null($body)) { + if (! is_null($body)) { \curl_setopt($ch, CURLOPT_POSTFIELDS, $body); } $response = \curl_exec($ch); if (\curl_errno($ch)) { - throw new \Exception('Error:' . \curl_error($ch)); + throw new \Exception('Error:'.\curl_error($ch)); } if (\curl_getinfo($ch, CURLINFO_HTTP_CODE) >= 400) { throw new \Exception($response); diff --git a/src/Utopia/Messaging/Adapters/Email.php b/src/Utopia/Messaging/Adapters/Email.php index 4cfff3fc..55318e46 100644 --- a/src/Utopia/Messaging/Adapters/Email.php +++ b/src/Utopia/Messaging/Adapters/Email.php @@ -19,24 +19,26 @@ public function getMessageType(): string } /** - * @inheritdoc + * {@inheritdoc} + * * @throws \Exception */ public function send(Message $message): string { - if (!\is_a($message, $this->getMessageType())) { + if (! \is_a($message, $this->getMessageType())) { throw new \Exception('Invalid message type.'); } if (\count($message->getTo()) > $this->getMaxMessagesPerRequest()) { throw new \Exception("{$this->getName()} can only send {$this->getMaxMessagesPerRequest()} messages per request."); } + return $this->process($message); } /** * Process an email message. * - * @param EmailMessage $message Message to process. + * @param EmailMessage $message Message to process. * @return string The response body. */ abstract protected function process(EmailMessage $message): string; diff --git a/src/Utopia/Messaging/Adapters/Email/Mailgun.php b/src/Utopia/Messaging/Adapters/Email/Mailgun.php index 1e022f04..872d6b09 100644 --- a/src/Utopia/Messaging/Adapters/Email/Mailgun.php +++ b/src/Utopia/Messaging/Adapters/Email/Mailgun.php @@ -2,14 +2,14 @@ namespace Utopia\Messaging\Adapters\Email; -use Utopia\Messaging\Messages\Email; use Utopia\Messaging\Adapters\Email as EmailAdapter; +use Utopia\Messaging\Messages\Email; class Mailgun extends EmailAdapter { /** - * @param string $apiKey Your Mailgun API key to authenticate with the API. - * @param string $domain Your Mailgun domain to send messages from. + * @param string $apiKey Your Mailgun API key to authenticate with the API. + * @param string $domain Your Mailgun domain to send messages from. */ public function __construct( private string $apiKey, @@ -28,7 +28,8 @@ public function getMaxMessagesPerRequest(): int } /** - * @inheritdoc + * {@inheritdoc} + * * @throws \Exception */ protected function process(Email $message): string @@ -37,7 +38,7 @@ protected function process(Email $message): string method: 'POST', url: "https://api.mailgun.net/v3/{$this->domain}/messages", headers: [ - 'Authorization: Basic ' . base64_encode('api:' . $this->apiKey) + 'Authorization: Basic '.base64_encode('api:'.$this->apiKey), ], body: [ 'from' => $message->getFrom(), diff --git a/src/Utopia/Messaging/Adapters/Email/Mock.php b/src/Utopia/Messaging/Adapters/Email/Mock.php index c13a43fa..0f326106 100644 --- a/src/Utopia/Messaging/Adapters/Email/Mock.php +++ b/src/Utopia/Messaging/Adapters/Email/Mock.php @@ -4,8 +4,8 @@ use PHPMailer\PHPMailer\Exception; use PHPMailer\PHPMailer\PHPMailer; -use Utopia\Messaging\Messages\Email; use Utopia\Messaging\Adapters\Email as EmailAdapter; +use Utopia\Messaging\Messages\Email; class Mock extends EmailAdapter { @@ -21,7 +21,8 @@ public function getMaxMessagesPerRequest(): int } /** - * @inheritdoc + * {@inheritdoc} + * * @throws Exception * @throws \Exception */ @@ -49,7 +50,7 @@ protected function process(Email $message): string $mail->addAddress($to); } - if (!$mail->send()) { + if (! $mail->send()) { throw new \Exception($mail->ErrorInfo); } diff --git a/src/Utopia/Messaging/Adapters/Email/Sendgrid.php b/src/Utopia/Messaging/Adapters/Email/Sendgrid.php index dc0ec8e3..17745c48 100644 --- a/src/Utopia/Messaging/Adapters/Email/Sendgrid.php +++ b/src/Utopia/Messaging/Adapters/Email/Sendgrid.php @@ -2,8 +2,8 @@ namespace Utopia\Messaging\Adapters\Email; -use Utopia\Messaging\Messages\Email; use Utopia\Messaging\Adapters\Email as EmailAdapter; +use Utopia\Messaging\Messages\Email; class Sendgrid extends EmailAdapter { @@ -28,14 +28,14 @@ protected function process(Email $message): string method: 'POST', url: 'https://api.sendgrid.com/v3/mail/send', headers: [ - 'Authorization: Bearer ' . $this->apiKey, + 'Authorization: Bearer '.$this->apiKey, 'Content-Type: application/json', ], body: \json_encode([ 'personalizations' => [ [ 'to' => \array_map( - fn($to) => ['email' => $to], + fn ($to) => ['email' => $to], $message->getTo() ), 'subject' => $message->getSubject(), diff --git a/src/Utopia/Messaging/Adapters/Push.php b/src/Utopia/Messaging/Adapters/Push.php index 419fc987..6d96d9c4 100644 --- a/src/Utopia/Messaging/Adapters/Push.php +++ b/src/Utopia/Messaging/Adapters/Push.php @@ -19,24 +19,26 @@ public function getMessageType(): string } /** - * @inheritdoc + * {@inheritdoc} + * * @throws \Exception */ public function send(Message $message): string { - if (!\is_a($message, $this->getMessageType())) { + if (! \is_a($message, $this->getMessageType())) { throw new \Exception('Invalid message type.'); } if (\count($message->getTo()) > $this->getMaxMessagesPerRequest()) { throw new \Exception("{$this->getName()} can only send {$this->getMaxMessagesPerRequest()} messages per request."); } + return $this->process($message); } /** * Send a push message. * - * @param PushMessage $message Message to process. + * @param PushMessage $message Message to process. * @return string The response body. */ abstract protected function process(PushMessage $message): string; diff --git a/src/Utopia/Messaging/Adapters/Push/FCM.php b/src/Utopia/Messaging/Adapters/Push/FCM.php index 4205dc8f..3734b16d 100644 --- a/src/Utopia/Messaging/Adapters/Push/FCM.php +++ b/src/Utopia/Messaging/Adapters/Push/FCM.php @@ -2,13 +2,13 @@ namespace Utopia\Messaging\Adapters\Push; -use Utopia\Messaging\Messages\Push; use Utopia\Messaging\Adapters\Push as PushAdapter; +use Utopia\Messaging\Messages\Push; class FCM extends PushAdapter { /** - * @param string $serverKey The FCM server key. + * @param string $serverKey The FCM server key. */ public function __construct( private string $serverKey, @@ -26,7 +26,8 @@ public function getMaxMessagesPerRequest(): int } /** - * @inheritdoc + * {@inheritdoc} + * * @throws \Exception */ protected function process(Push $message): string @@ -35,7 +36,7 @@ protected function process(Push $message): string method: 'POST', url: 'https://fcm.googleapis.com/fcm/send', headers: [ - "Content-Type: application/json", + 'Content-Type: application/json', "Authorization: key={$this->serverKey}", ], body: \json_encode([ diff --git a/src/Utopia/Messaging/Adapters/SMS.php b/src/Utopia/Messaging/Adapters/SMS.php index 7b28dff8..5a2b6c4e 100644 --- a/src/Utopia/Messaging/Adapters/SMS.php +++ b/src/Utopia/Messaging/Adapters/SMS.php @@ -19,24 +19,26 @@ public function getMessageType(): string } /** - * @inheritdoc + * {@inheritdoc} + * * @throws \Exception */ public function send(Message $message): string { - if (!\is_a($message, $this->getMessageType())) { + if (! \is_a($message, $this->getMessageType())) { throw new \Exception('Invalid message type.'); } if (\count($message->getTo()) > $this->getMaxMessagesPerRequest()) { throw new \Exception("{$this->getName()} can only send {$this->getMaxMessagesPerRequest()} messages per request."); } + return $this->process($message); } /** * Send an SMS message. * - * @param SMSMessage $message Message to send. + * @param SMSMessage $message Message to send. * @return string The response body. */ abstract protected function process(SMSMessage $message): string; diff --git a/src/Utopia/Messaging/Adapters/SMS/Mock.php b/src/Utopia/Messaging/Adapters/SMS/Mock.php index 8a29890b..a9cd0eb8 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Mock.php +++ b/src/Utopia/Messaging/Adapters/SMS/Mock.php @@ -2,14 +2,14 @@ namespace Utopia\Messaging\Adapters\SMS; -use Utopia\Messaging\Messages\SMS; use Utopia\Messaging\Adapters\SMS as SMSAdapter; +use Utopia\Messaging\Messages\SMS; class Mock extends SMSAdapter { /** - * @param string $user User ID - * @param string $secret User secret + * @param string $user User ID + * @param string $secret User secret */ public function __construct( private string $user, @@ -28,7 +28,8 @@ public function getMaxMessagesPerRequest(): int } /** - * @inheritdoc + * {@inheritdoc} + * * @throws \Exception */ protected function process(SMS $message): string @@ -37,7 +38,7 @@ protected function process(SMS $message): string method: 'POST', url: 'http://request-catcher:5000/mock-sms', headers: [ - "content-type: application/json", + 'content-type: application/json', "x-username: {$this->user}", "x-key: {$this->secret}", ], diff --git a/src/Utopia/Messaging/Adapters/SMS/Msg91.php b/src/Utopia/Messaging/Adapters/SMS/Msg91.php index a83e143d..82b2527d 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Msg91.php +++ b/src/Utopia/Messaging/Adapters/SMS/Msg91.php @@ -2,8 +2,8 @@ namespace Utopia\Messaging\Adapters\SMS; -use Utopia\Messaging\Messages\SMS; use Utopia\Messaging\Adapters\SMS as SMSAdapter; +use Utopia\Messaging\Messages\SMS; // Reference Material // https://docs.msg91.com/p/tf9GTextN/e/7WESqQ4RLu/MSG91 @@ -11,8 +11,8 @@ class Msg91 extends SMSAdapter { /** - * @param string $senderId Msg91 Sender ID - * @param string $authKey Msg91 Auth Key + * @param string $senderId Msg91 Sender ID + * @param string $authKey Msg91 Auth Key */ public function __construct( private string $senderId, @@ -32,13 +32,14 @@ public function getMaxMessagesPerRequest(): int } /** - * @inheritdoc + * {@inheritdoc} + * * @throws \Exception */ protected function process(SMS $message): string { $to = \array_map( - fn($to) => ['mobiles' => \ltrim($to, '+')], + fn ($to) => ['mobiles' => \ltrim($to, '+')], $message->getTo() ); @@ -46,14 +47,14 @@ protected function process(SMS $message): string method: 'POST', url: 'https://api.msg91.com/api/v5/flow/', headers: [ - "content-type: application/json", + 'content-type: application/json', "authkey: {$this->authKey}", ], body: \json_encode([ 'sender' => $this->senderId, 'otp' => $message->getContent(), 'flow_id' => $message->getFrom(), - 'recipients' => [$to] + 'recipients' => [$to], ]), ); } diff --git a/src/Utopia/Messaging/Adapters/SMS/Telesign.php b/src/Utopia/Messaging/Adapters/SMS/Telesign.php index 7cef0f45..96b60042 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Telesign.php +++ b/src/Utopia/Messaging/Adapters/SMS/Telesign.php @@ -2,8 +2,8 @@ namespace Utopia\Messaging\Adapters\SMS; -use Utopia\Messaging\Messages\SMS; use Utopia\Messaging\Adapters\SMS as SMSAdapter; +use Utopia\Messaging\Messages\SMS; // Reference Material // https://developer.telesign.com/enterprise/reference/sendbulksms @@ -11,8 +11,8 @@ class Telesign extends SMSAdapter { /** - * @param string $username Telesign account username - * @param string $password Telesign account password + * @param string $username Telesign account username + * @param string $password Telesign account password */ public function __construct( private string $username, @@ -31,13 +31,14 @@ public function getMaxMessagesPerRequest(): int } /** - * @inheritdoc + * {@inheritdoc} + * * @throws \Exception */ protected function process(SMS $message): string { $to = \array_map( - fn($to) => \ltrim($to, '+'), + fn ($to) => \ltrim($to, '+'), $message->getTo() ); @@ -45,11 +46,11 @@ protected function process(SMS $message): string method: 'POST', url: 'https://rest-ww.telesign.com/v1/verify/bulk_sms', headers: [ - 'Authorization: Basic ' . base64_encode("{$this->username}:{$this->password}") + 'Authorization: Basic '.base64_encode("{$this->username}:{$this->password}"), ], body: [ 'template' => $message->getContent(), - 'recipients' => \implode(',', $to) + 'recipients' => \implode(',', $to), ], ); } diff --git a/src/Utopia/Messaging/Adapters/SMS/TextMagic.php b/src/Utopia/Messaging/Adapters/SMS/TextMagic.php index a78a97dc..e941f3a5 100644 --- a/src/Utopia/Messaging/Adapters/SMS/TextMagic.php +++ b/src/Utopia/Messaging/Adapters/SMS/TextMagic.php @@ -5,14 +5,14 @@ // Reference Material // https://www.textmagic.com/docs/api/send-sms/#How-to-send-bulk-text-messages -use Utopia\Messaging\Messages\SMS; use Utopia\Messaging\Adapters\SMS as SMSAdapter; +use Utopia\Messaging\Messages\SMS; class TextMagic extends SMSAdapter { /** - * @param string $username TextMagic account username - * @param string $apiKey TextMagic account API key + * @param string $username TextMagic account username + * @param string $apiKey TextMagic account API key */ public function __construct( private string $username, @@ -31,13 +31,14 @@ public function getMaxMessagesPerRequest(): int } /** - * @inheritdoc + * {@inheritdoc} + * * @throws \Exception */ protected function process(SMS $message): string { $to = \array_map( - fn($to) => \ltrim($to, '+'), + fn ($to) => \ltrim($to, '+'), $message->getTo() ); diff --git a/src/Utopia/Messaging/Adapters/SMS/Twilio.php b/src/Utopia/Messaging/Adapters/SMS/Twilio.php index 9a65225a..9f28ff2c 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Twilio.php +++ b/src/Utopia/Messaging/Adapters/SMS/Twilio.php @@ -2,14 +2,14 @@ namespace Utopia\Messaging\Adapters\SMS; -use Utopia\Messaging\Messages\SMS; use Utopia\Messaging\Adapters\SMS as SMSAdapter; +use Utopia\Messaging\Messages\SMS; class Twilio extends SMSAdapter { /** - * @param string $accountSid Twilio Account SID - * @param string $authToken Twilio Auth Token + * @param string $accountSid Twilio Account SID + * @param string $authToken Twilio Auth Token */ public function __construct( private string $accountSid, @@ -28,7 +28,8 @@ public function getMaxMessagesPerRequest(): int } /** - * @inheritdoc + * {@inheritdoc} + * * @throws \Exception */ protected function process(SMS $message): string @@ -37,12 +38,12 @@ protected function process(SMS $message): string method: 'POST', url: "https://api.twilio.com/2010-04-01/Accounts/{$this->accountSid}/Messages.json", headers: [ - 'Authorization: Basic ' . base64_encode("{$this->accountSid}:{$this->authToken}") + 'Authorization: Basic '.base64_encode("{$this->accountSid}:{$this->authToken}"), ], body: \http_build_query([ 'Body' => $message->getContent(), 'From' => $message->getFrom(), - 'To' => $message->getTo()[0] + 'To' => $message->getTo()[0], ]), ); } diff --git a/src/Utopia/Messaging/Adapters/SMS/TwilioNotify.php b/src/Utopia/Messaging/Adapters/SMS/TwilioNotify.php index 64e07d8c..a977ed79 100644 --- a/src/Utopia/Messaging/Adapters/SMS/TwilioNotify.php +++ b/src/Utopia/Messaging/Adapters/SMS/TwilioNotify.php @@ -2,14 +2,14 @@ namespace Utopia\Messaging\Adapters\SMS; -use Utopia\Messaging\Messages\SMS; use Utopia\Messaging\Adapters\SMS as SMSAdapter; +use Utopia\Messaging\Messages\SMS; class TwilioNotify extends SMSAdapter { /** - * @param string $accountSid Twilio Account SID - * @param string $authToken Twilio Auth Token + * @param string $accountSid Twilio Account SID + * @param string $authToken Twilio Auth Token */ public function __construct( private string $accountSid, @@ -29,7 +29,8 @@ public function getMaxMessagesPerRequest(): int } /** - * @inheritdoc + * {@inheritdoc} + * * @throws \Exception */ protected function process(SMS $message): string @@ -38,12 +39,12 @@ protected function process(SMS $message): string method: 'POST', url: "https://notify.twilio.com/v1/Services/{$this->serviceSid}/Notifications", headers: [ - 'Authorization: Basic ' . base64_encode("{$this->accountSid}:{$this->authToken}") + 'Authorization: Basic '.base64_encode("{$this->accountSid}:{$this->authToken}"), ], body: \http_build_query([ 'Body' => $message->getContent(), 'ToBinding' => \json_encode(\array_map( - fn($to) => ['binding_type' => 'sms', 'address' => $to], + fn ($to) => ['binding_type' => 'sms', 'address' => $to], $message->getTo() )), ]), diff --git a/src/Utopia/Messaging/Adapters/SMS/Vonage.php b/src/Utopia/Messaging/Adapters/SMS/Vonage.php index 598029ea..2c945374 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Vonage.php +++ b/src/Utopia/Messaging/Adapters/SMS/Vonage.php @@ -5,14 +5,14 @@ // Reference Material // https://www.textmagic.com/docs/api/send-sms/#How-to-send-bulk-text-messages -use Utopia\Messaging\Messages\SMS; use Utopia\Messaging\Adapters\SMS as SMSAdapter; +use Utopia\Messaging\Messages\SMS; class Vonage extends SMSAdapter { /** - * @param string $apiKey Vonage API Key - * @param string $apiSecret Vonage API Secret + * @param string $apiKey Vonage API Key + * @param string $apiSecret Vonage API Secret */ public function __construct( private string $apiKey, @@ -31,13 +31,14 @@ public function getMaxMessagesPerRequest(): int } /** - * @inheritdoc + * {@inheritdoc} + * * @throws \Exception */ protected function process(SMS $message): string { $to = \array_map( - fn($to) => \ltrim($to, '+'), + fn ($to) => \ltrim($to, '+'), $message->getTo() ); @@ -49,7 +50,7 @@ protected function process(SMS $message): string 'from' => $message->getFrom(), 'to' => \implode(',', $to), 'api_key' => $this->apiKey, - 'api_secret' => $this->apiSecret + 'api_secret' => $this->apiSecret, ] ); } diff --git a/src/Utopia/Messaging/Messages/Email.php b/src/Utopia/Messaging/Messages/Email.php index e13ab30a..21fedeea 100644 --- a/src/Utopia/Messaging/Messages/Email.php +++ b/src/Utopia/Messaging/Messages/Email.php @@ -7,12 +7,12 @@ class Email implements Message { /** - * @param array $to The recipients of the email. - * @param string $subject The subject of the email. - * @param string $content The content of the email. - * @param string|null $from The sender of the email. - * @param array|null $attachments The attachments of the email. - * @param bool $html Whether the message is HTML or not. + * @param array $to The recipients of the email. + * @param string $subject The subject of the email. + * @param string $content The content of the email. + * @param string|null $from The sender of the email. + * @param array|null $attachments The attachments of the email. + * @param bool $html Whether the message is HTML or not. */ public function __construct( private array $to, diff --git a/src/Utopia/Messaging/Messages/Push.php b/src/Utopia/Messaging/Messages/Push.php index 4a86a05e..d4a4333b 100644 --- a/src/Utopia/Messaging/Messages/Push.php +++ b/src/Utopia/Messaging/Messages/Push.php @@ -7,16 +7,16 @@ class Push implements Message { /** - * @param array $to The recipients of the push notification. - * @param string $title The title of the push notification. - * @param string $body The body of the push notification. - * @param array|null $data This parameter specifies the custom key-value pairs of the message's payload. For example, with data:{"score":"3x1"}:

On Apple platforms, if the message is sent via APNs, it represents the custom data fields. If it is sent via FCM, it would be represented as key value dictionary in AppDelegate application:didReceiveRemoteNotification:.

On Android, this would result in an intent extra named score with the string value 3x1.

The key should not be a reserved word ("from", "message_type", or any word starting with "google" or "gcm"). Do not use any of the words defined in this table (such as collapse_key).

Values in string types are recommended. You have to convert values in objects or other non-string data types (e.g., integers or booleans) to string. - * @param string|null $sound The sound to play when the device receives the notification.

On Android, sound files must reside in /res/raw/.

On iOS, sounds files must reside in the main bundle of the client app or in the Library/Sounds folder of the app's data container. - * @param string|null $action The action associated with a user click on the notification.

On Android, this is the activity to launch.

On iOS, this is the category to launch. - * @param string|null $icon Android only. The icon of the push notification. Sets the notification icon to myicon for drawable resource myicon. If you don't send this key in the request, FCM displays the launcher icon specified in your app manifest. - * @param string|null $color Android only. The icon color of the push notification, expressed in #rrggbb format. - * @param string|null $tag Android only. Identifier used to replace existing notifications in the notification drawer.

If not specified, each request creates a new notification.

If specified and a notification with the same tag is already being shown, the new notification replaces the existing one in the notification drawer. - * @param string|null $badge iOS only. The value of the badge on the home screen app icon. If not specified, the badge is not changed. If set to 0, the badge is removed. + * @param array $to The recipients of the push notification. + * @param string $title The title of the push notification. + * @param string $body The body of the push notification. + * @param array|null $data This parameter specifies the custom key-value pairs of the message's payload. For example, with data:{"score":"3x1"}:

On Apple platforms, if the message is sent via APNs, it represents the custom data fields. If it is sent via FCM, it would be represented as key value dictionary in AppDelegate application:didReceiveRemoteNotification:.

On Android, this would result in an intent extra named score with the string value 3x1.

The key should not be a reserved word ("from", "message_type", or any word starting with "google" or "gcm"). Do not use any of the words defined in this table (such as collapse_key).

Values in string types are recommended. You have to convert values in objects or other non-string data types (e.g., integers or booleans) to string. + * @param string|null $sound The sound to play when the device receives the notification.

On Android, sound files must reside in /res/raw/.

On iOS, sounds files must reside in the main bundle of the client app or in the Library/Sounds folder of the app's data container. + * @param string|null $action The action associated with a user click on the notification.

On Android, this is the activity to launch.

On iOS, this is the category to launch. + * @param string|null $icon Android only. The icon of the push notification. Sets the notification icon to myicon for drawable resource myicon. If you don't send this key in the request, FCM displays the launcher icon specified in your app manifest. + * @param string|null $color Android only. The icon color of the push notification, expressed in #rrggbb format. + * @param string|null $tag Android only. Identifier used to replace existing notifications in the notification drawer.

If not specified, each request creates a new notification.

If specified and a notification with the same tag is already being shown, the new notification replaces the existing one in the notification drawer. + * @param string|null $badge iOS only. The value of the badge on the home screen app icon. If not specified, the badge is not changed. If set to 0, the badge is removed. */ public function __construct( private array $to, From 6e5dbb928f2259de59e4c0b6280f2386c074f97e Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 7 Dec 2022 18:29:00 +1300 Subject: [PATCH 004/106] Move send function up to base adapter --- src/Utopia/Messaging/Adapter.php | 12 +++++++++++- src/Utopia/Messaging/Adapters/Email.php | 15 --------------- src/Utopia/Messaging/Adapters/Push.php | 15 --------------- src/Utopia/Messaging/Adapters/SMS.php | 15 --------------- 4 files changed, 11 insertions(+), 46 deletions(-) diff --git a/src/Utopia/Messaging/Adapter.php b/src/Utopia/Messaging/Adapter.php index 83422709..68fd10c0 100644 --- a/src/Utopia/Messaging/Adapter.php +++ b/src/Utopia/Messaging/Adapter.php @@ -37,8 +37,18 @@ abstract public function getMaxMessagesPerRequest(): int; * * @param Message $message The message to send. * @return string The response body. + * @throws \Exception */ - abstract public function send(Message $message): string; + public function send(Message $message): string + { + if (!\is_a($message, $this->getMessageType())) { + throw new \Exception('Invalid message type.'); + } + if (\count($message->getTo()) > $this->getMaxMessagesPerRequest()) { + throw new \Exception("{$this->getName()} can only send {$this->getMaxMessagesPerRequest()} messages per request."); + } + return $this->process($message); + } /** * Send an HTTP request. diff --git a/src/Utopia/Messaging/Adapters/Email.php b/src/Utopia/Messaging/Adapters/Email.php index 4cfff3fc..427485f9 100644 --- a/src/Utopia/Messaging/Adapters/Email.php +++ b/src/Utopia/Messaging/Adapters/Email.php @@ -18,21 +18,6 @@ public function getMessageType(): string return EmailMessage::class; } - /** - * @inheritdoc - * @throws \Exception - */ - public function send(Message $message): string - { - if (!\is_a($message, $this->getMessageType())) { - throw new \Exception('Invalid message type.'); - } - if (\count($message->getTo()) > $this->getMaxMessagesPerRequest()) { - throw new \Exception("{$this->getName()} can only send {$this->getMaxMessagesPerRequest()} messages per request."); - } - return $this->process($message); - } - /** * Process an email message. * diff --git a/src/Utopia/Messaging/Adapters/Push.php b/src/Utopia/Messaging/Adapters/Push.php index 419fc987..e9d8d66b 100644 --- a/src/Utopia/Messaging/Adapters/Push.php +++ b/src/Utopia/Messaging/Adapters/Push.php @@ -18,21 +18,6 @@ public function getMessageType(): string return PushMessage::class; } - /** - * @inheritdoc - * @throws \Exception - */ - public function send(Message $message): string - { - if (!\is_a($message, $this->getMessageType())) { - throw new \Exception('Invalid message type.'); - } - if (\count($message->getTo()) > $this->getMaxMessagesPerRequest()) { - throw new \Exception("{$this->getName()} can only send {$this->getMaxMessagesPerRequest()} messages per request."); - } - return $this->process($message); - } - /** * Send a push message. * diff --git a/src/Utopia/Messaging/Adapters/SMS.php b/src/Utopia/Messaging/Adapters/SMS.php index 7b28dff8..60c84513 100644 --- a/src/Utopia/Messaging/Adapters/SMS.php +++ b/src/Utopia/Messaging/Adapters/SMS.php @@ -18,21 +18,6 @@ public function getMessageType(): string return SMSMessage::class; } - /** - * @inheritdoc - * @throws \Exception - */ - public function send(Message $message): string - { - if (!\is_a($message, $this->getMessageType())) { - throw new \Exception('Invalid message type.'); - } - if (\count($message->getTo()) > $this->getMaxMessagesPerRequest()) { - throw new \Exception("{$this->getName()} can only send {$this->getMaxMessagesPerRequest()} messages per request."); - } - return $this->process($message); - } - /** * Send an SMS message. * From 72fc8b660b5a1629d2252d83a85f7b69ff43ebcb Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 7 Dec 2022 18:40:24 +1300 Subject: [PATCH 005/106] Add discord adapter --- src/Utopia/Messaging/Adapters/Discord.php | 59 +++++++++++++++++++++++ src/Utopia/Messaging/Messages/Discord.php | 40 +++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 src/Utopia/Messaging/Adapters/Discord.php create mode 100644 src/Utopia/Messaging/Messages/Discord.php diff --git a/src/Utopia/Messaging/Adapters/Discord.php b/src/Utopia/Messaging/Adapters/Discord.php new file mode 100644 index 00000000..c1c19207 --- /dev/null +++ b/src/Utopia/Messaging/Adapters/Discord.php @@ -0,0 +1,59 @@ +request( + method: 'POST', + url: "https://discord.com/api/webhooks/{$this->webhookId}/{$this->webhookToken}", + headers: [ + 'Content-Type: application/json', + ], + body: \json_encode([ + 'content' => $message->getContent(), + 'username' => $message->getUsername(), + 'avatar_url' => $message->getAvatarUrl(), + ]), + ); + } +} diff --git a/src/Utopia/Messaging/Messages/Discord.php b/src/Utopia/Messaging/Messages/Discord.php new file mode 100644 index 00000000..c88af4da --- /dev/null +++ b/src/Utopia/Messaging/Messages/Discord.php @@ -0,0 +1,40 @@ +content; + } + + /** + * @return string|null + */ + public function getUsername(): ?string + { + return $this->username; + } + + /** + * @return string|null + */ + public function getAvatarUrl(): ?string + { + return $this->avatarUrl; + } +} \ No newline at end of file From 2cf800fed88cf7cc8f8fe1e8b1b827ed9280c107 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 26 Jan 2023 13:41:03 +1300 Subject: [PATCH 006/106] Fix adapters using application/xxx-form-urlencoded content type --- src/Utopia/Messaging/Adapter.php | 6 +++--- src/Utopia/Messaging/Adapters/Email/Mailgun.php | 6 +++--- src/Utopia/Messaging/Adapters/SMS/Telesign.php | 4 ++-- src/Utopia/Messaging/Adapters/SMS/TextMagic.php | 4 ++-- src/Utopia/Messaging/Adapters/SMS/Vonage.php | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Utopia/Messaging/Adapter.php b/src/Utopia/Messaging/Adapter.php index 38ae9496..7e0846a0 100644 --- a/src/Utopia/Messaging/Adapter.php +++ b/src/Utopia/Messaging/Adapter.php @@ -55,9 +55,9 @@ protected function request( string $method, string $url, array $headers = [], - mixed $body = null, + ?string $body = null, ): string { - $headers[] = 'Content-length: '.\strlen($body); + $headers[] = 'Content-length: ' . \strlen($body); $ch = \curl_init(); @@ -74,7 +74,7 @@ protected function request( $response = \curl_exec($ch); if (\curl_errno($ch)) { - throw new \Exception('Error:'.\curl_error($ch)); + throw new \Exception('Error:' . \curl_error($ch)); } if (\curl_getinfo($ch, CURLINFO_HTTP_CODE) >= 400) { throw new \Exception($response); diff --git a/src/Utopia/Messaging/Adapters/Email/Mailgun.php b/src/Utopia/Messaging/Adapters/Email/Mailgun.php index 872d6b09..6b300a5e 100644 --- a/src/Utopia/Messaging/Adapters/Email/Mailgun.php +++ b/src/Utopia/Messaging/Adapters/Email/Mailgun.php @@ -38,15 +38,15 @@ protected function process(Email $message): string method: 'POST', url: "https://api.mailgun.net/v3/{$this->domain}/messages", headers: [ - 'Authorization: Basic '.base64_encode('api:'.$this->apiKey), + 'Authorization: Basic ' . base64_encode('api:'.$this->apiKey), ], - body: [ + body: \http_build_query([ 'from' => $message->getFrom(), 'to' => \implode(',', $message->getTo()), 'subject' => $message->getSubject(), 'text' => $message->isHtml() ? null : $message->getContent(), 'html' => $message->isHtml() ? $message->getContent() : null, - ], + ]), ); } } diff --git a/src/Utopia/Messaging/Adapters/SMS/Telesign.php b/src/Utopia/Messaging/Adapters/SMS/Telesign.php index 96b60042..d19d5876 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Telesign.php +++ b/src/Utopia/Messaging/Adapters/SMS/Telesign.php @@ -48,10 +48,10 @@ protected function process(SMS $message): string headers: [ 'Authorization: Basic '.base64_encode("{$this->username}:{$this->password}"), ], - body: [ + body: \http_build_query([ 'template' => $message->getContent(), 'recipients' => \implode(',', $to), - ], + ]), ); } } diff --git a/src/Utopia/Messaging/Adapters/SMS/TextMagic.php b/src/Utopia/Messaging/Adapters/SMS/TextMagic.php index e941f3a5..68fb4e37 100644 --- a/src/Utopia/Messaging/Adapters/SMS/TextMagic.php +++ b/src/Utopia/Messaging/Adapters/SMS/TextMagic.php @@ -49,11 +49,11 @@ protected function process(SMS $message): string "X-TM-Username: {$this->username}", "X-TM-Key: {$this->apiKey}", ], - body: [ + body: \http_build_query([ 'text' => $message->getContent(), 'from' => \ltrim($message->getFrom(), '+'), 'phones' => \implode(',', $to), - ], + ]), ); } } diff --git a/src/Utopia/Messaging/Adapters/SMS/Vonage.php b/src/Utopia/Messaging/Adapters/SMS/Vonage.php index 2c945374..2643a6b0 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Vonage.php +++ b/src/Utopia/Messaging/Adapters/SMS/Vonage.php @@ -45,13 +45,13 @@ protected function process(SMS $message): string return $this->request( method: 'POST', url: 'https://rest.nexmo.com/sms/json', - body: [ + body: \http_build_query([ 'text' => $message->getContent(), 'from' => $message->getFrom(), 'to' => \implode(',', $to), 'api_key' => $this->apiKey, 'api_secret' => $this->apiSecret, - ] + ]), ); } } From 0443e4c6ff387c27c18eb0f10d3789a8dec28ac3 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 26 Jan 2023 17:19:34 +1300 Subject: [PATCH 007/106] Format --- src/Utopia/Messaging/Adapter.php | 4 ++-- src/Utopia/Messaging/Adapters/Email/Mailgun.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Utopia/Messaging/Adapter.php b/src/Utopia/Messaging/Adapter.php index 7e0846a0..8c3defce 100644 --- a/src/Utopia/Messaging/Adapter.php +++ b/src/Utopia/Messaging/Adapter.php @@ -57,7 +57,7 @@ protected function request( array $headers = [], ?string $body = null, ): string { - $headers[] = 'Content-length: ' . \strlen($body); + $headers[] = 'Content-length: '.\strlen($body); $ch = \curl_init(); @@ -74,7 +74,7 @@ protected function request( $response = \curl_exec($ch); if (\curl_errno($ch)) { - throw new \Exception('Error:' . \curl_error($ch)); + throw new \Exception('Error: '.\curl_error($ch)); } if (\curl_getinfo($ch, CURLINFO_HTTP_CODE) >= 400) { throw new \Exception($response); diff --git a/src/Utopia/Messaging/Adapters/Email/Mailgun.php b/src/Utopia/Messaging/Adapters/Email/Mailgun.php index 6b300a5e..ba64c906 100644 --- a/src/Utopia/Messaging/Adapters/Email/Mailgun.php +++ b/src/Utopia/Messaging/Adapters/Email/Mailgun.php @@ -38,7 +38,7 @@ protected function process(Email $message): string method: 'POST', url: "https://api.mailgun.net/v3/{$this->domain}/messages", headers: [ - 'Authorization: Basic ' . base64_encode('api:'.$this->apiKey), + 'Authorization: Basic '.base64_encode('api:'.$this->apiKey), ], body: \http_build_query([ 'from' => $message->getFrom(), From 33da81df3118b4273b5f6bcdf39239cfdf477fb9 Mon Sep 17 00:00:00 2001 From: Dovi Cowan Date: Thu, 26 Jan 2023 21:23:01 +0000 Subject: [PATCH 008/106] Implement Telnyx SMS adapter --- src/Utopia/Messaging/Adapters/SMS/Telnyx.php | 50 ++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/Utopia/Messaging/Adapters/SMS/Telnyx.php diff --git a/src/Utopia/Messaging/Adapters/SMS/Telnyx.php b/src/Utopia/Messaging/Adapters/SMS/Telnyx.php new file mode 100644 index 00000000..1cdd8c5e --- /dev/null +++ b/src/Utopia/Messaging/Adapters/SMS/Telnyx.php @@ -0,0 +1,50 @@ +request( + method: 'POST', + url: "https://api.telnyx.com/v2/messages", + headers: [ + 'Authorization: Bearer '.base64_encode($this->apiKey), + 'Content-Type: application/json' + ], + body: \json_encode([ + 'text' => $message->getContent(), + 'from' => $message->getFrom(), + 'to' => $message->getTo()[0], + ]), + ); + } +} From 70d937c4479f0444d67c71fc99d97f89dc621c5e Mon Sep 17 00:00:00 2001 From: Dovi Cowan Date: Thu, 26 Jan 2023 22:11:00 +0000 Subject: [PATCH 009/106] remove base64_encode Telnyx apikey --- src/Utopia/Messaging/Adapters/SMS/Telnyx.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/Telnyx.php b/src/Utopia/Messaging/Adapters/SMS/Telnyx.php index 1cdd8c5e..986f7019 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Telnyx.php +++ b/src/Utopia/Messaging/Adapters/SMS/Telnyx.php @@ -37,7 +37,7 @@ protected function process(SMS $message): string method: 'POST', url: "https://api.telnyx.com/v2/messages", headers: [ - 'Authorization: Bearer '.base64_encode($this->apiKey), + 'Authorization: Bearer '.$this->apiKey, 'Content-Type: application/json' ], body: \json_encode([ From d238169e2304f7a4cae495a12c7a651422b9352a Mon Sep 17 00:00:00 2001 From: Dovi Cowan Date: Thu, 26 Jan 2023 23:20:27 +0000 Subject: [PATCH 010/106] add trailing comma --- src/Utopia/Messaging/Adapters/SMS/Telnyx.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/Telnyx.php b/src/Utopia/Messaging/Adapters/SMS/Telnyx.php index 986f7019..b1feff86 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Telnyx.php +++ b/src/Utopia/Messaging/Adapters/SMS/Telnyx.php @@ -38,7 +38,7 @@ protected function process(SMS $message): string url: "https://api.telnyx.com/v2/messages", headers: [ 'Authorization: Bearer '.$this->apiKey, - 'Content-Type: application/json' + 'Content-Type: application/json', ], body: \json_encode([ 'text' => $message->getContent(), From 05c0f0da67aa4423b8298166d2f6192a31a443fe Mon Sep 17 00:00:00 2001 From: Dovi Cowan Date: Fri, 27 Jan 2023 15:39:59 +0000 Subject: [PATCH 011/106] Update PHPDoc Telnyx api key param --- src/Utopia/Messaging/Adapters/SMS/Telnyx.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/Telnyx.php b/src/Utopia/Messaging/Adapters/SMS/Telnyx.php index b1feff86..431736b5 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Telnyx.php +++ b/src/Utopia/Messaging/Adapters/SMS/Telnyx.php @@ -8,8 +8,7 @@ class Telnyx extends SMSAdapter { /** - * @param string $accountSid Twilio Account SID - * @param string $authToken Twilio Auth Token + * @param string $apiKey Telnyx APIv2 Key */ public function __construct( private string $apiKey, @@ -35,7 +34,7 @@ protected function process(SMS $message): string { return $this->request( method: 'POST', - url: "https://api.telnyx.com/v2/messages", + url: 'https://api.telnyx.com/v2/messages', headers: [ 'Authorization: Bearer '.$this->apiKey, 'Content-Type: application/json', From 15924c012a041c16592e61c1d15b9468f84621c8 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 2 Feb 2023 18:59:34 +1300 Subject: [PATCH 012/106] Avoid strlen null param warning --- src/Utopia/Messaging/Adapter.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Utopia/Messaging/Adapter.php b/src/Utopia/Messaging/Adapter.php index 8c3defce..48982ff0 100644 --- a/src/Utopia/Messaging/Adapter.php +++ b/src/Utopia/Messaging/Adapter.php @@ -57,20 +57,19 @@ protected function request( array $headers = [], ?string $body = null, ): string { - $headers[] = 'Content-length: '.\strlen($body); - $ch = \curl_init(); + if (!\is_null($body)) { + $headers[] = 'Content-Length: ' . \strlen($body); + \curl_setopt($ch, CURLOPT_POSTFIELDS, $body); + } + \curl_setopt($ch, CURLOPT_URL, $url); \curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); \curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); \curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); \curl_setopt($ch, CURLOPT_USERAGENT, "Appwrite {$this->getName()} Message Sender"); - if (! is_null($body)) { - \curl_setopt($ch, CURLOPT_POSTFIELDS, $body); - } - $response = \curl_exec($ch); if (\curl_errno($ch)) { From 0e5e9ba8c2451fc3f976eb1f9a53cbf38b1f3cc4 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 3 Feb 2023 15:52:09 +1300 Subject: [PATCH 013/106] Format --- src/Utopia/Messaging/Adapter.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Utopia/Messaging/Adapter.php b/src/Utopia/Messaging/Adapter.php index 48982ff0..60a909ef 100644 --- a/src/Utopia/Messaging/Adapter.php +++ b/src/Utopia/Messaging/Adapter.php @@ -59,8 +59,8 @@ protected function request( ): string { $ch = \curl_init(); - if (!\is_null($body)) { - $headers[] = 'Content-Length: ' . \strlen($body); + if (! \is_null($body)) { + $headers[] = 'Content-Length: '.\strlen($body); \curl_setopt($ch, CURLOPT_POSTFIELDS, $body); } From 5170f3c05a36d6bd742a3f3de2e1f1e24de65a9b Mon Sep 17 00:00:00 2001 From: byawitz Date: Tue, 28 Mar 2023 23:45:14 -0400 Subject: [PATCH 014/106] Add Plivo SMS adapter --- README.md | 2 +- src/Utopia/Messaging/Adapters/SMS/Plivo.php | 49 +++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 src/Utopia/Messaging/Adapters/SMS/Plivo.php diff --git a/README.md b/README.md index 445406d1..e268cd77 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ $messaging->send($message); - [x] [TextMagic](https://www.textmagic.com/) - [x] [Msg91](https://msg91.com/) - [x] [Vonage](https://www.vonage.com/) -- [ ] [Plivo](https://www.plivo.com/) +- [x] [Plivo](https://www.plivo.com/) - [ ] [Infobip](https://www.infobip.com/) - [ ] [Clickatell](https://www.clickatell.com/) - [ ] [AfricasTalking](https://africastalking.com/) diff --git a/src/Utopia/Messaging/Adapters/SMS/Plivo.php b/src/Utopia/Messaging/Adapters/SMS/Plivo.php new file mode 100644 index 00000000..b53c9df2 --- /dev/null +++ b/src/Utopia/Messaging/Adapters/SMS/Plivo.php @@ -0,0 +1,49 @@ +request( + method: 'POST', + url: "https://api.plivo.com/v1/Account/{$this->authId}/Message/", + headers: [ + 'Authorization: Basic ' . base64_encode("{$this->authId}:{$this->authToken}"), + ], + body: \http_build_query([ + 'text' => $message->getContent(), + 'src' => $message->getFrom(), + 'dst' => \implode('<', $message->getTo()), + ]), + ); + } +} From 5aeadafd663af40f4820c0e6a20c593da71d1c5f Mon Sep 17 00:00:00 2001 From: byawitz Date: Wed, 29 Mar 2023 00:08:31 -0400 Subject: [PATCH 015/106] Add Clickatell SMS adapter --- README.md | 2 +- .../Messaging/Adapters/SMS/Clickatell.php | 49 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 src/Utopia/Messaging/Adapters/SMS/Clickatell.php diff --git a/README.md b/README.md index e268cd77..9c961367 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ $messaging->send($message); - [x] [Vonage](https://www.vonage.com/) - [x] [Plivo](https://www.plivo.com/) - [ ] [Infobip](https://www.infobip.com/) -- [ ] [Clickatell](https://www.clickatell.com/) +- [x] [Clickatell](https://www.clickatell.com/) - [ ] [AfricasTalking](https://africastalking.com/) - [ ] [Sinch](https://www.sinch.com/) - [ ] [Sms77](https://www.sms77.io/) diff --git a/src/Utopia/Messaging/Adapters/SMS/Clickatell.php b/src/Utopia/Messaging/Adapters/SMS/Clickatell.php new file mode 100644 index 00000000..b8edb612 --- /dev/null +++ b/src/Utopia/Messaging/Adapters/SMS/Clickatell.php @@ -0,0 +1,49 @@ +request( + method: 'POST', + url: "https://platform.clickatell.com/messages", + headers: [ + 'content-type: application/json', + 'Authorization: ' . $this->apiKey, + ], + body: \json_encode([ + 'content' => $message->getContent(), + 'from' => $message->getFrom(), + 'to' => $message->getTo(), + ]), + ); + } +} From 72ae558d7fbf481b6a149097aa72f8604387e42a Mon Sep 17 00:00:00 2001 From: byawitz Date: Wed, 29 Mar 2023 00:26:59 -0400 Subject: [PATCH 016/106] Add Infobip SMS adapter --- README.md | 2 +- src/Utopia/Messaging/Adapters/SMS/Infobip.php | 54 +++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 src/Utopia/Messaging/Adapters/SMS/Infobip.php diff --git a/README.md b/README.md index 9c961367..5e6d0ec0 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ $messaging->send($message); - [x] [Msg91](https://msg91.com/) - [x] [Vonage](https://www.vonage.com/) - [x] [Plivo](https://www.plivo.com/) -- [ ] [Infobip](https://www.infobip.com/) +- [x] [Infobip](https://www.infobip.com/) - [x] [Clickatell](https://www.clickatell.com/) - [ ] [AfricasTalking](https://africastalking.com/) - [ ] [Sinch](https://www.sinch.com/) diff --git a/src/Utopia/Messaging/Adapters/SMS/Infobip.php b/src/Utopia/Messaging/Adapters/SMS/Infobip.php new file mode 100644 index 00000000..b13e452f --- /dev/null +++ b/src/Utopia/Messaging/Adapters/SMS/Infobip.php @@ -0,0 +1,54 @@ + ['to' => \ltrim($number, '+')], $message->getTo()); + + return $this->request( + method: 'POST', + url: "https://{$this->apiBaseUrl}/sms/2/text/advanced", + headers: [ + 'Authorization: App ' . $this->apiKey, + 'content-type: application/json', + ], + body: \json_encode([ + 'messages' => [ + 'text' => $message->getContent(), + 'from' => $message->getFrom(), + 'destinations' => $to, + ], + ]), + ); + } +} From 86d1771a927be8ed7d984881208a1a9aeaba0955 Mon Sep 17 00:00:00 2001 From: byawitz Date: Wed, 29 Mar 2023 00:41:09 -0400 Subject: [PATCH 017/106] Add Sinch SMS adapter --- src/Utopia/Messaging/Adapters/SMS/Sinch.php | 52 +++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/Utopia/Messaging/Adapters/SMS/Sinch.php diff --git a/src/Utopia/Messaging/Adapters/SMS/Sinch.php b/src/Utopia/Messaging/Adapters/SMS/Sinch.php new file mode 100644 index 00000000..57c8eb4c --- /dev/null +++ b/src/Utopia/Messaging/Adapters/SMS/Sinch.php @@ -0,0 +1,52 @@ + \ltrim($number, '+'), $message->getTo()); + + return $this->request( + method: 'POST', + url: "https://sms.api.sinch.com/xms/v1/{$this->servicePlanId}/batches", + headers: [ + 'Authorization: Bearer ' . $this->apiToken, + 'content-type: application/json', + ], + body: \json_encode([ + 'from' => $message->getFrom(), + 'to' => $to, + 'body' => $message->getContent(), + ]), + ); + } +} From a1ff7b7f2e337c3e63794761f1bb940ac00dcf0f Mon Sep 17 00:00:00 2001 From: byawitz Date: Wed, 29 Mar 2023 00:41:21 -0400 Subject: [PATCH 018/106] Add Sinch SMS adapter --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5e6d0ec0..110675a9 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ $messaging->send($message); - [x] [Infobip](https://www.infobip.com/) - [x] [Clickatell](https://www.clickatell.com/) - [ ] [AfricasTalking](https://africastalking.com/) -- [ ] [Sinch](https://www.sinch.com/) +- [x] [Sinch](https://www.sinch.com/) - [ ] [Sms77](https://www.sms77.io/) - [ ] [SmsGlobal](https://www.smsglobal.com/) From 83dd057a68ba6a89d5ed25b3b12576be1c038d92 Mon Sep 17 00:00:00 2001 From: byawitz Date: Wed, 29 Mar 2023 00:50:34 -0400 Subject: [PATCH 019/106] Add Seven (Formally sms77) SMS adapter --- README.md | 2 +- src/Utopia/Messaging/Adapters/SMS/Seven.php | 49 +++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 src/Utopia/Messaging/Adapters/SMS/Seven.php diff --git a/README.md b/README.md index 110675a9..f04d8969 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ $messaging->send($message); - [x] [Clickatell](https://www.clickatell.com/) - [ ] [AfricasTalking](https://africastalking.com/) - [x] [Sinch](https://www.sinch.com/) -- [ ] [Sms77](https://www.sms77.io/) +- [x] [Seven](https://www.seven.io/) - [ ] [SmsGlobal](https://www.smsglobal.com/) ### Push diff --git a/src/Utopia/Messaging/Adapters/SMS/Seven.php b/src/Utopia/Messaging/Adapters/SMS/Seven.php new file mode 100644 index 00000000..beaf0a6f --- /dev/null +++ b/src/Utopia/Messaging/Adapters/SMS/Seven.php @@ -0,0 +1,49 @@ +request( + method: 'POST', + url: "https://gateway.sms77.io/api/sms", + headers: [ + 'Authorization: Basic ' . $this->apiKey, + 'content-type: application/json', + ], + body: \json_encode([ + 'from' => $message->getFrom(), + 'to' => \implode(',', $message->getTo()), + 'text' => $message->getContent(), + ]), + ); + } +} From 1444cc16e4f1eb34303b60dfc9b7082e974714f9 Mon Sep 17 00:00:00 2001 From: byawitz Date: Wed, 29 Mar 2023 01:15:16 -0400 Subject: [PATCH 020/106] Implemented providers pricing compare table --- docs/sms-pricing.md | 63 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 docs/sms-pricing.md diff --git a/docs/sms-pricing.md b/docs/sms-pricing.md new file mode 100644 index 00000000..8a734fb6 --- /dev/null +++ b/docs/sms-pricing.md @@ -0,0 +1,63 @@ +# SMS Provider pricing + +### In case you wonder which provider will suite you with best price + +_This list includes only implemented providers_ + +## SMS Target + +_You can add your country with a full pricing table_ + +- [United States](#united-states) +- [India](#india) +- [Israel](#israel) + +## United States + +_In most providers when you're sending SMS to US numbers you must own a US phone number to provide it in the `from` field. Other might add random phone number they have_ + +| Provider | Unit Price | 10K | +|------------|------------|-------| +| Twilio | 0.0079 | 79 $ | +| Telesign | 0.0062 | 62 $ | +| TextMagic | 0.0400 | 400 $ | +| Msg91 | 0.0067 | 67 $ | +| Vonage | 0.0067 | 67 $ | +| Plivo | 0.0050 | 50 $ | +| Infobip | 0.0070 | 70 $ | +| Clickatell | 0.0075 | 75 $ | +| Seven | 0.0810 | 810 $ | +| Sinch | 0.0120 | 120 $ | +| Telnyx | 0.0440 | 440 $ | + +## India + +| Provider | Unit Price | 10K | +|------------|------------|----------| +| Twilio | 0.0490 | 490 $ | +| Telesign | 0.0485 | 485 $ | +| TextMagic | n/a | | +| Msg91 | 0.0030 | 30 $ | +| Vonage | 0.0449 | 449 $ | +| Plivo | 0.0560 | 560 $ | +| Infobip | n/a | | +| Clickatell | 0.0426 | 426.2 $ | +| Seven | 0.0800 | 81 $ | +| Sinch | n/a | | +| Telnyx | 0.0490 | 490 $ | + +## Israel + +| Provider | Unit Price | 10K | +|------------|------------|----------| +| Twilio | 0.112 | 1120 $ | +| Telesign | 0.0768 | 768 $ | +| TextMagic | n/a | | +| Msg91 | 0.0845 | 845 $ | +| Vonage | 0.1019 | 1019 $ | +| Plivo | 0.101 | 1010 $ | +| Infobip | 0.106 | 1060 $ | +| Clickatell | 0.13144 | 1314.4 $ | +| Seven | 0.08 | 81 $ | +| Sinch | n/a | | +| Telnyx | 0.1100 | 1100 $ | From a06462637e0f635cf6d7145a38ec68314eedca0f Mon Sep 17 00:00:00 2001 From: byawitz Date: Wed, 29 Mar 2023 01:23:56 -0400 Subject: [PATCH 021/106] Fixing small miss priced rows --- docs/sms-pricing.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sms-pricing.md b/docs/sms-pricing.md index 8a734fb6..bd717b3c 100644 --- a/docs/sms-pricing.md +++ b/docs/sms-pricing.md @@ -42,7 +42,7 @@ _In most providers when you're sending SMS to US numbers you must own a US phone | Plivo | 0.0560 | 560 $ | | Infobip | n/a | | | Clickatell | 0.0426 | 426.2 $ | -| Seven | 0.0800 | 81 $ | +| Seven | 0.0810 | 810 $ | | Sinch | n/a | | | Telnyx | 0.0490 | 490 $ | @@ -58,6 +58,6 @@ _In most providers when you're sending SMS to US numbers you must own a US phone | Plivo | 0.101 | 1010 $ | | Infobip | 0.106 | 1060 $ | | Clickatell | 0.13144 | 1314.4 $ | -| Seven | 0.08 | 81 $ | +| Seven | 0.0810 | 810 $ | | Sinch | n/a | | | Telnyx | 0.1100 | 1100 $ | From 2c75453fb86ff522cae19a3fb027321a6b0918cf Mon Sep 17 00:00:00 2001 From: byawitz Date: Wed, 29 Mar 2023 01:35:22 -0400 Subject: [PATCH 022/106] Update documentation link --- src/Utopia/Messaging/Adapters/SMS/Seven.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/Seven.php b/src/Utopia/Messaging/Adapters/SMS/Seven.php index beaf0a6f..6bae118f 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Seven.php +++ b/src/Utopia/Messaging/Adapters/SMS/Seven.php @@ -7,7 +7,7 @@ use Utopia\Messaging\Messages\SMS; // Reference Material -// https://developers.sinch.com/docs/sms/api-reference/ +// https://www.seven.io/en/docs/gateway/http-api/sms-dispatch/ class Seven extends SMSAdapter { /** * @param string $apiKey Seven API token From 2b69b48ac2b2b41eaba6bc8d17bc52c178cdae2a Mon Sep 17 00:00:00 2001 From: byawitz Date: Thu, 30 Mar 2023 09:52:57 -0400 Subject: [PATCH 023/106] Update sms pricing to be sorted by price --- docs/sms-pricing.md | 49 +++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/docs/sms-pricing.md b/docs/sms-pricing.md index bd717b3c..6f86f36b 100644 --- a/docs/sms-pricing.md +++ b/docs/sms-pricing.md @@ -2,11 +2,12 @@ ### In case you wonder which provider will suite you with best price -_This list includes only implemented providers_ +- _The list includes only implemented providers_ +- _The list is sorted by unit price low -> high_ ## SMS Target -_You can add your country with a full pricing table_ +_You can add your country with a full pricing table._ - [United States](#united-states) - [India](#india) @@ -18,46 +19,46 @@ _In most providers when you're sending SMS to US numbers you must own a US phone | Provider | Unit Price | 10K | |------------|------------|-------| -| Twilio | 0.0079 | 79 $ | +| Plivo | 0.0050 | 50 $ | | Telesign | 0.0062 | 62 $ | -| TextMagic | 0.0400 | 400 $ | | Msg91 | 0.0067 | 67 $ | | Vonage | 0.0067 | 67 $ | -| Plivo | 0.0050 | 50 $ | | Infobip | 0.0070 | 70 $ | | Clickatell | 0.0075 | 75 $ | -| Seven | 0.0810 | 810 $ | +| Twilio | 0.0079 | 79 $ | | Sinch | 0.0120 | 120 $ | +| TextMagic | 0.0400 | 400 $ | | Telnyx | 0.0440 | 440 $ | +| Seven | 0.0810 | 810 $ | ## India -| Provider | Unit Price | 10K | -|------------|------------|----------| -| Twilio | 0.0490 | 490 $ | -| Telesign | 0.0485 | 485 $ | -| TextMagic | n/a | | -| Msg91 | 0.0030 | 30 $ | -| Vonage | 0.0449 | 449 $ | -| Plivo | 0.0560 | 560 $ | -| Infobip | n/a | | -| Clickatell | 0.0426 | 426.2 $ | -| Seven | 0.0810 | 810 $ | -| Sinch | n/a | | -| Telnyx | 0.0490 | 490 $ | +| Provider | Unit Price | 10K | +|------------|------------|-------| +| Msg91 | 0.0030 | 30 $ | +| Clickatell | 0.0426 | 426 $ | +| Vonage | 0.0449 | 449 $ | +| Telesign | 0.0485 | 485 $ | +| Telnyx | 0.0490 | 490 $ | +| Twilio | 0.0490 | 490 $ | +| Plivo | 0.0560 | 560 $ | +| Seven | 0.0810 | 810 $ | +| Infobip | n/a | | +| Sinch | n/a | | +| TextMagic | n/a | | ## Israel | Provider | Unit Price | 10K | |------------|------------|----------| -| Twilio | 0.112 | 1120 $ | | Telesign | 0.0768 | 768 $ | -| TextMagic | n/a | | +| Seven | 0.0810 | 810 $ | | Msg91 | 0.0845 | 845 $ | -| Vonage | 0.1019 | 1019 $ | | Plivo | 0.101 | 1010 $ | +| Vonage | 0.1019 | 1019 $ | | Infobip | 0.106 | 1060 $ | +| Telnyx | 0.1100 | 1100 $ | +| Twilio | 0.112 | 1120 $ | | Clickatell | 0.13144 | 1314.4 $ | -| Seven | 0.0810 | 810 $ | | Sinch | n/a | | -| Telnyx | 0.1100 | 1100 $ | +| TextMagic | n/a | | From 43cc0067f5f41afd8d9e6806b36657fefe87c53a Mon Sep 17 00:00:00 2001 From: byawitz Date: Mon, 3 Apr 2023 15:48:17 -0400 Subject: [PATCH 024/106] Formatting & linting --- .../Messaging/Adapters/SMS/Clickatell.php | 76 +++++++++-------- src/Utopia/Messaging/Adapters/SMS/Infobip.php | 85 ++++++++++--------- src/Utopia/Messaging/Adapters/SMS/Plivo.php | 69 ++++++++------- src/Utopia/Messaging/Adapters/SMS/Seven.php | 76 +++++++++-------- src/Utopia/Messaging/Adapters/SMS/Sinch.php | 81 +++++++++--------- 5 files changed, 200 insertions(+), 187 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/Clickatell.php b/src/Utopia/Messaging/Adapters/SMS/Clickatell.php index b8edb612..c454137b 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Clickatell.php +++ b/src/Utopia/Messaging/Adapters/SMS/Clickatell.php @@ -1,6 +1,5 @@ request( - method: 'POST', - url: "https://platform.clickatell.com/messages", - headers: [ - 'content-type: application/json', - 'Authorization: ' . $this->apiKey, - ], - body: \json_encode([ - 'content' => $message->getContent(), - 'from' => $message->getFrom(), - 'to' => $message->getTo(), - ]), - ); - } + } + + public function getName(): string + { + return 'Clickatell'; + } + + public function getMaxMessagesPerRequest(): int + { + return 1000; + } + + /** + * {@inheritdoc} + * + * @throws \Exception + */ + protected function process(SMS $message): string + { + return $this->request( + method: 'POST', + url: 'https://platform.clickatell.com/messages', + headers: [ + 'content-type: application/json', + 'Authorization: '.$this->apiKey, + ], + body: \json_encode([ + 'content' => $message->getContent(), + 'from' => $message->getFrom(), + 'to' => $message->getTo(), + ]), + ); + } } diff --git a/src/Utopia/Messaging/Adapters/SMS/Infobip.php b/src/Utopia/Messaging/Adapters/SMS/Infobip.php index b13e452f..68e8f03a 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Infobip.php +++ b/src/Utopia/Messaging/Adapters/SMS/Infobip.php @@ -1,6 +1,5 @@ ['to' => \ltrim($number, '+')], $message->getTo()); - - return $this->request( - method: 'POST', - url: "https://{$this->apiBaseUrl}/sms/2/text/advanced", - headers: [ - 'Authorization: App ' . $this->apiKey, - 'content-type: application/json', - ], - body: \json_encode([ - 'messages' => [ - 'text' => $message->getContent(), - 'from' => $message->getFrom(), - 'destinations' => $to, - ], - ]), - ); - } + } + + public function getName(): string + { + return 'Infobip'; + } + + public function getMaxMessagesPerRequest(): int + { + return 1000; + } + + /** + * {@inheritdoc} + * + * @throws \Exception + */ + protected function process(SMS $message): string + { + $to = \array_map(fn ($number) => ['to' => \ltrim($number, '+')], $message->getTo()); + + return $this->request( + method: 'POST', + url: "https://{$this->apiBaseUrl}/sms/2/text/advanced", + headers: [ + 'Authorization: App '.$this->apiKey, + 'content-type: application/json', + ], + body: \json_encode([ + 'messages' => [ + 'text' => $message->getContent(), + 'from' => $message->getFrom(), + 'destinations' => $to, + ], + ]), + ); + } } diff --git a/src/Utopia/Messaging/Adapters/SMS/Plivo.php b/src/Utopia/Messaging/Adapters/SMS/Plivo.php index b53c9df2..009dafd6 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Plivo.php +++ b/src/Utopia/Messaging/Adapters/SMS/Plivo.php @@ -1,6 +1,5 @@ request( - method: 'POST', - url: "https://api.plivo.com/v1/Account/{$this->authId}/Message/", - headers: [ - 'Authorization: Basic ' . base64_encode("{$this->authId}:{$this->authToken}"), - ], - body: \http_build_query([ - 'text' => $message->getContent(), - 'src' => $message->getFrom(), - 'dst' => \implode('<', $message->getTo()), - ]), - ); - } + /** + * {@inheritdoc} + * + * @throws \Exception + */ + protected function process(SMS $message): string + { + return $this->request( + method: 'POST', + url: "https://api.plivo.com/v1/Account/{$this->authId}/Message/", + headers: [ + 'Authorization: Basic '.base64_encode("{$this->authId}:{$this->authToken}"), + ], + body: \http_build_query([ + 'text' => $message->getContent(), + 'src' => $message->getFrom(), + 'dst' => \implode('<', $message->getTo()), + ]), + ); + } } diff --git a/src/Utopia/Messaging/Adapters/SMS/Seven.php b/src/Utopia/Messaging/Adapters/SMS/Seven.php index 6bae118f..bdde00a4 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Seven.php +++ b/src/Utopia/Messaging/Adapters/SMS/Seven.php @@ -1,6 +1,5 @@ request( - method: 'POST', - url: "https://gateway.sms77.io/api/sms", - headers: [ - 'Authorization: Basic ' . $this->apiKey, - 'content-type: application/json', - ], - body: \json_encode([ - 'from' => $message->getFrom(), - 'to' => \implode(',', $message->getTo()), - 'text' => $message->getContent(), - ]), - ); - } + } + + public function getName(): string + { + return 'Seven'; + } + + public function getMaxMessagesPerRequest(): int + { + return 1000; + } + + /** + * {@inheritdoc} + * + * @throws \Exception + */ + protected function process(SMS $message): string + { + return $this->request( + method: 'POST', + url: 'https://gateway.sms77.io/api/sms', + headers: [ + 'Authorization: Basic '.$this->apiKey, + 'content-type: application/json', + ], + body: \json_encode([ + 'from' => $message->getFrom(), + 'to' => \implode(',', $message->getTo()), + 'text' => $message->getContent(), + ]), + ); + } } diff --git a/src/Utopia/Messaging/Adapters/SMS/Sinch.php b/src/Utopia/Messaging/Adapters/SMS/Sinch.php index 57c8eb4c..65f769eb 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Sinch.php +++ b/src/Utopia/Messaging/Adapters/SMS/Sinch.php @@ -1,6 +1,5 @@ \ltrim($number, '+'), $message->getTo()); - - return $this->request( - method: 'POST', - url: "https://sms.api.sinch.com/xms/v1/{$this->servicePlanId}/batches", - headers: [ - 'Authorization: Bearer ' . $this->apiToken, - 'content-type: application/json', - ], - body: \json_encode([ - 'from' => $message->getFrom(), - 'to' => $to, - 'body' => $message->getContent(), - ]), - ); - } + } + + public function getName(): string + { + return 'Sinch'; + } + + public function getMaxMessagesPerRequest(): int + { + return 1000; + } + + /** + * {@inheritdoc} + * + * @throws \Exception + */ + protected function process(SMS $message): string + { + $to = \array_map(fn ($number) => \ltrim($number, '+'), $message->getTo()); + + return $this->request( + method: 'POST', + url: "https://sms.api.sinch.com/xms/v1/{$this->servicePlanId}/batches", + headers: [ + 'Authorization: Bearer '.$this->apiToken, + 'content-type: application/json', + ], + body: \json_encode([ + 'from' => $message->getFrom(), + 'to' => $to, + 'body' => $message->getContent(), + ]), + ); + } } From 0f4033a528b28c821e9737f3b5d932101a41bb17 Mon Sep 17 00:00:00 2001 From: Binyamin Yawitz Date: Tue, 30 May 2023 20:29:41 -0400 Subject: [PATCH 025/106] [Correct] Formatting & linting --- src/Utopia/Messaging/Adapters/SMS/Clickatell.php | 4 ++-- src/Utopia/Messaging/Adapters/SMS/Infobip.php | 8 ++++---- src/Utopia/Messaging/Adapters/SMS/Plivo.php | 10 +++++----- src/Utopia/Messaging/Adapters/SMS/Seven.php | 4 ++-- src/Utopia/Messaging/Adapters/SMS/Sinch.php | 8 ++++---- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/Clickatell.php b/src/Utopia/Messaging/Adapters/SMS/Clickatell.php index c454137b..6b3ee1ee 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Clickatell.php +++ b/src/Utopia/Messaging/Adapters/SMS/Clickatell.php @@ -13,8 +13,8 @@ class Clickatell extends SMSAdapter * @param string $apiKey Clickatell API Key */ public function __construct( - private string $apiKey, - ) { + private string $apiKey, + ) { } public function getName(): string diff --git a/src/Utopia/Messaging/Adapters/SMS/Infobip.php b/src/Utopia/Messaging/Adapters/SMS/Infobip.php index 68e8f03a..9d1a584b 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Infobip.php +++ b/src/Utopia/Messaging/Adapters/SMS/Infobip.php @@ -11,12 +11,12 @@ class Infobip extends SMSAdapter { /** * @param string $apiBaseUrl Infobip API Base Url - * @param string $apiKey Infobip API Key + * @param string $apiKey Infobip API Key */ public function __construct( - private string $apiBaseUrl, - private string $apiKey - ) { + private string $apiBaseUrl, + private string $apiKey + ) { } public function getName(): string diff --git a/src/Utopia/Messaging/Adapters/SMS/Plivo.php b/src/Utopia/Messaging/Adapters/SMS/Plivo.php index 009dafd6..4f923fdf 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Plivo.php +++ b/src/Utopia/Messaging/Adapters/SMS/Plivo.php @@ -10,13 +10,13 @@ class Plivo extends SMSAdapter { /** - * @param string $authId Plivo Auth ID + * @param string $authId Plivo Auth ID * @param string $authToken Plivo Auth Token */ public function __construct( - private string $authId, - private string $authToken - ) { + private string $authId, + private string $authToken + ) { } public function getName(): string @@ -44,7 +44,7 @@ protected function process(SMS $message): string ], body: \http_build_query([ 'text' => $message->getContent(), - 'src' => $message->getFrom(), + 'src' => $message->getFrom() ?? 'Plivo', 'dst' => \implode('<', $message->getTo()), ]), ); diff --git a/src/Utopia/Messaging/Adapters/SMS/Seven.php b/src/Utopia/Messaging/Adapters/SMS/Seven.php index bdde00a4..383bdf94 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Seven.php +++ b/src/Utopia/Messaging/Adapters/SMS/Seven.php @@ -13,8 +13,8 @@ class Seven extends SMSAdapter * @param string $apiKey Seven API token */ public function __construct( - private string $apiKey - ) { + private string $apiKey + ) { } public function getName(): string diff --git a/src/Utopia/Messaging/Adapters/SMS/Sinch.php b/src/Utopia/Messaging/Adapters/SMS/Sinch.php index 65f769eb..ac0dc0b3 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Sinch.php +++ b/src/Utopia/Messaging/Adapters/SMS/Sinch.php @@ -11,12 +11,12 @@ class Sinch extends SMSAdapter { /** * @param string $servicePlanId Sinch Service plan ID - * @param string $apiToken Sinch API token + * @param string $apiToken Sinch API token */ public function __construct( - private string $servicePlanId, - private string $apiToken - ) { + private string $servicePlanId, + private string $apiToken + ) { } public function getName(): string From 0aef44f2bf934a311fd810a5a9c094b39a59f466 Mon Sep 17 00:00:00 2001 From: Binyamin Yawitz Date: Tue, 30 May 2023 21:03:38 -0400 Subject: [PATCH 026/106] Verify max messages --- src/Utopia/Messaging/Adapters/SMS/Clickatell.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/Clickatell.php b/src/Utopia/Messaging/Adapters/SMS/Clickatell.php index 6b3ee1ee..4e302b32 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Clickatell.php +++ b/src/Utopia/Messaging/Adapters/SMS/Clickatell.php @@ -24,7 +24,7 @@ public function getName(): string public function getMaxMessagesPerRequest(): int { - return 1000; + return 500; } /** From 52021eef254ac5a04947a9ea81c91c796f63d71c Mon Sep 17 00:00:00 2001 From: wess Date: Wed, 19 Jul 2023 09:36:11 -0400 Subject: [PATCH 027/106] Added start to APNS --- .gitignore | 1 + src/Utopia/Messaging/Adapters/Push/APNS.php | 33 +++++++++++++ src/Utopia/Messaging/Apple/Notification.php | 51 +++++++++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 src/Utopia/Messaging/Adapters/Push/APNS.php create mode 100644 src/Utopia/Messaging/Apple/Notification.php diff --git a/.gitignore b/.gitignore index 24265e89..7539ebce 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .idea vendor .phpunit.result.cache +Makefile \ No newline at end of file diff --git a/src/Utopia/Messaging/Adapters/Push/APNS.php b/src/Utopia/Messaging/Adapters/Push/APNS.php new file mode 100644 index 00000000..0cce5fd8 --- /dev/null +++ b/src/Utopia/Messaging/Adapters/Push/APNS.php @@ -0,0 +1,33 @@ +client = new ApplePushNotification($certificatePath, $passphrase, $ssl); + } + + public function getName(): string + { + return 'applePush'; + } + + public function process(Push $message): string + { + try { + $this->client->send($message->getTo(), $message->getBody()); + + return true; + } catch (\Exception $e) { + throw new \Exception($e->getMessage(), 500); + } + } +} + +?> diff --git a/src/Utopia/Messaging/Apple/Notification.php b/src/Utopia/Messaging/Apple/Notification.php new file mode 100644 index 00000000..7821f7f8 --- /dev/null +++ b/src/Utopia/Messaging/Apple/Notification.php @@ -0,0 +1,51 @@ +certificatePath = $certificatePath; + $this->passphrase = $passphrase; + $this->ssl = $ssl; + } + + public function send($deviceToken, $message) + { + $ctx = stream_context_create(); + stream_context_set_option($ctx, 'ssl', 'local_cert', $this->certificatePath); + stream_context_set_option($ctx, 'ssl', 'passphrase', $this->passphrase); + + $fp = stream_socket_client( + $this->ssl, $err, + $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx + ); + + if (!$fp) + exit("Failed to connect: $err $errstr" . PHP_EOL); + + $body['aps'] = array( + 'alert' => $message, + 'sound' => 'default' + ); + + $payload = json_encode($body); + + $msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload; + $result = fwrite($fp, $msg, strlen($msg)); + + if (!$result) + echo 'Message not delivered' . PHP_EOL; + else + echo 'Message successfully delivered' . PHP_EOL; + + fclose($fp); + } +} + +?> From 8ee18447c9d757ee572ddc0c21f63f47cf66e215 Mon Sep 17 00:00:00 2001 From: wess Date: Sat, 29 Jul 2023 09:41:20 -0400 Subject: [PATCH 028/106] Data structures and apns --- .../Adapters/Push/Apple/Rest/Config.php | 112 ++++++++++++++++++ .../Adapters/Push/Apple/Rest/Exception.php | 7 ++ .../Adapters/Push/Apple/Rest/Message.php | 41 +++++++ .../Adapters/Push/Apple/Rest/Request.php | 51 ++++++++ .../Adapters/Push/Apple/Rest/Response.php | 38 ++++++ .../Adapters/Push/{APNS.php => Apple/SSL.php} | 2 + .../Adapters/Push/Entities/Entity.php | 7 ++ .../Adapters/Push/Entities/Message.php | 43 +++++++ .../Adapters/Push/Entities/Provider.php | 35 ++++++ .../Adapters/Push/Entities/Subscriber.php | 31 +++++ .../Adapters/Push/Entities/Target.php | 35 ++++++ .../Adapters/Push/Entities/Topic.php | 29 +++++ 12 files changed, 431 insertions(+) create mode 100644 src/Utopia/Messaging/Adapters/Push/Apple/Rest/Config.php create mode 100644 src/Utopia/Messaging/Adapters/Push/Apple/Rest/Exception.php create mode 100644 src/Utopia/Messaging/Adapters/Push/Apple/Rest/Message.php create mode 100644 src/Utopia/Messaging/Adapters/Push/Apple/Rest/Request.php create mode 100644 src/Utopia/Messaging/Adapters/Push/Apple/Rest/Response.php rename src/Utopia/Messaging/Adapters/Push/{APNS.php => Apple/SSL.php} (94%) create mode 100644 src/Utopia/Messaging/Adapters/Push/Entities/Entity.php create mode 100644 src/Utopia/Messaging/Adapters/Push/Entities/Message.php create mode 100644 src/Utopia/Messaging/Adapters/Push/Entities/Provider.php create mode 100644 src/Utopia/Messaging/Adapters/Push/Entities/Subscriber.php create mode 100644 src/Utopia/Messaging/Adapters/Push/Entities/Target.php create mode 100644 src/Utopia/Messaging/Adapters/Push/Entities/Topic.php diff --git a/src/Utopia/Messaging/Adapters/Push/Apple/Rest/Config.php b/src/Utopia/Messaging/Adapters/Push/Apple/Rest/Config.php new file mode 100644 index 00000000..91f16fe0 --- /dev/null +++ b/src/Utopia/Messaging/Adapters/Push/Apple/Rest/Config.php @@ -0,0 +1,112 @@ + 'https://api.push.apple.com/3/device/', + 'sandbox' => 'https://api.development.push.apple.com/3/device/' + ]; + + /** + * @var string + */ + private $url; + + /** + * @var string + */ + private $keypath; + + /** + * @var string + */ + private $topic; + + /** + * @var string + */ + private $secretKey; + + /** + * @var string + */ + private $token; + + + /** + * Construct + * + * Construct a new APNS push configuration. + * + * @param string $env + * @param string $keypath + * @param string $secretKey + * @param string $topic + */ + public function __construct($env = Config::SANDBOX, $keypath, $secretKey, $topic) + { + $this->url = $this->endpoint[$env]; + $this->keypath = $keypath; + $this->secretKey = $secretKey; + $this->topic = $topic; + } + + /** + * Get Secret key + * + * @return string + */ + public function getSecretKey() + { + return $this->secretKey; + } + + /** + * Get Key path + * + * @return string + */ + public function getKeypath() + { + return $this->keypath; + } + + /** + * Get URL + * + * @return string + */ + public function getURL() + { + return $this->url; + } + + /** + * Get Topic + * + * @return string + */ + public function getTopic() + { + return $this->topic; + } + + /** + * Returns headers used for sending notification. + * + * @return associative array + * + * @todo: add support for various push types. + */ + public function getHeaders() { + return [ + 'apns-topic: ' . $this->getTopic(), + 'apns-push-type: ' . 'alert', + ]; + } +} \ No newline at end of file diff --git a/src/Utopia/Messaging/Adapters/Push/Apple/Rest/Exception.php b/src/Utopia/Messaging/Adapters/Push/Apple/Rest/Exception.php new file mode 100644 index 00000000..9eb94cbc --- /dev/null +++ b/src/Utopia/Messaging/Adapters/Push/Apple/Rest/Exception.php @@ -0,0 +1,7 @@ +title = $title; + $this->body = $body; + $this->sound = $sound; + } + + public function toJson() + { + return json_encode([ + 'aps' => [ + 'alert' => [ + 'title' => $this->title, + 'body' => $this->body + ], + 'sound' => $this->sound + ] + ]); + } +} \ No newline at end of file diff --git a/src/Utopia/Messaging/Adapters/Push/Apple/Rest/Request.php b/src/Utopia/Messaging/Adapters/Push/Apple/Rest/Request.php new file mode 100644 index 00000000..431f8f72 --- /dev/null +++ b/src/Utopia/Messaging/Adapters/Push/Apple/Rest/Request.php @@ -0,0 +1,51 @@ +config = $config; + } + + public function send(string $deviceToken, Message $message) + { + $url = $this->config->getURL() . $deviceToken; + + $ch = curl_init($url); + curl_setopt($ch, CURLOPT_HTTPHEADER, $this->config->getHeaders()); + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($message->toJson())); + curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); + + curl_setopt($ch, CURLOPT_SSLCERT, $this->config->getKeyPath()); + curl_setopt($ch, CURLOPT_SSLCERTPASSWD, $this->config->getSecretKey()); + + curl_setopt($ch, CURLOPT_FAILONERROR, true); + curl_exec($ch); + + $response = new Response(curl_getinfo($ch, CURLINFO_HTTP_CODE)); + + curl_close($ch); + + return [ + 'code' => $response->code, + 'response' => $response->description + ]; + } +} \ No newline at end of file diff --git a/src/Utopia/Messaging/Adapters/Push/Apple/Rest/Response.php b/src/Utopia/Messaging/Adapters/Push/Apple/Rest/Response.php new file mode 100644 index 00000000..df1ba709 --- /dev/null +++ b/src/Utopia/Messaging/Adapters/Push/Apple/Rest/Response.php @@ -0,0 +1,38 @@ + 'Invalid configuration.', + '200' => 'Success.', + '400' => 'Bad request.', + '403' => 'There was an error with the certificate or with the provider’s authentication token.', + '404' => 'The request contained an invalid :path value.', + '405' => 'The request used an invalid :method value. Only POST requests are supported.', + '410' => 'The device token is no longer active for the topic.', + '413' => 'The notification payload was too large.', + '429' => 'The server received too many requests for the same device token.', + '500' => 'Internal server error.', + '503' => 'The server is shutting down and unavailable.', + ]; + + /** + * @var string + */ + public $code; + + /** + * @var string + */ + public $description; + + public function __construct(string $statusCode) + { + $code = isset(self::$descriptions[$statusCode]) ? $statusCode : 0; + + $this->code = $code; + $this->description = self::$descriptions[$code]; + } +} \ No newline at end of file diff --git a/src/Utopia/Messaging/Adapters/Push/APNS.php b/src/Utopia/Messaging/Adapters/Push/Apple/SSL.php similarity index 94% rename from src/Utopia/Messaging/Adapters/Push/APNS.php rename to src/Utopia/Messaging/Adapters/Push/Apple/SSL.php index 0cce5fd8..21831f62 100644 --- a/src/Utopia/Messaging/Adapters/Push/APNS.php +++ b/src/Utopia/Messaging/Adapters/Push/Apple/SSL.php @@ -1,5 +1,7 @@ id = $id; + $this->providerId = $providerId; + $this->providerInternalId = $providerInternalId; + $this->data = $data; + $this->to = $to; + $this->deliveryTime = $deliveryTime; + $this->deliveryError = $deliveryError; + $this->deliveredTo = $deliveredTo; + $this->delivered = $delivered; + $this->search = $search; + } + +} \ No newline at end of file diff --git a/src/Utopia/Messaging/Adapters/Push/Entities/Provider.php b/src/Utopia/Messaging/Adapters/Push/Entities/Provider.php new file mode 100644 index 00000000..d85b604e --- /dev/null +++ b/src/Utopia/Messaging/Adapters/Push/Entities/Provider.php @@ -0,0 +1,35 @@ +id = $id; + $this->userId = $userId; + $this->name = $name; + $this->provider = $provider; + $this->type = $type; + $this->credentials = $credentials; + } + +} \ No newline at end of file diff --git a/src/Utopia/Messaging/Adapters/Push/Entities/Subscriber.php b/src/Utopia/Messaging/Adapters/Push/Entities/Subscriber.php new file mode 100644 index 00000000..d7594427 --- /dev/null +++ b/src/Utopia/Messaging/Adapters/Push/Entities/Subscriber.php @@ -0,0 +1,31 @@ +id = $id; + $this->userId = $userId; + $this->userInternalId = $userInternalId; + $this->targetId = $targetId; + $this->targetInternalId = $targetInternalId; + } + +} \ No newline at end of file diff --git a/src/Utopia/Messaging/Adapters/Push/Entities/Target.php b/src/Utopia/Messaging/Adapters/Push/Entities/Target.php new file mode 100644 index 00000000..2058440b --- /dev/null +++ b/src/Utopia/Messaging/Adapters/Push/Entities/Target.php @@ -0,0 +1,35 @@ +id = $id; + $this->userId = $userId; + $this->userInternalId = $userInternalId; + $this->providerId = $providerId; + $this->providerInternalId = $providerInternalId; + $this->providerType = $providerType; + $this->identifier = $identifier; + } + +} \ No newline at end of file diff --git a/src/Utopia/Messaging/Adapters/Push/Entities/Topic.php b/src/Utopia/Messaging/Adapters/Push/Entities/Topic.php new file mode 100644 index 00000000..b9759b8e --- /dev/null +++ b/src/Utopia/Messaging/Adapters/Push/Entities/Topic.php @@ -0,0 +1,29 @@ +id = $id; + $this->providerId = $providerId; + $this->providerInternalId = $providerInternalId; + $this->name = $name; + $this->description = $description; + } + +} \ No newline at end of file From 2e37e489e3f922d815baa37419bf61b18d616d61 Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 31 Jul 2023 11:54:40 -0400 Subject: [PATCH 029/106] working on email adapter for service and impl --- src/Utopia/Messaging/Message.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Utopia/Messaging/Message.php b/src/Utopia/Messaging/Message.php index 3b5e21ae..c9533ad1 100644 --- a/src/Utopia/Messaging/Message.php +++ b/src/Utopia/Messaging/Message.php @@ -7,4 +7,5 @@ */ interface Message { + function getTo():string; } From 5ccda373cd0376f407c7114f810d6815dba15215 Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 31 Jul 2023 12:10:29 -0400 Subject: [PATCH 030/106] Little reorg --- src/Utopia/Messaging/{Adapters/Push => }/Entities/Entity.php | 0 src/Utopia/Messaging/{Adapters/Push => }/Entities/Message.php | 0 src/Utopia/Messaging/{Adapters/Push => }/Entities/Provider.php | 0 .../Messaging/{Adapters/Push => }/Entities/Subscriber.php | 0 src/Utopia/Messaging/{Adapters/Push => }/Entities/Target.php | 0 src/Utopia/Messaging/{Adapters/Push => }/Entities/Topic.php | 0 src/Utopia/Messaging/Message.php | 3 ++- 7 files changed, 2 insertions(+), 1 deletion(-) rename src/Utopia/Messaging/{Adapters/Push => }/Entities/Entity.php (100%) rename src/Utopia/Messaging/{Adapters/Push => }/Entities/Message.php (100%) rename src/Utopia/Messaging/{Adapters/Push => }/Entities/Provider.php (100%) rename src/Utopia/Messaging/{Adapters/Push => }/Entities/Subscriber.php (100%) rename src/Utopia/Messaging/{Adapters/Push => }/Entities/Target.php (100%) rename src/Utopia/Messaging/{Adapters/Push => }/Entities/Topic.php (100%) diff --git a/src/Utopia/Messaging/Adapters/Push/Entities/Entity.php b/src/Utopia/Messaging/Entities/Entity.php similarity index 100% rename from src/Utopia/Messaging/Adapters/Push/Entities/Entity.php rename to src/Utopia/Messaging/Entities/Entity.php diff --git a/src/Utopia/Messaging/Adapters/Push/Entities/Message.php b/src/Utopia/Messaging/Entities/Message.php similarity index 100% rename from src/Utopia/Messaging/Adapters/Push/Entities/Message.php rename to src/Utopia/Messaging/Entities/Message.php diff --git a/src/Utopia/Messaging/Adapters/Push/Entities/Provider.php b/src/Utopia/Messaging/Entities/Provider.php similarity index 100% rename from src/Utopia/Messaging/Adapters/Push/Entities/Provider.php rename to src/Utopia/Messaging/Entities/Provider.php diff --git a/src/Utopia/Messaging/Adapters/Push/Entities/Subscriber.php b/src/Utopia/Messaging/Entities/Subscriber.php similarity index 100% rename from src/Utopia/Messaging/Adapters/Push/Entities/Subscriber.php rename to src/Utopia/Messaging/Entities/Subscriber.php diff --git a/src/Utopia/Messaging/Adapters/Push/Entities/Target.php b/src/Utopia/Messaging/Entities/Target.php similarity index 100% rename from src/Utopia/Messaging/Adapters/Push/Entities/Target.php rename to src/Utopia/Messaging/Entities/Target.php diff --git a/src/Utopia/Messaging/Adapters/Push/Entities/Topic.php b/src/Utopia/Messaging/Entities/Topic.php similarity index 100% rename from src/Utopia/Messaging/Adapters/Push/Entities/Topic.php rename to src/Utopia/Messaging/Entities/Topic.php diff --git a/src/Utopia/Messaging/Message.php b/src/Utopia/Messaging/Message.php index c9533ad1..0b70a2ce 100644 --- a/src/Utopia/Messaging/Message.php +++ b/src/Utopia/Messaging/Message.php @@ -7,5 +7,6 @@ */ interface Message { - function getTo():string; + function getTo():array; + function getFrom():?string; } From e9c792a82e722447573f571d415e3254868bfc28 Mon Sep 17 00:00:00 2001 From: wess Date: Wed, 2 Aug 2023 14:30:25 -0400 Subject: [PATCH 031/106] Sendgrid test and some key clean up --- .gitignore | 4 +- composer.json | 4 +- composer.lock | 49 ++++++++++--------- docker-compose.yml | 2 + phpunit.xml | 2 +- .../Messaging/Adapters/Email/Mailgun.php | 6 ++- .../Messaging/Adapters/Email/Sendgrid.php | 4 +- src/Utopia/Messaging/Entities/Target.php | 1 - tests/e2e/Email/MailgunTest.php | 40 +++++++++++++++ tests/e2e/Email/SendgridTest.php | 34 +++++++++++++ 10 files changed, 113 insertions(+), 33 deletions(-) create mode 100644 tests/e2e/Email/MailgunTest.php create mode 100644 tests/e2e/Email/SendgridTest.php diff --git a/.gitignore b/.gitignore index 7539ebce..5176c240 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ .idea vendor .phpunit.result.cache -Makefile \ No newline at end of file +Makefile +.envrc +.env \ No newline at end of file diff --git a/composer.json b/composer.json index 0e9de463..7dfe178e 100644 --- a/composer.json +++ b/composer.json @@ -26,8 +26,8 @@ "ext-curl": "*" }, "require-dev": { - "phpunit/phpunit": "9.5.*", - "phpmailer/phpmailer": "6.6.*", + "phpunit/phpunit": "^9.6", + "phpmailer/phpmailer": "^6.8", "laravel/pint": "^1.2" }, "config": { diff --git a/composer.lock b/composer.lock index c2118454..9f6b978b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1ca9da311c804e40032e90c09ad04d76", + "content-hash": "5ecbd865cbd7f14e7819fb79643573be", "packages": [], "packages-dev": [ { @@ -371,16 +371,16 @@ }, { "name": "phpmailer/phpmailer", - "version": "v6.6.4", + "version": "v6.8.0", "source": { "type": "git", "url": "https://github.com/PHPMailer/PHPMailer.git", - "reference": "a94fdebaea6bd17f51be0c2373ab80d3d681269b" + "reference": "df16b615e371d81fb79e506277faea67a1be18f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/a94fdebaea6bd17f51be0c2373ab80d3d681269b", - "reference": "a94fdebaea6bd17f51be0c2373ab80d3d681269b", + "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/df16b615e371d81fb79e506277faea67a1be18f1", + "reference": "df16b615e371d81fb79e506277faea67a1be18f1", "shasum": "" }, "require": { @@ -390,22 +390,24 @@ "php": ">=5.5.0" }, "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", - "doctrine/annotations": "^1.2", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.2", + "doctrine/annotations": "^1.2.6 || ^1.13.3", "php-parallel-lint/php-console-highlighter": "^1.0.0", "php-parallel-lint/php-parallel-lint": "^1.3.2", "phpcompatibility/php-compatibility": "^9.3.5", "roave/security-advisories": "dev-latest", - "squizlabs/php_codesniffer": "^3.6.2", - "yoast/phpunit-polyfills": "^1.0.0" + "squizlabs/php_codesniffer": "^3.7.1", + "yoast/phpunit-polyfills": "^1.0.4" }, "suggest": { "ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses", + "ext-openssl": "Needed for secure SMTP sending and DKIM signing", + "greew/oauth2-azure-provider": "Needed for Microsoft Azure XOAUTH2 authentication", "hayageek/oauth2-yahoo": "Needed for Yahoo XOAUTH2 authentication", "league/oauth2-google": "Needed for Google XOAUTH2 authentication", "psr/log": "For optional PSR-3 debug logging", - "stevenmaguire/oauth2-microsoft": "Needed for Microsoft XOAUTH2 authentication", - "symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)" + "symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)", + "thenetworg/oauth2-azure": "Needed for Microsoft XOAUTH2 authentication" }, "type": "library", "autoload": { @@ -437,7 +439,7 @@ "description": "PHPMailer is a full-featured email creation and transfer class for PHP", "support": { "issues": "https://github.com/PHPMailer/PHPMailer/issues", - "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.6.4" + "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.8.0" }, "funding": [ { @@ -445,7 +447,7 @@ "type": "github" } ], - "time": "2022-08-22T09:22:00+00:00" + "time": "2023-03-06T14:43:22+00:00" }, { "name": "phpunit/php-code-coverage", @@ -767,20 +769,20 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.25", + "version": "9.6.10", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d" + "reference": "a6d351645c3fe5a30f5e86be6577d946af65a328" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d", - "reference": "3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a6d351645c3fe5a30f5e86be6577d946af65a328", + "reference": "a6d351645c3fe5a30f5e86be6577d946af65a328", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1", + "doctrine/instantiator": "^1.3.1 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", @@ -809,8 +811,8 @@ "sebastian/version": "^3.0.2" }, "suggest": { - "ext-soap": "*", - "ext-xdebug": "*" + "ext-soap": "To be able to generate mocks based on WSDL files", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "bin": [ "phpunit" @@ -818,7 +820,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.5-dev" + "dev-master": "9.6-dev" } }, "autoload": { @@ -849,7 +851,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.25" + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.10" }, "funding": [ { @@ -865,7 +868,7 @@ "type": "tidelift" } ], - "time": "2022-09-25T03:44:45+00:00" + "time": "2023-07-10T04:04:23+00:00" }, { "name": "sebastian/cli-parser", diff --git a/docker-compose.yml b/docker-compose.yml index 96054433..e0a8130f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,6 +8,8 @@ services: - ./src:/usr/local/src/src - ./tests:/usr/local/src/tests - ./phpunit.xml:/usr/local/src/phpunit.xml + env_file: + - .env maildev: image: appwrite/mailcatcher:1.0.0 diff --git a/phpunit.xml b/phpunit.xml index 8db6586a..53cd4abd 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -6,7 +6,7 @@ convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" - stopOnFailure="false" + stopOnFailure="true" > diff --git a/src/Utopia/Messaging/Adapters/Email/Mailgun.php b/src/Utopia/Messaging/Adapters/Email/Mailgun.php index ba64c906..148cb174 100644 --- a/src/Utopia/Messaging/Adapters/Email/Mailgun.php +++ b/src/Utopia/Messaging/Adapters/Email/Mailgun.php @@ -34,19 +34,21 @@ public function getMaxMessagesPerRequest(): int */ protected function process(Email $message): string { - return $this->request( + $response = $this->request( method: 'POST', url: "https://api.mailgun.net/v3/{$this->domain}/messages", headers: [ 'Authorization: Basic '.base64_encode('api:'.$this->apiKey), ], body: \http_build_query([ - 'from' => $message->getFrom(), 'to' => \implode(',', $message->getTo()), + 'from' => $message->getFrom(), 'subject' => $message->getSubject(), 'text' => $message->isHtml() ? null : $message->getContent(), 'html' => $message->isHtml() ? $message->getContent() : null, ]), ); + + return $response; } } diff --git a/src/Utopia/Messaging/Adapters/Email/Sendgrid.php b/src/Utopia/Messaging/Adapters/Email/Sendgrid.php index 17745c48..a805e6c6 100644 --- a/src/Utopia/Messaging/Adapters/Email/Sendgrid.php +++ b/src/Utopia/Messaging/Adapters/Email/Sendgrid.php @@ -7,9 +7,7 @@ class Sendgrid extends EmailAdapter { - public function __construct( - private string $apiKey, - ) { + public function __construct(private string $apiKey) { } public function getName(): string diff --git a/src/Utopia/Messaging/Entities/Target.php b/src/Utopia/Messaging/Entities/Target.php index 2058440b..b0d37a35 100644 --- a/src/Utopia/Messaging/Entities/Target.php +++ b/src/Utopia/Messaging/Entities/Target.php @@ -2,7 +2,6 @@ namespace Utopia\Messaging\Adapters\Push\Entities; -use DateTime; use Utopia\Messaging\Adapters\Push\Entities\Entity; class Target extends Entity { diff --git a/tests/e2e/Email/MailgunTest.php b/tests/e2e/Email/MailgunTest.php new file mode 100644 index 00000000..0f55ee15 --- /dev/null +++ b/tests/e2e/Email/MailgunTest.php @@ -0,0 +1,40 @@ +send($message); + + $this->assertEquals(true, true); + } +} diff --git a/tests/e2e/Email/SendgridTest.php b/tests/e2e/Email/SendgridTest.php new file mode 100644 index 00000000..0786a1eb --- /dev/null +++ b/tests/e2e/Email/SendgridTest.php @@ -0,0 +1,34 @@ +send($message); + + $this->assertEquals(true, true); + } +} From cb8f99efa6244dd77809dc3607226999f401404f Mon Sep 17 00:00:00 2001 From: wess Date: Thu, 3 Aug 2023 15:48:09 -0400 Subject: [PATCH 032/106] Removes unneeded classes for apns Creates APNS Adapter Creates tests for Apple Push --- .gitignore | 3 +- src/Utopia/Messaging/Adapters/Push/APNS.php | 95 +++++++++++++++ .../Adapters/Push/Apple/Rest/Config.php | 112 ------------------ .../Adapters/Push/Apple/Rest/Exception.php | 7 -- .../Adapters/Push/Apple/Rest/Message.php | 41 ------- .../Adapters/Push/Apple/Rest/Request.php | 51 -------- .../Adapters/Push/Apple/Rest/Response.php | 38 ------ .../Messaging/Adapters/Push/Apple/SSL.php | 35 ------ src/Utopia/Messaging/Apple/Notification.php | 51 -------- src/Utopia/Messaging/Messages/Push.php | 5 + tests/e2e/Push/APNSTest.php | 37 ++++++ 11 files changed, 139 insertions(+), 336 deletions(-) create mode 100644 src/Utopia/Messaging/Adapters/Push/APNS.php delete mode 100644 src/Utopia/Messaging/Adapters/Push/Apple/Rest/Config.php delete mode 100644 src/Utopia/Messaging/Adapters/Push/Apple/Rest/Exception.php delete mode 100644 src/Utopia/Messaging/Adapters/Push/Apple/Rest/Message.php delete mode 100644 src/Utopia/Messaging/Adapters/Push/Apple/Rest/Request.php delete mode 100644 src/Utopia/Messaging/Adapters/Push/Apple/Rest/Response.php delete mode 100644 src/Utopia/Messaging/Adapters/Push/Apple/SSL.php delete mode 100644 src/Utopia/Messaging/Apple/Notification.php create mode 100644 tests/e2e/Push/APNSTest.php diff --git a/.gitignore b/.gitignore index 5176c240..03bf4c75 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ vendor .phpunit.result.cache Makefile .envrc -.env \ No newline at end of file +.env +*.p8 \ No newline at end of file diff --git a/src/Utopia/Messaging/Adapters/Push/APNS.php b/src/Utopia/Messaging/Adapters/Push/APNS.php new file mode 100644 index 00000000..b5bd8a03 --- /dev/null +++ b/src/Utopia/Messaging/Adapters/Push/APNS.php @@ -0,0 +1,95 @@ +authKey = $authKey; + $this->authKeyId = $authKeyId; + $this->teamId = $teamId; + $this->bundleId = $bundleId; + $this->endpoint = $endpoint; + } + + public function getName(): string + { + return 'APNS'; + } + + + public function getMaxMessagesPerRequest(): int + { + return 1000; + } + + public function process(Push $message): string + { + $headers = [ + 'authorization: bearer ' . $this->generateJwt(), + 'apns-topic: ' . $this->bundleId, + ]; + + $payload = json_encode([ + 'aps' => [ + 'alert' => [ + 'title' => $message->getTitle(), + 'body' => $message->getBody(), + ], + 'badge' => $message->getBadge(), + 'sound' => $message->getSound(), + 'data' => $message->getData(), + ], + ]); + + // Assuming the 'to' array contains device tokens for the push notification recipients. + foreach ($message->getTo() as $to) { + $url = $this->endpoint . '/3/device/' . $to; + $response = $this->request('POST', $url, $headers, $payload); + + // You might want to handle each response here, for instance, logging failures + } + + // This example simply returns the last response, adjust as needed + return $response; + } + + private function generateJwt(): string + { + $header = json_encode(['alg' => 'ES256', 'kid' => $this->authKeyId]); + $claims = json_encode([ + 'iss' => $this->teamId, + 'iat' => time(), + ]); + + $base64UrlHeader = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header)); + $base64UrlClaims = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($claims)); + + $privateKeyResource = openssl_pkey_get_private(file_get_contents($this->authKey)); + if (!$privateKeyResource) { + throw new \Exception('Invalid private key'); + } + + $signature = ''; + $success = openssl_sign("$base64UrlHeader.$base64UrlClaims", $signature, $privateKeyResource, OPENSSL_ALGO_SHA256); + + if (!$success) { + throw new \Exception('Failed to sign JWT'); + } + + $base64UrlSignature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature)); + + return "$base64UrlHeader.$base64UrlClaims.$base64UrlSignature"; + } + +} diff --git a/src/Utopia/Messaging/Adapters/Push/Apple/Rest/Config.php b/src/Utopia/Messaging/Adapters/Push/Apple/Rest/Config.php deleted file mode 100644 index 91f16fe0..00000000 --- a/src/Utopia/Messaging/Adapters/Push/Apple/Rest/Config.php +++ /dev/null @@ -1,112 +0,0 @@ - 'https://api.push.apple.com/3/device/', - 'sandbox' => 'https://api.development.push.apple.com/3/device/' - ]; - - /** - * @var string - */ - private $url; - - /** - * @var string - */ - private $keypath; - - /** - * @var string - */ - private $topic; - - /** - * @var string - */ - private $secretKey; - - /** - * @var string - */ - private $token; - - - /** - * Construct - * - * Construct a new APNS push configuration. - * - * @param string $env - * @param string $keypath - * @param string $secretKey - * @param string $topic - */ - public function __construct($env = Config::SANDBOX, $keypath, $secretKey, $topic) - { - $this->url = $this->endpoint[$env]; - $this->keypath = $keypath; - $this->secretKey = $secretKey; - $this->topic = $topic; - } - - /** - * Get Secret key - * - * @return string - */ - public function getSecretKey() - { - return $this->secretKey; - } - - /** - * Get Key path - * - * @return string - */ - public function getKeypath() - { - return $this->keypath; - } - - /** - * Get URL - * - * @return string - */ - public function getURL() - { - return $this->url; - } - - /** - * Get Topic - * - * @return string - */ - public function getTopic() - { - return $this->topic; - } - - /** - * Returns headers used for sending notification. - * - * @return associative array - * - * @todo: add support for various push types. - */ - public function getHeaders() { - return [ - 'apns-topic: ' . $this->getTopic(), - 'apns-push-type: ' . 'alert', - ]; - } -} \ No newline at end of file diff --git a/src/Utopia/Messaging/Adapters/Push/Apple/Rest/Exception.php b/src/Utopia/Messaging/Adapters/Push/Apple/Rest/Exception.php deleted file mode 100644 index 9eb94cbc..00000000 --- a/src/Utopia/Messaging/Adapters/Push/Apple/Rest/Exception.php +++ /dev/null @@ -1,7 +0,0 @@ -title = $title; - $this->body = $body; - $this->sound = $sound; - } - - public function toJson() - { - return json_encode([ - 'aps' => [ - 'alert' => [ - 'title' => $this->title, - 'body' => $this->body - ], - 'sound' => $this->sound - ] - ]); - } -} \ No newline at end of file diff --git a/src/Utopia/Messaging/Adapters/Push/Apple/Rest/Request.php b/src/Utopia/Messaging/Adapters/Push/Apple/Rest/Request.php deleted file mode 100644 index 431f8f72..00000000 --- a/src/Utopia/Messaging/Adapters/Push/Apple/Rest/Request.php +++ /dev/null @@ -1,51 +0,0 @@ -config = $config; - } - - public function send(string $deviceToken, Message $message) - { - $url = $this->config->getURL() . $deviceToken; - - $ch = curl_init($url); - curl_setopt($ch, CURLOPT_HTTPHEADER, $this->config->getHeaders()); - curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($message->toJson())); - curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); - - curl_setopt($ch, CURLOPT_SSLCERT, $this->config->getKeyPath()); - curl_setopt($ch, CURLOPT_SSLCERTPASSWD, $this->config->getSecretKey()); - - curl_setopt($ch, CURLOPT_FAILONERROR, true); - curl_exec($ch); - - $response = new Response(curl_getinfo($ch, CURLINFO_HTTP_CODE)); - - curl_close($ch); - - return [ - 'code' => $response->code, - 'response' => $response->description - ]; - } -} \ No newline at end of file diff --git a/src/Utopia/Messaging/Adapters/Push/Apple/Rest/Response.php b/src/Utopia/Messaging/Adapters/Push/Apple/Rest/Response.php deleted file mode 100644 index df1ba709..00000000 --- a/src/Utopia/Messaging/Adapters/Push/Apple/Rest/Response.php +++ /dev/null @@ -1,38 +0,0 @@ - 'Invalid configuration.', - '200' => 'Success.', - '400' => 'Bad request.', - '403' => 'There was an error with the certificate or with the provider’s authentication token.', - '404' => 'The request contained an invalid :path value.', - '405' => 'The request used an invalid :method value. Only POST requests are supported.', - '410' => 'The device token is no longer active for the topic.', - '413' => 'The notification payload was too large.', - '429' => 'The server received too many requests for the same device token.', - '500' => 'Internal server error.', - '503' => 'The server is shutting down and unavailable.', - ]; - - /** - * @var string - */ - public $code; - - /** - * @var string - */ - public $description; - - public function __construct(string $statusCode) - { - $code = isset(self::$descriptions[$statusCode]) ? $statusCode : 0; - - $this->code = $code; - $this->description = self::$descriptions[$code]; - } -} \ No newline at end of file diff --git a/src/Utopia/Messaging/Adapters/Push/Apple/SSL.php b/src/Utopia/Messaging/Adapters/Push/Apple/SSL.php deleted file mode 100644 index 21831f62..00000000 --- a/src/Utopia/Messaging/Adapters/Push/Apple/SSL.php +++ /dev/null @@ -1,35 +0,0 @@ -client = new ApplePushNotification($certificatePath, $passphrase, $ssl); - } - - public function getName(): string - { - return 'applePush'; - } - - public function process(Push $message): string - { - try { - $this->client->send($message->getTo(), $message->getBody()); - - return true; - } catch (\Exception $e) { - throw new \Exception($e->getMessage(), 500); - } - } -} - -?> diff --git a/src/Utopia/Messaging/Apple/Notification.php b/src/Utopia/Messaging/Apple/Notification.php deleted file mode 100644 index 7821f7f8..00000000 --- a/src/Utopia/Messaging/Apple/Notification.php +++ /dev/null @@ -1,51 +0,0 @@ -certificatePath = $certificatePath; - $this->passphrase = $passphrase; - $this->ssl = $ssl; - } - - public function send($deviceToken, $message) - { - $ctx = stream_context_create(); - stream_context_set_option($ctx, 'ssl', 'local_cert', $this->certificatePath); - stream_context_set_option($ctx, 'ssl', 'passphrase', $this->passphrase); - - $fp = stream_socket_client( - $this->ssl, $err, - $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx - ); - - if (!$fp) - exit("Failed to connect: $err $errstr" . PHP_EOL); - - $body['aps'] = array( - 'alert' => $message, - 'sound' => 'default' - ); - - $payload = json_encode($body); - - $msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload; - $result = fwrite($fp, $msg, strlen($msg)); - - if (!$result) - echo 'Message not delivered' . PHP_EOL; - else - echo 'Message successfully delivered' . PHP_EOL; - - fclose($fp); - } -} - -?> diff --git a/src/Utopia/Messaging/Messages/Push.php b/src/Utopia/Messaging/Messages/Push.php index d4a4333b..12e1d7c3 100644 --- a/src/Utopia/Messaging/Messages/Push.php +++ b/src/Utopia/Messaging/Messages/Push.php @@ -40,6 +40,11 @@ public function getTo(): array return $this->to; } + public function getFrom(): ?string + { + return null; + } + /** * @return string */ diff --git a/tests/e2e/Push/APNSTest.php b/tests/e2e/Push/APNSTest.php new file mode 100644 index 00000000..39fe3dd6 --- /dev/null +++ b/tests/e2e/Push/APNSTest.php @@ -0,0 +1,37 @@ +send($message); + + $this->assertEquals('', $response); + } +} From f0c5cbb762ae28e072a7574affa44798e1b34415 Mon Sep 17 00:00:00 2001 From: wess Date: Fri, 4 Aug 2023 13:45:25 -0400 Subject: [PATCH 033/106] Removes TwilioNotify as Twilio is ending it this year Adds FCM and FCM tests Twilio update and tests --- .../Messaging/Adapters/SMS/TwilioNotify.php | 53 ------------------- tests/e2e/Push/FCMTest.php | 33 ++++++++++++ tests/e2e/SMS/TwilioTest.php | 35 ++++++++++++ 3 files changed, 68 insertions(+), 53 deletions(-) delete mode 100644 src/Utopia/Messaging/Adapters/SMS/TwilioNotify.php create mode 100644 tests/e2e/Push/FCMTest.php create mode 100644 tests/e2e/SMS/TwilioTest.php diff --git a/src/Utopia/Messaging/Adapters/SMS/TwilioNotify.php b/src/Utopia/Messaging/Adapters/SMS/TwilioNotify.php deleted file mode 100644 index a977ed79..00000000 --- a/src/Utopia/Messaging/Adapters/SMS/TwilioNotify.php +++ /dev/null @@ -1,53 +0,0 @@ -request( - method: 'POST', - url: "https://notify.twilio.com/v1/Services/{$this->serviceSid}/Notifications", - headers: [ - 'Authorization: Basic '.base64_encode("{$this->accountSid}:{$this->authToken}"), - ], - body: \http_build_query([ - 'Body' => $message->getContent(), - 'ToBinding' => \json_encode(\array_map( - fn ($to) => ['binding_type' => 'sms', 'address' => $to], - $message->getTo() - )), - ]), - ); - } -} diff --git a/tests/e2e/Push/FCMTest.php b/tests/e2e/Push/FCMTest.php new file mode 100644 index 00000000..cd10658c --- /dev/null +++ b/tests/e2e/Push/FCMTest.php @@ -0,0 +1,33 @@ +send($message); + + $this->assertNotEmpty($response); + } +} diff --git a/tests/e2e/SMS/TwilioTest.php b/tests/e2e/SMS/TwilioTest.php new file mode 100644 index 00000000..21e1f87e --- /dev/null +++ b/tests/e2e/SMS/TwilioTest.php @@ -0,0 +1,35 @@ +send($message); + + $smsRequest = $this->getLastRequest(); + + $this->assertEquals('http://request-catcher:5000/mock-sms', $smsRequest['url']); + $this->assertEquals('Appwrite Mock Message Sender', $smsRequest['headers']['User-Agent']); + $this->assertEquals('username', $smsRequest['headers']['X-Username']); + $this->assertEquals('password', $smsRequest['headers']['X-Key']); + $this->assertEquals('POST', $smsRequest['method']); + $this->assertEquals('+987654321', $smsRequest['data']['from']); + $this->assertEquals('+123456789', $smsRequest['data']['to']); + } +} From 6472702c74a4e03c9b63ec572c6abcf80011571f Mon Sep 17 00:00:00 2001 From: wess Date: Fri, 4 Aug 2023 14:58:28 -0400 Subject: [PATCH 034/106] Twillio test Stubbed in, but on hold, other tests because of different requirements/issues --- tests/e2e/SMS/Msg91Test.php | 27 +++++++++++++++++++++++++++ tests/e2e/SMS/TelesignTest.php | 32 ++++++++++++++++++++++++++++++++ tests/e2e/SMS/TelnyxTest.php | 29 +++++++++++++++++++++++++++++ tests/e2e/SMS/TwilioTest.php | 14 +++----------- tests/e2e/SMS/vonage.php | 29 +++++++++++++++++++++++++++++ 5 files changed, 120 insertions(+), 11 deletions(-) create mode 100644 tests/e2e/SMS/Msg91Test.php create mode 100644 tests/e2e/SMS/TelesignTest.php create mode 100644 tests/e2e/SMS/TelnyxTest.php create mode 100644 tests/e2e/SMS/vonage.php diff --git a/tests/e2e/SMS/Msg91Test.php b/tests/e2e/SMS/Msg91Test.php new file mode 100644 index 00000000..3183d764 --- /dev/null +++ b/tests/e2e/SMS/Msg91Test.php @@ -0,0 +1,27 @@ +send($message), true); + + $this->assertEquals('success', $result["type"]); + } +} diff --git a/tests/e2e/SMS/TelesignTest.php b/tests/e2e/SMS/TelesignTest.php new file mode 100644 index 00000000..7cf276f9 --- /dev/null +++ b/tests/e2e/SMS/TelesignTest.php @@ -0,0 +1,32 @@ +send($message), true); + + // $this->assertEquals('success', $result["type"]); + + $this->markTestSkipped('Telesign requires sales calls and such to setup an account'); + } +} diff --git a/tests/e2e/SMS/TelnyxTest.php b/tests/e2e/SMS/TelnyxTest.php new file mode 100644 index 00000000..dc711498 --- /dev/null +++ b/tests/e2e/SMS/TelnyxTest.php @@ -0,0 +1,29 @@ +send($message), true); + + // $this->assertEquals('success', $result["type"]); + + $this->markTestSkipped('Telnyx had no testing numbers available at this time.'); + } +} diff --git a/tests/e2e/SMS/TwilioTest.php b/tests/e2e/SMS/TwilioTest.php index 21e1f87e..3c50ae4e 100644 --- a/tests/e2e/SMS/TwilioTest.php +++ b/tests/e2e/SMS/TwilioTest.php @@ -12,7 +12,7 @@ class TwilioTest extends Base */ public function testSendSMS() { - $sender = new Twilio('AC902ede6fda93fb923cc2c3128a2b79bd', 'cfc931ba5b7c1a3878ef5696938c8afc'); + $sender = new Twilio(getenv('TWILIO_ACCOUNT_SID'), getenv('TWILIO_AUTH_TOKEN')); $message = new SMS( to: ['+18034041123'], @@ -20,16 +20,8 @@ public function testSendSMS() from: '+15005550006' ); - $sender->send($message); + $result = $sender->send($message); - $smsRequest = $this->getLastRequest(); - - $this->assertEquals('http://request-catcher:5000/mock-sms', $smsRequest['url']); - $this->assertEquals('Appwrite Mock Message Sender', $smsRequest['headers']['User-Agent']); - $this->assertEquals('username', $smsRequest['headers']['X-Username']); - $this->assertEquals('password', $smsRequest['headers']['X-Key']); - $this->assertEquals('POST', $smsRequest['method']); - $this->assertEquals('+987654321', $smsRequest['data']['from']); - $this->assertEquals('+123456789', $smsRequest['data']['to']); + $this->assertNotEmpty($result); } } diff --git a/tests/e2e/SMS/vonage.php b/tests/e2e/SMS/vonage.php new file mode 100644 index 00000000..dc175df9 --- /dev/null +++ b/tests/e2e/SMS/vonage.php @@ -0,0 +1,29 @@ +send($message), true); + + // $this->assertEquals('success', $result["type"]); + + $this->markTestSkipped('Requires a business account, and to contact them first before getting access.'); + } +} From 40eada32e6357b5bd0495735f35ed8bd9f8b21da Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 7 Aug 2023 10:33:29 -0400 Subject: [PATCH 035/106] Removes, decided, unneeded entities Cleans up some docs Linted up the formatting --- .../Messaging/Adapters/Email/Mailgun.php | 10 +++ .../Messaging/Adapters/Email/Sendgrid.php | 26 +++++- src/Utopia/Messaging/Adapters/Push/APNS.php | 82 ++++++++++++------- src/Utopia/Messaging/Adapters/Push/FCM.php | 10 +++ src/Utopia/Messaging/Entities/Entity.php | 7 -- src/Utopia/Messaging/Entities/Message.php | 43 ---------- src/Utopia/Messaging/Entities/Provider.php | 35 -------- src/Utopia/Messaging/Entities/Subscriber.php | 31 ------- src/Utopia/Messaging/Entities/Target.php | 34 -------- src/Utopia/Messaging/Entities/Topic.php | 29 ------- src/Utopia/Messaging/Message.php | 5 +- src/Utopia/Messaging/Messages/Push.php | 2 +- tests/e2e/Email/MailgunTest.php | 7 +- tests/e2e/Push/APNSTest.php | 2 +- tests/e2e/Push/FCMTest.php | 22 ++--- tests/e2e/SMS/Msg91Test.php | 2 +- 16 files changed, 119 insertions(+), 228 deletions(-) delete mode 100644 src/Utopia/Messaging/Entities/Entity.php delete mode 100644 src/Utopia/Messaging/Entities/Message.php delete mode 100644 src/Utopia/Messaging/Entities/Provider.php delete mode 100644 src/Utopia/Messaging/Entities/Subscriber.php delete mode 100644 src/Utopia/Messaging/Entities/Target.php delete mode 100644 src/Utopia/Messaging/Entities/Topic.php diff --git a/src/Utopia/Messaging/Adapters/Email/Mailgun.php b/src/Utopia/Messaging/Adapters/Email/Mailgun.php index 148cb174..5fbdcb01 100644 --- a/src/Utopia/Messaging/Adapters/Email/Mailgun.php +++ b/src/Utopia/Messaging/Adapters/Email/Mailgun.php @@ -17,11 +17,21 @@ public function __construct( ) { } + /** + * Get adapter name. + * + * @return string + */ public function getName(): string { return 'Mailgun'; } + /** + * Get adapter description. + * + * @return int + */ public function getMaxMessagesPerRequest(): int { return 1000; diff --git a/src/Utopia/Messaging/Adapters/Email/Sendgrid.php b/src/Utopia/Messaging/Adapters/Email/Sendgrid.php index a805e6c6..28dc661b 100644 --- a/src/Utopia/Messaging/Adapters/Email/Sendgrid.php +++ b/src/Utopia/Messaging/Adapters/Email/Sendgrid.php @@ -2,24 +2,48 @@ namespace Utopia\Messaging\Adapters\Email; +use Exception; use Utopia\Messaging\Adapters\Email as EmailAdapter; use Utopia\Messaging\Messages\Email; class Sendgrid extends EmailAdapter { - public function __construct(private string $apiKey) { + /** + * @param string $apiKey Your Sendgrid API key to authenticate with the API. + * @return void + */ + public function __construct(private string $apiKey) + { } + /** + * Get adapter name. + * + * @return string + */ public function getName(): string { return 'Sendgrid'; } + /** + * Get max messages per request. + * + * @return int + */ public function getMaxMessagesPerRequest(): int { return 1000; } + /** + * {@inheritdoc} + * + * @param Email $message + * @return string + * + * @throws Exception + */ protected function process(Email $message): string { return $this->request( diff --git a/src/Utopia/Messaging/Adapters/Push/APNS.php b/src/Utopia/Messaging/Adapters/Push/APNS.php index b5bd8a03..8c5b2597 100644 --- a/src/Utopia/Messaging/Adapters/Push/APNS.php +++ b/src/Utopia/Messaging/Adapters/Push/APNS.php @@ -2,42 +2,62 @@ namespace Utopia\Messaging\Adapters\Push; +use Exception; use Utopia\Messaging\Adapters\Push as PushAdapter; use Utopia\Messaging\Messages\Push; class APNS extends PushAdapter { - private $authKey; - private $authKeyId; - private $teamId; - private $bundleId; - private $endpoint; - - public function __construct(string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint) - { - $this->authKey = $authKey; - $this->authKeyId = $authKeyId; - $this->teamId = $teamId; - $this->bundleId = $bundleId; - $this->endpoint = $endpoint; + /** + * @param string $authKey + * @param string $authKeyId + * @param string $teamId + * @param string $bundleId + * @param string $endpoint + * @return void + */ + public function __construct( + private string $authKey, + private string $authKeyId, + private string $teamId, + private string $bundleId, + private string $endpoint + ) { } + /** + * Get adapter name. + * + * @return string + */ public function getName(): string { return 'APNS'; } - + /** + * Get max messages per request. + * + * @return int + */ public function getMaxMessagesPerRequest(): int { return 1000; } + /** + * {@inheritdoc} + * + * @param Push $message + * @return string + * + * @throws Exception + */ public function process(Push $message): string { $headers = [ - 'authorization: bearer ' . $this->generateJwt(), - 'apns-topic: ' . $this->bundleId, + 'authorization: bearer '.$this->generateJwt(), + 'apns-topic: '.$this->bundleId, ]; $payload = json_encode([ @@ -54,16 +74,23 @@ public function process(Push $message): string // Assuming the 'to' array contains device tokens for the push notification recipients. foreach ($message->getTo() as $to) { - $url = $this->endpoint . '/3/device/' . $to; + $url = $this->endpoint.'/3/device/'.$to; $response = $this->request('POST', $url, $headers, $payload); - + // You might want to handle each response here, for instance, logging failures } // This example simply returns the last response, adjust as needed return $response; } - + + /** + * Generate JWT. + * + * @return string + * + * @throws Exception + */ private function generateJwt(): string { $header = json_encode(['alg' => 'ES256', 'kid' => $this->authKeyId]); @@ -71,25 +98,24 @@ private function generateJwt(): string 'iss' => $this->teamId, 'iat' => time(), ]); - + $base64UrlHeader = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header)); $base64UrlClaims = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($claims)); - + $privateKeyResource = openssl_pkey_get_private(file_get_contents($this->authKey)); - if (!$privateKeyResource) { + if (! $privateKeyResource) { throw new \Exception('Invalid private key'); } - + $signature = ''; $success = openssl_sign("$base64UrlHeader.$base64UrlClaims", $signature, $privateKeyResource, OPENSSL_ALGO_SHA256); - - if (!$success) { + + if (! $success) { throw new \Exception('Failed to sign JWT'); } - + $base64UrlSignature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature)); - + return "$base64UrlHeader.$base64UrlClaims.$base64UrlSignature"; } - } diff --git a/src/Utopia/Messaging/Adapters/Push/FCM.php b/src/Utopia/Messaging/Adapters/Push/FCM.php index 3734b16d..8a4d8ac2 100644 --- a/src/Utopia/Messaging/Adapters/Push/FCM.php +++ b/src/Utopia/Messaging/Adapters/Push/FCM.php @@ -15,11 +15,21 @@ public function __construct( ) { } + /** + * Get adapter name. + * + * @return string + */ public function getName(): string { return 'FCM'; } + /** + * Get max messages per request. + * + * @return int + */ public function getMaxMessagesPerRequest(): int { return 1000; diff --git a/src/Utopia/Messaging/Entities/Entity.php b/src/Utopia/Messaging/Entities/Entity.php deleted file mode 100644 index 126407e2..00000000 --- a/src/Utopia/Messaging/Entities/Entity.php +++ /dev/null @@ -1,7 +0,0 @@ -id = $id; - $this->providerId = $providerId; - $this->providerInternalId = $providerInternalId; - $this->data = $data; - $this->to = $to; - $this->deliveryTime = $deliveryTime; - $this->deliveryError = $deliveryError; - $this->deliveredTo = $deliveredTo; - $this->delivered = $delivered; - $this->search = $search; - } - -} \ No newline at end of file diff --git a/src/Utopia/Messaging/Entities/Provider.php b/src/Utopia/Messaging/Entities/Provider.php deleted file mode 100644 index d85b604e..00000000 --- a/src/Utopia/Messaging/Entities/Provider.php +++ /dev/null @@ -1,35 +0,0 @@ -id = $id; - $this->userId = $userId; - $this->name = $name; - $this->provider = $provider; - $this->type = $type; - $this->credentials = $credentials; - } - -} \ No newline at end of file diff --git a/src/Utopia/Messaging/Entities/Subscriber.php b/src/Utopia/Messaging/Entities/Subscriber.php deleted file mode 100644 index d7594427..00000000 --- a/src/Utopia/Messaging/Entities/Subscriber.php +++ /dev/null @@ -1,31 +0,0 @@ -id = $id; - $this->userId = $userId; - $this->userInternalId = $userInternalId; - $this->targetId = $targetId; - $this->targetInternalId = $targetInternalId; - } - -} \ No newline at end of file diff --git a/src/Utopia/Messaging/Entities/Target.php b/src/Utopia/Messaging/Entities/Target.php deleted file mode 100644 index b0d37a35..00000000 --- a/src/Utopia/Messaging/Entities/Target.php +++ /dev/null @@ -1,34 +0,0 @@ -id = $id; - $this->userId = $userId; - $this->userInternalId = $userInternalId; - $this->providerId = $providerId; - $this->providerInternalId = $providerInternalId; - $this->providerType = $providerType; - $this->identifier = $identifier; - } - -} \ No newline at end of file diff --git a/src/Utopia/Messaging/Entities/Topic.php b/src/Utopia/Messaging/Entities/Topic.php deleted file mode 100644 index b9759b8e..00000000 --- a/src/Utopia/Messaging/Entities/Topic.php +++ /dev/null @@ -1,29 +0,0 @@ -id = $id; - $this->providerId = $providerId; - $this->providerInternalId = $providerInternalId; - $this->name = $name; - $this->description = $description; - } - -} \ No newline at end of file diff --git a/src/Utopia/Messaging/Message.php b/src/Utopia/Messaging/Message.php index 0b70a2ce..5c335d17 100644 --- a/src/Utopia/Messaging/Message.php +++ b/src/Utopia/Messaging/Message.php @@ -7,6 +7,7 @@ */ interface Message { - function getTo():array; - function getFrom():?string; + public function getTo(): array; + + public function getFrom(): ?string; } diff --git a/src/Utopia/Messaging/Messages/Push.php b/src/Utopia/Messaging/Messages/Push.php index 12e1d7c3..93b8f5d7 100644 --- a/src/Utopia/Messaging/Messages/Push.php +++ b/src/Utopia/Messaging/Messages/Push.php @@ -44,7 +44,7 @@ public function getFrom(): ?string { return null; } - + /** * @return string */ diff --git a/tests/e2e/Email/MailgunTest.php b/tests/e2e/Email/MailgunTest.php index 0f55ee15..2426b03f 100644 --- a/tests/e2e/Email/MailgunTest.php +++ b/tests/e2e/Email/MailgunTest.php @@ -12,19 +12,18 @@ class MailgunTest extends Base */ public function testSendEmail() { - $key = getenv('MAILGUN_API_KEY'); $domain = getenv('MAILGUN_DOMAIN'); $sender = new Mailgun( - $key, - $domain + $key, + $domain ); $to = 'wcope@me.com'; $subject = 'Test Subject'; $content = 'Test Content'; - $from = 'sender@' . $domain; + $from = 'sender@'.$domain; $message = new Email( to: [$to], diff --git a/tests/e2e/Push/APNSTest.php b/tests/e2e/Push/APNSTest.php index 39fe3dd6..c008df84 100644 --- a/tests/e2e/Push/APNSTest.php +++ b/tests/e2e/Push/APNSTest.php @@ -9,7 +9,7 @@ class APNSTest extends Base { public function testSend(): void { - $authKey = __DIR__ . '/AuthKey_8KVVCLA3HL.p8'; + $authKey = __DIR__.'/AuthKey_8KVVCLA3HL.p8'; $authKeyId = '8KVVCLA3HL'; $teamId = 'ZZJ8NM59TE'; $bundleId = 'io.wess.appwritetest'; diff --git a/tests/e2e/Push/FCMTest.php b/tests/e2e/Push/FCMTest.php index cd10658c..0b429c6e 100644 --- a/tests/e2e/Push/FCMTest.php +++ b/tests/e2e/Push/FCMTest.php @@ -14,17 +14,17 @@ public function testSend(): void $adapter = new FCMAdapter($serverKey); $message = new Push( - ['eJa9AhokQUudfBPJwRx2OX:APA91bE0KbMkXU7a4eCyq1CyN1nR9TwOD5NQIaHADJBMBV1GjOjTfyPywOXKVeKVvvjz6nvB2jASGtRxGJHsM4Z4osoHnTx5IrnxCNUDEH11wsm4vMBiKW0zbugVis1MdtusTu9admrk'], - 'TestTitle', - 'TestBody', - null, - null, - 'default', - null, - null, - null, - '1' - ); + ['eJa9AhokQUudfBPJwRx2OX:APA91bE0KbMkXU7a4eCyq1CyN1nR9TwOD5NQIaHADJBMBV1GjOjTfyPywOXKVeKVvvjz6nvB2jASGtRxGJHsM4Z4osoHnTx5IrnxCNUDEH11wsm4vMBiKW0zbugVis1MdtusTu9admrk'], + 'TestTitle', + 'TestBody', + null, + null, + 'default', + null, + null, + null, + '1' + ); $response = $adapter->send($message); diff --git a/tests/e2e/SMS/Msg91Test.php b/tests/e2e/SMS/Msg91Test.php index 3183d764..07df9b1c 100644 --- a/tests/e2e/SMS/Msg91Test.php +++ b/tests/e2e/SMS/Msg91Test.php @@ -22,6 +22,6 @@ public function testSendSMS() $result = \json_decode($sender->send($message), true); - $this->assertEquals('success', $result["type"]); + $this->assertEquals('success', $result['type']); } } From 43bed4b545159a3c8081457c9ef83b6eb2980ffd Mon Sep 17 00:00:00 2001 From: wess Date: Fri, 11 Aug 2023 11:14:42 -0400 Subject: [PATCH 036/106] Updates gitignore, it was missing a good bit Removes .env from docker-compose file --- .gitignore | 94 +++++++++++++++++++++++++++++++++++++++++++++- docker-compose.yml | 4 +- 2 files changed, 93 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 03bf4c75..3640a16f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,97 @@ .idea vendor -.phpunit.result.cache Makefile .envrc .env -*.p8 \ No newline at end of file +*.p8 + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud + +### PHPUnit ### +# Covers PHPUnit +# Reference: https://phpunit.de/ + +# Generated files +.phpunit.result.cache +.phpunit.cache + +# PHPUnit +/app/phpunit.xml +/phpunit.xml + +# Build data +/build/ + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# End of https://www.toptal.com/developers/gitignore/api/macos,linux,windows,phpunit \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index e0a8130f..623519d5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,9 +8,7 @@ services: - ./src:/usr/local/src/src - ./tests:/usr/local/src/tests - ./phpunit.xml:/usr/local/src/phpunit.xml - env_file: - - .env - + maildev: image: appwrite/mailcatcher:1.0.0 ports: From 7f4448c63786c1f50d33181a5b448d84fd6d061c Mon Sep 17 00:00:00 2001 From: wess Date: Fri, 11 Aug 2023 11:16:01 -0400 Subject: [PATCH 037/106] Moves p8 to use env var --- tests/e2e/Push/APNSTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/Push/APNSTest.php b/tests/e2e/Push/APNSTest.php index c008df84..558c6c89 100644 --- a/tests/e2e/Push/APNSTest.php +++ b/tests/e2e/Push/APNSTest.php @@ -9,7 +9,7 @@ class APNSTest extends Base { public function testSend(): void { - $authKey = __DIR__.'/AuthKey_8KVVCLA3HL.p8'; + $authKey = getenv('AuthKey_8KVVCLA3HL.p8'); $authKeyId = '8KVVCLA3HL'; $teamId = 'ZZJ8NM59TE'; $bundleId = 'io.wess.appwritetest'; From 5d26fde36b1d66c56dec62e719d030ce30c7f851 Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 14 Aug 2023 10:53:27 -0400 Subject: [PATCH 038/106] Adds proper env vars to docker-compose.yml --- docker-compose.yml | 10 ++++++++++ src/Utopia/Messaging/Adapters/Push/APNS.php | 6 +++--- tests/e2e/Push/APNSTest.php | 2 +- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 623519d5..2f915c34 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,6 +4,16 @@ services: tests: build: context: . + environment: + - MAILGUN_API_KEY + - MAILGUN_DOMAIN + - SENDGRID_API_KEY + - FCM_SERVER_KEY + - TWILIO_ACCOUNT_SID + - TWILIO_AUTH_TOKEN + - TELNYX_API_KEY + - TELNYX_PUBLIC_KEY + - AUTHKEY_8KVVCLA3HL volumes: - ./src:/usr/local/src/src - ./tests:/usr/local/src/tests diff --git a/src/Utopia/Messaging/Adapters/Push/APNS.php b/src/Utopia/Messaging/Adapters/Push/APNS.php index 8c5b2597..4ec07464 100644 --- a/src/Utopia/Messaging/Adapters/Push/APNS.php +++ b/src/Utopia/Messaging/Adapters/Push/APNS.php @@ -102,13 +102,13 @@ private function generateJwt(): string $base64UrlHeader = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header)); $base64UrlClaims = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($claims)); - $privateKeyResource = openssl_pkey_get_private(file_get_contents($this->authKey)); - if (! $privateKeyResource) { + if (! $this->authKey) { + var_dump($this->authKey); throw new \Exception('Invalid private key'); } $signature = ''; - $success = openssl_sign("$base64UrlHeader.$base64UrlClaims", $signature, $privateKeyResource, OPENSSL_ALGO_SHA256); + $success = openssl_sign("$base64UrlHeader.$base64UrlClaims", $signature, $this->authKey, OPENSSL_ALGO_SHA256); if (! $success) { throw new \Exception('Failed to sign JWT'); diff --git a/tests/e2e/Push/APNSTest.php b/tests/e2e/Push/APNSTest.php index 558c6c89..b558a156 100644 --- a/tests/e2e/Push/APNSTest.php +++ b/tests/e2e/Push/APNSTest.php @@ -9,7 +9,7 @@ class APNSTest extends Base { public function testSend(): void { - $authKey = getenv('AuthKey_8KVVCLA3HL.p8'); + $authKey = getenv('AUTHKEY_8KVVCLA3HL'); $authKeyId = '8KVVCLA3HL'; $teamId = 'ZZJ8NM59TE'; $bundleId = 'io.wess.appwritetest'; From 0ea850d9033d267cd219a2142791b2b6ba99a7a6 Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 14 Aug 2023 11:36:33 -0400 Subject: [PATCH 039/106] lint all the things! (^_^)/ --- src/Utopia/Messaging/Adapters/Push/APNS.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Utopia/Messaging/Adapters/Push/APNS.php b/src/Utopia/Messaging/Adapters/Push/APNS.php index 4ec07464..e933d30d 100644 --- a/src/Utopia/Messaging/Adapters/Push/APNS.php +++ b/src/Utopia/Messaging/Adapters/Push/APNS.php @@ -103,7 +103,7 @@ private function generateJwt(): string $base64UrlClaims = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($claims)); if (! $this->authKey) { - var_dump($this->authKey); + var_dump($this->authKey); throw new \Exception('Invalid private key'); } From 6f2defbf50173a358bbea9caff6561b0894a320c Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 14 Aug 2023 16:04:20 -0400 Subject: [PATCH 040/106] Let's add EU --- src/Utopia/Messaging/Adapters/Email/Mailgun.php | 5 ++++- tests/e2e/Email/MailgunTest.php | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Utopia/Messaging/Adapters/Email/Mailgun.php b/src/Utopia/Messaging/Adapters/Email/Mailgun.php index 5fbdcb01..29e1abb7 100644 --- a/src/Utopia/Messaging/Adapters/Email/Mailgun.php +++ b/src/Utopia/Messaging/Adapters/Email/Mailgun.php @@ -44,9 +44,12 @@ public function getMaxMessagesPerRequest(): int */ protected function process(Email $message): string { + var_dump($this->domain); + exit; + $response = $this->request( method: 'POST', - url: "https://api.mailgun.net/v3/{$this->domain}/messages", + url: "https://api.eu.mailgun.net/v3/{$this->domain}/messages", headers: [ 'Authorization: Basic '.base64_encode('api:'.$this->apiKey), ], diff --git a/tests/e2e/Email/MailgunTest.php b/tests/e2e/Email/MailgunTest.php index 2426b03f..b4cb27c0 100644 --- a/tests/e2e/Email/MailgunTest.php +++ b/tests/e2e/Email/MailgunTest.php @@ -15,6 +15,10 @@ public function testSendEmail() $key = getenv('MAILGUN_API_KEY'); $domain = getenv('MAILGUN_DOMAIN'); + var_dump($key); + var_dump($domain); + die; + $sender = new Mailgun( $key, $domain From 5f85757316eb842e9169d318e234124ff252c404 Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 14 Aug 2023 16:35:31 -0400 Subject: [PATCH 041/106] Fixes lints and boom passing tests --- tests/e2e/Email/MailgunTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/e2e/Email/MailgunTest.php b/tests/e2e/Email/MailgunTest.php index b4cb27c0..db4b6115 100644 --- a/tests/e2e/Email/MailgunTest.php +++ b/tests/e2e/Email/MailgunTest.php @@ -15,9 +15,9 @@ public function testSendEmail() $key = getenv('MAILGUN_API_KEY'); $domain = getenv('MAILGUN_DOMAIN'); - var_dump($key); - var_dump($domain); - die; + var_dump($key); + var_dump($domain); + exit; $sender = new Mailgun( $key, From b8add141eebc67242658b3bf500ed30d858b6345 Mon Sep 17 00:00:00 2001 From: wess Date: Wed, 30 Aug 2023 08:35:23 -0400 Subject: [PATCH 042/106] PR requested updates APNS rewrite for batch sending using HTTP/2 --- docker-compose.yml | 12 +-- phpunit.xml | 2 +- .../Messaging/Adapters/Email/Mailgun.php | 10 ++- src/Utopia/Messaging/Adapters/Push/APNS.php | 88 ++++++++++++++++--- .../Messaging/Adapters/SMS/Telesign.php | 18 +++- src/Utopia/Messaging/Adapters/SMS/Vonage.php | 5 +- tests/e2e/Email/MailgunTest.php | 12 ++- tests/e2e/Push/APNSTest.php | 28 +++--- tests/e2e/Push/FCMTest.php | 24 ++--- tests/e2e/SMS/TelesignTest.php | 17 +--- tests/e2e/SMS/TwilioTest.php | 11 ++- tests/e2e/SMS/VonageTest.php | 32 +++++++ tests/e2e/SMS/vonage.php | 29 ------ 13 files changed, 173 insertions(+), 115 deletions(-) create mode 100644 tests/e2e/SMS/VonageTest.php delete mode 100644 tests/e2e/SMS/vonage.php diff --git a/docker-compose.yml b/docker-compose.yml index 2f915c34..11ef5e2c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,16 +4,8 @@ services: tests: build: context: . - environment: - - MAILGUN_API_KEY - - MAILGUN_DOMAIN - - SENDGRID_API_KEY - - FCM_SERVER_KEY - - TWILIO_ACCOUNT_SID - - TWILIO_AUTH_TOKEN - - TELNYX_API_KEY - - TELNYX_PUBLIC_KEY - - AUTHKEY_8KVVCLA3HL + env_file: + - .env volumes: - ./src:/usr/local/src/src - ./tests:/usr/local/src/tests diff --git a/phpunit.xml b/phpunit.xml index 53cd4abd..8db6586a 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -6,7 +6,7 @@ convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" - stopOnFailure="true" + stopOnFailure="false" > diff --git a/src/Utopia/Messaging/Adapters/Email/Mailgun.php b/src/Utopia/Messaging/Adapters/Email/Mailgun.php index 29e1abb7..a41e4dd9 100644 --- a/src/Utopia/Messaging/Adapters/Email/Mailgun.php +++ b/src/Utopia/Messaging/Adapters/Email/Mailgun.php @@ -42,14 +42,16 @@ public function getMaxMessagesPerRequest(): int * * @throws \Exception */ - protected function process(Email $message): string + protected function process(Email $message, bool $isUS = true): string { - var_dump($this->domain); - exit; + $usDomain = 'api.mailgun.net'; + $euDomain = 'api.eu.mailgun.net'; + $domain = $isUS ? $usDomain : $euDomain; + $response = $this->request( method: 'POST', - url: "https://api.eu.mailgun.net/v3/{$this->domain}/messages", + url: "https://$domain/v3/{$this->domain}/messages", headers: [ 'Authorization: Basic '.base64_encode('api:'.$this->apiKey), ], diff --git a/src/Utopia/Messaging/Adapters/Push/APNS.php b/src/Utopia/Messaging/Adapters/Push/APNS.php index e933d30d..288b329d 100644 --- a/src/Utopia/Messaging/Adapters/Push/APNS.php +++ b/src/Utopia/Messaging/Adapters/Push/APNS.php @@ -55,12 +55,7 @@ public function getMaxMessagesPerRequest(): int */ public function process(Push $message): string { - $headers = [ - 'authorization: bearer '.$this->generateJwt(), - 'apns-topic: '.$this->bundleId, - ]; - - $payload = json_encode([ + $payload = [ 'aps' => [ 'alert' => [ 'title' => $message->getTitle(), @@ -70,18 +65,82 @@ public function process(Push $message): string 'sound' => $message->getSound(), 'data' => $message->getData(), ], - ]); + ]; // Assuming the 'to' array contains device tokens for the push notification recipients. - foreach ($message->getTo() as $to) { - $url = $this->endpoint.'/3/device/'.$to; - $response = $this->request('POST', $url, $headers, $payload); + + // $url = $this->endpoint.'/3/device'; + // $response = $this->request('POST', $url, $headers, \json_encode($payloads)); + // // This example simply returns the last response, adjust as needed + // return $response; + + return $this->notify($message->getTo(), $payload); + } + + private function notify(array $to, array $payload) + { + $headers = [ + 'authorization: bearer '.$this->generateJwt(), + 'apns-topic: '.$this->bundleId, + ]; + + $ch = curl_init(); + + curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); + + curl_setopt_array($ch, array( + CURLOPT_PORT => 443, + CURLOPT_HTTPHEADER => $headers, + CURLOPT_POST => TRUE, + CURLOPT_POSTFIELDS => \json_encode($payload), + CURLOPT_RETURNTRANSFER => TRUE, + CURLOPT_TIMEOUT => 30, + CURLOPT_HEADER => TRUE + )); + + $response = ''; + + foreach($to as $token) { + curl_setopt($ch, CURLOPT_URL, $this->endpoint.'/3/device/'.$token); - // You might want to handle each response here, for instance, logging failures + $response = curl_exec($ch); + } + + curl_close($ch); + + $response = $this->formatResponse($response); + + var_dump($response); + die; + return $response; + } + + private function formatResponse(string $response):array + { + $filtered = array_filter( + explode("\r\n", $response), + function($value) { + return !empty($value); } + ); + + $result = []; + + foreach($filtered as $value) { + if(str_contains($value, 'HTTP')) { + $result['status'] = trim(str_replace('HTTP/2 ', '', $value)); + continue; + } + + $parts = explode(':', trim($value)); + + $result[$parts[0]] = $parts[1]; + } + + var_dump($result); + die; - // This example simply returns the last response, adjust as needed - return $response; + return $result; } /** @@ -99,11 +158,12 @@ private function generateJwt(): string 'iat' => time(), ]); + // Replaces URL sensitive characters that could be the result of base64 encoding. + // Replace to _ to avoid any special handling. $base64UrlHeader = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header)); $base64UrlClaims = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($claims)); if (! $this->authKey) { - var_dump($this->authKey); throw new \Exception('Invalid private key'); } diff --git a/src/Utopia/Messaging/Adapters/SMS/Telesign.php b/src/Utopia/Messaging/Adapters/SMS/Telesign.php index d19d5876..6cd83ac3 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Telesign.php +++ b/src/Utopia/Messaging/Adapters/SMS/Telesign.php @@ -37,10 +37,10 @@ public function getMaxMessagesPerRequest(): int */ protected function process(SMS $message): string { - $to = \array_map( - fn ($to) => \ltrim($to, '+'), + $to = $this->formatNumbers(\array_map( + fn ($to) => $to, $message->getTo() - ); + )); return $this->request( method: 'POST', @@ -50,8 +50,18 @@ protected function process(SMS $message): string ], body: \http_build_query([ 'template' => $message->getContent(), - 'recipients' => \implode(',', $to), + 'recipients' => $to, ]), ); } + + private function formatNumbers(array $numbers): string + { + $formatted = \array_map( + fn ($number) => $number . ':' . \uniqid(), + $numbers + ); + + return implode(',', $formatted); + } } diff --git a/src/Utopia/Messaging/Adapters/SMS/Vonage.php b/src/Utopia/Messaging/Adapters/SMS/Vonage.php index 2643a6b0..b724aae7 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Vonage.php +++ b/src/Utopia/Messaging/Adapters/SMS/Vonage.php @@ -37,18 +37,19 @@ public function getMaxMessagesPerRequest(): int */ protected function process(SMS $message): string { + $to = \array_map( fn ($to) => \ltrim($to, '+'), $message->getTo() ); - + return $this->request( method: 'POST', url: 'https://rest.nexmo.com/sms/json', body: \http_build_query([ 'text' => $message->getContent(), 'from' => $message->getFrom(), - 'to' => \implode(',', $to), + 'to' => $to[0], //\implode(',', $to), 'api_key' => $this->apiKey, 'api_secret' => $this->apiSecret, ]), diff --git a/tests/e2e/Email/MailgunTest.php b/tests/e2e/Email/MailgunTest.php index db4b6115..779e1bd8 100644 --- a/tests/e2e/Email/MailgunTest.php +++ b/tests/e2e/Email/MailgunTest.php @@ -15,10 +15,6 @@ public function testSendEmail() $key = getenv('MAILGUN_API_KEY'); $domain = getenv('MAILGUN_DOMAIN'); - var_dump($key); - var_dump($domain); - exit; - $sender = new Mailgun( $key, $domain @@ -36,8 +32,10 @@ public function testSendEmail() content: $content, ); - $sender->send($message); - - $this->assertEquals(true, true); + $result = (array)\json_decode($sender->send($message)); + + $this->assertArrayHasKey('id', $result); + $this->assertArrayHasKey('message', $result); + $this->assertTrue(str_contains(strtolower($result['message']), 'queued')); } } diff --git a/tests/e2e/Push/APNSTest.php b/tests/e2e/Push/APNSTest.php index b558a156..4212a3a5 100644 --- a/tests/e2e/Push/APNSTest.php +++ b/tests/e2e/Push/APNSTest.php @@ -9,25 +9,25 @@ class APNSTest extends Base { public function testSend(): void { - $authKey = getenv('AUTHKEY_8KVVCLA3HL'); - $authKeyId = '8KVVCLA3HL'; - $teamId = 'ZZJ8NM59TE'; - $bundleId = 'io.wess.appwritetest'; + $authKey = getenv('APNS_AUTHKEY_8KVVCLA3HL'); + $authKeyId = getenv('APNS_AUTH_ID'); + $teamId = getenv('APNS_TEAM_ID'); + $bundleId = getenv('APNS_BUNDLE_ID'); $endpoint = 'https://api.sandbox.push.apple.com:443'; $adapter = new APNSAdapter($authKey, $authKeyId, $teamId, $bundleId, $endpoint); $message = new Push( - ['80858be082476f1067ce737b69240bbea9b58676d0eef64960f3aa75b6cb7ca7656822f02a56960ff805b393ab7c82484f56229b69731f939ae8c3aa27399c29fe8efa26d272b5a1817813f023dee9fd'], - 'TestTitle', - 'TestBody', - null, - null, - 'default', - null, - null, - null, - '1' + to: ['80858be082476f1067ce737b69240bbea9b58676d0eef64960f3aa75b6cb7ca7656822f02a56960ff805b393ab7c82484f56229b69731f939ae8c3aa27399c29fe8efa26d272b5a1817813f023dee9fd'], + title: 'TestTitle', + body: 'TestBody', + data: null, + action: null, + sound: 'default', + icon: null, + color: null, + tag: null, + badge: '1' ); $response = $adapter->send($message); diff --git a/tests/e2e/Push/FCMTest.php b/tests/e2e/Push/FCMTest.php index 0b429c6e..71128e45 100644 --- a/tests/e2e/Push/FCMTest.php +++ b/tests/e2e/Push/FCMTest.php @@ -14,20 +14,22 @@ public function testSend(): void $adapter = new FCMAdapter($serverKey); $message = new Push( - ['eJa9AhokQUudfBPJwRx2OX:APA91bE0KbMkXU7a4eCyq1CyN1nR9TwOD5NQIaHADJBMBV1GjOjTfyPywOXKVeKVvvjz6nvB2jASGtRxGJHsM4Z4osoHnTx5IrnxCNUDEH11wsm4vMBiKW0zbugVis1MdtusTu9admrk'], - 'TestTitle', - 'TestBody', - null, - null, - 'default', - null, - null, - null, - '1' + to: ['eJa9AhokQUudfBPJwRx2OX:APA91bE0KbMkXU7a4eCyq1CyN1nR9TwOD5NQIaHADJBMBV1GjOjTfyPywOXKVeKVvvjz6nvB2jASGtRxGJHsM4Z4osoHnTx5IrnxCNUDEH11wsm4vMBiKW0zbugVis1MdtusTu9admrk'], + title: 'TestTitle', + body: 'TestBody', + data: null, + action: null, + sound: 'default', + icon: null, + color: null, + tag: null, + badge: '1' ); - $response = $adapter->send($message); + $response = \json_decode($adapter->send($message)); $this->assertNotEmpty($response); + $this->assertEquals(1, $response->success); + $this->assertEquals(0, $response->failure); } } diff --git a/tests/e2e/SMS/TelesignTest.php b/tests/e2e/SMS/TelesignTest.php index 7cf276f9..f78653e0 100644 --- a/tests/e2e/SMS/TelesignTest.php +++ b/tests/e2e/SMS/TelesignTest.php @@ -12,21 +12,6 @@ class TelesignTest extends Base */ public function testSendSMS() { - // $username = ''; - // $password = ''; - - // $sender = new Telesign($username, $password); - - // $message = new SMS( - // to: ['+18034041123'], - // content: 'Test Content', - // from: '+15005550006' - // ); - - // $result = \json_decode($sender->send($message), true); - - // $this->assertEquals('success', $result["type"]); - - $this->markTestSkipped('Telesign requires sales calls and such to setup an account'); + $this->markTestSkipped('Telesign requires support/sales call in order to enable bulk SMS'); } } diff --git a/tests/e2e/SMS/TwilioTest.php b/tests/e2e/SMS/TwilioTest.php index 3c50ae4e..c3b86760 100644 --- a/tests/e2e/SMS/TwilioTest.php +++ b/tests/e2e/SMS/TwilioTest.php @@ -13,15 +13,20 @@ class TwilioTest extends Base public function testSendSMS() { $sender = new Twilio(getenv('TWILIO_ACCOUNT_SID'), getenv('TWILIO_AUTH_TOKEN')); + $to = ['+18034041123']; + $from = '+15005550006'; $message = new SMS( - to: ['+18034041123'], + to: $to, content: 'Test Content', - from: '+15005550006' + from: $from ); - $result = $sender->send($message); + $result = \json_decode($sender->send($message)); $this->assertNotEmpty($result); + $this->assertEquals($to[0], $result->to); + $this->assertEquals($from, $result->from); + $this->assertNull($result->error_message); } } diff --git a/tests/e2e/SMS/VonageTest.php b/tests/e2e/SMS/VonageTest.php new file mode 100644 index 00000000..9fc71034 --- /dev/null +++ b/tests/e2e/SMS/VonageTest.php @@ -0,0 +1,32 @@ +send($message), true); + + $this->assertArrayHasKey("messages", $result); + $this->assertEquals(1, count($result['messages'])); + $this->assertEquals("1", $result['message-count']); + } +} diff --git a/tests/e2e/SMS/vonage.php b/tests/e2e/SMS/vonage.php deleted file mode 100644 index dc175df9..00000000 --- a/tests/e2e/SMS/vonage.php +++ /dev/null @@ -1,29 +0,0 @@ -send($message), true); - - // $this->assertEquals('success', $result["type"]); - - $this->markTestSkipped('Requires a business account, and to contact them first before getting access.'); - } -} From da94fa79a62d20c500a3c45cbddd66b7e48c0749 Mon Sep 17 00:00:00 2001 From: wess Date: Wed, 30 Aug 2023 08:51:53 -0400 Subject: [PATCH 043/106] Correction and clean up for APNS.php Updated tests to look for keys and status --- src/Utopia/Messaging/Adapters/Push/APNS.php | 13 +++---------- tests/e2e/Push/APNSTest.php | 6 ++++-- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/Push/APNS.php b/src/Utopia/Messaging/Adapters/Push/APNS.php index 288b329d..fc24c585 100644 --- a/src/Utopia/Messaging/Adapters/Push/APNS.php +++ b/src/Utopia/Messaging/Adapters/Push/APNS.php @@ -74,10 +74,10 @@ public function process(Push $message): string // // This example simply returns the last response, adjust as needed // return $response; - return $this->notify($message->getTo(), $payload); + return \json_encode($this->notify($message->getTo(), $payload)); } - private function notify(array $to, array $payload) + private function notify(array $to, array $payload):array { $headers = [ 'authorization: bearer '.$this->generateJwt(), @@ -108,11 +108,7 @@ private function notify(array $to, array $payload) curl_close($ch); - $response = $this->formatResponse($response); - - var_dump($response); - die; - return $response; + return $this->formatResponse($response); } private function formatResponse(string $response):array @@ -137,9 +133,6 @@ function($value) { $result[$parts[0]] = $parts[1]; } - var_dump($result); - die; - return $result; } diff --git a/tests/e2e/Push/APNSTest.php b/tests/e2e/Push/APNSTest.php index 4212a3a5..b666e658 100644 --- a/tests/e2e/Push/APNSTest.php +++ b/tests/e2e/Push/APNSTest.php @@ -30,8 +30,10 @@ public function testSend(): void badge: '1' ); - $response = $adapter->send($message); + $response = (array)\json_decode($adapter->send($message)); - $this->assertEquals('', $response); + $this->assertEquals("200", $response['status']); + $this->assertArrayHasKey('apns-id', $response); + $this->assertArrayHasKey('apns-unique-id', $response); } } From d43325af2669c8c3904d682e7116a309c0d46799 Mon Sep 17 00:00:00 2001 From: wess Date: Wed, 30 Aug 2023 10:53:34 -0400 Subject: [PATCH 044/106] Removes personal email and moves test emails into .env --- tests/e2e/Email/MailgunTest.php | 2 +- tests/e2e/Email/SendgridTest.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/e2e/Email/MailgunTest.php b/tests/e2e/Email/MailgunTest.php index 779e1bd8..2f880992 100644 --- a/tests/e2e/Email/MailgunTest.php +++ b/tests/e2e/Email/MailgunTest.php @@ -20,7 +20,7 @@ public function testSendEmail() $domain ); - $to = 'wcope@me.com'; + $to = getenv('TEST_EMAIL'); $subject = 'Test Subject'; $content = 'Test Content'; $from = 'sender@'.$domain; diff --git a/tests/e2e/Email/SendgridTest.php b/tests/e2e/Email/SendgridTest.php index 0786a1eb..05bcc3ab 100644 --- a/tests/e2e/Email/SendgridTest.php +++ b/tests/e2e/Email/SendgridTest.php @@ -15,10 +15,10 @@ public function testSendEmail() $key = getenv('SENDGRID_API_KEY'); $sender = new Sendgrid($key); - $to = 'wcope@me.com'; + $to = getenv('TEST_EMAIL'); $subject = 'Test Subject'; $content = 'Test Content'; - $from = 'devpipe@wess.io'; + $from = getenv('TEST_FROM_EMAIL'); $message = new Email( to: [$to], From 36aee6ae3c601b796364e35be083b909e02bef66 Mon Sep 17 00:00:00 2001 From: wess Date: Wed, 30 Aug 2023 14:32:54 -0400 Subject: [PATCH 045/106] Lint fixes --- .../Messaging/Adapters/Email/Mailgun.php | 2 +- src/Utopia/Messaging/Adapters/Push/APNS.php | 83 ++++++++++--------- .../Messaging/Adapters/SMS/Telesign.php | 4 +- src/Utopia/Messaging/Adapters/SMS/Vonage.php | 3 +- tests/e2e/Email/MailgunTest.php | 4 +- tests/e2e/Push/APNSTest.php | 4 +- tests/e2e/SMS/TelesignTest.php | 3 - tests/e2e/SMS/VonageTest.php | 8 +- 8 files changed, 54 insertions(+), 57 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/Email/Mailgun.php b/src/Utopia/Messaging/Adapters/Email/Mailgun.php index a41e4dd9..112d471f 100644 --- a/src/Utopia/Messaging/Adapters/Email/Mailgun.php +++ b/src/Utopia/Messaging/Adapters/Email/Mailgun.php @@ -48,7 +48,7 @@ protected function process(Email $message, bool $isUS = true): string $euDomain = 'api.eu.mailgun.net'; $domain = $isUS ? $usDomain : $euDomain; - + $response = $this->request( method: 'POST', url: "https://$domain/v3/{$this->domain}/messages", diff --git a/src/Utopia/Messaging/Adapters/Push/APNS.php b/src/Utopia/Messaging/Adapters/Push/APNS.php index fc24c585..4f8dda83 100644 --- a/src/Utopia/Messaging/Adapters/Push/APNS.php +++ b/src/Utopia/Messaging/Adapters/Push/APNS.php @@ -68,7 +68,7 @@ public function process(Push $message): string ]; // Assuming the 'to' array contains device tokens for the push notification recipients. - + // $url = $this->endpoint.'/3/device'; // $response = $this->request('POST', $url, $headers, \json_encode($payloads)); // // This example simply returns the last response, adjust as needed @@ -77,63 +77,64 @@ public function process(Push $message): string return \json_encode($this->notify($message->getTo(), $payload)); } - private function notify(array $to, array $payload):array + private function notify(array $to, array $payload): array { - $headers = [ - 'authorization: bearer '.$this->generateJwt(), - 'apns-topic: '.$this->bundleId, - ]; + $headers = [ + 'authorization: bearer '.$this->generateJwt(), + 'apns-topic: '.$this->bundleId, + ]; - $ch = curl_init(); + $ch = curl_init(); - curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); + curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); - curl_setopt_array($ch, array( - CURLOPT_PORT => 443, - CURLOPT_HTTPHEADER => $headers, - CURLOPT_POST => TRUE, - CURLOPT_POSTFIELDS => \json_encode($payload), - CURLOPT_RETURNTRANSFER => TRUE, - CURLOPT_TIMEOUT => 30, - CURLOPT_HEADER => TRUE - )); + curl_setopt_array($ch, [ + CURLOPT_PORT => 443, + CURLOPT_HTTPHEADER => $headers, + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => \json_encode($payload), + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 30, + CURLOPT_HEADER => true, + ]); - $response = ''; + $response = ''; - foreach($to as $token) { - curl_setopt($ch, CURLOPT_URL, $this->endpoint.'/3/device/'.$token); + foreach ($to as $token) { + curl_setopt($ch, CURLOPT_URL, $this->endpoint.'/3/device/'.$token); - $response = curl_exec($ch); - } + $response = curl_exec($ch); + } - curl_close($ch); + curl_close($ch); - return $this->formatResponse($response); + return $this->formatResponse($response); } - private function formatResponse(string $response):array + private function formatResponse(string $response): array { - $filtered = array_filter( - explode("\r\n", $response), - function($value) { - return !empty($value); - } - ); + $filtered = array_filter( + explode("\r\n", $response), + function ($value) { + return ! empty($value); + } + ); - $result = []; + $result = []; - foreach($filtered as $value) { - if(str_contains($value, 'HTTP')) { - $result['status'] = trim(str_replace('HTTP/2 ', '', $value)); - continue; - } + foreach ($filtered as $value) { + if (str_contains($value, 'HTTP')) { + $result['status'] = trim(str_replace('HTTP/2 ', '', $value)); - $parts = explode(':', trim($value)); + continue; + } - $result[$parts[0]] = $parts[1]; - } + $parts = explode(':', trim($value)); + + $result[$parts[0]] = $parts[1]; + } - return $result; + return $result; } /** diff --git a/src/Utopia/Messaging/Adapters/SMS/Telesign.php b/src/Utopia/Messaging/Adapters/SMS/Telesign.php index 6cd83ac3..6e77903e 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Telesign.php +++ b/src/Utopia/Messaging/Adapters/SMS/Telesign.php @@ -58,10 +58,10 @@ protected function process(SMS $message): string private function formatNumbers(array $numbers): string { $formatted = \array_map( - fn ($number) => $number . ':' . \uniqid(), + fn ($number) => $number.':'.\uniqid(), $numbers ); return implode(',', $formatted); - } + } } diff --git a/src/Utopia/Messaging/Adapters/SMS/Vonage.php b/src/Utopia/Messaging/Adapters/SMS/Vonage.php index b724aae7..7ed16714 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Vonage.php +++ b/src/Utopia/Messaging/Adapters/SMS/Vonage.php @@ -37,12 +37,11 @@ public function getMaxMessagesPerRequest(): int */ protected function process(SMS $message): string { - $to = \array_map( fn ($to) => \ltrim($to, '+'), $message->getTo() ); - + return $this->request( method: 'POST', url: 'https://rest.nexmo.com/sms/json', diff --git a/tests/e2e/Email/MailgunTest.php b/tests/e2e/Email/MailgunTest.php index 2f880992..250d98d7 100644 --- a/tests/e2e/Email/MailgunTest.php +++ b/tests/e2e/Email/MailgunTest.php @@ -32,8 +32,8 @@ public function testSendEmail() content: $content, ); - $result = (array)\json_decode($sender->send($message)); - + $result = (array) \json_decode($sender->send($message)); + $this->assertArrayHasKey('id', $result); $this->assertArrayHasKey('message', $result); $this->assertTrue(str_contains(strtolower($result['message']), 'queued')); diff --git a/tests/e2e/Push/APNSTest.php b/tests/e2e/Push/APNSTest.php index b666e658..1f7b860f 100644 --- a/tests/e2e/Push/APNSTest.php +++ b/tests/e2e/Push/APNSTest.php @@ -30,9 +30,9 @@ public function testSend(): void badge: '1' ); - $response = (array)\json_decode($adapter->send($message)); + $response = (array) \json_decode($adapter->send($message)); - $this->assertEquals("200", $response['status']); + $this->assertEquals('200', $response['status']); $this->assertArrayHasKey('apns-id', $response); $this->assertArrayHasKey('apns-unique-id', $response); } diff --git a/tests/e2e/SMS/TelesignTest.php b/tests/e2e/SMS/TelesignTest.php index f78653e0..30d2054a 100644 --- a/tests/e2e/SMS/TelesignTest.php +++ b/tests/e2e/SMS/TelesignTest.php @@ -2,9 +2,6 @@ namespace Tests\E2E; -use Utopia\Messaging\Adapters\SMS\Telesign; -use Utopia\Messaging\Messages\SMS; - class TelesignTest extends Base { /** diff --git a/tests/e2e/SMS/VonageTest.php b/tests/e2e/SMS/VonageTest.php index 9fc71034..7f812759 100644 --- a/tests/e2e/SMS/VonageTest.php +++ b/tests/e2e/SMS/VonageTest.php @@ -12,8 +12,8 @@ class VonageTest extends Base */ public function testSendSMS() { - $apiKey = "9bae1fbc"; - $apiSecret = "thVmE4JpL4sPu4f6"; + $apiKey = '9bae1fbc'; + $apiSecret = 'thVmE4JpL4sPu4f6'; $sender = new Vonage($apiKey, $apiSecret); @@ -25,8 +25,8 @@ public function testSendSMS() $result = \json_decode($sender->send($message), true); - $this->assertArrayHasKey("messages", $result); + $this->assertArrayHasKey('messages', $result); $this->assertEquals(1, count($result['messages'])); - $this->assertEquals("1", $result['message-count']); + $this->assertEquals('1', $result['message-count']); } } From ab0a41cf13b173b269bcc1f6264de3a18f1dd765 Mon Sep 17 00:00:00 2001 From: wess Date: Thu, 31 Aug 2023 11:31:47 -0400 Subject: [PATCH 046/106] Removes .env from docker compose --- docker-compose.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 11ef5e2c..623519d5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,8 +4,6 @@ services: tests: build: context: . - env_file: - - .env volumes: - ./src:/usr/local/src/src - ./tests:/usr/local/src/tests From 4ebebe97d80bb1de10d362c2464ba28717d333ac Mon Sep 17 00:00:00 2001 From: wess Date: Fri, 1 Sep 2023 10:13:03 -0400 Subject: [PATCH 047/106] Adds US flag to mailgun for region handling --- src/Utopia/Messaging/Adapters/Email/Mailgun.php | 5 +++-- tests/e2e/Email/MailgunTest.php | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/Email/Mailgun.php b/src/Utopia/Messaging/Adapters/Email/Mailgun.php index 112d471f..21c70118 100644 --- a/src/Utopia/Messaging/Adapters/Email/Mailgun.php +++ b/src/Utopia/Messaging/Adapters/Email/Mailgun.php @@ -14,6 +14,7 @@ class Mailgun extends EmailAdapter public function __construct( private string $apiKey, private string $domain, + private bool $isUS = true ) { } @@ -42,12 +43,12 @@ public function getMaxMessagesPerRequest(): int * * @throws \Exception */ - protected function process(Email $message, bool $isUS = true): string + protected function process(Email $message): string { $usDomain = 'api.mailgun.net'; $euDomain = 'api.eu.mailgun.net'; - $domain = $isUS ? $usDomain : $euDomain; + $domain = $this->isUS ? $usDomain : $euDomain; $response = $this->request( method: 'POST', diff --git a/tests/e2e/Email/MailgunTest.php b/tests/e2e/Email/MailgunTest.php index 250d98d7..81ae6497 100644 --- a/tests/e2e/Email/MailgunTest.php +++ b/tests/e2e/Email/MailgunTest.php @@ -16,8 +16,9 @@ public function testSendEmail() $domain = getenv('MAILGUN_DOMAIN'); $sender = new Mailgun( - $key, - $domain + apiKey: $key, + domain: $domain, + isUS: false ); $to = getenv('TEST_EMAIL'); From a1a1fb30a0b5e3888251e225d96b177f96a752b0 Mon Sep 17 00:00:00 2001 From: wess Date: Thu, 7 Sep 2023 09:07:17 -0400 Subject: [PATCH 048/106] Forwards env files in docker-composer.yml --- docker-compose.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index 623519d5..238cd4c1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,6 +2,23 @@ version: '3.9' services: tests: + environment: + - MAILGUN_API_KEY + - MAILGUN_DOMAIN + - SENDGRID_API_KEY + - FCM_SERVER_KEY + - TWILIO_ACCOUNT_SID + - TWILIO_AUTH_TOKEN + - TELNYX_API_KEY + - TELNYX_PUBLIC_KEY + - APNS_AUTHKEY_8KVVCLA3HL + - APNS_AUTH_ID + - APNS_TEAM_ID + - APNS_BUNDLE_ID + - MSG_91_SENDER_ID + - MSG_91_AUTH_KEY + - TEST_EMAIL + - TEST_FROM_EMAIL build: context: . volumes: From 1c5a451cb7c369ca15d610aeb823891642f81d14 Mon Sep 17 00:00:00 2001 From: wess Date: Thu, 7 Sep 2023 09:34:25 -0400 Subject: [PATCH 049/106] Updates workflow for runtime env vars --- .github/workflows/tests.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 901e25bf..4e0100fa 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,6 +13,23 @@ jobs: fetch-depth: 2 - run: git checkout HEAD^2 - name: Run Tests + env: + MAILGUN_API_KEY: ${{ secrets.MAILGUN_API_KEY }} + MAILGUN_DOMAIN: ${{ secrets.MAILGUN_DOMAIN }} + SENDGRID_API_KEY: ${{ secrets.SENDGRID_API_KEY }} + FCM_SERVER_KEY: ${{ secrets.FCM_SERVER_KEY }} + TWILIO_ACCOUNT_SID: ${{ secrets.TWILIO_ACCOUNT_SID }} + TWILIO_AUTH_TOKEN: ${{ secrets.TWILIO_AUTH_TOKEN }} + TELNYX_API_KEY: ${{ secrets.TELNYX_API_KEY }} + TELNYX_PUBLIC_KEY: ${{ secrets.TELNYX_PUBLIC_KEY }} + APNS_AUTHKEY_8KVVCLA3HL: ${{ secrets.APNS_AUTHKEY_8KVVCLA3HL }} + APNS_AUTH_ID: ${{ secrets.APNS_AUTH_ID }} + APNS_TEAM_ID: ${{ secrets.APNS_TEAM_ID }} + APNS_BUNDLE_ID: ${{ secrets.APN_BUNDLE_ID }} + MSG_91_SENDER_ID: ${{ secrets.MSG_91_SENDER_ID }} + MSG_91_AUTH_KEY: ${{ secrets.MSG_91_AUTH_KEY }} + TEST_EMAIL: ${{ secrets.TEST_EMAIL }} + TEST_FROM_EMAIL: ${{ secrets.TEST_FROM_EMAIL }} run: | docker compose up -d --build sleep 5 From 8f0e7608039d8ae8d25dc04c47b8d775c50aab70 Mon Sep 17 00:00:00 2001 From: wess Date: Thu, 7 Sep 2023 09:37:43 -0400 Subject: [PATCH 050/106] isUS, for mailgun, is true --- tests/e2e/Email/MailgunTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/Email/MailgunTest.php b/tests/e2e/Email/MailgunTest.php index 81ae6497..0a6f018f 100644 --- a/tests/e2e/Email/MailgunTest.php +++ b/tests/e2e/Email/MailgunTest.php @@ -18,7 +18,7 @@ public function testSendEmail() $sender = new Mailgun( apiKey: $key, domain: $domain, - isUS: false + isUS: true ); $to = getenv('TEST_EMAIL'); From b301211e3d34a527dabe490385462c8892ebf094 Mon Sep 17 00:00:00 2001 From: wess Date: Thu, 7 Sep 2023 09:41:40 -0400 Subject: [PATCH 051/106] Type-o in workflow --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4e0100fa..40e61b52 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -25,7 +25,7 @@ jobs: APNS_AUTHKEY_8KVVCLA3HL: ${{ secrets.APNS_AUTHKEY_8KVVCLA3HL }} APNS_AUTH_ID: ${{ secrets.APNS_AUTH_ID }} APNS_TEAM_ID: ${{ secrets.APNS_TEAM_ID }} - APNS_BUNDLE_ID: ${{ secrets.APN_BUNDLE_ID }} + APNS_BUNDLE_ID: ${{ secrets.APNS_BUNDLE_ID }} MSG_91_SENDER_ID: ${{ secrets.MSG_91_SENDER_ID }} MSG_91_AUTH_KEY: ${{ secrets.MSG_91_AUTH_KEY }} TEST_EMAIL: ${{ secrets.TEST_EMAIL }} From 5e5e06381a4b02601fca9285bb3afc564551c830 Mon Sep 17 00:00:00 2001 From: wess Date: Fri, 8 Sep 2023 18:47:57 -0400 Subject: [PATCH 052/106] Removes dead commented code --- src/Utopia/Messaging/Adapters/Push/APNS.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/Push/APNS.php b/src/Utopia/Messaging/Adapters/Push/APNS.php index 4f8dda83..ed89c4da 100644 --- a/src/Utopia/Messaging/Adapters/Push/APNS.php +++ b/src/Utopia/Messaging/Adapters/Push/APNS.php @@ -67,13 +67,6 @@ public function process(Push $message): string ], ]; - // Assuming the 'to' array contains device tokens for the push notification recipients. - - // $url = $this->endpoint.'/3/device'; - // $response = $this->request('POST', $url, $headers, \json_encode($payloads)); - // // This example simply returns the last response, adjust as needed - // return $response; - return \json_encode($this->notify($message->getTo(), $payload)); } From 3da89f1ef37df4bcfa9816bd26fa88af21591f1e Mon Sep 17 00:00:00 2001 From: wess Date: Fri, 8 Sep 2023 19:13:02 -0400 Subject: [PATCH 053/106] Updates requested for PR --- .github/workflows/tests.yml | 9 +++++++++ composer.json | 4 ++-- tests/e2e/Push/APNSTest.php | 2 +- tests/e2e/Push/FCMTest.php | 2 +- tests/e2e/SMS/Msg91Test.php | 6 +++--- tests/e2e/SMS/TwilioTest.php | 4 ++-- tests/e2e/SMS/VonageTest.php | 8 ++++---- 7 files changed, 22 insertions(+), 13 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 40e61b52..86d42d4c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -20,16 +20,25 @@ jobs: FCM_SERVER_KEY: ${{ secrets.FCM_SERVER_KEY }} TWILIO_ACCOUNT_SID: ${{ secrets.TWILIO_ACCOUNT_SID }} TWILIO_AUTH_TOKEN: ${{ secrets.TWILIO_AUTH_TOKEN }} + TWILIO_TO: ${{ secrets.TWILIO_TO }} + TWILIO_FROM: ${{ secrets.TWILIO_FROM }} TELNYX_API_KEY: ${{ secrets.TELNYX_API_KEY }} TELNYX_PUBLIC_KEY: ${{ secrets.TELNYX_PUBLIC_KEY }} APNS_AUTHKEY_8KVVCLA3HL: ${{ secrets.APNS_AUTHKEY_8KVVCLA3HL }} APNS_AUTH_ID: ${{ secrets.APNS_AUTH_ID }} APNS_TEAM_ID: ${{ secrets.APNS_TEAM_ID }} + APNS_TO: ${{ secrets.APNS_TO }} APNS_BUNDLE_ID: ${{ secrets.APNS_BUNDLE_ID }} MSG_91_SENDER_ID: ${{ secrets.MSG_91_SENDER_ID }} MSG_91_AUTH_KEY: ${{ secrets.MSG_91_AUTH_KEY }} + MSG_91_TO: ${{ secrets.MSG_91_TO}} + MSG_91_FROM: ${{ secrets.MSG_91_FROM }} TEST_EMAIL: ${{ secrets.TEST_EMAIL }} TEST_FROM_EMAIL: ${{ secrets.TEST_FROM_EMAIL }} + VONAGE_API_KEY: ${{ secrets.VONAGE_API_KEY }} + VONAGE_API_SECRET: ${{ secrets.VONAGE_API_SECRET }} + VONAGE_TO: ${{ secrets.VONAGE_TO }} + VONAGE_FROM: ${{ secrets.VONAGE_FROM }} run: | docker compose up -d --build sleep 5 diff --git a/composer.json b/composer.json index 7dfe178e..bac108a5 100644 --- a/composer.json +++ b/composer.json @@ -26,8 +26,8 @@ "ext-curl": "*" }, "require-dev": { - "phpunit/phpunit": "^9.6", - "phpmailer/phpmailer": "^6.8", + "phpunit/phpunit": "9.6.*", + "phpmailer/phpmailer": "6.8.*", "laravel/pint": "^1.2" }, "config": { diff --git a/tests/e2e/Push/APNSTest.php b/tests/e2e/Push/APNSTest.php index 1f7b860f..0be2613c 100644 --- a/tests/e2e/Push/APNSTest.php +++ b/tests/e2e/Push/APNSTest.php @@ -18,7 +18,7 @@ public function testSend(): void $adapter = new APNSAdapter($authKey, $authKeyId, $teamId, $bundleId, $endpoint); $message = new Push( - to: ['80858be082476f1067ce737b69240bbea9b58676d0eef64960f3aa75b6cb7ca7656822f02a56960ff805b393ab7c82484f56229b69731f939ae8c3aa27399c29fe8efa26d272b5a1817813f023dee9fd'], + to: [getenv("APNS_TO")], title: 'TestTitle', body: 'TestBody', data: null, diff --git a/tests/e2e/Push/FCMTest.php b/tests/e2e/Push/FCMTest.php index 71128e45..f3e86668 100644 --- a/tests/e2e/Push/FCMTest.php +++ b/tests/e2e/Push/FCMTest.php @@ -14,7 +14,7 @@ public function testSend(): void $adapter = new FCMAdapter($serverKey); $message = new Push( - to: ['eJa9AhokQUudfBPJwRx2OX:APA91bE0KbMkXU7a4eCyq1CyN1nR9TwOD5NQIaHADJBMBV1GjOjTfyPywOXKVeKVvvjz6nvB2jASGtRxGJHsM4Z4osoHnTx5IrnxCNUDEH11wsm4vMBiKW0zbugVis1MdtusTu9admrk'], + to: [getenv("FCM_SERVER_TO")], title: 'TestTitle', body: 'TestBody', data: null, diff --git a/tests/e2e/SMS/Msg91Test.php b/tests/e2e/SMS/Msg91Test.php index 07df9b1c..582bdf34 100644 --- a/tests/e2e/SMS/Msg91Test.php +++ b/tests/e2e/SMS/Msg91Test.php @@ -12,12 +12,12 @@ class Msg91Test extends Base */ public function testSendSMS() { - $sender = new Msg91('12345', '402985Ajm8DXo3EG4964cd3c10P1'); + $sender = new Msg91(getenv("MSG_91_SENDER_ID"), getenv("MSG_91_AUTH_KEY")); $message = new SMS( - to: ['+18034041123'], + to: [getenv("MSG_91_TO")], content: 'Test Content', - from: '+15005550006' + from: getenv("MSG_91_FROM") ); $result = \json_decode($sender->send($message), true); diff --git a/tests/e2e/SMS/TwilioTest.php b/tests/e2e/SMS/TwilioTest.php index c3b86760..90fad2df 100644 --- a/tests/e2e/SMS/TwilioTest.php +++ b/tests/e2e/SMS/TwilioTest.php @@ -13,8 +13,8 @@ class TwilioTest extends Base public function testSendSMS() { $sender = new Twilio(getenv('TWILIO_ACCOUNT_SID'), getenv('TWILIO_AUTH_TOKEN')); - $to = ['+18034041123']; - $from = '+15005550006'; + $to = [getenv("TWILIO_TO")]; + $from = getenv("TWILIO_FROM"); $message = new SMS( to: $to, diff --git a/tests/e2e/SMS/VonageTest.php b/tests/e2e/SMS/VonageTest.php index 7f812759..e5ccf009 100644 --- a/tests/e2e/SMS/VonageTest.php +++ b/tests/e2e/SMS/VonageTest.php @@ -12,15 +12,15 @@ class VonageTest extends Base */ public function testSendSMS() { - $apiKey = '9bae1fbc'; - $apiSecret = 'thVmE4JpL4sPu4f6'; + $apiKey = getenv("VONAGE_API_KEY"); + $apiSecret = getenv("VONAGE_API_SECRET"); $sender = new Vonage($apiKey, $apiSecret); $message = new SMS( - to: ['+18034041123'], + to: [getenv("VONAGE_TO")], content: 'Test Content', - from: '+12082740872' + from: getenv("VONAGE_FROM") ); $result = \json_decode($sender->send($message), true); From b67db7026d32069e772bf7d080d2f73fec46e1a2 Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 11 Sep 2023 11:02:07 -0400 Subject: [PATCH 054/106] Updates sendgrid to check for empty/success response --- tests/e2e/Email/SendgridTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/e2e/Email/SendgridTest.php b/tests/e2e/Email/SendgridTest.php index 05bcc3ab..b74646d6 100644 --- a/tests/e2e/Email/SendgridTest.php +++ b/tests/e2e/Email/SendgridTest.php @@ -27,8 +27,8 @@ public function testSendEmail() content: $content, ); - $sender->send($message); + $response = $sender->send($message); - $this->assertEquals(true, true); + $this->assertEquals($response, ""); } } From abb795fd85bb69f1c7532b1c3ddef8726ecf4396 Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 11 Sep 2023 12:14:45 -0400 Subject: [PATCH 055/106] LINT run. Telnyx and Msg91 skipped --- src/Utopia/Messaging/Adapters/SMS/Msg91.php | 18 ++++++++++++++++++ tests/e2e/Email/SendgridTest.php | 2 +- tests/e2e/Push/APNSTest.php | 2 +- tests/e2e/Push/FCMTest.php | 2 +- tests/e2e/SMS/Msg91Test.php | 19 +++++++++++-------- tests/e2e/SMS/TwilioTest.php | 4 ++-- tests/e2e/SMS/VonageTest.php | 8 ++++---- 7 files changed, 38 insertions(+), 17 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/Msg91.php b/src/Utopia/Messaging/Adapters/SMS/Msg91.php index 82b2527d..766832f8 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Msg91.php +++ b/src/Utopia/Messaging/Adapters/SMS/Msg91.php @@ -58,4 +58,22 @@ protected function process(SMS $message): string ]), ); } + + private function addTemplate(string $content, string $senderId, string $templateName, string $smsType = 'NORMAL') + { + return $this->request( + method: 'POST', + url: 'https://control.msg91.com/api/v5/sms/addTemplate', + headers: [ + 'content-type: application/json', + "authkey: {$this->authKey}", + ], + body: \json_encode([ + 'template' => $content, + 'sender_id' => $senderId, + 'template_name' => $templateName, + 'smsType' => 'NORMAL', + ]) + ); + } } diff --git a/tests/e2e/Email/SendgridTest.php b/tests/e2e/Email/SendgridTest.php index b74646d6..9437b167 100644 --- a/tests/e2e/Email/SendgridTest.php +++ b/tests/e2e/Email/SendgridTest.php @@ -29,6 +29,6 @@ public function testSendEmail() $response = $sender->send($message); - $this->assertEquals($response, ""); + $this->assertEquals($response, ''); } } diff --git a/tests/e2e/Push/APNSTest.php b/tests/e2e/Push/APNSTest.php index 0be2613c..dd7152ac 100644 --- a/tests/e2e/Push/APNSTest.php +++ b/tests/e2e/Push/APNSTest.php @@ -18,7 +18,7 @@ public function testSend(): void $adapter = new APNSAdapter($authKey, $authKeyId, $teamId, $bundleId, $endpoint); $message = new Push( - to: [getenv("APNS_TO")], + to: [getenv('APNS_TO')], title: 'TestTitle', body: 'TestBody', data: null, diff --git a/tests/e2e/Push/FCMTest.php b/tests/e2e/Push/FCMTest.php index f3e86668..78538d86 100644 --- a/tests/e2e/Push/FCMTest.php +++ b/tests/e2e/Push/FCMTest.php @@ -14,7 +14,7 @@ public function testSend(): void $adapter = new FCMAdapter($serverKey); $message = new Push( - to: [getenv("FCM_SERVER_TO")], + to: [getenv('FCM_SERVER_TO')], title: 'TestTitle', body: 'TestBody', data: null, diff --git a/tests/e2e/SMS/Msg91Test.php b/tests/e2e/SMS/Msg91Test.php index 582bdf34..df90f4c4 100644 --- a/tests/e2e/SMS/Msg91Test.php +++ b/tests/e2e/SMS/Msg91Test.php @@ -12,16 +12,19 @@ class Msg91Test extends Base */ public function testSendSMS() { - $sender = new Msg91(getenv("MSG_91_SENDER_ID"), getenv("MSG_91_AUTH_KEY")); + // $sender = new Msg91(getenv('MSG_91_SENDER_ID'), getenv('MSG_91_AUTH_KEY')); - $message = new SMS( - to: [getenv("MSG_91_TO")], - content: 'Test Content', - from: getenv("MSG_91_FROM") - ); + // $message = new SMS( + // to: [getenv('MSG_91_TO')], + // content: 'Test Content', + // from: getenv('MSG_91_FROM') + // ); - $result = \json_decode($sender->send($message), true); + // $response = $sender->send($message); + // $result = \json_decode($response, true); - $this->assertEquals('success', $result['type']); + // $this->assertEquals('success', $result['type']); + + $this->markTestSkipped('Msg91 requires business verification to use template and SMS api.'); } } diff --git a/tests/e2e/SMS/TwilioTest.php b/tests/e2e/SMS/TwilioTest.php index 90fad2df..7e45d620 100644 --- a/tests/e2e/SMS/TwilioTest.php +++ b/tests/e2e/SMS/TwilioTest.php @@ -13,8 +13,8 @@ class TwilioTest extends Base public function testSendSMS() { $sender = new Twilio(getenv('TWILIO_ACCOUNT_SID'), getenv('TWILIO_AUTH_TOKEN')); - $to = [getenv("TWILIO_TO")]; - $from = getenv("TWILIO_FROM"); + $to = [getenv('TWILIO_TO')]; + $from = getenv('TWILIO_FROM'); $message = new SMS( to: $to, diff --git a/tests/e2e/SMS/VonageTest.php b/tests/e2e/SMS/VonageTest.php index e5ccf009..9e012ea3 100644 --- a/tests/e2e/SMS/VonageTest.php +++ b/tests/e2e/SMS/VonageTest.php @@ -12,15 +12,15 @@ class VonageTest extends Base */ public function testSendSMS() { - $apiKey = getenv("VONAGE_API_KEY"); - $apiSecret = getenv("VONAGE_API_SECRET"); + $apiKey = getenv('VONAGE_API_KEY'); + $apiSecret = getenv('VONAGE_API_SECRET'); $sender = new Vonage($apiKey, $apiSecret); $message = new SMS( - to: [getenv("VONAGE_TO")], + to: [getenv('VONAGE_TO')], content: 'Test Content', - from: getenv("VONAGE_FROM") + from: getenv('VONAGE_FROM') ); $result = \json_decode($sender->send($message), true); From 91885b098372142a270b429f66bdcb0bee233528 Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 11 Sep 2023 12:24:33 -0400 Subject: [PATCH 056/106] Updates docker compose with vonage vars --- docker-compose.yml | 4 ++++ tests/e2e/SMS/VonageTest.php | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 238cd4c1..e8224aaa 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -19,6 +19,10 @@ services: - MSG_91_AUTH_KEY - TEST_EMAIL - TEST_FROM_EMAIL + - VONAGE_API_KEY + - VONAGE_API_SECRET + - VONAGE_TO + - VONAGE_FROM build: context: . volumes: diff --git a/tests/e2e/SMS/VonageTest.php b/tests/e2e/SMS/VonageTest.php index 9e012ea3..02f89228 100644 --- a/tests/e2e/SMS/VonageTest.php +++ b/tests/e2e/SMS/VonageTest.php @@ -23,7 +23,9 @@ public function testSendSMS() from: getenv('VONAGE_FROM') ); - $result = \json_decode($sender->send($message), true); + $response = $sender->send($message); + + $result = \json_decode($response, true); $this->assertArrayHasKey('messages', $result); $this->assertEquals(1, count($result['messages'])); From 5114e74ed35bb81ec2c9c9949b34a8aac5d7c22f Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 11 Sep 2023 12:27:09 -0400 Subject: [PATCH 057/106] Adds FCM key to env --- docker-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker-compose.yml b/docker-compose.yml index e8224aaa..9d621bde 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,6 +7,7 @@ services: - MAILGUN_DOMAIN - SENDGRID_API_KEY - FCM_SERVER_KEY + - FCM_SERVER_TO - TWILIO_ACCOUNT_SID - TWILIO_AUTH_TOKEN - TELNYX_API_KEY From ee8c94c26439b298fac7009a4b33cb6d93d772fc Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 11 Sep 2023 12:33:17 -0400 Subject: [PATCH 058/106] Adds vars to test workflow --- .github/workflows/tests.yml | 51 +++++++++++++++++++------------------ docker-compose.yml | 47 +++++++++++++++++++--------------- 2 files changed, 52 insertions(+), 46 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 86d42d4c..851daafd 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -14,31 +14,32 @@ jobs: - run: git checkout HEAD^2 - name: Run Tests env: - MAILGUN_API_KEY: ${{ secrets.MAILGUN_API_KEY }} - MAILGUN_DOMAIN: ${{ secrets.MAILGUN_DOMAIN }} - SENDGRID_API_KEY: ${{ secrets.SENDGRID_API_KEY }} - FCM_SERVER_KEY: ${{ secrets.FCM_SERVER_KEY }} - TWILIO_ACCOUNT_SID: ${{ secrets.TWILIO_ACCOUNT_SID }} - TWILIO_AUTH_TOKEN: ${{ secrets.TWILIO_AUTH_TOKEN }} - TWILIO_TO: ${{ secrets.TWILIO_TO }} - TWILIO_FROM: ${{ secrets.TWILIO_FROM }} - TELNYX_API_KEY: ${{ secrets.TELNYX_API_KEY }} - TELNYX_PUBLIC_KEY: ${{ secrets.TELNYX_PUBLIC_KEY }} - APNS_AUTHKEY_8KVVCLA3HL: ${{ secrets.APNS_AUTHKEY_8KVVCLA3HL }} - APNS_AUTH_ID: ${{ secrets.APNS_AUTH_ID }} - APNS_TEAM_ID: ${{ secrets.APNS_TEAM_ID }} - APNS_TO: ${{ secrets.APNS_TO }} - APNS_BUNDLE_ID: ${{ secrets.APNS_BUNDLE_ID }} - MSG_91_SENDER_ID: ${{ secrets.MSG_91_SENDER_ID }} - MSG_91_AUTH_KEY: ${{ secrets.MSG_91_AUTH_KEY }} - MSG_91_TO: ${{ secrets.MSG_91_TO}} - MSG_91_FROM: ${{ secrets.MSG_91_FROM }} - TEST_EMAIL: ${{ secrets.TEST_EMAIL }} - TEST_FROM_EMAIL: ${{ secrets.TEST_FROM_EMAIL }} - VONAGE_API_KEY: ${{ secrets.VONAGE_API_KEY }} - VONAGE_API_SECRET: ${{ secrets.VONAGE_API_SECRET }} - VONAGE_TO: ${{ secrets.VONAGE_TO }} - VONAGE_FROM: ${{ secrets.VONAGE_FROM }} + MAILGUN_API_KEY: $${{ secrets.MAILGUN_API_KEY }} + MAILGUN_DOMAIN: $${{ secrets.MAILGUN_DOMAIN }} + SENDGRID_API_KEY: $${{ secrets.SENDGRID_API_KEY }} + FCM_SERVER_KEY: $${{ secrets.FCM_SERVER_KEY }} + FCM_SERVER_TO: $${{ secrets.FCM_SERVER_TO }} + TWILIO_ACCOUNT_SID: $${{ secrets.TWILIO_ACCOUNT_SID }} + TWILIO_AUTH_TOKEN: $${{ secrets.TWILIO_AUTH_TOKEN }} + TWILIO_TO: $${{ secrets.TWILIO_TO }} + TWILIO_FROM: $${{ secrets.TWILIO_FROM }} + TELNYX_API_KEY: $${{ secrets.TELNYX_API_KEY }} + TELNYX_PUBLIC_KEY: $${{ secrets.TELNYX_PUBLIC_KEY }} + APNS_AUTHKEY_8KVVCLA3HL: $${{ secrets.APNS_AUTHKEY_8KVVCLA3HL }} + APNS_AUTH_ID: $${{ secrets.APNS_AUTH_ID }} + APNS_TEAM_ID: $${{ secrets.APNS_TEAM_ID }} + APNS_BUNDLE_ID: $${{ secrets.APNS_BUNDLE_ID }} + APNS_TO: $${{ secrets.APNS_TO }} + MSG_91_SENDER_ID: $${{ secrets.MSG_91_SENDER_ID }} + MSG_91_AUTH_KEY: $${{ secrets.MSG_91_AUTH_KEY }} + MSG_91_TO: $${{ secrets.MSG_91_TO }} + MSG_91_FROM: $${{ secrets.MSG_91_FROM }} + TEST_EMAIL: $${{ secrets.TEST_EMAIL }} + TEST_FROM_EMAIL: $${{ secrets.TEST_FROM_EMAIL }} + VONAGE_API_KEY: $${{ secrets.VONAGE_API_KEY }} + VONAGE_API_SECRET: $${{ secrets.VONAGE_API_SECRET }} + VONAGE_TO: $${{ secrets.VONAGE_TO }} + VONAGE_FROM: $${{ secrets.VONAGE_FROM }} run: | docker compose up -d --build sleep 5 diff --git a/docker-compose.yml b/docker-compose.yml index 9d621bde..80d626d9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,27 +3,32 @@ version: '3.9' services: tests: environment: - - MAILGUN_API_KEY - - MAILGUN_DOMAIN - - SENDGRID_API_KEY - - FCM_SERVER_KEY - - FCM_SERVER_TO - - TWILIO_ACCOUNT_SID - - TWILIO_AUTH_TOKEN - - TELNYX_API_KEY - - TELNYX_PUBLIC_KEY - - APNS_AUTHKEY_8KVVCLA3HL - - APNS_AUTH_ID - - APNS_TEAM_ID - - APNS_BUNDLE_ID - - MSG_91_SENDER_ID - - MSG_91_AUTH_KEY - - TEST_EMAIL - - TEST_FROM_EMAIL - - VONAGE_API_KEY - - VONAGE_API_SECRET - - VONAGE_TO - - VONAGE_FROM + - MAILGUN_API_KEY + - MAILGUN_DOMAIN + - SENDGRID_API_KEY + - FCM_SERVER_KEY + - FCM_SERVER_TO + - TWILIO_ACCOUNT_SID + - TWILIO_AUTH_TOKEN + - TWILIO_TO + - TWILIO_FROM + - TELNYX_API_KEY + - TELNYX_PUBLIC_KEY + - APNS_AUTHKEY_8KVVCLA3HL + - APNS_AUTH_ID + - APNS_TEAM_ID + - APNS_BUNDLE_ID + - APNS_TO + - MSG_91_SENDER_ID + - MSG_91_AUTH_KEY + - MSG_91_TO + - MSG_91_FROM + - TEST_EMAIL + - TEST_FROM_EMAIL + - VONAGE_API_KEY + - VONAGE_API_SECRET + - VONAGE_TO + - VONAGE_FROM build: context: . volumes: From a627f560716d1b1c6d86010908002e1f43fe8848 Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 11 Sep 2023 12:42:00 -0400 Subject: [PATCH 059/106] removed extra character in yml --- .github/workflows/tests.yml | 54 ++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 851daafd..552b207d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -12,34 +12,34 @@ jobs: with: fetch-depth: 2 - run: git checkout HEAD^2 - - name: Run Tests + - name: Run Tests env: - MAILGUN_API_KEY: $${{ secrets.MAILGUN_API_KEY }} - MAILGUN_DOMAIN: $${{ secrets.MAILGUN_DOMAIN }} - SENDGRID_API_KEY: $${{ secrets.SENDGRID_API_KEY }} - FCM_SERVER_KEY: $${{ secrets.FCM_SERVER_KEY }} - FCM_SERVER_TO: $${{ secrets.FCM_SERVER_TO }} - TWILIO_ACCOUNT_SID: $${{ secrets.TWILIO_ACCOUNT_SID }} - TWILIO_AUTH_TOKEN: $${{ secrets.TWILIO_AUTH_TOKEN }} - TWILIO_TO: $${{ secrets.TWILIO_TO }} - TWILIO_FROM: $${{ secrets.TWILIO_FROM }} - TELNYX_API_KEY: $${{ secrets.TELNYX_API_KEY }} - TELNYX_PUBLIC_KEY: $${{ secrets.TELNYX_PUBLIC_KEY }} - APNS_AUTHKEY_8KVVCLA3HL: $${{ secrets.APNS_AUTHKEY_8KVVCLA3HL }} - APNS_AUTH_ID: $${{ secrets.APNS_AUTH_ID }} - APNS_TEAM_ID: $${{ secrets.APNS_TEAM_ID }} - APNS_BUNDLE_ID: $${{ secrets.APNS_BUNDLE_ID }} - APNS_TO: $${{ secrets.APNS_TO }} - MSG_91_SENDER_ID: $${{ secrets.MSG_91_SENDER_ID }} - MSG_91_AUTH_KEY: $${{ secrets.MSG_91_AUTH_KEY }} - MSG_91_TO: $${{ secrets.MSG_91_TO }} - MSG_91_FROM: $${{ secrets.MSG_91_FROM }} - TEST_EMAIL: $${{ secrets.TEST_EMAIL }} - TEST_FROM_EMAIL: $${{ secrets.TEST_FROM_EMAIL }} - VONAGE_API_KEY: $${{ secrets.VONAGE_API_KEY }} - VONAGE_API_SECRET: $${{ secrets.VONAGE_API_SECRET }} - VONAGE_TO: $${{ secrets.VONAGE_TO }} - VONAGE_FROM: $${{ secrets.VONAGE_FROM }} + MAILGUN_API_KEY: ${{ secrets.MAILGUN_API_KEY }} + MAILGUN_DOMAIN: ${{ secrets.MAILGUN_DOMAIN }} + SENDGRID_API_KEY: ${{ secrets.SENDGRID_API_KEY }} + FCM_SERVER_KEY: ${{ secrets.FCM_SERVER_KEY }} + FCM_SERVER_TO: ${{ secrets.FCM_SERVER_TO }} + TWILIO_ACCOUNT_SID: ${{ secrets.TWILIO_ACCOUNT_SID }} + TWILIO_AUTH_TOKEN: ${{ secrets.TWILIO_AUTH_TOKEN }} + TWILIO_TO: ${{ secrets.TWILIO_TO }} + TWILIO_FROM: ${{ secrets.TWILIO_FROM }} + TELNYX_API_KEY: ${{ secrets.TELNYX_API_KEY }} + TELNYX_PUBLIC_KEY: ${{ secrets.TELNYX_PUBLIC_KEY }} + APNS_AUTHKEY_8KVVCLA3HL: ${{ secrets.APNS_AUTHKEY_8KVVCLA3HL }} + APNS_AUTH_ID: ${{ secrets.APNS_AUTH_ID }} + APNS_TEAM_ID: ${{ secrets.APNS_TEAM_ID }} + APNS_BUNDLE_ID: ${{ secrets.APNS_BUNDLE_ID }} + APNS_TO: ${{ secrets.APNS_TO }} + MSG_91_SENDER_ID: ${{ secrets.MSG_91_SENDER_ID }} + MSG_91_AUTH_KEY: ${{ secrets.MSG_91_AUTH_KEY }} + MSG_91_TO: ${{ secrets.MSG_91_TO }} + MSG_91_FROM: ${{ secrets.MSG_91_FROM }} + TEST_EMAIL: ${{ secrets.TEST_EMAIL }} + TEST_FROM_EMAIL: ${{ secrets.TEST_FROM_EMAIL }} + VONAGE_API_KEY: ${{ secrets.VONAGE_API_KEY }} + VONAGE_API_SECRET: ${{ secrets.VONAGE_API_SECRET }} + VONAGE_TO: ${{ secrets.VONAGE_TO }} + VONAGE_FROM: ${{ secrets.VONAGE_FROM }} run: | docker compose up -d --build sleep 5 From 2d7001fb2ee514bfd7997df1f3a629fb08ec2420 Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 11 Sep 2023 12:45:34 -0400 Subject: [PATCH 060/106] Restart job --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 445406d1..09fef071 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Install using composer: composer require utopia-php/messaging ``` -## Email +## Email ```php Date: Mon, 11 Sep 2023 13:05:36 -0400 Subject: [PATCH 061/106] testing with inline value --- tests/e2e/Push/FCMTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/e2e/Push/FCMTest.php b/tests/e2e/Push/FCMTest.php index 78538d86..d2c97fe6 100644 --- a/tests/e2e/Push/FCMTest.php +++ b/tests/e2e/Push/FCMTest.php @@ -13,8 +13,10 @@ public function testSend(): void $adapter = new FCMAdapter($serverKey); + $to = "eJa9AhokQUudfBPJwRx2OX:APA91bE0KbMkXU7a4eCyq1CyN1nR9TwOD5NQIaHADJBMBV1GjOjTfyPywOXKVeKVvvjz6nvB2jASGtRxGJHsM4Z4osoHnTx5IrnxCNUDEH11wsm4vMBiKW0zbugVis1MdtusTu9admrk"; //getenv('FCM_SERVER_TO'); + $message = new Push( - to: [getenv('FCM_SERVER_TO')], + to: [$to], title: 'TestTitle', body: 'TestBody', data: null, From a9e900002c94da7ec7fb7b3967b6b59238c4e6b2 Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 11 Sep 2023 13:07:26 -0400 Subject: [PATCH 062/106] Adds FCM_SERVER_TO back in to ENV --- tests/e2e/Push/FCMTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/Push/FCMTest.php b/tests/e2e/Push/FCMTest.php index d2c97fe6..f7befabe 100644 --- a/tests/e2e/Push/FCMTest.php +++ b/tests/e2e/Push/FCMTest.php @@ -13,7 +13,7 @@ public function testSend(): void $adapter = new FCMAdapter($serverKey); - $to = "eJa9AhokQUudfBPJwRx2OX:APA91bE0KbMkXU7a4eCyq1CyN1nR9TwOD5NQIaHADJBMBV1GjOjTfyPywOXKVeKVvvjz6nvB2jASGtRxGJHsM4Z4osoHnTx5IrnxCNUDEH11wsm4vMBiKW0zbugVis1MdtusTu9admrk"; //getenv('FCM_SERVER_TO'); + $to = getenv('FCM_SERVER_TO'); $message = new Push( to: [$to], From 6367acc3329f31c59fc3326db15ce914a3d4c0f4 Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 11 Sep 2023 17:04:17 -0400 Subject: [PATCH 063/106] Lint and changes --- src/Utopia/Messaging/Adapters/Email/Mailgun.php | 4 ++-- src/Utopia/Messaging/Adapters/Email/Sendgrid.php | 1 - src/Utopia/Messaging/Adapters/Push/APNS.php | 6 ++++++ tests/e2e/Email/MailgunTest.php | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/Email/Mailgun.php b/src/Utopia/Messaging/Adapters/Email/Mailgun.php index 21c70118..4e3882e8 100644 --- a/src/Utopia/Messaging/Adapters/Email/Mailgun.php +++ b/src/Utopia/Messaging/Adapters/Email/Mailgun.php @@ -14,7 +14,7 @@ class Mailgun extends EmailAdapter public function __construct( private string $apiKey, private string $domain, - private bool $isUS = true + private bool $isEU = false ) { } @@ -48,7 +48,7 @@ protected function process(Email $message): string $usDomain = 'api.mailgun.net'; $euDomain = 'api.eu.mailgun.net'; - $domain = $this->isUS ? $usDomain : $euDomain; + $domain = $this->isEU ? $euDomain : $usDomain; $response = $this->request( method: 'POST', diff --git a/src/Utopia/Messaging/Adapters/Email/Sendgrid.php b/src/Utopia/Messaging/Adapters/Email/Sendgrid.php index 28dc661b..e91c31cc 100644 --- a/src/Utopia/Messaging/Adapters/Email/Sendgrid.php +++ b/src/Utopia/Messaging/Adapters/Email/Sendgrid.php @@ -2,7 +2,6 @@ namespace Utopia\Messaging\Adapters\Email; -use Exception; use Utopia\Messaging\Adapters\Email as EmailAdapter; use Utopia\Messaging\Messages\Email; diff --git a/src/Utopia/Messaging/Adapters/Push/APNS.php b/src/Utopia/Messaging/Adapters/Push/APNS.php index ed89c4da..40658e32 100644 --- a/src/Utopia/Messaging/Adapters/Push/APNS.php +++ b/src/Utopia/Messaging/Adapters/Push/APNS.php @@ -75,10 +75,16 @@ private function notify(array $to, array $payload): array $headers = [ 'authorization: bearer '.$this->generateJwt(), 'apns-topic: '.$this->bundleId, + 'apns-push-type: alert', ]; + $sh = curl_share_init(); + + curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT); + $ch = curl_init(); + curl_setopt($ch, CURLOPT_SHARE, $sh); curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); curl_setopt_array($ch, [ diff --git a/tests/e2e/Email/MailgunTest.php b/tests/e2e/Email/MailgunTest.php index 0a6f018f..fed2489d 100644 --- a/tests/e2e/Email/MailgunTest.php +++ b/tests/e2e/Email/MailgunTest.php @@ -18,7 +18,7 @@ public function testSendEmail() $sender = new Mailgun( apiKey: $key, domain: $domain, - isUS: true + isEU: false ); $to = getenv('TEST_EMAIL'); From fcde4b47a1cb0477cf24c0825b3334a214885813 Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 11 Sep 2023 19:16:52 -0400 Subject: [PATCH 064/106] APNS max send bumped to 5k --- src/Utopia/Messaging/Adapters/Push/APNS.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Utopia/Messaging/Adapters/Push/APNS.php b/src/Utopia/Messaging/Adapters/Push/APNS.php index 40658e32..75d94dcc 100644 --- a/src/Utopia/Messaging/Adapters/Push/APNS.php +++ b/src/Utopia/Messaging/Adapters/Push/APNS.php @@ -42,7 +42,7 @@ public function getName(): string */ public function getMaxMessagesPerRequest(): int { - return 1000; + return 5000; } /** From 2bb09220d0993a9f8f0afc63ff51382b13d93e18 Mon Sep 17 00:00:00 2001 From: wess Date: Thu, 14 Sep 2023 16:29:49 -0400 Subject: [PATCH 065/106] Uses curl_multi for apple push --- src/Utopia/Messaging/Adapters/Push/APNS.php | 46 +++++++++++++++++++-- tests/e2e/Push/APNSTest.php | 8 ++-- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/Push/APNS.php b/src/Utopia/Messaging/Adapters/Push/APNS.php index 75d94dcc..56282d83 100644 --- a/src/Utopia/Messaging/Adapters/Push/APNS.php +++ b/src/Utopia/Messaging/Adapters/Push/APNS.php @@ -99,15 +99,55 @@ private function notify(array $to, array $payload): array $response = ''; + $mh = curl_multi_init(); + $handles = []; + + // Create a handle for each request foreach ($to as $token) { curl_setopt($ch, CURLOPT_URL, $this->endpoint.'/3/device/'.$token); - $response = curl_exec($ch); + $handle = curl_copy_handle($ch); + curl_multi_add_handle($mh, $handle); + + $handles[] = $handle; + } + + $active = null; + $status = CURLM_OK; + + // Execute the handles + while ($active && $status == CURLM_OK) { + $status = curl_multi_exec($mh, $active); + } + + // Check each handle's result + $responses = []; + foreach ($handles as $ch) { + $urlInfo = curl_getinfo($ch); + $device = basename($urlInfo['url']); // Extracts deviceToken from the URL + + if (! curl_errno($ch)) { + $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + $responses[] = [ + 'device' => $device, + 'status' => 'success', + 'statusCode' => $statusCode, + ]; + } else { + $responses[$device] = [ + 'status' => 'error', + 'error' => curl_error($ch), + ]; + } + + curl_multi_remove_handle($mh, $ch); + curl_close($ch); } - curl_close($ch); + curl_multi_close($mh); + curl_share_close($sh); - return $this->formatResponse($response); + return $responses; } private function formatResponse(string $response): array diff --git a/tests/e2e/Push/APNSTest.php b/tests/e2e/Push/APNSTest.php index dd7152ac..cbd1a354 100644 --- a/tests/e2e/Push/APNSTest.php +++ b/tests/e2e/Push/APNSTest.php @@ -30,10 +30,10 @@ public function testSend(): void badge: '1' ); - $response = (array) \json_decode($adapter->send($message)); + $responses = \json_decode($adapter->send($message)); - $this->assertEquals('200', $response['status']); - $this->assertArrayHasKey('apns-id', $response); - $this->assertArrayHasKey('apns-unique-id', $response); + foreach ($responses as $response) { + $this->assertEquals('success', $response->status); + } } } From ef2caf9212c4aa51bd0a6b58102d7e50a774a475 Mon Sep 17 00:00:00 2001 From: wess Date: Tue, 24 Oct 2023 15:47:46 -0400 Subject: [PATCH 066/106] Fixes issue with to grouping --- src/Utopia/Messaging/Adapters/SMS/Msg91.php | 10 +++++---- tests/e2e/SMS/Msg91Test.php | 23 ++++++++++++--------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/Msg91.php b/src/Utopia/Messaging/Adapters/SMS/Msg91.php index 766832f8..bdf3b014 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Msg91.php +++ b/src/Utopia/Messaging/Adapters/SMS/Msg91.php @@ -38,10 +38,12 @@ public function getMaxMessagesPerRequest(): int */ protected function process(SMS $message): string { - $to = \array_map( - fn ($to) => ['mobiles' => \ltrim($to, '+')], - $message->getTo() - ); + // $to = \array_map( + // fn ($to) => ['mobiles' => \ltrim($to, '+')], + // $message->getTo() + // ); + + $to = ['mobiles' => $message->getTo()]; return $this->request( method: 'POST', diff --git a/tests/e2e/SMS/Msg91Test.php b/tests/e2e/SMS/Msg91Test.php index df90f4c4..55ce9c3e 100644 --- a/tests/e2e/SMS/Msg91Test.php +++ b/tests/e2e/SMS/Msg91Test.php @@ -12,19 +12,22 @@ class Msg91Test extends Base */ public function testSendSMS() { - // $sender = new Msg91(getenv('MSG_91_SENDER_ID'), getenv('MSG_91_AUTH_KEY')); + $sender = new Msg91(getenv('MSG_91_SENDER_ID'), getenv('MSG_91_AUTH_KEY')); - // $message = new SMS( - // to: [getenv('MSG_91_TO')], - // content: 'Test Content', - // from: getenv('MSG_91_FROM') - // ); + $message = new SMS( + to: [getenv('MSG_91_TO')], + content: 'Test Content', + from: getenv('MSG_91_FROM') + ); - // $response = $sender->send($message); - // $result = \json_decode($response, true); + $response = $sender->send($message); + $result = \json_decode($response, true); - // $this->assertEquals('success', $result['type']); + var_dump($result); + die; + + $this->assertEquals('success', $result['type']); - $this->markTestSkipped('Msg91 requires business verification to use template and SMS api.'); + // $this->markTestSkipped('Msg91 requires business verification to use template and SMS api.'); } } From 0ee2ebeaac9da307f418bfa5efa900c0d762a88a Mon Sep 17 00:00:00 2001 From: wess Date: Wed, 25 Oct 2023 11:14:48 -0400 Subject: [PATCH 067/106] Fixing Msg91 delivery --- src/Utopia/Messaging/Adapters/SMS/Msg91.php | 7 +------ tests/e2e/SMS/Msg91Test.php | 3 --- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/Msg91.php b/src/Utopia/Messaging/Adapters/SMS/Msg91.php index bdf3b014..2c51450c 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Msg91.php +++ b/src/Utopia/Messaging/Adapters/SMS/Msg91.php @@ -38,12 +38,7 @@ public function getMaxMessagesPerRequest(): int */ protected function process(SMS $message): string { - // $to = \array_map( - // fn ($to) => ['mobiles' => \ltrim($to, '+')], - // $message->getTo() - // ); - - $to = ['mobiles' => $message->getTo()]; + $to = ['mobiles' => \implode($message->getTo())]; return $this->request( method: 'POST', diff --git a/tests/e2e/SMS/Msg91Test.php b/tests/e2e/SMS/Msg91Test.php index 55ce9c3e..33fad69f 100644 --- a/tests/e2e/SMS/Msg91Test.php +++ b/tests/e2e/SMS/Msg91Test.php @@ -23,9 +23,6 @@ public function testSendSMS() $response = $sender->send($message); $result = \json_decode($response, true); - var_dump($result); - die; - $this->assertEquals('success', $result['type']); // $this->markTestSkipped('Msg91 requires business verification to use template and SMS api.'); From ae5aed1a0a24d75644255ac4dba90dbf3c21c51a Mon Sep 17 00:00:00 2001 From: wess Date: Wed, 25 Oct 2023 12:04:57 -0400 Subject: [PATCH 068/106] Updates $to for Msg91 recipents Updates tests --- src/Utopia/Messaging/Adapters/SMS/Msg91.php | 4 ++-- tests/e2e/SMS/Msg91Test.php | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/Msg91.php b/src/Utopia/Messaging/Adapters/SMS/Msg91.php index 2c51450c..3cd1f081 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Msg91.php +++ b/src/Utopia/Messaging/Adapters/SMS/Msg91.php @@ -38,7 +38,7 @@ public function getMaxMessagesPerRequest(): int */ protected function process(SMS $message): string { - $to = ['mobiles' => \implode($message->getTo())]; + $to = ['mobiles' => \implode(",", $message->getTo())]; return $this->request( method: 'POST', @@ -69,7 +69,7 @@ private function addTemplate(string $content, string $senderId, string $template 'template' => $content, 'sender_id' => $senderId, 'template_name' => $templateName, - 'smsType' => 'NORMAL', + 'smsType' => $smsType, ]) ); } diff --git a/tests/e2e/SMS/Msg91Test.php b/tests/e2e/SMS/Msg91Test.php index 33fad69f..55ce9c3e 100644 --- a/tests/e2e/SMS/Msg91Test.php +++ b/tests/e2e/SMS/Msg91Test.php @@ -23,6 +23,9 @@ public function testSendSMS() $response = $sender->send($message); $result = \json_decode($response, true); + var_dump($result); + die; + $this->assertEquals('success', $result['type']); // $this->markTestSkipped('Msg91 requires business verification to use template and SMS api.'); From 9be0501ffaa7f7f3ad21d2c3d70e0985fc41f0f2 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 2 Nov 2023 00:00:30 +1300 Subject: [PATCH 069/106] Update workflows --- .github/workflows/analyse.yml | 20 +++++ .github/workflows/{linter.yml => lint.yml} | 0 .github/workflows/{tests.yml => test.yml} | 0 composer.json | 10 ++- composer.lock | 92 ++++++++++++++++++---- 5 files changed, 103 insertions(+), 19 deletions(-) create mode 100644 .github/workflows/analyse.yml rename .github/workflows/{linter.yml => lint.yml} (100%) rename .github/workflows/{tests.yml => test.yml} (100%) diff --git a/.github/workflows/analyse.yml b/.github/workflows/analyse.yml new file mode 100644 index 00000000..72ed14c1 --- /dev/null +++ b/.github/workflows/analyse.yml @@ -0,0 +1,20 @@ +name: "Static Analysis" + +on: [pull_request] +jobs: + analyse: + name: Analyse + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + fetch-depth: 2 + + - run: git checkout HEAD^2 + + - name: Run Static Analysis + run: | + docker run --rm -v $PWD:/app composer sh -c \ + "composer install --profile --ignore-platform-reqs && composer analyse" diff --git a/.github/workflows/linter.yml b/.github/workflows/lint.yml similarity index 100% rename from .github/workflows/linter.yml rename to .github/workflows/lint.yml diff --git a/.github/workflows/tests.yml b/.github/workflows/test.yml similarity index 100% rename from .github/workflows/tests.yml rename to .github/workflows/test.yml diff --git a/composer.json b/composer.json index bac108a5..d081f24c 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,8 @@ "scripts": { "test": "vendor/bin/phpunit", "lint": "./vendor/bin/pint --test", - "format": "./vendor/bin/pint" + "format": "./vendor/bin/pint", + "analyse": "./vendor/bin/phpstan analyse --memory-limit=2G --level=6 src tests" }, "autoload": { "psr-4": { @@ -17,8 +18,7 @@ }, "autoload-dev": { "psr-4": { - "Tests\\E2E\\": "tests/e2e", - "Tests\\Unit\\": "tests/unit" + "Utopia\\Tests\\": "tests/Messaging" } }, "require": { @@ -26,9 +26,11 @@ "ext-curl": "*" }, "require-dev": { + "ext-openssl": "*", "phpunit/phpunit": "9.6.*", "phpmailer/phpmailer": "6.8.*", - "laravel/pint": "^1.2" + "laravel/pint": "1.13.*", + "phpstan/phpstan": "1.10.*" }, "config": { "platform": { diff --git a/composer.lock b/composer.lock index 9f6b978b..6994d832 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "5ecbd865cbd7f14e7819fb79643573be", + "content-hash": "af54d4a3e39567814f90395c0d3ceb8a", "packages": [], "packages-dev": [ { @@ -79,16 +79,16 @@ }, { "name": "laravel/pint", - "version": "v1.2.0", + "version": "v1.13.5", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "1d276e4c803397a26cc337df908f55c2a4e90d86" + "reference": "df105cf8ce7a8f0b8a9425ff45cd281a5448e423" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/1d276e4c803397a26cc337df908f55c2a4e90d86", - "reference": "1d276e4c803397a26cc337df908f55c2a4e90d86", + "url": "https://api.github.com/repos/laravel/pint/zipball/df105cf8ce7a8f0b8a9425ff45cd281a5448e423", + "reference": "df105cf8ce7a8f0b8a9425ff45cd281a5448e423", "shasum": "" }, "require": { @@ -96,16 +96,16 @@ "ext-mbstring": "*", "ext-tokenizer": "*", "ext-xml": "*", - "php": "^8.0" + "php": "^8.1.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.11.0", - "illuminate/view": "^9.27", - "laravel-zero/framework": "^9.1.3", - "mockery/mockery": "^1.5.0", - "nunomaduro/larastan": "^2.2", - "nunomaduro/termwind": "^1.14.0", - "pestphp/pest": "^1.22.1" + "friendsofphp/php-cs-fixer": "^3.34.1", + "illuminate/view": "^10.26.2", + "laravel-zero/framework": "^10.1.2", + "mockery/mockery": "^1.6.6", + "nunomaduro/larastan": "^2.6.4", + "nunomaduro/termwind": "^1.15.1", + "pestphp/pest": "^2.20.0" }, "bin": [ "builds/pint" @@ -141,7 +141,7 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2022-09-13T15:07:15+00:00" + "time": "2023-10-26T09:26:10+00:00" }, { "name": "myclabs/deep-copy", @@ -449,6 +449,68 @@ ], "time": "2023-03-06T14:43:22+00:00" }, + { + "name": "phpstan/phpstan", + "version": "1.10.40", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "93c84b5bf7669920d823631e39904d69b9c7dc5d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/93c84b5bf7669920d823631e39904d69b9c7dc5d", + "reference": "93c84b5bf7669920d823631e39904d69b9c7dc5d", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" + } + ], + "time": "2023-10-30T14:48:31+00:00" + }, { "name": "phpunit/php-code-coverage", "version": "9.2.17", @@ -1898,5 +1960,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } From b24deb9fed3194450660b0da1bf8a339dc0556b0 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 2 Nov 2023 00:00:44 +1300 Subject: [PATCH 070/106] Add discord test --- docker-compose.yml | 2 + docs/add-new-adapter.md | 4 +- src/Utopia/Messaging/Adapter.php | 21 ++-- .../{Adapters => Adapter/App}/Discord.php | 37 ++++-- .../Messaging/{Adapters => Adapter}/Email.php | 2 +- .../{Adapters => Adapter}/Email/Mailgun.php | 8 +- .../{Adapters => Adapter}/Email/Mock.php | 8 +- .../{Adapters => Adapter}/Email/Sendgrid.php | 12 +- .../Messaging/{Adapters => Adapter}/Push.php | 2 +- .../{Adapters => Adapter}/Push/APNS.php | 108 ++++++------------ .../{Adapters => Adapter}/Push/FCM.php | 8 +- .../Messaging/{Adapters => Adapter}/SMS.php | 2 +- .../{Adapters => Adapter}/SMS/Clickatell.php | 4 +- .../{Adapters => Adapter}/SMS/Infobip.php | 4 +- .../{Adapters => Adapter}/SMS/Mock.php | 4 +- .../{Adapters => Adapter}/SMS/Msg91.php | 22 +--- .../{Adapters => Adapter}/SMS/Plivo.php | 4 +- .../{Adapters => Adapter}/SMS/Seven.php | 4 +- .../{Adapters => Adapter}/SMS/Sinch.php | 4 +- .../{Adapters => Adapter}/SMS/Telesign.php | 8 +- .../{Adapters => Adapter}/SMS/Telnyx.php | 4 +- .../{Adapters => Adapter}/SMS/TextMagic.php | 4 +- .../{Adapters => Adapter}/SMS/Twilio.php | 4 +- .../{Adapters => Adapter}/SMS/Vonage.php | 4 +- src/Utopia/Messaging/Message.php | 3 - src/Utopia/Messaging/Messages/Discord.php | 92 +++++++++++++-- src/Utopia/Messaging/Messages/Email.php | 21 +--- src/Utopia/Messaging/Messages/Push.php | 32 +----- src/Utopia/Messaging/Messages/SMS.php | 16 +-- tests/Messaging/Adapter/App/DiscordTest.php | 33 ++++++ tests/{e2e => Messaging/Adapter}/Base.php | 8 +- .../Adapter}/Email/EmailTest.php | 7 +- .../Adapter}/Email/MailgunTest.php | 19 +-- .../Adapter}/Email/SendgridTest.php | 15 +-- .../Adapter}/Push/APNSTest.php | 15 +-- .../Adapter}/Push/FCMTest.php | 9 +- .../Adapter}/SMS/Msg91Test.php | 13 +-- .../Adapter}/SMS/SMSTest.php | 7 +- .../Adapter}/SMS/TelesignTest.php | 6 +- .../Adapter}/SMS/TelnyxTest.php | 9 +- .../Adapter}/SMS/TwilioTest.php | 13 ++- .../Adapter}/SMS/VonageTest.php | 15 +-- tests/unit/.gitkeep | 0 43 files changed, 328 insertions(+), 289 deletions(-) rename src/Utopia/Messaging/{Adapters => Adapter/App}/Discord.php (50%) rename src/Utopia/Messaging/{Adapters => Adapter}/Email.php (93%) rename src/Utopia/Messaging/{Adapters => Adapter}/Email/Mailgun.php (91%) rename src/Utopia/Messaging/{Adapters => Adapter}/Email/Mock.php (89%) rename src/Utopia/Messaging/{Adapters => Adapter}/Email/Sendgrid.php (87%) rename src/Utopia/Messaging/{Adapters => Adapter}/Push.php (93%) rename src/Utopia/Messaging/{Adapters => Adapter}/Push/APNS.php (55%) rename src/Utopia/Messaging/{Adapters => Adapter}/Push/FCM.php (91%) rename src/Utopia/Messaging/{Adapters => Adapter}/SMS.php (93%) rename src/Utopia/Messaging/{Adapters => Adapter}/SMS/Clickatell.php (92%) rename src/Utopia/Messaging/{Adapters => Adapter}/SMS/Infobip.php (93%) rename src/Utopia/Messaging/{Adapters => Adapter}/SMS/Mock.php (92%) rename src/Utopia/Messaging/{Adapters => Adapter}/SMS/Msg91.php (65%) rename src/Utopia/Messaging/{Adapters => Adapter}/SMS/Plivo.php (92%) rename src/Utopia/Messaging/{Adapters => Adapter}/SMS/Seven.php (92%) rename src/Utopia/Messaging/{Adapters => Adapter}/SMS/Sinch.php (93%) rename src/Utopia/Messaging/{Adapters => Adapter}/SMS/Telesign.php (90%) rename src/Utopia/Messaging/{Adapters => Adapter}/SMS/Telnyx.php (91%) rename src/Utopia/Messaging/{Adapters => Adapter}/SMS/TextMagic.php (93%) rename src/Utopia/Messaging/{Adapters => Adapter}/SMS/Twilio.php (92%) rename src/Utopia/Messaging/{Adapters => Adapter}/SMS/Vonage.php (93%) create mode 100644 tests/Messaging/Adapter/App/DiscordTest.php rename tests/{e2e => Messaging/Adapter}/Base.php (82%) rename tests/{e2e => Messaging/Adapter}/Email/EmailTest.php (84%) rename tests/{e2e => Messaging/Adapter}/Email/MailgunTest.php (59%) rename tests/{e2e => Messaging/Adapter}/Email/SendgridTest.php (63%) rename tests/{e2e => Messaging/Adapter}/Push/APNSTest.php (67%) rename tests/{e2e => Messaging/Adapter}/Push/FCMTest.php (76%) rename tests/{e2e => Messaging/Adapter}/SMS/Msg91Test.php (59%) rename tests/{e2e => Messaging/Adapter}/SMS/SMSTest.php (86%) rename tests/{e2e => Messaging/Adapter}/SMS/TelesignTest.php (64%) rename tests/{e2e => Messaging/Adapter}/SMS/TelnyxTest.php (71%) rename tests/{e2e => Messaging/Adapter}/SMS/TwilioTest.php (61%) rename tests/{e2e => Messaging/Adapter}/SMS/VonageTest.php (62%) delete mode 100644 tests/unit/.gitkeep diff --git a/docker-compose.yml b/docker-compose.yml index 80d626d9..6cb8400a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -29,6 +29,8 @@ services: - VONAGE_API_SECRET - VONAGE_TO - VONAGE_FROM + - DISCORD_WEBHOOK_ID + - DISCORD_WEBHOOK_TOKEN build: context: . volumes: diff --git a/docs/add-new-adapter.md b/docs/add-new-adapter.md index a720bbc0..70d3d38d 100644 --- a/docs/add-new-adapter.md +++ b/docs/add-new-adapter.md @@ -81,10 +81,10 @@ Putting it all together, the `SendGrid` adapter should look like this: ```php getMessageType())) { + if (! \is_a($message, $this->getMessageType())) { throw new \Exception('Invalid message type.'); } - if (\count($message->getTo()) > $this->getMaxMessagesPerRequest()) { + if (\method_exists($message, 'getTo') && \count($message->getTo()) > $this->getMaxMessagesPerRequest()) { throw new \Exception("{$this->getName()} can only send {$this->getMaxMessagesPerRequest()} messages per request."); } + if (! \method_exists($this, 'process')) { + throw new \Exception('Adapter does not implement process method.'); + } + return $this->process($message); } @@ -55,7 +52,7 @@ public function send(Message $message): string * * @param string $method The HTTP method to use. * @param string $url The URL to send the request to. - * @param array $headers An array of headers to send with the request. + * @param array $headers An array of headers to send with the request. * @param string|null $body The body of the request. * @return string The response body. * @@ -65,7 +62,7 @@ protected function request( string $method, string $url, array $headers = [], - ?string $body = null, + string $body = null, ): string { $ch = \curl_init(); diff --git a/src/Utopia/Messaging/Adapters/Discord.php b/src/Utopia/Messaging/Adapter/App/Discord.php similarity index 50% rename from src/Utopia/Messaging/Adapters/Discord.php rename to src/Utopia/Messaging/Adapter/App/Discord.php index c1c19207..af3582ab 100644 --- a/src/Utopia/Messaging/Adapters/Discord.php +++ b/src/Utopia/Messaging/Adapter/App/Discord.php @@ -1,6 +1,6 @@ getWait())) { + $query['wait'] = $message->getWait(); + } + if (! \is_null($message->getThreadId())) { + $query['thread_id'] = $message->getThreadId(); + } + + $queryString = ''; + foreach ($query as $key => $value) { + if (empty($queryString)) { + $queryString .= '?'; + } + $queryString .= $key.'='.$value; + } + return $this->request( method: 'POST', - url: "https://discord.com/api/webhooks/{$this->webhookId}/{$this->webhookToken}", + url: "https://discord.com/api/webhooks/{$this->webhookId}/{$this->webhookToken}{$queryString}", headers: [ 'Content-Type: application/json', ], @@ -53,6 +69,13 @@ protected function process(DiscordMessage $message): string 'content' => $message->getContent(), 'username' => $message->getUsername(), 'avatar_url' => $message->getAvatarUrl(), + 'tts' => $message->getTTS(), + 'embeds' => $message->getEmbeds(), + 'allowed_mentions' => $message->getAllowedMentions(), + 'components' => $message->getComponents(), + 'attachments' => $message->getAttachments(), + 'flags' => $message->getFlags(), + 'thread_name' => $message->getThreadName(), ]), ); } diff --git a/src/Utopia/Messaging/Adapters/Email.php b/src/Utopia/Messaging/Adapter/Email.php similarity index 93% rename from src/Utopia/Messaging/Adapters/Email.php rename to src/Utopia/Messaging/Adapter/Email.php index e1fcf967..9b395a0e 100644 --- a/src/Utopia/Messaging/Adapters/Email.php +++ b/src/Utopia/Messaging/Adapter/Email.php @@ -1,6 +1,6 @@ SMTPAuth = false; $mail->Username = ''; $mail->Password = ''; - $mail->SMTPSecure = false; + $mail->SMTPSecure = ''; $mail->SMTPAutoTLS = false; $mail->CharSet = 'UTF-8'; $mail->Subject = $message->getSubject(); @@ -54,6 +54,6 @@ protected function process(Email $message): string throw new \Exception($mail->ErrorInfo); } - return true; + return \json_encode($message); } } diff --git a/src/Utopia/Messaging/Adapters/Email/Sendgrid.php b/src/Utopia/Messaging/Adapter/Email/Sendgrid.php similarity index 87% rename from src/Utopia/Messaging/Adapters/Email/Sendgrid.php rename to src/Utopia/Messaging/Adapter/Email/Sendgrid.php index e91c31cc..27be13bc 100644 --- a/src/Utopia/Messaging/Adapters/Email/Sendgrid.php +++ b/src/Utopia/Messaging/Adapter/Email/Sendgrid.php @@ -1,8 +1,8 @@ notify($message->getTo(), $payload)); } + /** + * @param array $to + * @param array $payload + * @return array + * @throws Exception + */ private function notify(array $to, array $payload): array { $headers = [ @@ -78,16 +73,16 @@ private function notify(array $to, array $payload): array 'apns-push-type: alert', ]; - $sh = curl_share_init(); + $sh = \curl_share_init(); - curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT); + \curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT); - $ch = curl_init(); + $ch = \curl_init(); - curl_setopt($ch, CURLOPT_SHARE, $sh); - curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); + \curl_setopt($ch, CURLOPT_SHARE, $sh); + \curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); - curl_setopt_array($ch, [ + \curl_setopt_array($ch, [ CURLOPT_PORT => 443, CURLOPT_HTTPHEADER => $headers, CURLOPT_POST => true, @@ -97,17 +92,15 @@ private function notify(array $to, array $payload): array CURLOPT_HEADER => true, ]); - $response = ''; - - $mh = curl_multi_init(); + $mh = \curl_multi_init(); $handles = []; // Create a handle for each request foreach ($to as $token) { - curl_setopt($ch, CURLOPT_URL, $this->endpoint.'/3/device/'.$token); + \curl_setopt($ch, CURLOPT_URL, $this->endpoint.'/3/device/'.$token); - $handle = curl_copy_handle($ch); - curl_multi_add_handle($mh, $handle); + $handle = \curl_copy_handle($ch); + \curl_multi_add_handle($mh, $handle); $handles[] = $handle; } @@ -117,17 +110,17 @@ private function notify(array $to, array $payload): array // Execute the handles while ($active && $status == CURLM_OK) { - $status = curl_multi_exec($mh, $active); + $status = \curl_multi_exec($mh, $active); } - // Check each handle's result + // Check each handles result $responses = []; foreach ($handles as $ch) { - $urlInfo = curl_getinfo($ch); + $urlInfo = \curl_getinfo($ch); $device = basename($urlInfo['url']); // Extracts deviceToken from the URL - if (! curl_errno($ch)) { - $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + if (! \curl_errno($ch)) { + $statusCode = \curl_getinfo($ch, CURLINFO_HTTP_CODE); $responses[] = [ 'device' => $device, 'status' => 'success', @@ -136,50 +129,23 @@ private function notify(array $to, array $payload): array } else { $responses[$device] = [ 'status' => 'error', - 'error' => curl_error($ch), + 'error' => \curl_error($ch), ]; } - curl_multi_remove_handle($mh, $ch); - curl_close($ch); + \curl_multi_remove_handle($mh, $ch); + \curl_close($ch); } - curl_multi_close($mh); - curl_share_close($sh); + \curl_multi_close($mh); + \curl_share_close($sh); return $responses; } - private function formatResponse(string $response): array - { - $filtered = array_filter( - explode("\r\n", $response), - function ($value) { - return ! empty($value); - } - ); - - $result = []; - - foreach ($filtered as $value) { - if (str_contains($value, 'HTTP')) { - $result['status'] = trim(str_replace('HTTP/2 ', '', $value)); - - continue; - } - - $parts = explode(':', trim($value)); - - $result[$parts[0]] = $parts[1]; - } - - return $result; - } - /** * Generate JWT. * - * @return string * * @throws Exception */ @@ -193,21 +159,21 @@ private function generateJwt(): string // Replaces URL sensitive characters that could be the result of base64 encoding. // Replace to _ to avoid any special handling. - $base64UrlHeader = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header)); - $base64UrlClaims = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($claims)); + $base64UrlHeader = \str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header)); + $base64UrlClaims = \str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($claims)); if (! $this->authKey) { throw new \Exception('Invalid private key'); } $signature = ''; - $success = openssl_sign("$base64UrlHeader.$base64UrlClaims", $signature, $this->authKey, OPENSSL_ALGO_SHA256); + $success = \openssl_sign("$base64UrlHeader.$base64UrlClaims", $signature, $this->authKey, OPENSSL_ALGO_SHA256); if (! $success) { throw new \Exception('Failed to sign JWT'); } - $base64UrlSignature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature)); + $base64UrlSignature = \str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature)); return "$base64UrlHeader.$base64UrlClaims.$base64UrlSignature"; } diff --git a/src/Utopia/Messaging/Adapters/Push/FCM.php b/src/Utopia/Messaging/Adapter/Push/FCM.php similarity index 91% rename from src/Utopia/Messaging/Adapters/Push/FCM.php rename to src/Utopia/Messaging/Adapter/Push/FCM.php index 8a4d8ac2..4625b905 100644 --- a/src/Utopia/Messaging/Adapters/Push/FCM.php +++ b/src/Utopia/Messaging/Adapter/Push/FCM.php @@ -1,8 +1,8 @@ request( - method: 'POST', - url: 'https://control.msg91.com/api/v5/sms/addTemplate', - headers: [ - 'content-type: application/json', - "authkey: {$this->authKey}", - ], - body: \json_encode([ - 'template' => $content, - 'sender_id' => $senderId, - 'template_name' => $templateName, - 'smsType' => 'NORMAL', - ]) - ); - } } diff --git a/src/Utopia/Messaging/Adapters/SMS/Plivo.php b/src/Utopia/Messaging/Adapter/SMS/Plivo.php similarity index 92% rename from src/Utopia/Messaging/Adapters/SMS/Plivo.php rename to src/Utopia/Messaging/Adapter/SMS/Plivo.php index 4f923fdf..edfd01ff 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Plivo.php +++ b/src/Utopia/Messaging/Adapter/SMS/Plivo.php @@ -1,8 +1,8 @@ $numbers + * @return string + */ private function formatNumbers(array $numbers): string { $formatted = \array_map( diff --git a/src/Utopia/Messaging/Adapters/SMS/Telnyx.php b/src/Utopia/Messaging/Adapter/SMS/Telnyx.php similarity index 91% rename from src/Utopia/Messaging/Adapters/SMS/Telnyx.php rename to src/Utopia/Messaging/Adapter/SMS/Telnyx.php index 431736b5..85719c4f 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Telnyx.php +++ b/src/Utopia/Messaging/Adapter/SMS/Telnyx.php @@ -1,8 +1,8 @@ |null $embeds + * @param array|null $allowedMentions + * @param array|null $components + * @param array|null $attachments + * @param string|null $flags + * @param string|null $threadName + * @param bool|null $wait + * @param string|null $threadId + */ public function __construct( private string $content, private ?string $username = null, private ?string $avatarUrl = null, - ) + private ?bool $tts = null, + private ?array $embeds = null, + private ?array $allowedMentions = null, + private ?array $components = null, + private ?array $attachments = null, + private ?string $flags = null, + private ?string $threadName = null, + private ?bool $wait = null, + private ?string $threadId = null + ) { + } + + public function getContent(): string { + return $this->content; + } + + public function getUsername(): ?string + { + return $this->username; + } + + public function getAvatarUrl(): ?string + { + return $this->avatarUrl; + } + + public function getTts(): ?bool + { + return $this->tts; } /** - * @return string + * @return array|null */ - public function getContent(): string + public function getEmbeds(): ?array { - return $this->content; + return $this->embeds; } /** - * @return string|null + * @return array|null */ - public function getUsername(): ?string + public function getAllowedMentions(): ?array { - return $this->username; + return $this->allowedMentions; } /** - * @return string|null + * @return array|null */ - public function getAvatarUrl(): ?string + public function getComponents(): ?array { - return $this->avatarUrl; + return $this->components; + } + + /** + * @return array|null + */ + public function getAttachments(): ?array + { + return $this->attachments; + } + + public function getFlags(): ?string + { + return $this->flags; + } + + public function getThreadName(): ?string + { + return $this->threadName; + } + + public function getWait(): ?bool + { + return $this->wait; + } + + public function getThreadId(): ?string + { + return $this->threadId; } -} \ No newline at end of file +} diff --git a/src/Utopia/Messaging/Messages/Email.php b/src/Utopia/Messaging/Messages/Email.php index 21fedeea..633d72e0 100644 --- a/src/Utopia/Messaging/Messages/Email.php +++ b/src/Utopia/Messaging/Messages/Email.php @@ -6,12 +6,13 @@ class Email implements Message { + /** - * @param array $to The recipients of the email. + * @param array $to The recipients of the email. * @param string $subject The subject of the email. * @param string $content The content of the email. * @param string|null $from The sender of the email. - * @param array|null $attachments The attachments of the email. + * @param array|null $attachments The attachments of the email. * @param bool $html Whether the message is HTML or not. */ public function __construct( @@ -25,48 +26,36 @@ public function __construct( } /** - * @return array + * @return array */ public function getTo(): array { return $this->to; } - /** - * @return string - */ public function getSubject(): string { return $this->subject; } - /** - * @return string - */ public function getContent(): string { return $this->content; } - /** - * @return string|null - */ public function getFrom(): ?string { return $this->from; } /** - * @return array|null + * @return array|null */ public function getAttachments(): ?array { return $this->attachments; } - /** - * @return bool - */ public function isHtml(): bool { return $this->html; diff --git a/src/Utopia/Messaging/Messages/Push.php b/src/Utopia/Messaging/Messages/Push.php index 93b8f5d7..bf1712f6 100644 --- a/src/Utopia/Messaging/Messages/Push.php +++ b/src/Utopia/Messaging/Messages/Push.php @@ -7,10 +7,10 @@ class Push implements Message { /** - * @param array $to The recipients of the push notification. + * @param array $to The recipients of the push notification. * @param string $title The title of the push notification. * @param string $body The body of the push notification. - * @param array|null $data This parameter specifies the custom key-value pairs of the message's payload. For example, with data:{"score":"3x1"}:

On Apple platforms, if the message is sent via APNs, it represents the custom data fields. If it is sent via FCM, it would be represented as key value dictionary in AppDelegate application:didReceiveRemoteNotification:.

On Android, this would result in an intent extra named score with the string value 3x1.

The key should not be a reserved word ("from", "message_type", or any word starting with "google" or "gcm"). Do not use any of the words defined in this table (such as collapse_key).

Values in string types are recommended. You have to convert values in objects or other non-string data types (e.g., integers or booleans) to string. + * @param array|null $data This parameter specifies the custom key-value pairs of the message's payload. For example, with data:{"score":"3x1"}:

On Apple platforms, if the message is sent via APNs, it represents the custom data fields. If it is sent via FCM, it would be represented as key value dictionary in AppDelegate application:didReceiveRemoteNotification:.

On Android, this would result in an intent extra named score with the string value 3x1.

The key should not be a reserved word ("from", "message_type", or any word starting with "google" or "gcm"). Do not use any of the words defined in this table (such as collapse_key).

Values in string types are recommended. You have to convert values in objects or other non-string data types (e.g., integers or booleans) to string. * @param string|null $sound The sound to play when the device receives the notification.

On Android, sound files must reside in /res/raw/.

On iOS, sounds files must reside in the main bundle of the client app or in the Library/Sounds folder of the app's data container. * @param string|null $action The action associated with a user click on the notification.

On Android, this is the activity to launch.

On iOS, this is the category to launch. * @param string|null $icon Android only. The icon of the push notification. Sets the notification icon to myicon for drawable resource myicon. If you don't send this key in the request, FCM displays the launcher icon specified in your app manifest. @@ -33,7 +33,7 @@ public function __construct( } /** - * @return array + * @return array */ public function getTo(): array { @@ -45,73 +45,49 @@ public function getFrom(): ?string return null; } - /** - * @return string - */ public function getTitle(): string { return $this->title; } - /** - * @return string - */ public function getBody(): string { return $this->body; } /** - * @return array|null + * @return array|null */ public function getData(): ?array { return $this->data; } - /** - * @return string|null - */ public function getAction(): ?string { return $this->action; } - /** - * @return string|null - */ public function getSound(): ?string { return $this->sound; } - /** - * @return string|null - */ public function getIcon(): ?string { return $this->icon; } - /** - * @return string|null - */ public function getColor(): ?string { return $this->color; } - /** - * @return string|null - */ public function getTag(): ?string { return $this->tag; } - /** - * @return string|null - */ public function getBadge(): ?string { return $this->badge; diff --git a/src/Utopia/Messaging/Messages/SMS.php b/src/Utopia/Messaging/Messages/SMS.php index bcb913c0..d96f582b 100644 --- a/src/Utopia/Messaging/Messages/SMS.php +++ b/src/Utopia/Messaging/Messages/SMS.php @@ -6,6 +6,12 @@ class SMS implements Message { + /** + * @param array $to + * @param string $content + * @param string|null $from + * @param array|null $attachments + */ public function __construct( private array $to, private string $content, @@ -15,31 +21,25 @@ public function __construct( } /** - * @return array + * @return array */ public function getTo(): array { return $this->to; } - /** - * @return string - */ public function getContent(): string { return $this->content; } - /** - * @return string|null - */ public function getFrom(): ?string { return $this->from; } /** - * @return array|null + * @return array|null */ public function getAttachments(): ?array { diff --git a/tests/Messaging/Adapter/App/DiscordTest.php b/tests/Messaging/Adapter/App/DiscordTest.php new file mode 100644 index 00000000..967d1888 --- /dev/null +++ b/tests/Messaging/Adapter/App/DiscordTest.php @@ -0,0 +1,33 @@ +send($message), true); + + $this->assertNotEmpty($result); + $this->assertNotEmpty($result['id']); + } +} \ No newline at end of file diff --git a/tests/e2e/Base.php b/tests/Messaging/Adapter/Base.php similarity index 82% rename from tests/e2e/Base.php rename to tests/Messaging/Adapter/Base.php index 14970e51..218cadd9 100644 --- a/tests/e2e/Base.php +++ b/tests/Messaging/Adapter/Base.php @@ -1,11 +1,14 @@ + */ protected function getLastRequest(): array { \sleep(2); @@ -16,6 +19,9 @@ protected function getLastRequest(): array return $request; } + /** + * @return array + */ protected function getLastEmail(): array { sleep(3); diff --git a/tests/e2e/Email/EmailTest.php b/tests/Messaging/Adapter/Email/EmailTest.php similarity index 84% rename from tests/e2e/Email/EmailTest.php rename to tests/Messaging/Adapter/Email/EmailTest.php index 40606255..edd568a4 100644 --- a/tests/e2e/Email/EmailTest.php +++ b/tests/Messaging/Adapter/Email/EmailTest.php @@ -1,8 +1,9 @@ send($message)); + $result = \json_decode($sender->send($message), true); $this->assertArrayHasKey('id', $result); $this->assertArrayHasKey('message', $result); - $this->assertTrue(str_contains(strtolower($result['message']), 'queued')); + $this->assertTrue(\str_contains(\strtolower($result['message']), 'queued')); } } diff --git a/tests/e2e/Email/SendgridTest.php b/tests/Messaging/Adapter/Email/SendgridTest.php similarity index 63% rename from tests/e2e/Email/SendgridTest.php rename to tests/Messaging/Adapter/Email/SendgridTest.php index 9437b167..98426ea3 100644 --- a/tests/e2e/Email/SendgridTest.php +++ b/tests/Messaging/Adapter/Email/SendgridTest.php @@ -1,8 +1,9 @@ send($message); diff --git a/tests/e2e/Push/APNSTest.php b/tests/Messaging/Adapter/Push/APNSTest.php similarity index 67% rename from tests/e2e/Push/APNSTest.php rename to tests/Messaging/Adapter/Push/APNSTest.php index cbd1a354..c24470f0 100644 --- a/tests/e2e/Push/APNSTest.php +++ b/tests/Messaging/Adapter/Push/APNSTest.php @@ -1,24 +1,25 @@ send($message); diff --git a/tests/e2e/SMS/SMSTest.php b/tests/Messaging/Adapter/SMS/SMSTest.php similarity index 86% rename from tests/e2e/SMS/SMSTest.php rename to tests/Messaging/Adapter/SMS/SMSTest.php index b7cdb8be..c935d834 100644 --- a/tests/e2e/SMS/SMSTest.php +++ b/tests/Messaging/Adapter/SMS/SMSTest.php @@ -1,8 +1,9 @@ markTestSkipped('Telesign requires support/sales call in order to enable bulk SMS'); } diff --git a/tests/e2e/SMS/TelnyxTest.php b/tests/Messaging/Adapter/SMS/TelnyxTest.php similarity index 71% rename from tests/e2e/SMS/TelnyxTest.php rename to tests/Messaging/Adapter/SMS/TelnyxTest.php index dc711498..3db276a5 100644 --- a/tests/e2e/SMS/TelnyxTest.php +++ b/tests/Messaging/Adapter/SMS/TelnyxTest.php @@ -1,18 +1,17 @@ send($message); diff --git a/tests/unit/.gitkeep b/tests/unit/.gitkeep deleted file mode 100644 index e69de29b..00000000 From aa635f12eb6e26b6380430201d8865883fdd4a8d Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 2 Nov 2023 00:12:49 +1300 Subject: [PATCH 071/106] Add discord keys to workflow --- .github/workflows/test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 552b207d..47086952 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,6 +40,8 @@ jobs: VONAGE_API_SECRET: ${{ secrets.VONAGE_API_SECRET }} VONAGE_TO: ${{ secrets.VONAGE_TO }} VONAGE_FROM: ${{ secrets.VONAGE_FROM }} + DISCORD_WEBHOOK_ID: ${{ secrets.DISCORD_WEBHOOK_ID }} + DISCORD_WEBHOOK_TOKEN: ${{ secrets.DISCORD_WEBHOOK_TOKEN }} run: | docker compose up -d --build sleep 5 From 327acfdde3dddd565386bfc82d5f0913e743031c Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 2 Nov 2023 21:52:32 +1300 Subject: [PATCH 072/106] Lint --- composer.json | 2 +- composer.lock | 167 +++++++++--------- src/Utopia/Messaging/Adapter/Push/APNS.php | 5 +- src/Utopia/Messaging/Adapter/SMS/Telesign.php | 3 +- src/Utopia/Messaging/Messages/Discord.php | 16 +- src/Utopia/Messaging/Messages/Email.php | 1 - src/Utopia/Messaging/Messages/SMS.php | 6 +- tests/Messaging/Adapter/App/DiscordTest.php | 4 +- tests/Messaging/Adapter/Email/EmailTest.php | 2 +- tests/Messaging/Adapter/Email/MailgunTest.php | 2 +- .../Messaging/Adapter/Email/SendgridTest.php | 2 +- tests/Messaging/Adapter/Push/APNSTest.php | 2 +- tests/Messaging/Adapter/Push/FCMTest.php | 2 +- tests/Messaging/Adapter/SMS/SMSTest.php | 2 +- tests/Messaging/Adapter/SMS/TwilioTest.php | 2 +- tests/Messaging/Adapter/SMS/VonageTest.php | 2 +- 16 files changed, 106 insertions(+), 114 deletions(-) diff --git a/composer.json b/composer.json index d081f24c..a422b9f3 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,7 @@ "license": "MIT", "minimum-stability": "stable", "scripts": { - "test": "vendor/bin/phpunit", + "test": "./vendor/bin/phpunit", "lint": "./vendor/bin/pint --test", "format": "./vendor/bin/pint", "analyse": "./vendor/bin/phpstan analyse --memory-limit=2G --level=6 src tests" diff --git a/composer.lock b/composer.lock index 6994d832..80172ea8 100644 --- a/composer.lock +++ b/composer.lock @@ -4,35 +4,35 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "af54d4a3e39567814f90395c0d3ceb8a", + "content-hash": "0afb85e3cb0d85adca85fb5d778af118", "packages": [], "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.4.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc" + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^9", + "doctrine/coding-standard": "^11", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^0.16 || ^1", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.22" + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.9.4", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5.27", + "vimeo/psalm": "^5.4" }, "type": "library", "autoload": { @@ -59,7 +59,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.4.1" + "source": "https://github.com/doctrine/instantiator/tree/2.0.0" }, "funding": [ { @@ -75,7 +75,7 @@ "type": "tidelift" } ], - "time": "2022-03-03T08:28:38+00:00" + "time": "2022-12-30T00:23:10+00:00" }, { "name": "laravel/pint", @@ -145,16 +145,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.11.0", + "version": "1.11.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", "shasum": "" }, "require": { @@ -192,7 +192,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" }, "funding": [ { @@ -200,20 +200,20 @@ "type": "tidelift" } ], - "time": "2022-03-03T13:19:32+00:00" + "time": "2023-03-08T13:26:56+00:00" }, { "name": "nikic/php-parser", - "version": "v4.15.1", + "version": "v4.17.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900" + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/0ef6c55a3f47f89d7a374e6f835197a0b5fcf900", - "reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", "shasum": "" }, "require": { @@ -254,9 +254,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" }, - "time": "2022-09-04T07:30:47+00:00" + "time": "2023-08-13T19:53:39+00:00" }, { "name": "phar-io/manifest", @@ -371,16 +371,16 @@ }, { "name": "phpmailer/phpmailer", - "version": "v6.8.0", + "version": "v6.8.1", "source": { "type": "git", "url": "https://github.com/PHPMailer/PHPMailer.git", - "reference": "df16b615e371d81fb79e506277faea67a1be18f1" + "reference": "e88da8d679acc3824ff231fdc553565b802ac016" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/df16b615e371d81fb79e506277faea67a1be18f1", - "reference": "df16b615e371d81fb79e506277faea67a1be18f1", + "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/e88da8d679acc3824ff231fdc553565b802ac016", + "reference": "e88da8d679acc3824ff231fdc553565b802ac016", "shasum": "" }, "require": { @@ -390,13 +390,13 @@ "php": ">=5.5.0" }, "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.7.2", + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", "doctrine/annotations": "^1.2.6 || ^1.13.3", "php-parallel-lint/php-console-highlighter": "^1.0.0", "php-parallel-lint/php-parallel-lint": "^1.3.2", "phpcompatibility/php-compatibility": "^9.3.5", "roave/security-advisories": "dev-latest", - "squizlabs/php_codesniffer": "^3.7.1", + "squizlabs/php_codesniffer": "^3.7.2", "yoast/phpunit-polyfills": "^1.0.4" }, "suggest": { @@ -439,7 +439,7 @@ "description": "PHPMailer is a full-featured email creation and transfer class for PHP", "support": { "issues": "https://github.com/PHPMailer/PHPMailer/issues", - "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.8.0" + "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.8.1" }, "funding": [ { @@ -447,7 +447,7 @@ "type": "github" } ], - "time": "2023-03-06T14:43:22+00:00" + "time": "2023-08-29T08:26:30+00:00" }, { "name": "phpstan/phpstan", @@ -513,23 +513,23 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.17", + "version": "9.2.29", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "aa94dc41e8661fe90c7316849907cba3007b10d8" + "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/aa94dc41e8661fe90c7316849907cba3007b10d8", - "reference": "aa94dc41e8661fe90c7316849907cba3007b10d8", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6a3a87ac2bbe33b25042753df8195ba4aa534c76", + "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.14", + "nikic/php-parser": "^4.15", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", @@ -544,8 +544,8 @@ "phpunit/phpunit": "^9.3" }, "suggest": { - "ext-pcov": "*", - "ext-xdebug": "*" + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "type": "library", "extra": { @@ -578,7 +578,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.17" + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.29" }, "funding": [ { @@ -586,7 +587,7 @@ "type": "github" } ], - "time": "2022-08-30T12:24:04+00:00" + "time": "2023-09-19T04:57:46+00:00" }, { "name": "phpunit/php-file-iterator", @@ -831,16 +832,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.10", + "version": "9.6.13", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "a6d351645c3fe5a30f5e86be6577d946af65a328" + "reference": "f3d767f7f9e191eab4189abe41ab37797e30b1be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a6d351645c3fe5a30f5e86be6577d946af65a328", - "reference": "a6d351645c3fe5a30f5e86be6577d946af65a328", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f3d767f7f9e191eab4189abe41ab37797e30b1be", + "reference": "f3d767f7f9e191eab4189abe41ab37797e30b1be", "shasum": "" }, "require": { @@ -855,7 +856,7 @@ "phar-io/manifest": "^2.0.3", "phar-io/version": "^3.0.2", "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.13", + "phpunit/php-code-coverage": "^9.2.28", "phpunit/php-file-iterator": "^3.0.5", "phpunit/php-invoker": "^3.1.1", "phpunit/php-text-template": "^2.0.3", @@ -914,7 +915,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.10" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.13" }, "funding": [ { @@ -930,7 +931,7 @@ "type": "tidelift" } ], - "time": "2023-07-10T04:04:23+00:00" + "time": "2023-09-19T05:39:22+00:00" }, { "name": "sebastian/cli-parser", @@ -1232,16 +1233,16 @@ }, { "name": "sebastian/diff", - "version": "4.0.4", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" + "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", + "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", "shasum": "" }, "require": { @@ -1286,7 +1287,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" }, "funding": [ { @@ -1294,20 +1295,20 @@ "type": "github" } ], - "time": "2020-10-26T13:10:38+00:00" + "time": "2023-05-07T05:35:17+00:00" }, { "name": "sebastian/environment", - "version": "5.1.4", + "version": "5.1.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7" + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", "shasum": "" }, "require": { @@ -1349,7 +1350,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.4" + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" }, "funding": [ { @@ -1357,7 +1358,7 @@ "type": "github" } ], - "time": "2022-04-03T09:37:03+00:00" + "time": "2023-02-03T06:03:51+00:00" }, { "name": "sebastian/exporter", @@ -1438,16 +1439,16 @@ }, { "name": "sebastian/global-state", - "version": "5.0.5", + "version": "5.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" + "reference": "bde739e7565280bda77be70044ac1047bc007e34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", + "reference": "bde739e7565280bda77be70044ac1047bc007e34", "shasum": "" }, "require": { @@ -1490,7 +1491,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6" }, "funding": [ { @@ -1498,7 +1499,7 @@ "type": "github" } ], - "time": "2022-02-14T08:28:10+00:00" + "time": "2023-08-02T09:26:13+00:00" }, { "name": "sebastian/lines-of-code", @@ -1671,16 +1672,16 @@ }, { "name": "sebastian/recursion-context", - "version": "4.0.4", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", "shasum": "" }, "require": { @@ -1719,10 +1720,10 @@ } ], "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" }, "funding": [ { @@ -1730,7 +1731,7 @@ "type": "github" } ], - "time": "2020-10-26T13:17:30+00:00" + "time": "2023-02-03T06:07:39+00:00" }, { "name": "sebastian/resource-operations", @@ -1789,16 +1790,16 @@ }, { "name": "sebastian/type", - "version": "3.2.0", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e" + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", - "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", "shasum": "" }, "require": { @@ -1833,7 +1834,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2.0" + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" }, "funding": [ { @@ -1841,7 +1842,7 @@ "type": "github" } ], - "time": "2022-09-12T14:47:03+00:00" + "time": "2023-02-03T06:13:03+00:00" }, { "name": "sebastian/version", @@ -1956,7 +1957,9 @@ "php": ">=8.0.0", "ext-curl": "*" }, - "platform-dev": [], + "platform-dev": { + "ext-openssl": "*" + }, "platform-overrides": { "php": "8.0" }, diff --git a/src/Utopia/Messaging/Adapter/Push/APNS.php b/src/Utopia/Messaging/Adapter/Push/APNS.php index fa5d30b9..45766fd9 100644 --- a/src/Utopia/Messaging/Adapter/Push/APNS.php +++ b/src/Utopia/Messaging/Adapter/Push/APNS.php @@ -60,9 +60,10 @@ public function process(Push $message): string } /** - * @param array $to - * @param array $payload + * @param array $to + * @param array $payload * @return array + * * @throws Exception */ private function notify(array $to, array $payload): array diff --git a/src/Utopia/Messaging/Adapter/SMS/Telesign.php b/src/Utopia/Messaging/Adapter/SMS/Telesign.php index a0959908..896e90d2 100644 --- a/src/Utopia/Messaging/Adapter/SMS/Telesign.php +++ b/src/Utopia/Messaging/Adapter/SMS/Telesign.php @@ -56,8 +56,7 @@ protected function process(SMS $message): string } /** - * @param array $numbers - * @return string + * @param array $numbers */ private function formatNumbers(array $numbers): string { diff --git a/src/Utopia/Messaging/Messages/Discord.php b/src/Utopia/Messaging/Messages/Discord.php index 7b678988..dffa5fec 100644 --- a/src/Utopia/Messaging/Messages/Discord.php +++ b/src/Utopia/Messaging/Messages/Discord.php @@ -7,18 +7,10 @@ class Discord implements Message { /** - * @param string $content - * @param string|null $username - * @param string|null $avatarUrl - * @param bool|null $tts - * @param array|null $embeds - * @param array|null $allowedMentions - * @param array|null $components - * @param array|null $attachments - * @param string|null $flags - * @param string|null $threadName - * @param bool|null $wait - * @param string|null $threadId + * @param array|null $embeds + * @param array|null $allowedMentions + * @param array|null $components + * @param array|null $attachments */ public function __construct( private string $content, diff --git a/src/Utopia/Messaging/Messages/Email.php b/src/Utopia/Messaging/Messages/Email.php index 633d72e0..8e79c10c 100644 --- a/src/Utopia/Messaging/Messages/Email.php +++ b/src/Utopia/Messaging/Messages/Email.php @@ -6,7 +6,6 @@ class Email implements Message { - /** * @param array $to The recipients of the email. * @param string $subject The subject of the email. diff --git a/src/Utopia/Messaging/Messages/SMS.php b/src/Utopia/Messaging/Messages/SMS.php index d96f582b..a2eb2bad 100644 --- a/src/Utopia/Messaging/Messages/SMS.php +++ b/src/Utopia/Messaging/Messages/SMS.php @@ -7,10 +7,8 @@ class SMS implements Message { /** - * @param array $to - * @param string $content - * @param string|null $from - * @param array|null $attachments + * @param array $to + * @param array|null $attachments */ public function __construct( private array $to, diff --git a/tests/Messaging/Adapter/App/DiscordTest.php b/tests/Messaging/Adapter/App/DiscordTest.php index 967d1888..9096c1d9 100644 --- a/tests/Messaging/Adapter/App/DiscordTest.php +++ b/tests/Messaging/Adapter/App/DiscordTest.php @@ -2,9 +2,9 @@ namespace Utopia\Tests\Adapter\App; -use Utopia\Tests\Adapter\Base; use Utopia\Messaging\Adapter\App\Discord; use Utopia\Messaging\Messages\Discord as DiscordMessage; +use Utopia\Tests\Adapter\Base; class DiscordTest extends Base { @@ -30,4 +30,4 @@ public function testSendMessage(): void $this->assertNotEmpty($result); $this->assertNotEmpty($result['id']); } -} \ No newline at end of file +} diff --git a/tests/Messaging/Adapter/Email/EmailTest.php b/tests/Messaging/Adapter/Email/EmailTest.php index edd568a4..f0064acd 100644 --- a/tests/Messaging/Adapter/Email/EmailTest.php +++ b/tests/Messaging/Adapter/Email/EmailTest.php @@ -2,9 +2,9 @@ namespace Utopia\Tests\Adapter\Email; -use Utopia\Tests\Adapter\Base; use Utopia\Messaging\Adapter\Email\Mock; use Utopia\Messaging\Messages\Email; +use Utopia\Tests\Adapter\Base; class EmailTest extends Base { diff --git a/tests/Messaging/Adapter/Email/MailgunTest.php b/tests/Messaging/Adapter/Email/MailgunTest.php index a6bd0cdb..24fc886c 100644 --- a/tests/Messaging/Adapter/Email/MailgunTest.php +++ b/tests/Messaging/Adapter/Email/MailgunTest.php @@ -2,9 +2,9 @@ namespace Utopia\Tests\Adapter\Email; -use Utopia\Tests\Adapter\Base; use Utopia\Messaging\Adapter\Email\Mailgun; use Utopia\Messaging\Messages\Email; +use Utopia\Tests\Adapter\Base; class MailgunTest extends Base { diff --git a/tests/Messaging/Adapter/Email/SendgridTest.php b/tests/Messaging/Adapter/Email/SendgridTest.php index 98426ea3..244cb93d 100644 --- a/tests/Messaging/Adapter/Email/SendgridTest.php +++ b/tests/Messaging/Adapter/Email/SendgridTest.php @@ -2,9 +2,9 @@ namespace Utopia\Tests\Adapter\Email; -use Utopia\Tests\Adapter\Base; use Utopia\Messaging\Adapter\Email\Sendgrid; use Utopia\Messaging\Messages\Email; +use Utopia\Tests\Adapter\Base; class SendgridTest extends Base { diff --git a/tests/Messaging/Adapter/Push/APNSTest.php b/tests/Messaging/Adapter/Push/APNSTest.php index c24470f0..b612b614 100644 --- a/tests/Messaging/Adapter/Push/APNSTest.php +++ b/tests/Messaging/Adapter/Push/APNSTest.php @@ -2,9 +2,9 @@ namespace Utopia\Tests\Adapter\Push; -use Utopia\Tests\Adapter\Base; use Utopia\Messaging\Adapter\Push\APNS as APNSAdapter; use Utopia\Messaging\Messages\Push; +use Utopia\Tests\Adapter\Base; class APNSTest extends Base { diff --git a/tests/Messaging/Adapter/Push/FCMTest.php b/tests/Messaging/Adapter/Push/FCMTest.php index 121fd5d6..3008962b 100644 --- a/tests/Messaging/Adapter/Push/FCMTest.php +++ b/tests/Messaging/Adapter/Push/FCMTest.php @@ -2,9 +2,9 @@ namespace Utopia\Tests\Adapter\Push; -use Utopia\Tests\Adapter\Base; use Utopia\Messaging\Adapter\Push\FCM as FCMAdapter; use Utopia\Messaging\Messages\Push; +use Utopia\Tests\Adapter\Base; class FCMTest extends Base { diff --git a/tests/Messaging/Adapter/SMS/SMSTest.php b/tests/Messaging/Adapter/SMS/SMSTest.php index c935d834..848b034a 100644 --- a/tests/Messaging/Adapter/SMS/SMSTest.php +++ b/tests/Messaging/Adapter/SMS/SMSTest.php @@ -2,9 +2,9 @@ namespace Utopia\Tests\Adapter\SMS; -use Utopia\Tests\Adapter\Base; use Utopia\Messaging\Adapter\SMS\Mock; use Utopia\Messaging\Messages\SMS; +use Utopia\Tests\Adapter\Base; class SMSTest extends Base { diff --git a/tests/Messaging/Adapter/SMS/TwilioTest.php b/tests/Messaging/Adapter/SMS/TwilioTest.php index 6c1933d4..5a1b7f96 100644 --- a/tests/Messaging/Adapter/SMS/TwilioTest.php +++ b/tests/Messaging/Adapter/SMS/TwilioTest.php @@ -2,9 +2,9 @@ namespace Utopia\Tests\Adapter\SMS; -use Utopia\Tests\Adapter\Base; use Utopia\Messaging\Adapter\SMS\Twilio; use Utopia\Messaging\Messages\SMS; +use Utopia\Tests\Adapter\Base; class TwilioTest extends Base { diff --git a/tests/Messaging/Adapter/SMS/VonageTest.php b/tests/Messaging/Adapter/SMS/VonageTest.php index 3e5d97c1..19d67620 100644 --- a/tests/Messaging/Adapter/SMS/VonageTest.php +++ b/tests/Messaging/Adapter/SMS/VonageTest.php @@ -2,9 +2,9 @@ namespace Utopia\Tests\Adapter\SMS; -use Utopia\Tests\Adapter\Base; use Utopia\Messaging\Adapter\SMS\Vonage; use Utopia\Messaging\Messages\SMS; +use Utopia\Tests\Adapter\Base; class VonageTest extends Base { From 1060cc150138f483b44dfa57940a978892abcda6 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 2 Nov 2023 21:54:15 +1300 Subject: [PATCH 073/106] Fix test config --- phpunit.xml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/phpunit.xml b/phpunit.xml index 8db6586a..bb763030 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -9,11 +9,8 @@ stopOnFailure="false" > - - ./tests/unit - - - ./tests/e2e/ + + ./tests/ \ No newline at end of file From 983914c516a7f35eacfd7266a68a7009d7f5e39d Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Tue, 7 Nov 2023 14:08:56 +0000 Subject: [PATCH 074/106] feat: geosms adapter --- src/Utopia/Messaging/Adapters/SMS/GEOSMS.php | 281 +++++++++++++++++++ tests/e2e/SMS/GEOSMSTest.php | 57 ++++ 2 files changed, 338 insertions(+) create mode 100644 src/Utopia/Messaging/Adapters/SMS/GEOSMS.php create mode 100644 tests/e2e/SMS/GEOSMSTest.php diff --git a/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php b/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php new file mode 100644 index 00000000..49e4e516 --- /dev/null +++ b/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php @@ -0,0 +1,281 @@ + 'UK (+44)', + '1' => 'USA (+1)', + '213' => 'Algeria (+213)', + '376' => 'Andorra (+376)', + '244' => 'Angola (+244)', + '1264' => 'Anguilla (+1264)', + '1268' => 'Antigua & Barbuda (+1268)', + '54' => 'Argentina (+54)', + '374' => 'Armenia (+374)', + '297' => 'Aruba (+297)', + '61' => 'Australia (+61)', + '43' => 'Austria (+43)', + '994' => 'Azerbaijan (+994)', + '1242' => 'Bahamas (+1242)', + '973' => 'Bahrain (+973)', + '880' => 'Bangladesh (+880)', + '1246' => 'Barbados (+1246)', + '375' => 'Belarus (+375)', + '32' => 'Belgium (+32)', + '501' => 'Belize (+501)', + '229' => 'Benin (+229)', + '1441' => 'Bermuda (+1441)', + '975' => 'Bhutan (+975)', + '591' => 'Bolivia (+591)', + '387' => 'Bosnia Herzegovina (+387)', + '267' => 'Botswana (+267)', + '55' => 'Brazil (+55)', + '673' => 'Brunei (+673)', + '359' => 'Bulgaria (+359)', + '226' => 'Burkina Faso (+226)', + '257' => 'Burundi (+257)', + '855' => 'Cambodia (+855)', + '237' => 'Cameroon (+237)', + '1' => 'Canada (+1)', + '238' => 'Cape Verde Islands (+238)', + '1345' => 'Cayman Islands (+1345)', + '236' => 'Central African Republic (+236)', + '56' => 'Chile (+56)', + '86' => 'China (+86)', + '57' => 'Colombia (+57)', + '269' => 'Comoros (+269)', + '242' => 'Congo (+242)', + '682' => 'Cook Islands (+682)', + '506' => 'Costa Rica (+506)', + '385' => 'Croatia (+385)', + '53' => 'Cuba (+53)', + '90392' => 'Cyprus North (+90392)', + '357' => 'Cyprus South (+357)', + '42' => 'Czech Republic (+42)', + '45' => 'Denmark (+45)', + '253' => 'Djibouti (+253)', + '1809' => 'Dominica (+1809)', + '1809' => 'Dominican Republic (+1809)', + '593' => 'Ecuador (+593)', + '20' => 'Egypt (+20)', + '503' => 'El Salvador (+503)', + '240' => 'Equatorial Guinea (+240)', + '291' => 'Eritrea (+291)', + '372' => 'Estonia (+372)', + '251' => 'Ethiopia (+251)', + '500' => 'Falkland Islands (+500)', + '298' => 'Faroe Islands (+298)', + '679' => 'Fiji (+679)', + '358' => 'Finland (+358)', + '33' => 'France (+33)', + '594' => 'French Guiana (+594)', + '689' => 'French Polynesia (+689)', + '241' => 'Gabon (+241)', + '220' => 'Gambia (+220)', + '7880' => 'Georgia (+7880)', + '49' => 'Germany (+49)', + '233' => 'Ghana (+233)', + '350' => 'Gibraltar (+350)', + '30' => 'Greece (+30)', + '299' => 'Greenland (+299)', + '1473' => 'Grenada (+1473)', + '590' => 'Guadeloupe (+590)', + '671' => 'Guam (+671)', + '502' => 'Guatemala (+502)', + '224' => 'Guinea (+224)', + '245' => 'Guinea - Bissau (+245)', + '592' => 'Guyana (+592)', + '509' => 'Haiti (+509)', + '504' => 'Honduras (+504)', + '852' => 'Hong Kong (+852)', + '36' => 'Hungary (+36)', + '354' => 'Iceland (+354)', + '91' => 'India (+91)', + '62' => 'Indonesia (+62)', + '98' => 'Iran (+98)', + '964' => 'Iraq (+964)', + '353' => 'Ireland (+353)', + '972' => 'Israel (+972)', + '39' => 'Italy (+39)', + '1876' => 'Jamaica (+1876)', + '81' => 'Japan (+81)', + '962' => 'Jordan (+962)', + '7' => 'Kazakhstan (+7)', + '254' => 'Kenya (+254)', + '686' => 'Kiribati (+686)', + '850' => 'Korea North (+850)', + '82' => 'Korea South (+82)', + '965' => 'Kuwait (+965)', + '996' => 'Kyrgyzstan (+996)', + '856' => 'Laos (+856)', + '371' => 'Latvia (+371)', + '961' => 'Lebanon (+961)', + '266' => 'Lesotho (+266)', + '231' => 'Liberia (+231)', + '218' => 'Libya (+218)', + '417' => 'Liechtenstein (+417)', + '370' => 'Lithuania (+370)', + '352' => 'Luxembourg (+352)', + '853' => 'Macao (+853)', + '389' => 'Macedonia (+389)', + '261' => 'Madagascar (+261)', + '265' => 'Malawi (+265)', + '60' => 'Malaysia (+60)', + '960' => 'Maldives (+960)', + '223' => 'Mali (+223)', + '356' => 'Malta (+356)', + '692' => 'Marshall Islands (+692)', + '596' => 'Martinique (+596)', + '222' => 'Mauritania (+222)', + '269' => 'Mayotte (+269)', + '52' => 'Mexico (+52)', + '691' => 'Micronesia (+691)', + '373' => 'Moldova (+373)', + '377' => 'Monaco (+377)', + '976' => 'Mongolia (+976)', + '1664' => 'Montserrat (+1664)', + '212' => 'Morocco (+212)', + '258' => 'Mozambique (+258)', + '95' => 'Myanmar (+95)', + '264' => 'Namibia (+264)', + '674' => 'Nauru (+674)', + '977' => 'Nepal (+977)', + '31' => 'Netherlands (+31)', + '687' => 'New Caledonia (+687)', + '64' => 'New Zealand (+64)', + '505' => 'Nicaragua (+505)', + '227' => 'Niger (+227)', + '234' => 'Nigeria (+234)', + '683' => 'Niue (+683)', + '672' => 'Norfolk Islands (+672)', + '670' => 'Northern Marianas (+670)', + '47' => 'Norway (+47)', + '968' => 'Oman (+968)', + '680' => 'Palau (+680)', + '507' => 'Panama (+507)', + '675' => 'Papua New Guinea (+675)', + '595' => 'Paraguay (+595)', + '51' => 'Peru (+51)', + '63' => 'Philippines (+63)', + '48' => 'Poland (+48)', + '351' => 'Portugal (+351)', + '1787' => 'Puerto Rico (+1787)', + '974' => 'Qatar (+974)', + '262' => 'Reunion (+262)', + '40' => 'Romania (+40)', + '7' => 'Russia (+7)', + '250' => 'Rwanda (+250)', + '378' => 'San Marino (+378)', + '239' => 'Sao Tome & Principe (+239)', + '966' => 'Saudi Arabia (+966)', + '221' => 'Senegal (+221)', + '381' => 'Serbia (+381)', + '248' => 'Seychelles (+248)', + '232' => 'Sierra Leone (+232)', + '65' => 'Singapore (+65)', + '421' => 'Slovak Republic (+421)', + '386' => 'Slovenia (+386)', + '677' => 'Solomon Islands (+677)', + '252' => 'Somalia (+252)', + '27' => 'South Africa (+27)', + '34' => 'Spain (+34)', + '94' => 'Sri Lanka (+94)', + '290' => 'St. Helena (+290)', + '1869' => 'St. Kitts (+1869)', + '1758' => 'St. Lucia (+1758)', + '249' => 'Sudan (+249)', + '597' => 'Suriname (+597)', + '268' => 'Swaziland (+268)', + '46' => 'Sweden (+46)', + '41' => 'Switzerland (+41)', + '963' => 'Syria (+963)', + '886' => 'Taiwan (+886)', + '7' => 'Tajikstan (+7)', + '66' => 'Thailand (+66)', + '228' => 'Togo (+228)', + '676' => 'Tonga (+676)', + '1868' => 'Trinidad & Tobago (+1868)', + '216' => 'Tunisia (+216)', + '90' => 'Turkey (+90)', + '7' => 'Turkmenistan (+7)', + '993' => 'Turkmenistan (+993)', + '1649' => 'Turks & Caicos Islands (+1649)', + '688' => 'Tuvalu (+688)', + '256' => 'Uganda (+256)', + '380' => 'Ukraine (+380)', + '971' => 'United Arab Emirates (+971)', + '598' => 'Uruguay (+598)', + '7' => 'Uzbekistan (+7)', + '678' => 'Vanuatu (+678)', + '379' => 'Vatican City (+379)', + '58' => 'Venezuela (+58)', + '84' => 'Vietnam (+84)', + '84' => 'Virgin Islands - British (+1284)', + '84' => 'Virgin Islands - US (+1340)', + '681' => 'Wallis & Futuna (+681)', + '969' => 'Yemen (North)(+969)', + '967' => 'Yemen (South)(+967)', + '260' => 'Zambia (+260)', + '263' => 'Zimbabwe (+263)', + ]; + + protected $defaultAdapter; + protected $localAdapters = []; + + public function __construct(SMSAdapter $defaultAdapter) + { + $this->defaultAdapter = $defaultAdapter; + } + + public function getName(): string + { + return 'GEOSMS'; + } + + public function getMaxMessagesPerRequest(): int + { + return $this->defaultAdapter->getMaxMessagesPerRequest(); + } + + public function setLocal(string $prefix, SMSAdapter $adapter): self + { + $this->localAdapters[$prefix] = $adapter; + return $this; + } + + protected function process(SMS $message): string + { + $adapter = $this->getAdapterForMessage($message); + return $adapter->send($message); + } + + protected function getAdapterForMessage(SMS $message): SMSAdapter + { + foreach ($message->getTo() as $recipient) { + $prefix = $this->extractPrefix($recipient); + if (!empty($prefix) && array_key_exists($prefix, $this->localAdapters)) { + return $this->localAdapters[$prefix]; + } + } + + return $this->defaultAdapter; + } + + protected function extractPrefix(string $phoneNumber): string + { + $digits = preg_replace('/\D/', '', $phoneNumber); + foreach ([3, 2, 1] as $length) { + $prefix = substr($digits, 0, $length); + if (isset(self::COUNTRY_CODES[$prefix])) { + return '+' . $prefix; + } + } + return ''; + } +} diff --git a/tests/e2e/SMS/GEOSMSTest.php b/tests/e2e/SMS/GEOSMSTest.php new file mode 100644 index 00000000..b259c9a6 --- /dev/null +++ b/tests/e2e/SMS/GEOSMSTest.php @@ -0,0 +1,57 @@ +createMock(SMSAdapter::class); + $defaultAdapterMock->method('send') + ->willReturn(json_encode(['status' => 'success'])); + + $adapter = new GeoSms($defaultAdapterMock); + + $to = ['+11234567890']; + $from = 'Sender'; + + $message = new SMS( + to: $to, + content: 'Test Content', + from: $from + ); + + $result = json_decode($adapter->send($message)); + + $this->assertEquals('success', $result->status); + } + + public function testSendSMSUsingLocalAdapter() + { + $defaultAdapterMock = $this->createMock(SMSAdapter::class); + $localAdapterMock = $this->createMock(SMSAdapter::class); + $localAdapterMock->method('send') + ->willReturn(json_encode(['status' => 'success', 'adapter' => 'local'])); + + $adapter = new GEOSMS($defaultAdapterMock); + $adapter->setLocal('44', $localAdapterMock); + + $to = ['+441234567890']; + $from = 'Sender'; + + $message = new SMS( + to: $to, + content: 'Test Content', + from: $from + ); + + $result = json_decode($adapter->send($message)); + + $this->assertEquals('success', $result->status); + $this->assertEquals('local', $result->adapter); + } +} From 1284c5bdd92047fac0a42ec309103558029fb179 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Tue, 7 Nov 2023 14:14:32 +0000 Subject: [PATCH 075/106] test: enable msg91 --- tests/e2e/SMS/Msg91Test.php | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/tests/e2e/SMS/Msg91Test.php b/tests/e2e/SMS/Msg91Test.php index df90f4c4..61ec35f0 100644 --- a/tests/e2e/SMS/Msg91Test.php +++ b/tests/e2e/SMS/Msg91Test.php @@ -12,19 +12,17 @@ class Msg91Test extends Base */ public function testSendSMS() { - // $sender = new Msg91(getenv('MSG_91_SENDER_ID'), getenv('MSG_91_AUTH_KEY')); + $sender = new Msg91(getenv('MSG_91_SENDER_ID'), getenv('MSG_91_AUTH_KEY')); - // $message = new SMS( - // to: [getenv('MSG_91_TO')], - // content: 'Test Content', - // from: getenv('MSG_91_FROM') - // ); + $message = new SMS( + to: [getenv('MSG_91_TO')], + content: 'Test Content', + from: getenv('MSG_91_FROM') + ); - // $response = $sender->send($message); - // $result = \json_decode($response, true); + $response = $sender->send($message); + $result = \json_decode($response, true); - // $this->assertEquals('success', $result['type']); - - $this->markTestSkipped('Msg91 requires business verification to use template and SMS api.'); + $this->assertEquals('success', $result['type']); } } From a9e2d22d101db98751c02536e54681cda376148e Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Tue, 7 Nov 2023 14:16:27 +0000 Subject: [PATCH 076/106] chore: fmt --- src/Utopia/Messaging/Adapters/SMS/GEOSMS.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php b/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php index 49e4e516..cb153711 100644 --- a/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php +++ b/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php @@ -5,7 +5,6 @@ use Utopia\Messaging\Adapters\SMS as SMSAdapter; use Utopia\Messaging\Messages\SMS; - class GEOSMS extends SMSAdapter { protected const COUNTRY_CODES = [ @@ -226,6 +225,7 @@ class GEOSMS extends SMSAdapter ]; protected $defaultAdapter; + protected $localAdapters = []; public function __construct(SMSAdapter $defaultAdapter) @@ -246,12 +246,14 @@ public function getMaxMessagesPerRequest(): int public function setLocal(string $prefix, SMSAdapter $adapter): self { $this->localAdapters[$prefix] = $adapter; + return $this; } protected function process(SMS $message): string { $adapter = $this->getAdapterForMessage($message); + return $adapter->send($message); } @@ -259,7 +261,7 @@ protected function getAdapterForMessage(SMS $message): SMSAdapter { foreach ($message->getTo() as $recipient) { $prefix = $this->extractPrefix($recipient); - if (!empty($prefix) && array_key_exists($prefix, $this->localAdapters)) { + if (! empty($prefix) && array_key_exists($prefix, $this->localAdapters)) { return $this->localAdapters[$prefix]; } } @@ -273,9 +275,10 @@ protected function extractPrefix(string $phoneNumber): string foreach ([3, 2, 1] as $length) { $prefix = substr($digits, 0, $length); if (isset(self::COUNTRY_CODES[$prefix])) { - return '+' . $prefix; + return '+'.$prefix; } } + return ''; } } From 1c6b1c7875f2bfe0c2440e420f2c3aab449c57ee Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Tue, 7 Nov 2023 14:18:49 +0000 Subject: [PATCH 077/106] fix: geosms namespace --- src/Utopia/Messaging/Adapters/SMS/GEOSMS.php | 6 +++--- tests/e2e/SMS/GEOSMSTest.php | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php b/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php index cb153711..dedc9f22 100644 --- a/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php +++ b/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php @@ -1,6 +1,6 @@ getTo() as $recipient) { $prefix = $this->extractPrefix($recipient); - if (! empty($prefix) && array_key_exists($prefix, $this->localAdapters)) { + if (!empty($prefix) && array_key_exists($prefix, $this->localAdapters)) { return $this->localAdapters[$prefix]; } } @@ -275,7 +275,7 @@ protected function extractPrefix(string $phoneNumber): string foreach ([3, 2, 1] as $length) { $prefix = substr($digits, 0, $length); if (isset(self::COUNTRY_CODES[$prefix])) { - return '+'.$prefix; + return '+' . $prefix; } } diff --git a/tests/e2e/SMS/GEOSMSTest.php b/tests/e2e/SMS/GEOSMSTest.php index b259c9a6..dbf775dc 100644 --- a/tests/e2e/SMS/GEOSMSTest.php +++ b/tests/e2e/SMS/GEOSMSTest.php @@ -2,7 +2,7 @@ namespace Tests\E2E; -use Utopia\Messaging\Adapters\GEOSMS; +use Utopia\Messaging\Adapters\SMS\GEOSMS; use Utopia\Messaging\Adapters\SMS as SMSAdapter; use Utopia\Messaging\Messages\SMS; @@ -14,7 +14,7 @@ public function testSendSMSUsingDefaultAdapter() $defaultAdapterMock->method('send') ->willReturn(json_encode(['status' => 'success'])); - $adapter = new GeoSms($defaultAdapterMock); + $adapter = new GEOSMS($defaultAdapterMock); $to = ['+11234567890']; $from = 'Sender'; From 83641f13b47d6194835ddbfb98f0814396a1499e Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Tue, 7 Nov 2023 14:19:38 +0000 Subject: [PATCH 078/106] chore: fmt --- src/Utopia/Messaging/Adapters/SMS/GEOSMS.php | 4 ++-- tests/e2e/SMS/GEOSMSTest.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php b/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php index dedc9f22..c726d872 100644 --- a/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php +++ b/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php @@ -261,7 +261,7 @@ protected function getAdapterForMessage(SMS $message): SMSAdapter { foreach ($message->getTo() as $recipient) { $prefix = $this->extractPrefix($recipient); - if (!empty($prefix) && array_key_exists($prefix, $this->localAdapters)) { + if (! empty($prefix) && array_key_exists($prefix, $this->localAdapters)) { return $this->localAdapters[$prefix]; } } @@ -275,7 +275,7 @@ protected function extractPrefix(string $phoneNumber): string foreach ([3, 2, 1] as $length) { $prefix = substr($digits, 0, $length); if (isset(self::COUNTRY_CODES[$prefix])) { - return '+' . $prefix; + return '+'.$prefix; } } diff --git a/tests/e2e/SMS/GEOSMSTest.php b/tests/e2e/SMS/GEOSMSTest.php index dbf775dc..c56c95ff 100644 --- a/tests/e2e/SMS/GEOSMSTest.php +++ b/tests/e2e/SMS/GEOSMSTest.php @@ -2,8 +2,8 @@ namespace Tests\E2E; -use Utopia\Messaging\Adapters\SMS\GEOSMS; use Utopia\Messaging\Adapters\SMS as SMSAdapter; +use Utopia\Messaging\Adapters\SMS\GEOSMS; use Utopia\Messaging\Messages\SMS; class GEOSMSTest extends Base From fe65ede70e3430cdb760c04896274ef0f8845d20 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Tue, 7 Nov 2023 14:23:10 +0000 Subject: [PATCH 079/106] fix: geosms mock --- tests/e2e/SMS/GEOSMSTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/e2e/SMS/GEOSMSTest.php b/tests/e2e/SMS/GEOSMSTest.php index c56c95ff..ed39f235 100644 --- a/tests/e2e/SMS/GEOSMSTest.php +++ b/tests/e2e/SMS/GEOSMSTest.php @@ -11,6 +11,8 @@ class GEOSMSTest extends Base public function testSendSMSUsingDefaultAdapter() { $defaultAdapterMock = $this->createMock(SMSAdapter::class); + $defaultAdapterMock->method('getMaxMessagesPerRequest') + ->willReturn(1); $defaultAdapterMock->method('send') ->willReturn(json_encode(['status' => 'success'])); @@ -33,6 +35,8 @@ public function testSendSMSUsingDefaultAdapter() public function testSendSMSUsingLocalAdapter() { $defaultAdapterMock = $this->createMock(SMSAdapter::class); + $defaultAdapterMock->method('getMaxMessagesPerRequest') + ->willReturn(1); $localAdapterMock = $this->createMock(SMSAdapter::class); $localAdapterMock->method('send') ->willReturn(json_encode(['status' => 'success', 'adapter' => 'local'])); From f212fc8dae1751dfeefeedaed92c45bff6bd5650 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Tue, 7 Nov 2023 14:33:42 +0000 Subject: [PATCH 080/106] fix: geosms remove + --- src/Utopia/Messaging/Adapters/SMS/GEOSMS.php | 3 ++- tests/e2e/Email/SendgridTest.php | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php b/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php index c726d872..d00b9860 100644 --- a/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php +++ b/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php @@ -245,6 +245,7 @@ public function getMaxMessagesPerRequest(): int public function setLocal(string $prefix, SMSAdapter $adapter): self { + $prefix = preg_replace('/\+/', '', $prefix); $this->localAdapters[$prefix] = $adapter; return $this; @@ -275,7 +276,7 @@ protected function extractPrefix(string $phoneNumber): string foreach ([3, 2, 1] as $length) { $prefix = substr($digits, 0, $length); if (isset(self::COUNTRY_CODES[$prefix])) { - return '+'.$prefix; + return $prefix; } } diff --git a/tests/e2e/Email/SendgridTest.php b/tests/e2e/Email/SendgridTest.php index 9437b167..ddce65bd 100644 --- a/tests/e2e/Email/SendgridTest.php +++ b/tests/e2e/Email/SendgridTest.php @@ -12,6 +12,7 @@ class SendgridTest extends Base */ public function testSendEmail() { + /* $key = getenv('SENDGRID_API_KEY'); $sender = new Sendgrid($key); @@ -30,5 +31,8 @@ public function testSendEmail() $response = $sender->send($message); $this->assertEquals($response, ''); + */ + + $this->markTestSkipped('Sendgrid: Authenticated user is not authorized to send mail'); } } From e199d58790038c4be05387fb300fa9c753dbcc26 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Tue, 7 Nov 2023 15:02:02 +0000 Subject: [PATCH 081/106] feat: return lowest of adapters for getMaxMessagesPerRequest --- src/Utopia/Messaging/Adapters/SMS/GEOSMS.php | 6 +++++- tests/e2e/SMS/GEOSMSTest.php | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php b/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php index d00b9860..500077a3 100644 --- a/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php +++ b/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php @@ -228,9 +228,12 @@ class GEOSMS extends SMSAdapter protected $localAdapters = []; + protected $maxMessagesPerRequest; + public function __construct(SMSAdapter $defaultAdapter) { $this->defaultAdapter = $defaultAdapter; + $this->maxMessagesPerRequest = $defaultAdapter->getMaxMessagesPerRequest(); } public function getName(): string @@ -240,13 +243,14 @@ public function getName(): string public function getMaxMessagesPerRequest(): int { - return $this->defaultAdapter->getMaxMessagesPerRequest(); + return $this->maxMessagesPerRequest; } public function setLocal(string $prefix, SMSAdapter $adapter): self { $prefix = preg_replace('/\+/', '', $prefix); $this->localAdapters[$prefix] = $adapter; + $this->maxMessagesPerRequest = min($this->maxMessagesPerRequest, $adapter->getMaxMessagesPerRequest()); return $this; } diff --git a/tests/e2e/SMS/GEOSMSTest.php b/tests/e2e/SMS/GEOSMSTest.php index ed39f235..255f6601 100644 --- a/tests/e2e/SMS/GEOSMSTest.php +++ b/tests/e2e/SMS/GEOSMSTest.php @@ -38,6 +38,8 @@ public function testSendSMSUsingLocalAdapter() $defaultAdapterMock->method('getMaxMessagesPerRequest') ->willReturn(1); $localAdapterMock = $this->createMock(SMSAdapter::class); + $localAdapterMock->method('getMaxMessagesPerRequest') + ->willReturn(1); $localAdapterMock->method('send') ->willReturn(json_encode(['status' => 'success', 'adapter' => 'local'])); @@ -58,4 +60,19 @@ public function testSendSMSUsingLocalAdapter() $this->assertEquals('success', $result->status); $this->assertEquals('local', $result->adapter); } + + public function testMaxMessagesPerRequestIsLowest() + { + $defaultAdapterMock = $this->createMock(SMSAdapter::class); + $defaultAdapterMock->method('getMaxMessagesPerRequest') + ->willReturn(1000); + $localAdapterMock = $this->createMock(SMSAdapter::class); + $localAdapterMock->method('getMaxMessagesPerRequest') + ->willReturn(2); + + $adapter = new GEOSMS($defaultAdapterMock); + $adapter->setLocal('44', $localAdapterMock); + + $this->assertEquals(2, $adapter->getMaxMessagesPerRequest()); + } } From cb5ffeadd0bf6953c01e995e2b0a6bb42879c963 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Wed, 8 Nov 2023 09:48:44 +0000 Subject: [PATCH 082/106] feat: extract calling code --- src/Utopia/Messaging/Adapters/SMS/GEOSMS.php | 272 ++---------------- .../Adapters/SMS/GEOSMS/CallingCode.php | 219 ++++++++++++++ tests/e2e/SMS/GEOSMS/CallingCodeTest.php | 16 ++ tests/e2e/SMS/GEOSMSTest.php | 18 +- 4 files changed, 261 insertions(+), 264 deletions(-) create mode 100644 src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php create mode 100644 tests/e2e/SMS/GEOSMS/CallingCodeTest.php diff --git a/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php b/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php index 500077a3..a9e1a3ec 100644 --- a/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php +++ b/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php @@ -2,238 +2,18 @@ namespace Utopia\Messaging\Adapters\SMS; +use Utopia\Messaging\Adapters\SMS\GEOSMS\CallingCode; use Utopia\Messaging\Adapters\SMS as SMSAdapter; use Utopia\Messaging\Messages\SMS; class GEOSMS extends SMSAdapter { - protected const COUNTRY_CODES = [ - '44' => 'UK (+44)', - '1' => 'USA (+1)', - '213' => 'Algeria (+213)', - '376' => 'Andorra (+376)', - '244' => 'Angola (+244)', - '1264' => 'Anguilla (+1264)', - '1268' => 'Antigua & Barbuda (+1268)', - '54' => 'Argentina (+54)', - '374' => 'Armenia (+374)', - '297' => 'Aruba (+297)', - '61' => 'Australia (+61)', - '43' => 'Austria (+43)', - '994' => 'Azerbaijan (+994)', - '1242' => 'Bahamas (+1242)', - '973' => 'Bahrain (+973)', - '880' => 'Bangladesh (+880)', - '1246' => 'Barbados (+1246)', - '375' => 'Belarus (+375)', - '32' => 'Belgium (+32)', - '501' => 'Belize (+501)', - '229' => 'Benin (+229)', - '1441' => 'Bermuda (+1441)', - '975' => 'Bhutan (+975)', - '591' => 'Bolivia (+591)', - '387' => 'Bosnia Herzegovina (+387)', - '267' => 'Botswana (+267)', - '55' => 'Brazil (+55)', - '673' => 'Brunei (+673)', - '359' => 'Bulgaria (+359)', - '226' => 'Burkina Faso (+226)', - '257' => 'Burundi (+257)', - '855' => 'Cambodia (+855)', - '237' => 'Cameroon (+237)', - '1' => 'Canada (+1)', - '238' => 'Cape Verde Islands (+238)', - '1345' => 'Cayman Islands (+1345)', - '236' => 'Central African Republic (+236)', - '56' => 'Chile (+56)', - '86' => 'China (+86)', - '57' => 'Colombia (+57)', - '269' => 'Comoros (+269)', - '242' => 'Congo (+242)', - '682' => 'Cook Islands (+682)', - '506' => 'Costa Rica (+506)', - '385' => 'Croatia (+385)', - '53' => 'Cuba (+53)', - '90392' => 'Cyprus North (+90392)', - '357' => 'Cyprus South (+357)', - '42' => 'Czech Republic (+42)', - '45' => 'Denmark (+45)', - '253' => 'Djibouti (+253)', - '1809' => 'Dominica (+1809)', - '1809' => 'Dominican Republic (+1809)', - '593' => 'Ecuador (+593)', - '20' => 'Egypt (+20)', - '503' => 'El Salvador (+503)', - '240' => 'Equatorial Guinea (+240)', - '291' => 'Eritrea (+291)', - '372' => 'Estonia (+372)', - '251' => 'Ethiopia (+251)', - '500' => 'Falkland Islands (+500)', - '298' => 'Faroe Islands (+298)', - '679' => 'Fiji (+679)', - '358' => 'Finland (+358)', - '33' => 'France (+33)', - '594' => 'French Guiana (+594)', - '689' => 'French Polynesia (+689)', - '241' => 'Gabon (+241)', - '220' => 'Gambia (+220)', - '7880' => 'Georgia (+7880)', - '49' => 'Germany (+49)', - '233' => 'Ghana (+233)', - '350' => 'Gibraltar (+350)', - '30' => 'Greece (+30)', - '299' => 'Greenland (+299)', - '1473' => 'Grenada (+1473)', - '590' => 'Guadeloupe (+590)', - '671' => 'Guam (+671)', - '502' => 'Guatemala (+502)', - '224' => 'Guinea (+224)', - '245' => 'Guinea - Bissau (+245)', - '592' => 'Guyana (+592)', - '509' => 'Haiti (+509)', - '504' => 'Honduras (+504)', - '852' => 'Hong Kong (+852)', - '36' => 'Hungary (+36)', - '354' => 'Iceland (+354)', - '91' => 'India (+91)', - '62' => 'Indonesia (+62)', - '98' => 'Iran (+98)', - '964' => 'Iraq (+964)', - '353' => 'Ireland (+353)', - '972' => 'Israel (+972)', - '39' => 'Italy (+39)', - '1876' => 'Jamaica (+1876)', - '81' => 'Japan (+81)', - '962' => 'Jordan (+962)', - '7' => 'Kazakhstan (+7)', - '254' => 'Kenya (+254)', - '686' => 'Kiribati (+686)', - '850' => 'Korea North (+850)', - '82' => 'Korea South (+82)', - '965' => 'Kuwait (+965)', - '996' => 'Kyrgyzstan (+996)', - '856' => 'Laos (+856)', - '371' => 'Latvia (+371)', - '961' => 'Lebanon (+961)', - '266' => 'Lesotho (+266)', - '231' => 'Liberia (+231)', - '218' => 'Libya (+218)', - '417' => 'Liechtenstein (+417)', - '370' => 'Lithuania (+370)', - '352' => 'Luxembourg (+352)', - '853' => 'Macao (+853)', - '389' => 'Macedonia (+389)', - '261' => 'Madagascar (+261)', - '265' => 'Malawi (+265)', - '60' => 'Malaysia (+60)', - '960' => 'Maldives (+960)', - '223' => 'Mali (+223)', - '356' => 'Malta (+356)', - '692' => 'Marshall Islands (+692)', - '596' => 'Martinique (+596)', - '222' => 'Mauritania (+222)', - '269' => 'Mayotte (+269)', - '52' => 'Mexico (+52)', - '691' => 'Micronesia (+691)', - '373' => 'Moldova (+373)', - '377' => 'Monaco (+377)', - '976' => 'Mongolia (+976)', - '1664' => 'Montserrat (+1664)', - '212' => 'Morocco (+212)', - '258' => 'Mozambique (+258)', - '95' => 'Myanmar (+95)', - '264' => 'Namibia (+264)', - '674' => 'Nauru (+674)', - '977' => 'Nepal (+977)', - '31' => 'Netherlands (+31)', - '687' => 'New Caledonia (+687)', - '64' => 'New Zealand (+64)', - '505' => 'Nicaragua (+505)', - '227' => 'Niger (+227)', - '234' => 'Nigeria (+234)', - '683' => 'Niue (+683)', - '672' => 'Norfolk Islands (+672)', - '670' => 'Northern Marianas (+670)', - '47' => 'Norway (+47)', - '968' => 'Oman (+968)', - '680' => 'Palau (+680)', - '507' => 'Panama (+507)', - '675' => 'Papua New Guinea (+675)', - '595' => 'Paraguay (+595)', - '51' => 'Peru (+51)', - '63' => 'Philippines (+63)', - '48' => 'Poland (+48)', - '351' => 'Portugal (+351)', - '1787' => 'Puerto Rico (+1787)', - '974' => 'Qatar (+974)', - '262' => 'Reunion (+262)', - '40' => 'Romania (+40)', - '7' => 'Russia (+7)', - '250' => 'Rwanda (+250)', - '378' => 'San Marino (+378)', - '239' => 'Sao Tome & Principe (+239)', - '966' => 'Saudi Arabia (+966)', - '221' => 'Senegal (+221)', - '381' => 'Serbia (+381)', - '248' => 'Seychelles (+248)', - '232' => 'Sierra Leone (+232)', - '65' => 'Singapore (+65)', - '421' => 'Slovak Republic (+421)', - '386' => 'Slovenia (+386)', - '677' => 'Solomon Islands (+677)', - '252' => 'Somalia (+252)', - '27' => 'South Africa (+27)', - '34' => 'Spain (+34)', - '94' => 'Sri Lanka (+94)', - '290' => 'St. Helena (+290)', - '1869' => 'St. Kitts (+1869)', - '1758' => 'St. Lucia (+1758)', - '249' => 'Sudan (+249)', - '597' => 'Suriname (+597)', - '268' => 'Swaziland (+268)', - '46' => 'Sweden (+46)', - '41' => 'Switzerland (+41)', - '963' => 'Syria (+963)', - '886' => 'Taiwan (+886)', - '7' => 'Tajikstan (+7)', - '66' => 'Thailand (+66)', - '228' => 'Togo (+228)', - '676' => 'Tonga (+676)', - '1868' => 'Trinidad & Tobago (+1868)', - '216' => 'Tunisia (+216)', - '90' => 'Turkey (+90)', - '7' => 'Turkmenistan (+7)', - '993' => 'Turkmenistan (+993)', - '1649' => 'Turks & Caicos Islands (+1649)', - '688' => 'Tuvalu (+688)', - '256' => 'Uganda (+256)', - '380' => 'Ukraine (+380)', - '971' => 'United Arab Emirates (+971)', - '598' => 'Uruguay (+598)', - '7' => 'Uzbekistan (+7)', - '678' => 'Vanuatu (+678)', - '379' => 'Vatican City (+379)', - '58' => 'Venezuela (+58)', - '84' => 'Vietnam (+84)', - '84' => 'Virgin Islands - British (+1284)', - '84' => 'Virgin Islands - US (+1340)', - '681' => 'Wallis & Futuna (+681)', - '969' => 'Yemen (North)(+969)', - '967' => 'Yemen (South)(+967)', - '260' => 'Zambia (+260)', - '263' => 'Zimbabwe (+263)', - ]; - protected $defaultAdapter; - protected $localAdapters = []; - protected $maxMessagesPerRequest; - public function __construct(SMSAdapter $defaultAdapter) { $this->defaultAdapter = $defaultAdapter; - $this->maxMessagesPerRequest = $defaultAdapter->getMaxMessagesPerRequest(); } public function getName(): string @@ -243,47 +23,43 @@ public function getName(): string public function getMaxMessagesPerRequest(): int { - return $this->maxMessagesPerRequest; + return PHP_INT_MAX; } - public function setLocal(string $prefix, SMSAdapter $adapter): self + public function setLocal(CallingCode $callingCode, SMSAdapter $adapter): self { - $prefix = preg_replace('/\+/', '', $prefix); - $this->localAdapters[$prefix] = $adapter; - $this->maxMessagesPerRequest = min($this->maxMessagesPerRequest, $adapter->getMaxMessagesPerRequest()); - + $this->localAdapters[$callingCode->value] = $adapter; return $this; } protected function process(SMS $message): string { - $adapter = $this->getAdapterForMessage($message); - - return $adapter->send($message); - } - - protected function getAdapterForMessage(SMS $message): SMSAdapter - { - foreach ($message->getTo() as $recipient) { - $prefix = $this->extractPrefix($recipient); - if (! empty($prefix) && array_key_exists($prefix, $this->localAdapters)) { - return $this->localAdapters[$prefix]; - } + $recipientsByCallingCode = $this->groupRecipientsByCallingCode($message->getTo()); + $responses = []; + + foreach ($recipientsByCallingCode as $callingCode => $recipients) { + $adapter = isset($this->localAdapters[$callingCode]) ? $this->localAdapters[$callingCode] : $this->defaultAdapter; + + $responses[] = $adapter->send(new SMS( + to: $recipients, + content: $message->getContent(), + from: $message->getFrom(), + attachments: $message->getAttachments() + )); } - return $this->defaultAdapter; + return $responses[0]; } - protected function extractPrefix(string $phoneNumber): string + protected function groupRecipientsByCallingCode(array $recipients): array { - $digits = preg_replace('/\D/', '', $phoneNumber); - foreach ([3, 2, 1] as $length) { - $prefix = substr($digits, 0, $length); - if (isset(self::COUNTRY_CODES[$prefix])) { - return $prefix; - } + $result = []; + + foreach ($recipients as $recipient) { + $callingCode = CallingCode::fromPhoneNumber($recipient); + $result[$callingCode->value][] = $recipient; } - return ''; + return $result; } } diff --git a/src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php b/src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php new file mode 100644 index 00000000..0e416ef3 --- /dev/null +++ b/src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php @@ -0,0 +1,219 @@ +assertEquals(CallingCode::USA_AND_CANADA, CallingCode::fromPhoneNumber('+11234567890')); + $this->assertEquals(CallingCode::INDIA, CallingCode::fromPhoneNumber('+911234567890'),); + $this->assertEquals(CallingCode::UNITED_ARAB_EMIRATES, CallingCode::fromPhoneNumber('009711234567890')); + $this->assertEquals(CallingCode::UNITED_KINGDOM, CallingCode::fromPhoneNumber('011441234567890')); + } +} diff --git a/tests/e2e/SMS/GEOSMSTest.php b/tests/e2e/SMS/GEOSMSTest.php index 255f6601..26b0794e 100644 --- a/tests/e2e/SMS/GEOSMSTest.php +++ b/tests/e2e/SMS/GEOSMSTest.php @@ -4,6 +4,7 @@ use Utopia\Messaging\Adapters\SMS as SMSAdapter; use Utopia\Messaging\Adapters\SMS\GEOSMS; +use Utopia\Messaging\Adapters\SMS\GEOSMS\CallingCode; use Utopia\Messaging\Messages\SMS; class GEOSMSTest extends Base @@ -44,7 +45,7 @@ public function testSendSMSUsingLocalAdapter() ->willReturn(json_encode(['status' => 'success', 'adapter' => 'local'])); $adapter = new GEOSMS($defaultAdapterMock); - $adapter->setLocal('44', $localAdapterMock); + $adapter->setLocal(CallingCode::UNITED_KINGDOM, $localAdapterMock); $to = ['+441234567890']; $from = 'Sender'; @@ -60,19 +61,4 @@ public function testSendSMSUsingLocalAdapter() $this->assertEquals('success', $result->status); $this->assertEquals('local', $result->adapter); } - - public function testMaxMessagesPerRequestIsLowest() - { - $defaultAdapterMock = $this->createMock(SMSAdapter::class); - $defaultAdapterMock->method('getMaxMessagesPerRequest') - ->willReturn(1000); - $localAdapterMock = $this->createMock(SMSAdapter::class); - $localAdapterMock->method('getMaxMessagesPerRequest') - ->willReturn(2); - - $adapter = new GEOSMS($defaultAdapterMock); - $adapter->setLocal('44', $localAdapterMock); - - $this->assertEquals(2, $adapter->getMaxMessagesPerRequest()); - } } From 13eaea3e0098bd894149dac4e30abc742118a6cc Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Wed, 8 Nov 2023 09:49:38 +0000 Subject: [PATCH 083/106] chore: rename na code --- src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php | 2 +- tests/e2e/SMS/GEOSMS/CallingCodeTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php b/src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php index 0e416ef3..5cc38a46 100644 --- a/src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php +++ b/src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php @@ -188,7 +188,7 @@ enum CallingCode: string case UNITED_ARAB_EMIRATES = '971'; case UNITED_KINGDOM = '44'; case URUGUAY = '598'; - case USA_AND_CANADA = '1'; + case NORTH_AMERICA = '1'; case VANUATU = '678'; case VENEZUELA = '58'; case VIETNAM = '84'; diff --git a/tests/e2e/SMS/GEOSMS/CallingCodeTest.php b/tests/e2e/SMS/GEOSMS/CallingCodeTest.php index 8feaaa26..50818193 100644 --- a/tests/e2e/SMS/GEOSMS/CallingCodeTest.php +++ b/tests/e2e/SMS/GEOSMS/CallingCodeTest.php @@ -8,7 +8,7 @@ class CallingCodeTest extends Base { public function testFromPhoneNumber() { - $this->assertEquals(CallingCode::USA_AND_CANADA, CallingCode::fromPhoneNumber('+11234567890')); + $this->assertEquals(CallingCode::NORTH_AMERICA, CallingCode::fromPhoneNumber('+11234567890')); $this->assertEquals(CallingCode::INDIA, CallingCode::fromPhoneNumber('+911234567890'),); $this->assertEquals(CallingCode::UNITED_ARAB_EMIRATES, CallingCode::fromPhoneNumber('009711234567890')); $this->assertEquals(CallingCode::UNITED_KINGDOM, CallingCode::fromPhoneNumber('011441234567890')); From 33ccaefdf35e65d253726aaf834dea6f6335dfdf Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Wed, 8 Nov 2023 10:11:49 +0000 Subject: [PATCH 084/106] chore: fmt --- src/Utopia/Messaging/Adapters/SMS/GEOSMS.php | 4 +++- src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php | 7 ++++--- tests/e2e/SMS/GEOSMS/CallingCodeTest.php | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php b/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php index a9e1a3ec..bd13018f 100644 --- a/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php +++ b/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php @@ -2,13 +2,14 @@ namespace Utopia\Messaging\Adapters\SMS; -use Utopia\Messaging\Adapters\SMS\GEOSMS\CallingCode; use Utopia\Messaging\Adapters\SMS as SMSAdapter; +use Utopia\Messaging\Adapters\SMS\GEOSMS\CallingCode; use Utopia\Messaging\Messages\SMS; class GEOSMS extends SMSAdapter { protected $defaultAdapter; + protected $localAdapters = []; public function __construct(SMSAdapter $defaultAdapter) @@ -29,6 +30,7 @@ public function getMaxMessagesPerRequest(): int public function setLocal(CallingCode $callingCode, SMSAdapter $adapter): self { $this->localAdapters[$callingCode->value] = $adapter; + return $this; } diff --git a/src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php b/src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php index 5cc38a46..38e08ac5 100644 --- a/src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php +++ b/src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php @@ -9,7 +9,6 @@ enum CallingCode: string { - case ALGERIA = '213'; case ANDORRA = '376'; case ANGOLA = '244'; @@ -203,7 +202,7 @@ public static function fromPhoneNumber($number): ?CallingCode $digits = str_replace(['+', ' ', '(', ')', '-'], '', $number); // International call prefix is usually 00 or 011 - // https://en.wikipedia.org/wiki/List_of_international_call_prefixes + // https://en.wikipedia.org/wiki/List_of_international_call_prefixes $digits = preg_replace('/^00|^011/', '', $digits); // Prefixes can be 3, 2, or 1 digits long @@ -211,7 +210,9 @@ public static function fromPhoneNumber($number): ?CallingCode foreach ([3, 2, 1] as $length) { $codeScalar = substr($digits, 0, $length); $code = CallingCode::tryFrom($codeScalar); - if ($code) return $code; + if ($code) { + return $code; + } } return null; diff --git a/tests/e2e/SMS/GEOSMS/CallingCodeTest.php b/tests/e2e/SMS/GEOSMS/CallingCodeTest.php index 50818193..74f4a60b 100644 --- a/tests/e2e/SMS/GEOSMS/CallingCodeTest.php +++ b/tests/e2e/SMS/GEOSMS/CallingCodeTest.php @@ -9,7 +9,7 @@ class CallingCodeTest extends Base public function testFromPhoneNumber() { $this->assertEquals(CallingCode::NORTH_AMERICA, CallingCode::fromPhoneNumber('+11234567890')); - $this->assertEquals(CallingCode::INDIA, CallingCode::fromPhoneNumber('+911234567890'),); + $this->assertEquals(CallingCode::INDIA, CallingCode::fromPhoneNumber('+911234567890')); $this->assertEquals(CallingCode::UNITED_ARAB_EMIRATES, CallingCode::fromPhoneNumber('009711234567890')); $this->assertEquals(CallingCode::UNITED_KINGDOM, CallingCode::fromPhoneNumber('011441234567890')); } From 6e2dbcbb0de824b1750ec0d0c2c82a4fef1c596d Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Wed, 8 Nov 2023 10:34:03 +0000 Subject: [PATCH 085/106] feat: use fields instead of enum --- src/Utopia/Messaging/Adapters/SMS/GEOSMS.php | 10 +- .../Adapters/SMS/GEOSMS/CallingCode.php | 761 +++++++++++++----- 2 files changed, 574 insertions(+), 197 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php b/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php index bd13018f..a48b3b91 100644 --- a/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php +++ b/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php @@ -27,9 +27,9 @@ public function getMaxMessagesPerRequest(): int return PHP_INT_MAX; } - public function setLocal(CallingCode $callingCode, SMSAdapter $adapter): self + public function setLocal(string $callingCode, SMSAdapter $adapter): self { - $this->localAdapters[$callingCode->value] = $adapter; + $this->localAdapters[$callingCode] = $adapter; return $this; } @@ -40,7 +40,9 @@ protected function process(SMS $message): string $responses = []; foreach ($recipientsByCallingCode as $callingCode => $recipients) { - $adapter = isset($this->localAdapters[$callingCode]) ? $this->localAdapters[$callingCode] : $this->defaultAdapter; + $adapter = isset($this->localAdapters[$callingCode]) + ? $this->localAdapters[$callingCode] + : $this->defaultAdapter; $responses[] = $adapter->send(new SMS( to: $recipients, @@ -59,7 +61,7 @@ protected function groupRecipientsByCallingCode(array $recipients): array foreach ($recipients as $recipient) { $callingCode = CallingCode::fromPhoneNumber($recipient); - $result[$callingCode->value][] = $recipient; + $result[$callingCode][] = $recipient; } return $result; diff --git a/src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php b/src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php index 38e08ac5..b63c079d 100644 --- a/src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php +++ b/src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php @@ -7,197 +7,573 @@ * @link https://en.wikipedia.org/wiki/List_of_country_calling_codes */ -enum CallingCode: string +class CallingCode { - case ALGERIA = '213'; - case ANDORRA = '376'; - case ANGOLA = '244'; - case ARGENTINA = '54'; - case ARMENIA = '374'; - case ARUBA = '297'; - case AUSTRALIA = '61'; - case AUSTRIA = '43'; - case AZERBAIJAN = '994'; - case BAHRAIN = '973'; - case BANGLADESH = '880'; - case BELARUS = '375'; - case BELGIUM = '32'; - case BELIZE = '501'; - case BENIN = '229'; - case BHUTAN = '975'; - case BOLIVIA = '591'; - case BOSNIA_HERZEGOVINA = '387'; - case BOTSWANA = '267'; - case BRAZIL = '55'; - case BRUNEI = '673'; - case BULGARIA = '359'; - case BURKINA_FASO = '226'; - case BURUNDI = '257'; - case CAMBODIA = '855'; - case CAMEROON = '237'; - case CAPE_VERDE_ISLANDS = '238'; - case CENTRAL_AFRICAN_REPUBLIC = '236'; - case CHILE = '56'; - case CHINA = '86'; - case COLOMBIA = '57'; - case COMOROS_AND_MAYOTTE = '269'; - case CONGO = '242'; - case COOK_ISLANDS = '682'; - case COSTA_RICA = '506'; - case CROATIA = '385'; - case CUBA = '53'; - case CYPRUS = '357'; - case CZECH_REPUBLIC = '420'; - case DENMARK = '45'; - case DJIBOUTI = '253'; - case ECUADOR = '593'; - case EGYPT = '20'; - case EL_SALVADOR = '503'; - case EQUATORIAL_GUINEA = '240'; - case ERITREA = '291'; - case ESTONIA = '372'; - case ETHIOPIA = '251'; - case FALKLAND_ISLANDS = '500'; - case FAROE_ISLANDS = '298'; - case FIJI = '679'; - case FINLAND = '358'; - case FRANCE = '33'; - case FRENCH_GUIANA = '594'; - case FRENCH_POLYNESIA = '689'; - case GABON = '241'; - case GAMBIA = '220'; - case GEORGIA = '995'; - case GERMANY = '49'; - case GHANA = '233'; - case GIBRALTAR = '350'; - case GREECE = '30'; - case GREENLAND = '299'; - case GUADELOUPE = '590'; - case GUAM = '671'; - case GUATEMALA = '502'; - case GUINEA = '224'; - case GUINEA_BISSAU = '245'; - case GUYANA = '592'; - case HAITI = '509'; - case HONDURAS = '504'; - case HONG_KONG = '852'; - case HUNGARY = '36'; - case ICELAND = '354'; - case INDIA = '91'; - case INDONESIA = '62'; - case IRAN = '98'; - case IRAQ = '964'; - case IRELAND = '353'; - case ISRAEL = '972'; - case ITALY = '39'; - case JAPAN = '81'; - case JORDAN = '962'; - case KENYA = '254'; - case KIRIBATI = '686'; - case NORTH_KOREA = '850'; - case SOUTH_KOREA = '82'; - case KUWAIT = '965'; - case KYRGYZSTAN = '996'; - case LAOS = '856'; - case LATVIA = '371'; - case LEBANON = '961'; - case LESOTHO = '266'; - case LIBERIA = '231'; - case LIBYA = '218'; - case LIECHTENSTEIN = '417'; - case LITHUANIA = '370'; - case LUXEMBOURG = '352'; - case MACAO = '853'; - case MACEDONIA = '389'; - case MADAGASCAR = '261'; - case MALAWI = '265'; - case MALAYSIA = '60'; - case MALDIVES = '960'; - case MALI = '223'; - case MALTA = '356'; - case MARSHALL_ISLANDS = '692'; - case MARTINIQUE = '596'; - case MAURITANIA = '222'; - case MEXICO = '52'; - case MICRONESIA = '691'; - case MOLDOVA = '373'; - case MONACO = '377'; - case MONGOLIA = '976'; - case MOROCCO = '212'; - case MOZAMBIQUE = '258'; - case MYANMAR = '95'; - case NAMIBIA = '264'; - case NAURU = '674'; - case NEPAL = '977'; - case NETHERLANDS = '31'; - case NEW_CALEDONIA = '687'; - case NEW_ZEALAND = '64'; - case NICARAGUA = '505'; - case NIGER = '227'; - case NIGERIA = '234'; - case NIUE = '683'; - case NORFOLK_ISLANDS = '672'; - case NORTHERN_MARIANA_ISLANDS = '670'; - case NORWAY = '47'; - case OMAN = '968'; - case PALAU = '680'; - case PANAMA = '507'; - case PAPUA_NEW_GUINEA = '675'; - case PARAGUAY = '595'; - case PERU = '51'; - case PHILIPPINES = '63'; - case POLAND = '48'; - case PORTUGAL = '351'; - case QATAR = '974'; - case REUNION = '262'; - case ROMANIA = '40'; - case RUSSIA_KAZAKHSTAN_UZBEKISTAN_TURKMENISTAN_AND_TAJIKSTAN = '7'; - case RWANDA = '250'; - case SAN_MARINO = '378'; - case SAO_TOME_AND_PRINCIPE = '239'; - case SAUDI_ARABIA = '966'; - case SENEGAL = '221'; - case SERBIA = '381'; - case SEYCHELLES = '248'; - case SIERRA_LEONE = '232'; - case SINGAPORE = '65'; - case SLOVAK_REPUBLIC = '421'; - case SLOVENIA = '386'; - case SOLOMON_ISLANDS = '677'; - case SOMALIA = '252'; - case SOUTH_AFRICA = '27'; - case SPAIN = '34'; - case SRI_LANKA = '94'; - case ST_HELENA = '290'; - case SUDAN = '249'; - case SURINAME = '597'; - case SWAZILAND = '268'; - case SWEDEN = '46'; - case SWITZERLAND = '41'; - case SYRIA = '963'; - case TAIWAN = '886'; - case THAILAND = '66'; - case TOGO = '228'; - case TONGA = '676'; - case TUNISIA = '216'; - case TURKEY = '90'; - case TUVALU = '688'; - case UGANDA = '256'; - case UKRAINE = '380'; - case UNITED_ARAB_EMIRATES = '971'; - case UNITED_KINGDOM = '44'; - case URUGUAY = '598'; - case NORTH_AMERICA = '1'; - case VANUATU = '678'; - case VENEZUELA = '58'; - case VIETNAM = '84'; - case WALLIS_AND_FUTUNA = '681'; - case YEMEN = '967'; - case ZAMBIA = '260'; - case ZANZIBAR = '255'; - case ZIMBABWE = '263'; - - public static function fromPhoneNumber($number): ?CallingCode + public const ALGERIA = '213'; + + public const ANDORRA = '376'; + + public const ANGOLA = '244'; + + public const ARGENTINA = '54'; + + public const ARMENIA = '374'; + + public const ARUBA = '297'; + + public const AUSTRALIA = '61'; + + public const AUSTRIA = '43'; + + public const AZERBAIJAN = '994'; + + public const BAHRAIN = '973'; + + public const BANGLADESH = '880'; + + public const BELARUS = '375'; + + public const BELGIUM = '32'; + + public const BELIZE = '501'; + + public const BENIN = '229'; + + public const BHUTAN = '975'; + + public const BOLIVIA = '591'; + + public const BOSNIA_HERZEGOVINA = '387'; + + public const BOTSWANA = '267'; + + public const BRAZIL = '55'; + + public const BRUNEI = '673'; + + public const BULGARIA = '359'; + + public const BURKINA_FASO = '226'; + + public const BURUNDI = '257'; + + public const CAMBODIA = '855'; + + public const CAMEROON = '237'; + + public const CAPE_VERDE_ISLANDS = '238'; + + public const CENTRAL_AFRICAN_REPUBLIC = '236'; + + public const CHILE = '56'; + + public const CHINA = '86'; + + public const COLOMBIA = '57'; + + public const COMOROS_AND_MAYOTTE = '269'; + + public const CONGO = '242'; + + public const COOK_ISLANDS = '682'; + + public const COSTA_RICA = '506'; + + public const CROATIA = '385'; + + public const CUBA = '53'; + + public const CYPRUS = '357'; + + public const CZECH_REPUBLIC = '420'; + + public const DENMARK = '45'; + + public const DJIBOUTI = '253'; + + public const ECUADOR = '593'; + + public const EGYPT = '20'; + + public const EL_SALVADOR = '503'; + + public const EQUATORIAL_GUINEA = '240'; + + public const ERITREA = '291'; + + public const ESTONIA = '372'; + + public const ETHIOPIA = '251'; + + public const FALKLAND_ISLANDS = '500'; + + public const FAROE_ISLANDS = '298'; + + public const FIJI = '679'; + + public const FINLAND = '358'; + + public const FRANCE = '33'; + + public const FRENCH_GUIANA = '594'; + + public const FRENCH_POLYNESIA = '689'; + + public const GABON = '241'; + + public const GAMBIA = '220'; + + public const GEORGIA = '995'; + + public const GERMANY = '49'; + + public const GHANA = '233'; + + public const GIBRALTAR = '350'; + + public const GREECE = '30'; + + public const GREENLAND = '299'; + + public const GUADELOUPE = '590'; + + public const GUAM = '671'; + + public const GUATEMALA = '502'; + + public const GUINEA = '224'; + + public const GUINEA_BISSAU = '245'; + + public const GUYANA = '592'; + + public const HAITI = '509'; + + public const HONDURAS = '504'; + + public const HONG_KONG = '852'; + + public const HUNGARY = '36'; + + public const ICELAND = '354'; + + public const INDIA = '91'; + + public const INDONESIA = '62'; + + public const IRAN = '98'; + + public const IRAQ = '964'; + + public const IRELAND = '353'; + + public const ISRAEL = '972'; + + public const ITALY = '39'; + + public const JAPAN = '81'; + + public const JORDAN = '962'; + + public const KENYA = '254'; + + public const KIRIBATI = '686'; + + public const NORTH_KOREA = '850'; + + public const SOUTH_KOREA = '82'; + + public const KUWAIT = '965'; + + public const KYRGYZSTAN = '996'; + + public const LAOS = '856'; + + public const LATVIA = '371'; + + public const LEBANON = '961'; + + public const LESOTHO = '266'; + + public const LIBERIA = '231'; + + public const LIBYA = '218'; + + public const LIECHTENSTEIN = '417'; + + public const LITHUANIA = '370'; + + public const LUXEMBOURG = '352'; + + public const MACAO = '853'; + + public const MACEDONIA = '389'; + + public const MADAGASCAR = '261'; + + public const MALAWI = '265'; + + public const MALAYSIA = '60'; + + public const MALDIVES = '960'; + + public const MALI = '223'; + + public const MALTA = '356'; + + public const MARSHALL_ISLANDS = '692'; + + public const MARTINIQUE = '596'; + + public const MAURITANIA = '222'; + + public const MEXICO = '52'; + + public const MICRONESIA = '691'; + + public const MOLDOVA = '373'; + + public const MONACO = '377'; + + public const MONGOLIA = '976'; + + public const MOROCCO = '212'; + + public const MOZAMBIQUE = '258'; + + public const MYANMAR = '95'; + + public const NAMIBIA = '264'; + + public const NAURU = '674'; + + public const NEPAL = '977'; + + public const NETHERLANDS = '31'; + + public const NEW_CALEDONIA = '687'; + + public const NEW_ZEALAND = '64'; + + public const NICARAGUA = '505'; + + public const NIGER = '227'; + + public const NIGERIA = '234'; + + public const NIUE = '683'; + + public const NORFOLK_ISLANDS = '672'; + + public const NORTHERN_MARIANA_ISLANDS = '670'; + + public const NORWAY = '47'; + + public const OMAN = '968'; + + public const PALAU = '680'; + + public const PANAMA = '507'; + + public const PAPUA_NEW_GUINEA = '675'; + + public const PARAGUAY = '595'; + + public const PERU = '51'; + + public const PHILIPPINES = '63'; + + public const POLAND = '48'; + + public const PORTUGAL = '351'; + + public const QATAR = '974'; + + public const REUNION = '262'; + + public const ROMANIA = '40'; + + public const RUSSIA_KAZAKHSTAN_UZBEKISTAN_TURKMENISTAN_AND_TAJIKSTAN = '7'; + + public const RWANDA = '250'; + + public const SAN_MARINO = '378'; + + public const SAO_TOME_AND_PRINCIPE = '239'; + + public const SAUDI_ARABIA = '966'; + + public const SENEGAL = '221'; + + public const SERBIA = '381'; + + public const SEYCHELLES = '248'; + + public const SIERRA_LEONE = '232'; + + public const SINGAPORE = '65'; + + public const SLOVAK_REPUBLIC = '421'; + + public const SLOVENIA = '386'; + + public const SOLOMON_ISLANDS = '677'; + + public const SOMALIA = '252'; + + public const SOUTH_AFRICA = '27'; + + public const SPAIN = '34'; + + public const SRI_LANKA = '94'; + + public const ST_HELENA = '290'; + + public const SUDAN = '249'; + + public const SURINAME = '597'; + + public const SWAZILAND = '268'; + + public const SWEDEN = '46'; + + public const SWITZERLAND = '41'; + + public const SYRIA = '963'; + + public const TAIWAN = '886'; + + public const THAILAND = '66'; + + public const TOGO = '228'; + + public const TONGA = '676'; + + public const TUNISIA = '216'; + + public const TURKEY = '90'; + + public const TUVALU = '688'; + + public const UGANDA = '256'; + + public const UKRAINE = '380'; + + public const UNITED_ARAB_EMIRATES = '971'; + + public const UNITED_KINGDOM = '44'; + + public const URUGUAY = '598'; + + public const NORTH_AMERICA = '1'; + + public const VANUATU = '678'; + + public const VENEZUELA = '58'; + + public const VIETNAM = '84'; + + public const WALLIS_AND_FUTUNA = '681'; + + public const YEMEN = '967'; + + public const ZAMBIA = '260'; + + public const ZANZIBAR = '255'; + + public const ZIMBABWE = '263'; + + protected const CODES = [ + self::ALGERIA => true, + self::ANDORRA => true, + self::ANGOLA => true, + self::ARGENTINA => true, + self::ARMENIA => true, + self::ARUBA => true, + self::AUSTRALIA => true, + self::AUSTRIA => true, + self::AZERBAIJAN => true, + self::BAHRAIN => true, + self::BANGLADESH => true, + self::BELARUS => true, + self::BELGIUM => true, + self::BELIZE => true, + self::BENIN => true, + self::BHUTAN => true, + self::BOLIVIA => true, + self::BOSNIA_HERZEGOVINA => true, + self::BOTSWANA => true, + self::BRAZIL => true, + self::BRUNEI => true, + self::BULGARIA => true, + self::BURKINA_FASO => true, + self::BURUNDI => true, + self::CAMBODIA => true, + self::CAMEROON => true, + self::CAPE_VERDE_ISLANDS => true, + self::CENTRAL_AFRICAN_REPUBLIC => true, + self::CHILE => true, + self::CHINA => true, + self::COLOMBIA => true, + self::COMOROS_AND_MAYOTTE => true, + self::CONGO => true, + self::COOK_ISLANDS => true, + self::COSTA_RICA => true, + self::CROATIA => true, + self::CUBA => true, + self::CYPRUS => true, + self::CZECH_REPUBLIC => true, + self::DENMARK => true, + self::DJIBOUTI => true, + self::ECUADOR => true, + self::EGYPT => true, + self::EL_SALVADOR => true, + self::EQUATORIAL_GUINEA => true, + self::ERITREA => true, + self::ESTONIA => true, + self::ETHIOPIA => true, + self::FALKLAND_ISLANDS => true, + self::FAROE_ISLANDS => true, + self::FIJI => true, + self::FINLAND => true, + self::FRANCE => true, + self::FRENCH_GUIANA => true, + self::FRENCH_POLYNESIA => true, + self::GABON => true, + self::GAMBIA => true, + self::GEORGIA => true, + self::GERMANY => true, + self::GHANA => true, + self::GIBRALTAR => true, + self::GREECE => true, + self::GREENLAND => true, + self::GUADELOUPE => true, + self::GUAM => true, + self::GUATEMALA => true, + self::GUINEA => true, + self::GUINEA_BISSAU => true, + self::GUYANA => true, + self::HAITI => true, + self::HONDURAS => true, + self::HONG_KONG => true, + self::HUNGARY => true, + self::ICELAND => true, + self::INDIA => true, + self::INDONESIA => true, + self::IRAN => true, + self::IRAQ => true, + self::IRELAND => true, + self::ISRAEL => true, + self::ITALY => true, + self::JAPAN => true, + self::JORDAN => true, + self::KENYA => true, + self::KIRIBATI => true, + self::NORTH_KOREA => true, + self::SOUTH_KOREA => true, + self::KUWAIT => true, + self::KYRGYZSTAN => true, + self::LAOS => true, + self::LATVIA => true, + self::LEBANON => true, + self::LESOTHO => true, + self::LIBERIA => true, + self::LIBYA => true, + self::LIECHTENSTEIN => true, + self::LITHUANIA => true, + self::LUXEMBOURG => true, + self::MACAO => true, + self::MACEDONIA => true, + self::MADAGASCAR => true, + self::MALAWI => true, + self::MALAYSIA => true, + self::MALDIVES => true, + self::MALI => true, + self::MALTA => true, + self::MARSHALL_ISLANDS => true, + self::MARTINIQUE => true, + self::MAURITANIA => true, + self::MEXICO => true, + self::MICRONESIA => true, + self::MOLDOVA => true, + self::MONACO => true, + self::MONGOLIA => true, + self::MOROCCO => true, + self::MOZAMBIQUE => true, + self::MYANMAR => true, + self::NAMIBIA => true, + self::NAURU => true, + self::NEPAL => true, + self::NETHERLANDS => true, + self::NEW_CALEDONIA => true, + self::NEW_ZEALAND => true, + self::NICARAGUA => true, + self::NIGER => true, + self::NIGERIA => true, + self::NIUE => true, + self::NORFOLK_ISLANDS => true, + self::NORTHERN_MARIANA_ISLANDS => true, + self::NORWAY => true, + self::OMAN => true, + self::PALAU => true, + self::PANAMA => true, + self::PAPUA_NEW_GUINEA => true, + self::PARAGUAY => true, + self::PERU => true, + self::PHILIPPINES => true, + self::POLAND => true, + self::PORTUGAL => true, + self::QATAR => true, + self::REUNION => true, + self::ROMANIA => true, + self::RUSSIA_KAZAKHSTAN_UZBEKISTAN_TURKMENISTAN_AND_TAJIKSTAN => true, + self::RWANDA => true, + self::SAN_MARINO => true, + self::SAO_TOME_AND_PRINCIPE => true, + self::SAUDI_ARABIA => true, + self::SENEGAL => true, + self::SERBIA => true, + self::SEYCHELLES => true, + self::SIERRA_LEONE => true, + self::SINGAPORE => true, + self::SLOVAK_REPUBLIC => true, + self::SLOVENIA => true, + self::SOLOMON_ISLANDS => true, + self::SOMALIA => true, + self::SOUTH_AFRICA => true, + self::SPAIN => true, + self::SRI_LANKA => true, + self::ST_HELENA => true, + self::SUDAN => true, + self::SURINAME => true, + self::SWAZILAND => true, + self::SWEDEN => true, + self::SWITZERLAND => true, + self::SYRIA => true, + self::TAIWAN => true, + self::THAILAND => true, + self::TOGO => true, + self::TONGA => true, + self::TUNISIA => true, + self::TURKEY => true, + self::TUVALU => true, + self::UGANDA => true, + self::UKRAINE => true, + self::UNITED_ARAB_EMIRATES => true, + self::UNITED_KINGDOM => true, + self::URUGUAY => true, + self::NORTH_AMERICA => true, + self::VANUATU => true, + self::VENEZUELA => true, + self::VIETNAM => true, + self::WALLIS_AND_FUTUNA => true, + self::YEMEN => true, + self::ZAMBIA => true, + self::ZANZIBAR => true, + self::ZIMBABWE => true, + ]; + + public static function fromPhoneNumber($number): ?string { $digits = str_replace(['+', ' ', '(', ')', '-'], '', $number); @@ -208,9 +584,8 @@ public static function fromPhoneNumber($number): ?CallingCode // Prefixes can be 3, 2, or 1 digits long // Attempt to match the longest first foreach ([3, 2, 1] as $length) { - $codeScalar = substr($digits, 0, $length); - $code = CallingCode::tryFrom($codeScalar); - if ($code) { + $code = substr($digits, 0, $length); + if (isset(self::CODES[$code])) { return $code; } } From 47b612244dd263e390af54b054ed94ed2c70c4c9 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Wed, 8 Nov 2023 16:38:03 +0000 Subject: [PATCH 086/106] feat: exception handling --- src/Utopia/Messaging/Adapters/SMS/GEOSMS.php | 21 +++++++++++++------ .../Adapters/SMS/GEOSMS/CallingCode.php | 2 +- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php b/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php index a48b3b91..190db71a 100644 --- a/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php +++ b/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php @@ -38,18 +38,27 @@ protected function process(SMS $message): string { $recipientsByCallingCode = $this->groupRecipientsByCallingCode($message->getTo()); $responses = []; + $errors = []; foreach ($recipientsByCallingCode as $callingCode => $recipients) { $adapter = isset($this->localAdapters[$callingCode]) ? $this->localAdapters[$callingCode] : $this->defaultAdapter; - $responses[] = $adapter->send(new SMS( - to: $recipients, - content: $message->getContent(), - from: $message->getFrom(), - attachments: $message->getAttachments() - )); + try { + $responses[] = $adapter->send(new SMS( + to: $recipients, + content: $message->getContent(), + from: $message->getFrom(), + attachments: $message->getAttachments() + )); + } catch (\Exception $e) { + $errors[] = $e; + } + } + + if (count($errors) > 0) { + throw new \Exception('Failed to send SMS to some recipients', 0, $errors[0]); } return $responses[0]; diff --git a/src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php b/src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php index b63c079d..836264bd 100644 --- a/src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php +++ b/src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php @@ -577,7 +577,7 @@ public static function fromPhoneNumber($number): ?string { $digits = str_replace(['+', ' ', '(', ')', '-'], '', $number); - // International call prefix is usually 00 or 011 + // Remove international call prefix, usually `00` or `011` // https://en.wikipedia.org/wiki/List_of_international_call_prefixes $digits = preg_replace('/^00|^011/', '', $digits); From 5e2f0a26b6a4ce611431fb227627a200bb8190a0 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Wed, 8 Nov 2023 19:14:30 +0000 Subject: [PATCH 087/106] test: msg91 --- tests/e2e/SMS/Msg91Test.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/e2e/SMS/Msg91Test.php b/tests/e2e/SMS/Msg91Test.php index 61ec35f0..514847d5 100644 --- a/tests/e2e/SMS/Msg91Test.php +++ b/tests/e2e/SMS/Msg91Test.php @@ -24,5 +24,6 @@ public function testSendSMS() $result = \json_decode($response, true); $this->assertEquals('success', $result['type']); + $this->assertEquals('Test Content', $result['message']); } } From 67da6a3f95357f09bfd5222d75c9f064cf5052ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=B7=E5=8D=8E=20=E5=88=98?= Date: Wed, 8 Nov 2023 22:12:26 +0000 Subject: [PATCH 088/106] chore: update tests --- tests/e2e/SMS/Msg91Test.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/e2e/SMS/Msg91Test.php b/tests/e2e/SMS/Msg91Test.php index 514847d5..680112f8 100644 --- a/tests/e2e/SMS/Msg91Test.php +++ b/tests/e2e/SMS/Msg91Test.php @@ -22,6 +22,7 @@ public function testSendSMS() $response = $sender->send($message); $result = \json_decode($response, true); + var_dump($response); $this->assertEquals('success', $result['type']); $this->assertEquals('Test Content', $result['message']); From 4ee281401dca91c1070cf899c5bbee6ddb59f4ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=B7=E5=8D=8E=20=E5=88=98?= Date: Wed, 8 Nov 2023 22:52:10 +0000 Subject: [PATCH 089/106] chore: remove checks for message assertion --- tests/e2e/SMS/Msg91Test.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/e2e/SMS/Msg91Test.php b/tests/e2e/SMS/Msg91Test.php index 680112f8..61ec35f0 100644 --- a/tests/e2e/SMS/Msg91Test.php +++ b/tests/e2e/SMS/Msg91Test.php @@ -22,9 +22,7 @@ public function testSendSMS() $response = $sender->send($message); $result = \json_decode($response, true); - var_dump($response); $this->assertEquals('success', $result['type']); - $this->assertEquals('Test Content', $result['message']); } } From b5b64c32003beec3ac3902fbb625bcc513abb19b Mon Sep 17 00:00:00 2001 From: wess Date: Wed, 8 Nov 2023 18:44:43 -0800 Subject: [PATCH 090/106] Formatting --- src/Utopia/Messaging/Adapters/SMS/Msg91.php | 2 +- tests/e2e/SMS/Msg91Test.php | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/Msg91.php b/src/Utopia/Messaging/Adapters/SMS/Msg91.php index 3cd1f081..32bac4ec 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Msg91.php +++ b/src/Utopia/Messaging/Adapters/SMS/Msg91.php @@ -38,7 +38,7 @@ public function getMaxMessagesPerRequest(): int */ protected function process(SMS $message): string { - $to = ['mobiles' => \implode(",", $message->getTo())]; + $to = ['mobiles' => \implode(',', $message->getTo())]; return $this->request( method: 'POST', diff --git a/tests/e2e/SMS/Msg91Test.php b/tests/e2e/SMS/Msg91Test.php index 55ce9c3e..33fad69f 100644 --- a/tests/e2e/SMS/Msg91Test.php +++ b/tests/e2e/SMS/Msg91Test.php @@ -23,9 +23,6 @@ public function testSendSMS() $response = $sender->send($message); $result = \json_decode($response, true); - var_dump($result); - die; - $this->assertEquals('success', $result['type']); // $this->markTestSkipped('Msg91 requires business verification to use template and SMS api.'); From faf88d15f8c1548b02007c8820dca2a9e4dc4ff6 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Thu, 9 Nov 2023 11:42:56 +0000 Subject: [PATCH 091/106] feat: group by adapter --- src/Utopia/Messaging/Adapters/SMS/GEOSMS.php | 78 ++++++++++++----- .../Adapters/SMS/GEOSMS/CallingCode.php | 4 +- tests/e2e/SMS/GEOSMS/CallingCodeTest.php | 2 + tests/e2e/SMS/GEOSMSTest.php | 87 ++++++++++++++++--- 4 files changed, 132 insertions(+), 39 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php b/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php index 190db71a..da2e4ed8 100644 --- a/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php +++ b/src/Utopia/Messaging/Adapters/SMS/GEOSMS.php @@ -34,45 +34,77 @@ public function setLocal(string $callingCode, SMSAdapter $adapter): self return $this; } + protected function filterCallingCodesByAdapter(SMSAdapter $adapter): array + { + $result = []; + + foreach ($this->localAdapters as $callingCode => $localAdapter) { + if ($localAdapter === $adapter) { + $result[] = $callingCode; + } + } + + return $result; + } + protected function process(SMS $message): string { - $recipientsByCallingCode = $this->groupRecipientsByCallingCode($message->getTo()); - $responses = []; - $errors = []; + $results = []; + $recipients = $message->getTo(); - foreach ($recipientsByCallingCode as $callingCode => $recipients) { - $adapter = isset($this->localAdapters[$callingCode]) - ? $this->localAdapters[$callingCode] - : $this->defaultAdapter; + do { + [$nextRecipients, $nextAdapter] = $this->getNextRecipientsAndAdapter($recipients); try { - $responses[] = $adapter->send(new SMS( - to: $recipients, - content: $message->getContent(), - from: $message->getFrom(), - attachments: $message->getAttachments() + $results[$nextAdapter->getName()] = json_decode($nextAdapter->send( + new SMS( + to: $nextRecipients, + content: $message->getContent(), + from: $message->getFrom(), + attachments: $message->getAttachments() + ) )); } catch (\Exception $e) { - $errors[] = $e; + $results[$nextAdapter->getName()] = [ + 'type' => 'error', + 'message' => $e->getMessage(), + ]; } - } - if (count($errors) > 0) { - throw new \Exception('Failed to send SMS to some recipients', 0, $errors[0]); - } + $recipients = \array_diff($recipients, $nextRecipients); + } while (count($recipients) > 0); - return $responses[0]; + return \json_encode($results); } - protected function groupRecipientsByCallingCode(array $recipients): array + protected function getNextRecipientsAndAdapter(array $recipients): array { - $result = []; + $nextRecipients = []; + $nextAdapter = null; foreach ($recipients as $recipient) { - $callingCode = CallingCode::fromPhoneNumber($recipient); - $result[$callingCode][] = $recipient; + $adapter = $this->getAdapterByPhoneNumber($recipient); + + if ($nextAdapter === null || $adapter === $nextAdapter) { + $nextAdapter = $adapter; + $nextRecipients[] = $recipient; + } } - return $result; + return [$nextRecipients, $nextAdapter]; + } + + protected function getAdapterByPhoneNumber(?string $phoneNumber): SMSAdapter + { + $callingCode = CallingCode::fromPhoneNumber($phoneNumber); + if ($callingCode === null || empty($callingCode)) { + return $this->defaultAdapter; + } + + if (isset($this->localAdapters[$callingCode])) { + return $this->localAdapters[$callingCode]; + } + + return $this->defaultAdapter; } } diff --git a/src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php b/src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php index 836264bd..141c9250 100644 --- a/src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php +++ b/src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php @@ -265,6 +265,8 @@ class CallingCode public const NORFOLK_ISLANDS = '672'; + public const NORTH_AMERICA = '1'; + public const NORTHERN_MARIANA_ISLANDS = '670'; public const NORWAY = '47'; @@ -365,8 +367,6 @@ class CallingCode public const URUGUAY = '598'; - public const NORTH_AMERICA = '1'; - public const VANUATU = '678'; public const VENEZUELA = '58'; diff --git a/tests/e2e/SMS/GEOSMS/CallingCodeTest.php b/tests/e2e/SMS/GEOSMS/CallingCodeTest.php index 74f4a60b..7a460d83 100644 --- a/tests/e2e/SMS/GEOSMS/CallingCodeTest.php +++ b/tests/e2e/SMS/GEOSMS/CallingCodeTest.php @@ -10,7 +10,9 @@ public function testFromPhoneNumber() { $this->assertEquals(CallingCode::NORTH_AMERICA, CallingCode::fromPhoneNumber('+11234567890')); $this->assertEquals(CallingCode::INDIA, CallingCode::fromPhoneNumber('+911234567890')); + $this->assertEquals(CallingCode::ISRAEL, CallingCode::fromPhoneNumber('9721234567890')); $this->assertEquals(CallingCode::UNITED_ARAB_EMIRATES, CallingCode::fromPhoneNumber('009711234567890')); $this->assertEquals(CallingCode::UNITED_KINGDOM, CallingCode::fromPhoneNumber('011441234567890')); + $this->assertEquals(null, CallingCode::fromPhoneNumber('2')); } } diff --git a/tests/e2e/SMS/GEOSMSTest.php b/tests/e2e/SMS/GEOSMSTest.php index 26b0794e..d635ca45 100644 --- a/tests/e2e/SMS/GEOSMSTest.php +++ b/tests/e2e/SMS/GEOSMSTest.php @@ -12,8 +12,8 @@ class GEOSMSTest extends Base public function testSendSMSUsingDefaultAdapter() { $defaultAdapterMock = $this->createMock(SMSAdapter::class); - $defaultAdapterMock->method('getMaxMessagesPerRequest') - ->willReturn(1); + $defaultAdapterMock->method('getName') + ->willReturn('default'); $defaultAdapterMock->method('send') ->willReturn(json_encode(['status' => 'success'])); @@ -28,26 +28,85 @@ public function testSendSMSUsingDefaultAdapter() from: $from ); - $result = json_decode($adapter->send($message)); + $result = json_decode($adapter->send($message), true); - $this->assertEquals('success', $result->status); + $this->assertEquals(1, count($result)); + $this->assertEquals('success', $result['default']['status']); } public function testSendSMSUsingLocalAdapter() { $defaultAdapterMock = $this->createMock(SMSAdapter::class); - $defaultAdapterMock->method('getMaxMessagesPerRequest') - ->willReturn(1); $localAdapterMock = $this->createMock(SMSAdapter::class); - $localAdapterMock->method('getMaxMessagesPerRequest') - ->willReturn(1); + $localAdapterMock->method('getName') + ->willReturn('local'); $localAdapterMock->method('send') - ->willReturn(json_encode(['status' => 'success', 'adapter' => 'local'])); + ->willReturn(json_encode(['status' => 'success'])); + + $adapter = new GEOSMS($defaultAdapterMock); + $adapter->setLocal(CallingCode::INDIA, $localAdapterMock); + + $to = ['+911234567890']; + $from = 'Sender'; + + $message = new SMS( + to: $to, + content: 'Test Content', + from: $from + ); + + $result = json_decode($adapter->send($message), true); + + $this->assertEquals(1, count($result)); + $this->assertEquals('success', $result['local']['status']); + } + + public function testSendSMSUsingLocalAdapterAndDefault() + { + $defaultAdapterMock = $this->createMock(SMSAdapter::class); + $defaultAdapterMock->method('getName') + ->willReturn('default'); + $defaultAdapterMock->method('send') + ->willReturn(json_encode(['status' => 'success'])); + $localAdapterMock = $this->createMock(SMSAdapter::class); + $localAdapterMock->method('getName') + ->willReturn('local'); + $localAdapterMock->method('send') + ->willReturn(json_encode(['status' => 'success'])); + + $adapter = new GEOSMS($defaultAdapterMock); + $adapter->setLocal(CallingCode::INDIA, $localAdapterMock); + + $to = ['+911234567890', '+11234567890']; + $from = 'Sender'; + + $message = new SMS( + to: $to, + content: 'Test Content', + from: $from + ); + + $result = json_decode($adapter->send($message), true); + + $this->assertEquals(2, count($result)); + $this->assertEquals('success', $result['local']['status']); + $this->assertEquals('success', $result['default']['status']); + } + + public function testSendSMSUsingGroupedLocalAdapter() + { + $defaultAdapterMock = $this->createMock(SMSAdapter::class); + $localAdapterMock = $this->createMock(SMSAdapter::class); + $localAdapterMock->method('getName') + ->willReturn('local'); + $localAdapterMock->method('send') + ->willReturn(json_encode(['status' => 'success'])); $adapter = new GEOSMS($defaultAdapterMock); - $adapter->setLocal(CallingCode::UNITED_KINGDOM, $localAdapterMock); + $adapter->setLocal(CallingCode::INDIA, $localAdapterMock); + $adapter->setLocal(CallingCode::NORTH_AMERICA, $localAdapterMock); - $to = ['+441234567890']; + $to = ['+911234567890', '+11234567890']; $from = 'Sender'; $message = new SMS( @@ -56,9 +115,9 @@ public function testSendSMSUsingLocalAdapter() from: $from ); - $result = json_decode($adapter->send($message)); + $result = json_decode($adapter->send($message), true); - $this->assertEquals('success', $result->status); - $this->assertEquals('local', $result->adapter); + $this->assertEquals(1, count($result)); + $this->assertEquals('success', $result['local']['status']); } } From 537aab3ae365f37b406a0b885b12fc45afe138b6 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Thu, 9 Nov 2023 12:13:44 +0000 Subject: [PATCH 092/106] chore: revert msg91 --- tests/e2e/SMS/Msg91Test.php | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/tests/e2e/SMS/Msg91Test.php b/tests/e2e/SMS/Msg91Test.php index 61ec35f0..df90f4c4 100644 --- a/tests/e2e/SMS/Msg91Test.php +++ b/tests/e2e/SMS/Msg91Test.php @@ -12,17 +12,19 @@ class Msg91Test extends Base */ public function testSendSMS() { - $sender = new Msg91(getenv('MSG_91_SENDER_ID'), getenv('MSG_91_AUTH_KEY')); + // $sender = new Msg91(getenv('MSG_91_SENDER_ID'), getenv('MSG_91_AUTH_KEY')); - $message = new SMS( - to: [getenv('MSG_91_TO')], - content: 'Test Content', - from: getenv('MSG_91_FROM') - ); + // $message = new SMS( + // to: [getenv('MSG_91_TO')], + // content: 'Test Content', + // from: getenv('MSG_91_FROM') + // ); - $response = $sender->send($message); - $result = \json_decode($response, true); + // $response = $sender->send($message); + // $result = \json_decode($response, true); - $this->assertEquals('success', $result['type']); + // $this->assertEquals('success', $result['type']); + + $this->markTestSkipped('Msg91 requires business verification to use template and SMS api.'); } } From c40274d078cb90c9dbd14b91c248ff972d17612a Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Thu, 9 Nov 2023 12:20:03 +0000 Subject: [PATCH 093/106] fix: msg91 payload --- src/Utopia/Messaging/Adapters/SMS/Msg91.php | 40 ++++++++++----------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/Msg91.php b/src/Utopia/Messaging/Adapters/SMS/Msg91.php index 32bac4ec..c2ce2ff0 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Msg91.php +++ b/src/Utopia/Messaging/Adapters/SMS/Msg91.php @@ -10,6 +10,8 @@ class Msg91 extends SMSAdapter { + private $templateId; + /** * @param string $senderId Msg91 Sender ID * @param string $authKey Msg91 Auth Key @@ -31,6 +33,13 @@ public function getMaxMessagesPerRequest(): int return 1000; } + public function setTemplate(string $templateId): self + { + $this->templateId = $templateId; + + return $this; + } + /** * {@inheritdoc} * @@ -38,7 +47,13 @@ public function getMaxMessagesPerRequest(): int */ protected function process(SMS $message): string { - $to = ['mobiles' => \implode(',', $message->getTo())]; + $recipients = []; + foreach ($message->getTo() as $recipient) { + $recipients[] = [ + 'mobiles' => $recipient, + 'content' => $message->getContent(), + ]; + } return $this->request( method: 'POST', @@ -49,28 +64,9 @@ protected function process(SMS $message): string ], body: \json_encode([ 'sender' => $this->senderId, - 'otp' => $message->getContent(), - 'flow_id' => $message->getFrom(), - 'recipients' => [$to], + 'template_id' => $this->templateId, + 'recipients' => $recipients, ]), ); } - - private function addTemplate(string $content, string $senderId, string $templateName, string $smsType = 'NORMAL') - { - return $this->request( - method: 'POST', - url: 'https://control.msg91.com/api/v5/sms/addTemplate', - headers: [ - 'content-type: application/json', - "authkey: {$this->authKey}", - ], - body: \json_encode([ - 'template' => $content, - 'sender_id' => $senderId, - 'template_name' => $templateName, - 'smsType' => $smsType, - ]) - ); - } } From fd88522db3cb852aa62af3b60790510cef9f8f89 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Thu, 9 Nov 2023 12:24:48 +0000 Subject: [PATCH 094/106] test: fix msg91 --- tests/e2e/SMS/Msg91Test.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/e2e/SMS/Msg91Test.php b/tests/e2e/SMS/Msg91Test.php index 33fad69f..6849b061 100644 --- a/tests/e2e/SMS/Msg91Test.php +++ b/tests/e2e/SMS/Msg91Test.php @@ -13,18 +13,17 @@ class Msg91Test extends Base public function testSendSMS() { $sender = new Msg91(getenv('MSG_91_SENDER_ID'), getenv('MSG_91_AUTH_KEY')); + $sender->setTemplate(getenv('MSG_91_FROM')); $message = new SMS( to: [getenv('MSG_91_TO')], content: 'Test Content', - from: getenv('MSG_91_FROM') ); $response = $sender->send($message); $result = \json_decode($response, true); $this->assertEquals('success', $result['type']); - - // $this->markTestSkipped('Msg91 requires business verification to use template and SMS api.'); + $this->assertNotEmpty($result['message']); } } From fee654ef61160e92350551e0081baac857a6a268 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Thu, 9 Nov 2023 16:17:55 +0000 Subject: [PATCH 095/106] feat: add otp variable --- src/Utopia/Messaging/Adapters/SMS/Msg91.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Utopia/Messaging/Adapters/SMS/Msg91.php b/src/Utopia/Messaging/Adapters/SMS/Msg91.php index c2ce2ff0..f21ddbf6 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Msg91.php +++ b/src/Utopia/Messaging/Adapters/SMS/Msg91.php @@ -52,6 +52,7 @@ protected function process(SMS $message): string $recipients[] = [ 'mobiles' => $recipient, 'content' => $message->getContent(), + 'otp' => $message->getContent(), ]; } From 28f059927eed9c8e1b9d4317431a66ee34a34142 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 10 Nov 2023 12:21:58 +1300 Subject: [PATCH 096/106] Refactor `App` namespace to `Chat` --- src/Utopia/Messaging/Adapter/{App => Chat}/Discord.php | 2 +- tests/Messaging/Adapter/App/DiscordTest.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename src/Utopia/Messaging/Adapter/{App => Chat}/Discord.php (98%) diff --git a/src/Utopia/Messaging/Adapter/App/Discord.php b/src/Utopia/Messaging/Adapter/Chat/Discord.php similarity index 98% rename from src/Utopia/Messaging/Adapter/App/Discord.php rename to src/Utopia/Messaging/Adapter/Chat/Discord.php index af3582ab..7b0deea6 100644 --- a/src/Utopia/Messaging/Adapter/App/Discord.php +++ b/src/Utopia/Messaging/Adapter/Chat/Discord.php @@ -1,6 +1,6 @@ Date: Fri, 10 Nov 2023 19:38:03 +1300 Subject: [PATCH 097/106] Stan fixes --- README.md | 10 ++++---- src/Utopia/Messaging/Adapter/SMS/GEOSMS.php | 23 ++++++++++++++----- .../Adapter/SMS/GEOSMS/CallingCode.php | 4 ++-- .../Adapter/SMS/GEOSMS/CallingCodeTest.php | 7 +++--- tests/Messaging/Adapter/SMS/GEOSMSTest.php | 17 +++++++------- 5 files changed, 37 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index d745b630..363d928e 100644 --- a/README.md +++ b/README.md @@ -21,8 +21,8 @@ composer require utopia-php/messaging send($message); send($message); + */ + protected array $localAdapters = []; public function __construct(SMSAdapter $defaultAdapter) { @@ -34,6 +37,10 @@ public function setLocal(string $callingCode, SMSAdapter $adapter): self return $this; } + /** + * @param SMSAdapter $adapter + * @return array + */ protected function filterCallingCodesByAdapter(SMSAdapter $adapter): array { $result = []; @@ -77,6 +84,10 @@ protected function process(SMS $message): string return \json_encode($results); } + /** + * @param array $recipients + * @return array|SMSAdapter> + */ protected function getNextRecipientsAndAdapter(array $recipients): array { $nextRecipients = []; @@ -97,7 +108,7 @@ protected function getNextRecipientsAndAdapter(array $recipients): array protected function getAdapterByPhoneNumber(?string $phoneNumber): SMSAdapter { $callingCode = CallingCode::fromPhoneNumber($phoneNumber); - if ($callingCode === null || empty($callingCode)) { + if (empty($callingCode)) { return $this->defaultAdapter; } diff --git a/src/Utopia/Messaging/Adapter/SMS/GEOSMS/CallingCode.php b/src/Utopia/Messaging/Adapter/SMS/GEOSMS/CallingCode.php index 141c9250..35e8fe0d 100644 --- a/src/Utopia/Messaging/Adapter/SMS/GEOSMS/CallingCode.php +++ b/src/Utopia/Messaging/Adapter/SMS/GEOSMS/CallingCode.php @@ -1,6 +1,6 @@ true, ]; - public static function fromPhoneNumber($number): ?string + public static function fromPhoneNumber(string $number): ?string { $digits = str_replace(['+', ' ', '(', ')', '-'], '', $number); diff --git a/tests/Messaging/Adapter/SMS/GEOSMS/CallingCodeTest.php b/tests/Messaging/Adapter/SMS/GEOSMS/CallingCodeTest.php index 7a460d83..bf64abf5 100644 --- a/tests/Messaging/Adapter/SMS/GEOSMS/CallingCodeTest.php +++ b/tests/Messaging/Adapter/SMS/GEOSMS/CallingCodeTest.php @@ -1,12 +1,13 @@ assertEquals(CallingCode::NORTH_AMERICA, CallingCode::fromPhoneNumber('+11234567890')); $this->assertEquals(CallingCode::INDIA, CallingCode::fromPhoneNumber('+911234567890')); diff --git a/tests/Messaging/Adapter/SMS/GEOSMSTest.php b/tests/Messaging/Adapter/SMS/GEOSMSTest.php index d635ca45..d10b7799 100644 --- a/tests/Messaging/Adapter/SMS/GEOSMSTest.php +++ b/tests/Messaging/Adapter/SMS/GEOSMSTest.php @@ -1,15 +1,16 @@ createMock(SMSAdapter::class); $defaultAdapterMock->method('getName') @@ -34,7 +35,7 @@ public function testSendSMSUsingDefaultAdapter() $this->assertEquals('success', $result['default']['status']); } - public function testSendSMSUsingLocalAdapter() + public function testSendSMSUsingLocalAdapter(): void { $defaultAdapterMock = $this->createMock(SMSAdapter::class); $localAdapterMock = $this->createMock(SMSAdapter::class); @@ -61,7 +62,7 @@ public function testSendSMSUsingLocalAdapter() $this->assertEquals('success', $result['local']['status']); } - public function testSendSMSUsingLocalAdapterAndDefault() + public function testSendSMSUsingLocalAdapterAndDefault(): void { $defaultAdapterMock = $this->createMock(SMSAdapter::class); $defaultAdapterMock->method('getName') @@ -93,7 +94,7 @@ public function testSendSMSUsingLocalAdapterAndDefault() $this->assertEquals('success', $result['default']['status']); } - public function testSendSMSUsingGroupedLocalAdapter() + public function testSendSMSUsingGroupedLocalAdapter(): void { $defaultAdapterMock = $this->createMock(SMSAdapter::class); $localAdapterMock = $this->createMock(SMSAdapter::class); From d38ab4a55acd95a4a6e7388be4087d998d666d87 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 10 Nov 2023 19:42:01 +1300 Subject: [PATCH 098/106] Lint --- src/Utopia/Messaging/Adapter/SMS/GEOSMS.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Utopia/Messaging/Adapter/SMS/GEOSMS.php b/src/Utopia/Messaging/Adapter/SMS/GEOSMS.php index 12b627e3..b3f66429 100644 --- a/src/Utopia/Messaging/Adapter/SMS/GEOSMS.php +++ b/src/Utopia/Messaging/Adapter/SMS/GEOSMS.php @@ -38,7 +38,6 @@ public function setLocal(string $callingCode, SMSAdapter $adapter): self } /** - * @param SMSAdapter $adapter * @return array */ protected function filterCallingCodesByAdapter(SMSAdapter $adapter): array @@ -85,7 +84,7 @@ protected function process(SMS $message): string } /** - * @param array $recipients + * @param array $recipients * @return array|SMSAdapter> */ protected function getNextRecipientsAndAdapter(array $recipients): array From 40e24843500e6eb65702318eb9568f8e9e4c25f3 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 10 Nov 2023 20:01:35 +1300 Subject: [PATCH 099/106] Test downgrade PHPUnit --- composer.json | 2 +- composer.lock | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index a422b9f3..f76d03af 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ }, "require-dev": { "ext-openssl": "*", - "phpunit/phpunit": "9.6.*", + "phpunit/phpunit": "9.6.10", "phpmailer/phpmailer": "6.8.*", "laravel/pint": "1.13.*", "phpstan/phpstan": "1.10.*" diff --git a/composer.lock b/composer.lock index 80172ea8..d07a8bfb 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "0afb85e3cb0d85adca85fb5d778af118", + "content-hash": "1acdc1e8f88c00fae7fc271daa90a725", "packages": [], "packages-dev": [ { @@ -832,16 +832,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.13", + "version": "9.6.10", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "f3d767f7f9e191eab4189abe41ab37797e30b1be" + "reference": "a6d351645c3fe5a30f5e86be6577d946af65a328" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f3d767f7f9e191eab4189abe41ab37797e30b1be", - "reference": "f3d767f7f9e191eab4189abe41ab37797e30b1be", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a6d351645c3fe5a30f5e86be6577d946af65a328", + "reference": "a6d351645c3fe5a30f5e86be6577d946af65a328", "shasum": "" }, "require": { @@ -856,7 +856,7 @@ "phar-io/manifest": "^2.0.3", "phar-io/version": "^3.0.2", "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.28", + "phpunit/php-code-coverage": "^9.2.13", "phpunit/php-file-iterator": "^3.0.5", "phpunit/php-invoker": "^3.1.1", "phpunit/php-text-template": "^2.0.3", @@ -915,7 +915,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.13" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.10" }, "funding": [ { @@ -931,7 +931,7 @@ "type": "tidelift" } ], - "time": "2023-09-19T05:39:22+00:00" + "time": "2023-07-10T04:04:23+00:00" }, { "name": "sebastian/cli-parser", From d327e235e9faf5477995363b3d8392e7afca5d30 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Fri, 10 Nov 2023 09:46:30 +0000 Subject: [PATCH 100/106] feat: trim + from msg91 numbers --- src/Utopia/Messaging/Adapters/SMS/Msg91.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/Msg91.php b/src/Utopia/Messaging/Adapters/SMS/Msg91.php index f21ddbf6..5a217a30 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Msg91.php +++ b/src/Utopia/Messaging/Adapters/SMS/Msg91.php @@ -50,7 +50,7 @@ protected function process(SMS $message): string $recipients = []; foreach ($message->getTo() as $recipient) { $recipients[] = [ - 'mobiles' => $recipient, + 'mobiles' => \ltrim($recipient, '+'), 'content' => $message->getContent(), 'otp' => $message->getContent(), ]; From b4d370475cd3afdf4b5570572047f83eace4e1fa Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 14 Nov 2023 13:04:26 +1300 Subject: [PATCH 101/106] Update src/Utopia/Messaging/Adapters/SMS/Msg91.php --- src/Utopia/Messaging/Adapters/SMS/Msg91.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/Msg91.php b/src/Utopia/Messaging/Adapters/SMS/Msg91.php index 5a217a30..ed89ccb2 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Msg91.php +++ b/src/Utopia/Messaging/Adapters/SMS/Msg91.php @@ -10,7 +10,7 @@ class Msg91 extends SMSAdapter { - private $templateId; + private string $templateId; /** * @param string $senderId Msg91 Sender ID From b0a314f743d5b0ea5604c6b86ef7cf3c6eedf8e4 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Mon, 20 Nov 2023 10:03:47 +0000 Subject: [PATCH 102/106] feat: add sms from override to constructor --- src/Utopia/Messaging/Adapters/SMS/Clickatell.php | 3 ++- src/Utopia/Messaging/Adapters/SMS/Infobip.php | 5 +++-- src/Utopia/Messaging/Adapters/SMS/Plivo.php | 5 +++-- src/Utopia/Messaging/Adapters/SMS/Seven.php | 5 +++-- src/Utopia/Messaging/Adapters/SMS/Sinch.php | 5 +++-- src/Utopia/Messaging/Adapters/SMS/Telnyx.php | 3 ++- src/Utopia/Messaging/Adapters/SMS/TextMagic.php | 5 +++-- src/Utopia/Messaging/Adapters/SMS/Twilio.php | 5 +++-- src/Utopia/Messaging/Adapters/SMS/Vonage.php | 5 +++-- 9 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/SMS/Clickatell.php b/src/Utopia/Messaging/Adapters/SMS/Clickatell.php index 4e302b32..1d004713 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Clickatell.php +++ b/src/Utopia/Messaging/Adapters/SMS/Clickatell.php @@ -14,6 +14,7 @@ class Clickatell extends SMSAdapter */ public function __construct( private string $apiKey, + private ?string $from = null ) { } @@ -43,7 +44,7 @@ protected function process(SMS $message): string ], body: \json_encode([ 'content' => $message->getContent(), - 'from' => $message->getFrom(), + 'from' => $this->from ?? $message->getFrom(), 'to' => $message->getTo(), ]), ); diff --git a/src/Utopia/Messaging/Adapters/SMS/Infobip.php b/src/Utopia/Messaging/Adapters/SMS/Infobip.php index 9d1a584b..f18a62f2 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Infobip.php +++ b/src/Utopia/Messaging/Adapters/SMS/Infobip.php @@ -15,7 +15,8 @@ class Infobip extends SMSAdapter */ public function __construct( private string $apiBaseUrl, - private string $apiKey + private string $apiKey, + private ?string $from = null ) { } @@ -48,7 +49,7 @@ protected function process(SMS $message): string body: \json_encode([ 'messages' => [ 'text' => $message->getContent(), - 'from' => $message->getFrom(), + 'from' => $this->from ?? $message->getFrom(), 'destinations' => $to, ], ]), diff --git a/src/Utopia/Messaging/Adapters/SMS/Plivo.php b/src/Utopia/Messaging/Adapters/SMS/Plivo.php index 4f923fdf..b16642a2 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Plivo.php +++ b/src/Utopia/Messaging/Adapters/SMS/Plivo.php @@ -15,7 +15,8 @@ class Plivo extends SMSAdapter */ public function __construct( private string $authId, - private string $authToken + private string $authToken, + private ?string $from = null ) { } @@ -44,7 +45,7 @@ protected function process(SMS $message): string ], body: \http_build_query([ 'text' => $message->getContent(), - 'src' => $message->getFrom() ?? 'Plivo', + 'src' => $this->from ?? $message->getFrom() ?? 'Plivo', 'dst' => \implode('<', $message->getTo()), ]), ); diff --git a/src/Utopia/Messaging/Adapters/SMS/Seven.php b/src/Utopia/Messaging/Adapters/SMS/Seven.php index 383bdf94..2b3af28e 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Seven.php +++ b/src/Utopia/Messaging/Adapters/SMS/Seven.php @@ -13,7 +13,8 @@ class Seven extends SMSAdapter * @param string $apiKey Seven API token */ public function __construct( - private string $apiKey + private string $apiKey, + private ?string $from = null ) { } @@ -42,7 +43,7 @@ protected function process(SMS $message): string 'content-type: application/json', ], body: \json_encode([ - 'from' => $message->getFrom(), + 'from' => $this->from ?? $message->getFrom(), 'to' => \implode(',', $message->getTo()), 'text' => $message->getContent(), ]), diff --git a/src/Utopia/Messaging/Adapters/SMS/Sinch.php b/src/Utopia/Messaging/Adapters/SMS/Sinch.php index ac0dc0b3..7c30b363 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Sinch.php +++ b/src/Utopia/Messaging/Adapters/SMS/Sinch.php @@ -15,7 +15,8 @@ class Sinch extends SMSAdapter */ public function __construct( private string $servicePlanId, - private string $apiToken + private string $apiToken, + private ?string $from = null ) { } @@ -46,7 +47,7 @@ protected function process(SMS $message): string 'content-type: application/json', ], body: \json_encode([ - 'from' => $message->getFrom(), + 'from' => $this->from ?? $message->getFrom(), 'to' => $to, 'body' => $message->getContent(), ]), diff --git a/src/Utopia/Messaging/Adapters/SMS/Telnyx.php b/src/Utopia/Messaging/Adapters/SMS/Telnyx.php index 431736b5..06b262d2 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Telnyx.php +++ b/src/Utopia/Messaging/Adapters/SMS/Telnyx.php @@ -12,6 +12,7 @@ class Telnyx extends SMSAdapter */ public function __construct( private string $apiKey, + private ?string $from = null ) { } @@ -41,7 +42,7 @@ protected function process(SMS $message): string ], body: \json_encode([ 'text' => $message->getContent(), - 'from' => $message->getFrom(), + 'from' => $this->from ?? $message->getFrom(), 'to' => $message->getTo()[0], ]), ); diff --git a/src/Utopia/Messaging/Adapters/SMS/TextMagic.php b/src/Utopia/Messaging/Adapters/SMS/TextMagic.php index 68fb4e37..bd74102c 100644 --- a/src/Utopia/Messaging/Adapters/SMS/TextMagic.php +++ b/src/Utopia/Messaging/Adapters/SMS/TextMagic.php @@ -16,7 +16,8 @@ class TextMagic extends SMSAdapter */ public function __construct( private string $username, - private string $apiKey + private string $apiKey, + private ?string $from = null ) { } @@ -51,7 +52,7 @@ protected function process(SMS $message): string ], body: \http_build_query([ 'text' => $message->getContent(), - 'from' => \ltrim($message->getFrom(), '+'), + 'from' => \ltrim($this->from ?? $message->getFrom(), '+'), 'phones' => \implode(',', $to), ]), ); diff --git a/src/Utopia/Messaging/Adapters/SMS/Twilio.php b/src/Utopia/Messaging/Adapters/SMS/Twilio.php index 9f28ff2c..bbcdd854 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Twilio.php +++ b/src/Utopia/Messaging/Adapters/SMS/Twilio.php @@ -13,7 +13,8 @@ class Twilio extends SMSAdapter */ public function __construct( private string $accountSid, - private string $authToken + private string $authToken, + private ?string $from = null ) { } @@ -42,7 +43,7 @@ protected function process(SMS $message): string ], body: \http_build_query([ 'Body' => $message->getContent(), - 'From' => $message->getFrom(), + 'From' => $this->from ?? $message->getFrom(), 'To' => $message->getTo()[0], ]), ); diff --git a/src/Utopia/Messaging/Adapters/SMS/Vonage.php b/src/Utopia/Messaging/Adapters/SMS/Vonage.php index 7ed16714..cdb58c42 100644 --- a/src/Utopia/Messaging/Adapters/SMS/Vonage.php +++ b/src/Utopia/Messaging/Adapters/SMS/Vonage.php @@ -16,7 +16,8 @@ class Vonage extends SMSAdapter */ public function __construct( private string $apiKey, - private string $apiSecret + private string $apiSecret, + private ?string $from = null ) { } @@ -47,7 +48,7 @@ protected function process(SMS $message): string url: 'https://rest.nexmo.com/sms/json', body: \http_build_query([ 'text' => $message->getContent(), - 'from' => $message->getFrom(), + 'from' => $this->from ?? $message->getFrom(), 'to' => $to[0], //\implode(',', $to), 'api_key' => $this->apiKey, 'api_secret' => $this->apiSecret, From 7223f34ec951df85eab1bd8802141154b4f1160e Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 21 Nov 2023 18:50:12 +1300 Subject: [PATCH 103/106] Use default false bool sandbox instead of endpoint param --- src/Utopia/Messaging/Adapters/Push/APNS.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/Push/APNS.php b/src/Utopia/Messaging/Adapters/Push/APNS.php index 56282d83..30fa0368 100644 --- a/src/Utopia/Messaging/Adapters/Push/APNS.php +++ b/src/Utopia/Messaging/Adapters/Push/APNS.php @@ -13,7 +13,7 @@ class APNS extends PushAdapter * @param string $authKeyId * @param string $teamId * @param string $bundleId - * @param string $endpoint + * @param bool $sandbox * @return void */ public function __construct( @@ -21,7 +21,7 @@ public function __construct( private string $authKeyId, private string $teamId, private string $bundleId, - private string $endpoint + private bool $sandbox = false ) { } @@ -98,13 +98,18 @@ private function notify(array $to, array $payload): array ]); $response = ''; + $endpoint = 'api.push.apple.com'; + + if ($this->sandbox) { + $endpoint = 'api.development.push.apple.com'; + } $mh = curl_multi_init(); $handles = []; // Create a handle for each request foreach ($to as $token) { - curl_setopt($ch, CURLOPT_URL, $this->endpoint.'/3/device/'.$token); + curl_setopt($ch, CURLOPT_URL, $endpoint.'/3/device/'.$token); $handle = curl_copy_handle($ch); curl_multi_add_handle($mh, $handle); From 4ba7e302486cf7e1f734d93930566895ebf5c0c1 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 21 Nov 2023 18:53:48 +1300 Subject: [PATCH 104/106] Add https scheme --- src/Utopia/Messaging/Adapters/Push/APNS.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Utopia/Messaging/Adapters/Push/APNS.php b/src/Utopia/Messaging/Adapters/Push/APNS.php index 30fa0368..6c2d0f38 100644 --- a/src/Utopia/Messaging/Adapters/Push/APNS.php +++ b/src/Utopia/Messaging/Adapters/Push/APNS.php @@ -98,10 +98,10 @@ private function notify(array $to, array $payload): array ]); $response = ''; - $endpoint = 'api.push.apple.com'; + $endpoint = 'https://api.push.apple.com'; if ($this->sandbox) { - $endpoint = 'api.development.push.apple.com'; + $endpoint = 'https://api.development.push.apple.com'; } $mh = curl_multi_init(); From 8e49773b7395c7ad74ba572a2148068891aa0968 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 21 Nov 2023 19:03:46 +1300 Subject: [PATCH 105/106] Format --- composer.json | 2 +- composer.lock | 30 +++++++++---------- src/Utopia/Messaging/Adapter.php | 10 +------ .../Messaging/Adapters/Email/Mailgun.php | 4 --- .../Messaging/Adapters/Email/Sendgrid.php | 6 ---- src/Utopia/Messaging/Adapters/Push/APNS.php | 22 ++++---------- src/Utopia/Messaging/Adapters/Push/FCM.php | 4 --- src/Utopia/Messaging/Messages/Email.php | 18 ----------- src/Utopia/Messaging/Messages/Push.php | 30 ------------------- src/Utopia/Messaging/Messages/SMS.php | 12 -------- tests/e2e/Email/EmailTest.php | 3 +- tests/e2e/Email/MailgunTest.php | 3 +- tests/e2e/Email/SendgridTest.php | 2 +- tests/e2e/Push/APNSTest.php | 2 +- tests/e2e/Push/FCMTest.php | 3 +- tests/e2e/SMS/GEOSMS/CallingCodeTest.php | 3 +- tests/e2e/SMS/GEOSMSTest.php | 3 +- tests/e2e/SMS/Msg91Test.php | 3 +- tests/e2e/SMS/SMSTest.php | 3 +- tests/e2e/SMS/TelesignTest.php | 4 ++- tests/e2e/SMS/TelnyxTest.php | 3 +- tests/e2e/SMS/TwilioTest.php | 3 +- tests/e2e/SMS/VonageTest.php | 3 +- 23 files changed, 47 insertions(+), 129 deletions(-) diff --git a/composer.json b/composer.json index bac108a5..8f77b494 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ "require-dev": { "phpunit/phpunit": "9.6.*", "phpmailer/phpmailer": "6.8.*", - "laravel/pint": "^1.2" + "laravel/pint": "1.13.*" }, "config": { "platform": { diff --git a/composer.lock b/composer.lock index 9f6b978b..835860e3 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "5ecbd865cbd7f14e7819fb79643573be", + "content-hash": "31345eedeb45973edbfc61a2c6b722b6", "packages": [], "packages-dev": [ { @@ -79,16 +79,16 @@ }, { "name": "laravel/pint", - "version": "v1.2.0", + "version": "v1.13.6", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "1d276e4c803397a26cc337df908f55c2a4e90d86" + "reference": "3e3d2ab01c7d8b484c18e6100ecf53639c744fa7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/1d276e4c803397a26cc337df908f55c2a4e90d86", - "reference": "1d276e4c803397a26cc337df908f55c2a4e90d86", + "url": "https://api.github.com/repos/laravel/pint/zipball/3e3d2ab01c7d8b484c18e6100ecf53639c744fa7", + "reference": "3e3d2ab01c7d8b484c18e6100ecf53639c744fa7", "shasum": "" }, "require": { @@ -96,16 +96,16 @@ "ext-mbstring": "*", "ext-tokenizer": "*", "ext-xml": "*", - "php": "^8.0" + "php": "^8.1.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.11.0", - "illuminate/view": "^9.27", - "laravel-zero/framework": "^9.1.3", - "mockery/mockery": "^1.5.0", - "nunomaduro/larastan": "^2.2", - "nunomaduro/termwind": "^1.14.0", - "pestphp/pest": "^1.22.1" + "friendsofphp/php-cs-fixer": "^3.38.0", + "illuminate/view": "^10.30.1", + "laravel-zero/framework": "^10.3.0", + "mockery/mockery": "^1.6.6", + "nunomaduro/larastan": "^2.6.4", + "nunomaduro/termwind": "^1.15.1", + "pestphp/pest": "^2.24.2" }, "bin": [ "builds/pint" @@ -141,7 +141,7 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2022-09-13T15:07:15+00:00" + "time": "2023-11-07T17:59:57+00:00" }, { "name": "myclabs/deep-copy", @@ -1898,5 +1898,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/src/Utopia/Messaging/Adapter.php b/src/Utopia/Messaging/Adapter.php index 60a909ef..f616600b 100644 --- a/src/Utopia/Messaging/Adapter.php +++ b/src/Utopia/Messaging/Adapter.php @@ -6,29 +6,21 @@ abstract class Adapter { /** * Get the name of the adapter. - * - * @return string */ abstract public function getName(): string; /** * Get the type of the adapter. - * - * @return string */ abstract public function getType(): string; /** * Get the type of the message the adapter can send. - * - * @return string */ abstract public function getMessageType(): string; /** * Get the maximum number of messages that can be sent in a single request. - * - * @return int */ abstract public function getMaxMessagesPerRequest(): int; @@ -55,7 +47,7 @@ protected function request( string $method, string $url, array $headers = [], - ?string $body = null, + string $body = null, ): string { $ch = \curl_init(); diff --git a/src/Utopia/Messaging/Adapters/Email/Mailgun.php b/src/Utopia/Messaging/Adapters/Email/Mailgun.php index 4e3882e8..09ad8895 100644 --- a/src/Utopia/Messaging/Adapters/Email/Mailgun.php +++ b/src/Utopia/Messaging/Adapters/Email/Mailgun.php @@ -20,8 +20,6 @@ public function __construct( /** * Get adapter name. - * - * @return string */ public function getName(): string { @@ -30,8 +28,6 @@ public function getName(): string /** * Get adapter description. - * - * @return int */ public function getMaxMessagesPerRequest(): int { diff --git a/src/Utopia/Messaging/Adapters/Email/Sendgrid.php b/src/Utopia/Messaging/Adapters/Email/Sendgrid.php index e91c31cc..18dccc20 100644 --- a/src/Utopia/Messaging/Adapters/Email/Sendgrid.php +++ b/src/Utopia/Messaging/Adapters/Email/Sendgrid.php @@ -17,8 +17,6 @@ public function __construct(private string $apiKey) /** * Get adapter name. - * - * @return string */ public function getName(): string { @@ -27,8 +25,6 @@ public function getName(): string /** * Get max messages per request. - * - * @return int */ public function getMaxMessagesPerRequest(): int { @@ -38,8 +34,6 @@ public function getMaxMessagesPerRequest(): int /** * {@inheritdoc} * - * @param Email $message - * @return string * * @throws Exception */ diff --git a/src/Utopia/Messaging/Adapters/Push/APNS.php b/src/Utopia/Messaging/Adapters/Push/APNS.php index 6c2d0f38..f501daab 100644 --- a/src/Utopia/Messaging/Adapters/Push/APNS.php +++ b/src/Utopia/Messaging/Adapters/Push/APNS.php @@ -9,26 +9,19 @@ class APNS extends PushAdapter { /** - * @param string $authKey - * @param string $authKeyId - * @param string $teamId - * @param string $bundleId - * @param bool $sandbox * @return void */ public function __construct( - private string $authKey, - private string $authKeyId, - private string $teamId, - private string $bundleId, - private bool $sandbox = false + private string $authKey, + private string $authKeyId, + private string $teamId, + private string $bundleId, + private bool $sandbox = false ) { } /** * Get adapter name. - * - * @return string */ public function getName(): string { @@ -37,8 +30,6 @@ public function getName(): string /** * Get max messages per request. - * - * @return int */ public function getMaxMessagesPerRequest(): int { @@ -48,8 +39,6 @@ public function getMaxMessagesPerRequest(): int /** * {@inheritdoc} * - * @param Push $message - * @return string * * @throws Exception */ @@ -184,7 +173,6 @@ function ($value) { /** * Generate JWT. * - * @return string * * @throws Exception */ diff --git a/src/Utopia/Messaging/Adapters/Push/FCM.php b/src/Utopia/Messaging/Adapters/Push/FCM.php index 8a4d8ac2..4a028f62 100644 --- a/src/Utopia/Messaging/Adapters/Push/FCM.php +++ b/src/Utopia/Messaging/Adapters/Push/FCM.php @@ -17,8 +17,6 @@ public function __construct( /** * Get adapter name. - * - * @return string */ public function getName(): string { @@ -27,8 +25,6 @@ public function getName(): string /** * Get max messages per request. - * - * @return int */ public function getMaxMessagesPerRequest(): int { diff --git a/src/Utopia/Messaging/Messages/Email.php b/src/Utopia/Messaging/Messages/Email.php index 21fedeea..545b1d54 100644 --- a/src/Utopia/Messaging/Messages/Email.php +++ b/src/Utopia/Messaging/Messages/Email.php @@ -24,49 +24,31 @@ public function __construct( ) { } - /** - * @return array - */ public function getTo(): array { return $this->to; } - /** - * @return string - */ public function getSubject(): string { return $this->subject; } - /** - * @return string - */ public function getContent(): string { return $this->content; } - /** - * @return string|null - */ public function getFrom(): ?string { return $this->from; } - /** - * @return array|null - */ public function getAttachments(): ?array { return $this->attachments; } - /** - * @return bool - */ public function isHtml(): bool { return $this->html; diff --git a/src/Utopia/Messaging/Messages/Push.php b/src/Utopia/Messaging/Messages/Push.php index 93b8f5d7..337d0fbd 100644 --- a/src/Utopia/Messaging/Messages/Push.php +++ b/src/Utopia/Messaging/Messages/Push.php @@ -32,9 +32,6 @@ public function __construct( ) { } - /** - * @return array - */ public function getTo(): array { return $this->to; @@ -45,73 +42,46 @@ public function getFrom(): ?string return null; } - /** - * @return string - */ public function getTitle(): string { return $this->title; } - /** - * @return string - */ public function getBody(): string { return $this->body; } - /** - * @return array|null - */ public function getData(): ?array { return $this->data; } - /** - * @return string|null - */ public function getAction(): ?string { return $this->action; } - /** - * @return string|null - */ public function getSound(): ?string { return $this->sound; } - /** - * @return string|null - */ public function getIcon(): ?string { return $this->icon; } - /** - * @return string|null - */ public function getColor(): ?string { return $this->color; } - /** - * @return string|null - */ public function getTag(): ?string { return $this->tag; } - /** - * @return string|null - */ public function getBadge(): ?string { return $this->badge; diff --git a/src/Utopia/Messaging/Messages/SMS.php b/src/Utopia/Messaging/Messages/SMS.php index bcb913c0..31be8d99 100644 --- a/src/Utopia/Messaging/Messages/SMS.php +++ b/src/Utopia/Messaging/Messages/SMS.php @@ -14,33 +14,21 @@ public function __construct( ) { } - /** - * @return array - */ public function getTo(): array { return $this->to; } - /** - * @return string - */ public function getContent(): string { return $this->content; } - /** - * @return string|null - */ public function getFrom(): ?string { return $this->from; } - /** - * @return array|null - */ public function getAttachments(): ?array { return $this->attachments; diff --git a/tests/e2e/Email/EmailTest.php b/tests/e2e/Email/EmailTest.php index 40606255..f72fe37e 100644 --- a/tests/e2e/Email/EmailTest.php +++ b/tests/e2e/Email/EmailTest.php @@ -1,7 +1,8 @@ Date: Tue, 21 Nov 2023 23:11:22 +1300 Subject: [PATCH 106/106] Fix missing base imports --- tests/e2e/Email/SendgridTest.php | 1 + tests/e2e/Push/APNSTest.php | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/e2e/Email/SendgridTest.php b/tests/e2e/Email/SendgridTest.php index 5924992d..d2b5ea00 100644 --- a/tests/e2e/Email/SendgridTest.php +++ b/tests/e2e/Email/SendgridTest.php @@ -2,6 +2,7 @@ namespace Tests\E2E\Email; +use Tests\E2E\Base; use Utopia\Messaging\Adapters\Email\Sendgrid; use Utopia\Messaging\Messages\Email; diff --git a/tests/e2e/Push/APNSTest.php b/tests/e2e/Push/APNSTest.php index 4a066132..335449ca 100644 --- a/tests/e2e/Push/APNSTest.php +++ b/tests/e2e/Push/APNSTest.php @@ -2,6 +2,7 @@ namespace Tests\E2E\Push; +use Tests\E2E\Base; use Utopia\Messaging\Adapters\Push\APNS as APNSAdapter; use Utopia\Messaging\Messages\Push;