From 6de775c8b77d625c254629219bbb831b5f53ac12 Mon Sep 17 00:00:00 2001 From: Maxime Renou Date: Fri, 13 Dec 2024 11:52:01 +0100 Subject: [PATCH] init --- .gitignore | 2 + README.md | 92 ++++++++++++++ composer.json | 41 ++++++ config/push.php | 6 + src/PushApi.php | 97 +++++++++++++++ src/PushChannel.php | 29 +++++ src/PushException.php | 5 + src/PushServiceProvider.php | 37 ++++++ src/PushTemplate.php | 296 ++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 605 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 composer.json create mode 100644 config/push.php create mode 100644 src/PushApi.php create mode 100644 src/PushChannel.php create mode 100644 src/PushException.php create mode 100644 src/PushServiceProvider.php create mode 100644 src/PushTemplate.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1ddcf91 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea/ +/vendor/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..aab1029 --- /dev/null +++ b/README.md @@ -0,0 +1,92 @@ +# laravel-push + +The Bluesquare Push package allows you to send Push templates using Laravel notification system. + +## Installation + +First prepare your composer.json: + +``` +composer config repositories.push vcs https://git.bluesquare.io/bluesquare/laravel-push.git -n +``` + +Then install the package: + +```bash +composer require bluesquare/laravel-push +``` + +If you want to customize the config system: + +```bash +php artisan vendor:publish +``` + +Finally, copy your API key from Bluesquare Push (senders section), and add it in your `.env`: + +```bash +PUSH_API_KEY=your_api_key +``` + +You may also want to use your own API: + +```bash +PUSH_API_URL=https://push.bluesquare.io/api/send +``` + +## Usage + +First, create a new notification or use an existing one: + +```bash +php artisan make:notification MyAwesomeNotification +``` + +Add BluescaleMailChannel in the `via()` method: + +```php +return [PushChannel::class]; +``` + +Then, create a 'toTemplate()' method, in which you specify your template fields : + +```php +public function toTemplate($notifiable) +{ + return (new PushTemplate("my-template-slug")) + ->sender("john.doe@gmail.com", "John OPTIONAL") // OPTIONAL + ->replyTo("jean.grey@gmail.com", "Jean OPTIONAL") // OPTIONAL + ->recipients([ + [ + "email" => "elvis@gmail.com", + "name": "Elvis", // OPTIONAL + "parameters": ["key" => "value"] // OPTIONAL + "unsubscribe_url": "https://my-unsubscribe-url.com" // OPTIONAL + ], + // ... + ]) + ->addRecipient("edward@gmail.com") // OPTIONAL + ->addRecipient( + email: "edward@gmail.com", + name: "Edward", // OPTIONAL + parameters: ["key" => "value"], // OPTIONAL + unsubscribe_url: "https://my-unsubscribe-url.com" // OPTIONAL + ) + ->parameters(["key" => "value", "key" => "value"]) // OPTIONAL + ->addParameter("key", "value") // OPTIONAL + ->bulkMode() // OPTIONAL + ->testMode() // OPTIONAL + ->unsubscribeUrl("https://group-unsubscribe-url.com") // OPTIONAL + ; +} +``` + +The $notifiable is automatically added as recipient. + +In your controller, you can now send your template: + +```php +User::first()->notify(new MyAwesomeNotification); +``` + + diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..4e61e91 --- /dev/null +++ b/composer.json @@ -0,0 +1,41 @@ +{ + "name": "bluesquare/laravel-push", + "description": "Send Bluesquare Push templates from your Laravel notifications.", + "keywords": [ + "package", + "bluesquare", + "push", + "mail", + "api", + "template", + "email" + ], + "homepage": "https://git.bluesquare.io/bluesquare/laravel-push", + "license": "proprietary", + "authors": [ + { + "name": "Maxime Renou", + "email": "maxime@bluesquare.io", + "homepage": "https://bluesquare.io/", + "role": "Developer" + } + ], + "minimum-stability": "dev", + "autoload": { + "psr-4": { + "Bluesquare\\Push\\": "src/" + } + }, + "extra": { + "laravel": { + "providers": [ + "PushServiceProvider" + ] + } + }, + "require": { + "guzzlehttp/guzzle": "^7.0.1", + "php": "^7.3 | ^8.0" + }, + "prefer-stable": true +} diff --git a/config/push.php b/config/push.php new file mode 100644 index 0000000..64d8f31 --- /dev/null +++ b/config/push.php @@ -0,0 +1,6 @@ + env('PUSH_API_KEY', null), + 'api_url' => env('PUSH_API_URL', null) +]; diff --git a/src/PushApi.php b/src/PushApi.php new file mode 100644 index 0000000..a614988 --- /dev/null +++ b/src/PushApi.php @@ -0,0 +1,97 @@ +api_key = $api_key; + } + + /** + * @param PushTemplate $template + * @param $notifiable + * @return \Psr\Http\Message\StreamInterface + * @throws PushException + */ + public function send($template, $notifiable): StreamInterface + { + $url = config('push.api_url') ?? 'https://push.bluesquare.io/api/send'; + + $client = new Client(); + + if (is_object($notifiable) && isset($notifiable->email)) { + $notifiable_recipient = false; + $notifiable_email = $notifiable->email; + $recipients = $template->recipients; + + if (count($recipients) > 0) + foreach ($recipients as $recipient) + if (! empty($recipient['email'])) + if ($notifiable_email == $recipient['email']) + $notifiable_recipient = true; + + if (! $notifiable_recipient) + $template->recipients[] = [ + 'email' => $notifiable->email + ]; + } + + $multipart_form = []; + + foreach ($template as $key => $value) { + if ($key == 'attachments') { + foreach ($value as $i => $attachment) { + $multipart_form[] = [ + 'name' => "{$key}[$i]", + 'contents' => file_get_contents($attachment['path']), + 'filename' => $attachment['filename'] + ]; + } + + continue; + } + + if (! is_array($value)) { + $multipart_form[] = [ + 'name' => $key, + 'contents' => $value + ]; + continue; + } + + foreach ($value as $subkey => $subvalue) { + $multipart_form[] = [ + 'name' => "{$key}[$subkey]" . (is_array($subvalue) ? '[' . key($subvalue) . ']' : '' ), + 'contents' => (is_array($subvalue) ? reset($subvalue) : $subvalue) + ]; + } + } + + try { + return $client->request('post', $url, [ + 'multipart' => $multipart_form, + 'headers' => [ + 'Authorization' => 'Bearer ' . $this->api_key, + 'Accept' => 'application/json' + ] + ])->getBody(); + + } catch(\Exception $e) { + throw new PushException($e->getMessage()); + } + } +} diff --git a/src/PushChannel.php b/src/PushChannel.php new file mode 100644 index 0000000..96558c7 --- /dev/null +++ b/src/PushChannel.php @@ -0,0 +1,29 @@ +api = $api; + } + + /** + * @param $notifiable + * @param Notification $notification + * @return \Psr\Http\Message\StreamInterface + * @throws PushException + */ + public function send($notifiable, Notification $notification): StreamInterface + { + $template = $notification->toTemplate($notifiable); + + return $this->api->send($template, $notifiable); + } +} diff --git a/src/PushException.php b/src/PushException.php new file mode 100644 index 0000000..63dbc18 --- /dev/null +++ b/src/PushException.php @@ -0,0 +1,5 @@ +mergeConfigFrom( + __DIR__ . '/../config/push.php', + 'push' + ); + + $this->app->singleton(PushApi::class, function ($app) { + return new PushApi($app['config']['push']['api_key']); + }); + } + + /** + * Bootstrap any application services. + * + * @return void + */ + public function boot() + { + $this->publishes([ + __DIR__ . '/../config/push.php' => config_path('push.php') + ], 'config'); + } +} diff --git a/src/PushTemplate.php b/src/PushTemplate.php new file mode 100644 index 0000000..d64b1ef --- /dev/null +++ b/src/PushTemplate.php @@ -0,0 +1,296 @@ +template_id = $template_id; + } + + /** + * @param string $email + * @param string|null $name + * @return $this + */ + public function sender(string $email, string $name = null): PushTemplate + { + $this->sender['email'] = $email; + + if ($name) + $this->sender['name'] = $name; + + return $this; + } + + /** + * @param string $email + * @param string|null $name + * @return $this + */ + public function replyTo(string $email, string $name = null): PushTemplate + { + $this->replyTo['email'] = $email; + + if ($name) + $this->replyTo['name'] = $name; + + return $this; + } + + /** + * @param array $recipients + * @return $this + */ + public function recipients(array $recipients): PushTemplate + { + if (! empty($recipients)) { + foreach ($recipients as $recipient) { + if (empty($recipient['email'])) { + continue; + } + + $data = [ + 'email' => $recipient['email'] + ]; + + if (! empty($recipient['name'])) { + $data['name'] = $recipient['name']; + } + + if (! empty($recipient['parameters']) && is_array($recipient['parameters'])) { + $data['parameters'] = $recipient['parameters']; + } + + if (! empty($recipient['unsubscribe_url'])) { + $data['unsubscribe_url'] = $recipient['unsubscribe_url']; + } + + $this->recipients[] = $data; + } + } + + return $this; + } + + /** + * @param string $email + * @param string|null $name + * @param array $parameters + * @param string|null $unsubscribe_url + * @return $this + */ + public function addRecipient(string $email, string $name = null, array $parameters = [], string $unsubscribe_url = null): PushTemplate + { + $data = [ + 'email' => $email + ]; + + if (! is_null($name)) { + $data['name'] = $name; + } + + if (! empty($parameters)) { + $data['parameters'] = $parameters; + } + + if (! is_null($unsubscribe_url)) { + $data['unsubscribe_url'] = $unsubscribe_url; + } + + $this->recipients[] = $data; + + return $this; + } + + /** + * @param array $parameters + * @return $this + */ + public function parameters(array $parameters): PushTemplate + { + $this->parameters = $parameters; + + return $this; + } + + /** + * @param array $attachments + * @return $this + */ + public function attachments(array $attachments): PushTemplate + { + foreach ($attachments as $attachment) { + $this->addAttachment($attachment['path'] ?? $attachment['file'], $attachment['filename'] ?? null); + } + + return $this; + } + + /** + * @param $file + * @param $filename + * @return $this + */ + public function addAttachment($file, $filename = null) + { + $file = is_object($file) && method_exists($file, 'getRealPath') ? $file->getRealPath() : $file; + + $this->attachments[] = [ + 'path' => $file, + 'filename' => $filename ?? basename($file) + ]; + + return $this; + } + + /** + * @param string $key + * @param string $value + * @return $this + */ + public function addParameter(string $key, string $value): PushTemplate + { + $this->parameters[$key] = $value; + + return $this; + } + + /** + * @param $bulk_mode + * @return $this + */ + public function bulkMode($bulk_mode = true) + { + $this->bulk_mode = $bulk_mode; + + return $this; + } + + /** + * @param $test_mode + * @return $this + */ + public function testMode($test_mode = true) + { + $this->test_mode = $test_mode; + + return $this; + } + + /** + * @param string|null $locale + * @return $this + */ + public function locale(string $locale = null) + { + $this->locale = $locale; + + return $this; + } + + public function unsubscribeUrl($url = null) + { + $this->unsubscribe_url = $url; + + return $this; + } + + /** + * Get an array representation of the message. + * + * @return array + */ + public function toArray(): array + { + return [ + 'template' => $this->template_id, + 'locale' => $this->locale, + 'recipients' => $this->recipients, + 'parameters' => $this->parameters, + 'reply_to' => $this->replyTo, + 'sender' => $this->sender, + 'bulk' => $this->bulk, + 'test' => $this->test_mode, + 'unsubscribe_url' => $this->unsubscribe_url, + 'attachments' => $this->attachments, + ]; + } + + public function jsonSerialize() + { + return $this->toArray(); + } +}