5 Commits
0.1 ... 0.6

Author SHA1 Message Date
00ea95cc8d php 8.4 support 2025-12-16 16:30:18 +01:00
a076368f51 refine test mode 2025-02-10 21:28:42 +01:00
6ebae6201c global test mode + fixes 2025-02-05 19:42:54 +01:00
9df8151682 add custom locale per recipient 2025-01-23 15:40:48 +01:00
3178fc309c fix composer.json 2025-01-20 14:28:12 +01:00
6 changed files with 56 additions and 27 deletions

View File

@@ -29,7 +29,7 @@
"extra": { "extra": {
"laravel": { "laravel": {
"providers": [ "providers": [
"PushServiceProvider" "Bluesquare\\Push\\PushServiceProvider"
] ]
} }
}, },

View File

@@ -2,5 +2,6 @@
return [ return [
'api_key' => env('PUSH_API_KEY', null), 'api_key' => env('PUSH_API_KEY', null),
'api_url' => env('PUSH_API_URL', null) 'api_url' => env('PUSH_API_URL', null),
'test_mode' => env('PUSH_TEST_MODE', false),
]; ];

View File

@@ -4,6 +4,8 @@ namespace Bluesquare\Push;
use Bluesquare\Push\PushTemplate; use Bluesquare\Push\PushTemplate;
use GuzzleHttp\Client; use GuzzleHttp\Client;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;
use Psr\Http\Message\StreamInterface; use Psr\Http\Message\StreamInterface;
use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\File\UploadedFile;
@@ -16,9 +18,17 @@ class PushApi
*/ */
private $api_key; private $api_key;
public function __construct(string $api_key) /**
* Test mode
*
* @var bool
*/
private $test_mode;
public function __construct(string $api_key, bool $test_mode = false)
{ {
$this->api_key = $api_key; $this->api_key = $api_key;
$this->test_mode = $test_mode;
} }
/** /**
@@ -27,7 +37,7 @@ class PushApi
* @return \Psr\Http\Message\StreamInterface * @return \Psr\Http\Message\StreamInterface
* @throws PushException * @throws PushException
*/ */
public function send($template, $notifiable): StreamInterface public function send($template, $notifiable): StreamInterface|false
{ {
$url = config('push.api_url') ?? 'https://push.bluesquare.io/api/send'; $url = config('push.api_url') ?? 'https://push.bluesquare.io/api/send';
@@ -50,6 +60,17 @@ class PushApi
]; ];
} }
if ($this->test_mode) {
if (! empty($this->api_key)) {
$template->testMode();
} else {
Log::debug("Push test mode: API key missing, discarding notification", $template->toArray());
return false;
}
} elseif (empty($this->api_key)) {
throw new PushException('Push API key is required');
}
$multipart_form = []; $multipart_form = [];
foreach ($template as $key => $value) { foreach ($template as $key => $value) {
@@ -73,25 +94,24 @@ class PushApi
continue; continue;
} }
foreach ($value as $subkey => $subvalue) { $values = Arr::dot($value);
foreach ($values as $subkey => $subvalue) {
$subkey = str_replace('.', '][', $subkey);
$multipart_form[] = [ $multipart_form[] = [
'name' => "{$key}[$subkey]" . (is_array($subvalue) ? '[' . key($subvalue) . ']' : '' ), 'name' => "{$key}[$subkey]",
'contents' => (is_array($subvalue) ? reset($subvalue) : $subvalue) 'contents' => is_array($subvalue) ? json_encode($subvalue) : $subvalue
]; ];
} }
} }
try { return $client->request('post', $url, [
return $client->request('post', $url, [ 'multipart' => $multipart_form,
'multipart' => $multipart_form, 'headers' => [
'headers' => [ 'Authorization' => 'Bearer ' . $this->api_key,
'Authorization' => 'Bearer ' . $this->api_key, 'Accept' => 'application/json'
'Accept' => 'application/json' ]
] ])->getBody();
])->getBody();
} catch(\Exception $e) {
throw new PushException($e->getMessage());
}
} }
} }

View File

@@ -20,7 +20,7 @@ class PushChannel
* @return \Psr\Http\Message\StreamInterface * @return \Psr\Http\Message\StreamInterface
* @throws PushException * @throws PushException
*/ */
public function send($notifiable, Notification $notification): StreamInterface public function send($notifiable, Notification $notification): StreamInterface|false
{ {
$template = $notification->toTemplate($notifiable); $template = $notification->toTemplate($notifiable);

View File

@@ -19,7 +19,7 @@ class PushServiceProvider extends ServiceProvider
); );
$this->app->singleton(PushApi::class, function ($app) { $this->app->singleton(PushApi::class, function ($app) {
return new PushApi($app['config']['push']['api_key']); return new PushApi($app['config']['push']['api_key'], $app['config']['push']['test_mode']);
}); });
} }

View File

@@ -85,7 +85,7 @@ class PushTemplate implements \JsonSerializable
* @param string|null $name * @param string|null $name
* @return $this * @return $this
*/ */
public function sender(string $email, string $name = null): PushTemplate public function sender(string $email, ?string $name = null): PushTemplate
{ {
$this->sender['email'] = $email; $this->sender['email'] = $email;
@@ -100,7 +100,7 @@ class PushTemplate implements \JsonSerializable
* @param string|null $name * @param string|null $name
* @return $this * @return $this
*/ */
public function replyTo(string $email, string $name = null): PushTemplate public function replyTo(string $email, ?string $name = null): PushTemplate
{ {
$this->replyTo['email'] = $email; $this->replyTo['email'] = $email;
@@ -138,6 +138,10 @@ class PushTemplate implements \JsonSerializable
$data['unsubscribe_url'] = $recipient['unsubscribe_url']; $data['unsubscribe_url'] = $recipient['unsubscribe_url'];
} }
if (! empty($recipient['locale'])) {
$data['locale'] = $recipient['locale'];
}
$this->recipients[] = $data; $this->recipients[] = $data;
} }
} }
@@ -152,7 +156,7 @@ class PushTemplate implements \JsonSerializable
* @param string|null $unsubscribe_url * @param string|null $unsubscribe_url
* @return $this * @return $this
*/ */
public function addRecipient(string $email, string $name = null, array $parameters = [], string $unsubscribe_url = null): PushTemplate public function addRecipient(string $email, ?string $name = null, array $parameters = [], ?string $unsubscribe_url = null, ?string $locale = null): PushTemplate
{ {
$data = [ $data = [
'email' => $email 'email' => $email
@@ -170,6 +174,10 @@ class PushTemplate implements \JsonSerializable
$data['unsubscribe_url'] = $unsubscribe_url; $data['unsubscribe_url'] = $unsubscribe_url;
} }
if (! is_null($locale)) {
$data['locale'] = $locale;
}
$this->recipients[] = $data; $this->recipients[] = $data;
return $this; return $this;
@@ -204,7 +212,7 @@ class PushTemplate implements \JsonSerializable
* @param $filename * @param $filename
* @return $this * @return $this
*/ */
public function addAttachment($file, $filename = null) public function addAttachment($file, ?string $filename = null)
{ {
$file = is_object($file) && method_exists($file, 'getRealPath') ? $file->getRealPath() : $file; $file = is_object($file) && method_exists($file, 'getRealPath') ? $file->getRealPath() : $file;
@@ -254,14 +262,14 @@ class PushTemplate implements \JsonSerializable
* @param string|null $locale * @param string|null $locale
* @return $this * @return $this
*/ */
public function locale(string $locale = null) public function locale(?string $locale = null)
{ {
$this->locale = $locale; $this->locale = $locale;
return $this; return $this;
} }
public function unsubscribeUrl($url = null) public function unsubscribeUrl(?string $url = null)
{ {
$this->unsubscribe_url = $url; $this->unsubscribe_url = $url;