From 0c99f9e43b8a78af76dbb30ba59cb19c34f30f5e Mon Sep 17 00:00:00 2001 From: Lynh Tran Date: Tue, 2 Jan 2018 10:19:08 +0700 Subject: [PATCH 01/45] Notification channels and message --- src/Channels/ApnChannel.php | 76 +++++++++++++++++++++ src/Channels/FcmChannel.php | 74 +++++++++++++++++++++ src/Events/NotificationPushed.php | 29 ++++++++ src/Messages/PushMessage.php | 107 ++++++++++++++++++++++++++++++ 4 files changed, 286 insertions(+) create mode 100644 src/Channels/ApnChannel.php create mode 100644 src/Channels/FcmChannel.php create mode 100644 src/Events/NotificationPushed.php create mode 100644 src/Messages/PushMessage.php diff --git a/src/Channels/ApnChannel.php b/src/Channels/ApnChannel.php new file mode 100644 index 0000000..be303cc --- /dev/null +++ b/src/Channels/ApnChannel.php @@ -0,0 +1,76 @@ +push = $push; + } + + /** + * Send the given notification. + * + * @param mixed $notifiable + * @param \Illuminate\Notifications\Notification $notification + * @return void + */ + public function send($notifiable, Notification $notification) + { + if (! $to = $notifiable->routeNotificationFor('Apn')) { + return; + } + + $message = $notification->toApn($notifiable); + + if (is_string($message)) { + $message = new PushMessage($message); + } + + $data = [ + 'aps' => [ + 'alert' => [ + 'title' => $message->title, + 'body' => $message->body, + ], + 'sound' => $message->sound, + ], + ]; + + if (! empty($message->extra)) { + $data['extraPayLoad'] = $message->extra; + } + + $this->push->setMessage($data) + ->setService('apn') + ->setDevicesToken($to); + + if (! empty($message->config)) { + $this->push->setConfig($message->config); + } + + $feedback = $this->push->send() + ->getFeedback(); + + broadcast(new NotificationPushed($this->push)); + + return $feedback; + } +} diff --git a/src/Channels/FcmChannel.php b/src/Channels/FcmChannel.php new file mode 100644 index 0000000..eb767a2 --- /dev/null +++ b/src/Channels/FcmChannel.php @@ -0,0 +1,74 @@ +push = $push; + } + + /** + * Send the given notification. + * + * @param mixed $notifiable + * @param \Illuminate\Notifications\Notification $notification + * @return void + */ + public function send($notifiable, Notification $notification) + { + if (! $to = $notifiable->routeNotificationFor('Fcm')) { + return; + } + + $message = $notification->toFcm($notifiable); + + if (is_string($message)) { + $message = new PushMessage($message); + } + + $data = [ + 'notification' => [ + 'title' => $message->title, + 'body' => $message->body, + 'sound' => $message->sound, + ], + ]; + + if (! empty($message->extra)) { + $data['data'] = $message->extra; + } + + $this->push->setMessage($data) + ->setService('fcm') + ->setDevicesToken($to); + + if (! empty($message->config)) { + $this->push->setConfig($message->config); + } + + $feedback = $this->push->send() + ->getFeedback(); + + broadcast(new NotificationPushed($this->push)); + + return $feedback; + } +} diff --git a/src/Events/NotificationPushed.php b/src/Events/NotificationPushed.php new file mode 100644 index 0000000..87c7150 --- /dev/null +++ b/src/Events/NotificationPushed.php @@ -0,0 +1,29 @@ +push = $push; + } +} diff --git a/src/Messages/PushMessage.php b/src/Messages/PushMessage.php new file mode 100644 index 0000000..13f1ee6 --- /dev/null +++ b/src/Messages/PushMessage.php @@ -0,0 +1,107 @@ +body = $body; + } + + /** + * Set the message body. + * + * @param string $title + * @return $this + */ + public function body($body) + { + $this->body = $body; + + return $this; + } + + /** + * Set the message title. + * + * @param string $title + * @return $this + */ + public function title($title) + { + $this->title = $title; + + return $this; + } + + /** + * Set the notification sound. + * + * @param string $sound + * @return void + */ + public function sound($sound) + { + $this->sound = $sound; + + return $this; + } + + /** + * Set message extra data. + * + * @param array $extra + * @return $this + */ + public function extra(array $extra) + { + $this->extra = $extra; + + return $this; + } + + /** + * Set message config. + * + * @param array $config + * @return $this + */ + public function config(array $config) + { + $this->config = $config; + + return $this; + } +} From e44661688a73836411695538e2cc4aaffaa4613b Mon Sep 17 00:00:00 2001 From: Lynh Tran Date: Tue, 2 Jan 2018 11:05:08 +0700 Subject: [PATCH 02/45] Update channels --- src/Channels/ApnChannel.php | 35 ++---------------------- src/Channels/FcmChannel.php | 35 ++---------------------- src/Channels/GcmChannel.php | 43 +++++++++++++++++++++++++++++ src/Channels/PushChannel.php | 53 ++++++++++++++++++++++++++++++++++++ 4 files changed, 100 insertions(+), 66 deletions(-) create mode 100644 src/Channels/GcmChannel.php create mode 100644 src/Channels/PushChannel.php diff --git a/src/Channels/ApnChannel.php b/src/Channels/ApnChannel.php index be303cc..cb7ac48 100644 --- a/src/Channels/ApnChannel.php +++ b/src/Channels/ApnChannel.php @@ -2,29 +2,11 @@ namespace Edujugon\PushNotification\Channels; -use Edujugon\PushNotification\Events\NotificationPushed; use Edujugon\PushNotification\Messages\PushMessage; -use Edujugon\PushNotification\PushNotification; use Illuminate\Notifications\Notification; -class ApnChannel +class ApnChannel extends PushChannel { - /** - * @var \Edujugon\PushNotification\PushNotification - */ - protected $push; - - /** - * Create a new Apn channel instance. - * - * @param \Edujugon\PushNotification\Facades\PushNotification $push - * @return void - */ - public function __construct(PushNotification $push) - { - $this->push = $push; - } - /** * Send the given notification. * @@ -58,19 +40,6 @@ public function send($notifiable, Notification $notification) $data['extraPayLoad'] = $message->extra; } - $this->push->setMessage($data) - ->setService('apn') - ->setDevicesToken($to); - - if (! empty($message->config)) { - $this->push->setConfig($message->config); - } - - $feedback = $this->push->send() - ->getFeedback(); - - broadcast(new NotificationPushed($this->push)); - - return $feedback; + return $this->push('apn', $to, $data, $message); } } diff --git a/src/Channels/FcmChannel.php b/src/Channels/FcmChannel.php index eb767a2..2e61c98 100644 --- a/src/Channels/FcmChannel.php +++ b/src/Channels/FcmChannel.php @@ -2,29 +2,11 @@ namespace Edujugon\PushNotification\Channels; -use Edujugon\PushNotification\Events\NotificationPushed; use Edujugon\PushNotification\Messages\PushMessage; -use Edujugon\PushNotification\PushNotification; use Illuminate\Notifications\Notification; -class FcmChannel +class FcmChannel extends PushChannel { - /** - * @var \Edujugon\PushNotification\PushNotification - */ - protected $push; - - /** - * Create a new Apn channel instance. - * - * @param \Edujugon\PushNotification\Facades\PushNotification $push - * @return void - */ - public function __construct(PushNotification $push) - { - $this->push = $push; - } - /** * Send the given notification. * @@ -56,19 +38,6 @@ public function send($notifiable, Notification $notification) $data['data'] = $message->extra; } - $this->push->setMessage($data) - ->setService('fcm') - ->setDevicesToken($to); - - if (! empty($message->config)) { - $this->push->setConfig($message->config); - } - - $feedback = $this->push->send() - ->getFeedback(); - - broadcast(new NotificationPushed($this->push)); - - return $feedback; + return $this->push('fcm', $to, $data, $message); } } diff --git a/src/Channels/GcmChannel.php b/src/Channels/GcmChannel.php new file mode 100644 index 0000000..1250d41 --- /dev/null +++ b/src/Channels/GcmChannel.php @@ -0,0 +1,43 @@ +routeNotificationFor('Gcm')) { + return; + } + + $message = $notification->toGcm($notifiable); + + if (is_string($message)) { + $message = new PushMessage($message); + } + + $data = [ + 'notification' => [ + 'title' => $message->title, + 'body' => $message->body, + 'sound' => $message->sound, + ], + ]; + + if (! empty($message->extra)) { + $data['data'] = $message->extra; + } + + return $this->push('gpn', $to, $data, $message); + } +} diff --git a/src/Channels/PushChannel.php b/src/Channels/PushChannel.php new file mode 100644 index 0000000..7ff21a0 --- /dev/null +++ b/src/Channels/PushChannel.php @@ -0,0 +1,53 @@ +push = $push; + } + + /** + * Send the push notification. + * + * @param string $service + * @param mixed $to + * @param array $data + * @param \Edujugon\PushNotification\Messages\PushMessage $message + * @return mixed + */ + protected function push($service, $to, $data, PushMessage $message) + { + $this->push->setMessage($data) + ->setService($service) + ->setDevicesToken($to); + + if (! empty($message->config)) { + $this->push->setConfig($message->config); + } + + $feedback = $this->push->send() + ->getFeedback(); + + broadcast(new NotificationPushed($this->push)); + + return $feedback; + } +} From b4c73d6e6c6b5ad029e3e1e25f47a05d2c4d0d9c Mon Sep 17 00:00:00 2001 From: Lynh Tran Date: Tue, 2 Jan 2018 11:52:17 +0700 Subject: [PATCH 03/45] Set api key --- src/Channels/PushChannel.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Channels/PushChannel.php b/src/Channels/PushChannel.php index 7ff21a0..34998c4 100644 --- a/src/Channels/PushChannel.php +++ b/src/Channels/PushChannel.php @@ -41,6 +41,10 @@ protected function push($service, $to, $data, PushMessage $message) if (! empty($message->config)) { $this->push->setConfig($message->config); + + if (! empty($message->config['apiKey'])) { + $this->push->setApiKey($message->config['apiKey']); + } } $feedback = $this->push->send() From 64e1031486d508095e7b0a36dfc73be1d433110d Mon Sep 17 00:00:00 2001 From: Lynh Tran Date: Tue, 2 Jan 2018 11:54:53 +0700 Subject: [PATCH 04/45] Update readme --- readme.md | 248 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 155 insertions(+), 93 deletions(-) diff --git a/readme.md b/readme.md index d8c6197..020f2b5 100644 --- a/readme.md +++ b/readme.md @@ -79,8 +79,8 @@ You can dynamically update those values or adding new ones calling the method se The default configuration parameters for **APN** are: -*   ```certificate => __DIR__ . '/iosCertificates/yourCertificate.pem'``` -*   ```passPhrase => 'MyPassPhrase'``` +* ```certificate => __DIR__ . '/iosCertificates/yourCertificate.pem'``` +* ```passPhrase => 'MyPassPhrase'``` * ```passFile => __DIR__ . '/iosCertificates/yourKey.pem' //Optional``` * ```dry_run => false``` @@ -111,7 +111,7 @@ For APN Service: For FCM Service: $push = new PushNotification('fcm'); - + Now you may use any method what you need. Please see the API List. @@ -200,7 +200,7 @@ object getFeedback() #### getUnregisteredDeviceTokens -`getUnregisteredDeviceTokens` method gets the devices' tokens that couldn't receive the notification because they aren't registered to the Push service provider. +`getUnregisteredDeviceTokens` method gets the devices' tokens that couldn't receive the notification because they aren't registered to the Push service provider. You may use it chaining it to `send` method or call it whenever after sending a notification. **Syntax** @@ -250,79 +250,81 @@ object sendByTopic($topic,$isCondition) GCM sample: ```php - $push->setMessage([ - 'notification' => [ - 'title'=>'This is the title', - 'body'=>'This is the message', - 'sound' => 'default' - ], - 'data' => [ - 'extraPayLoad1' => 'value1', - 'extraPayLoad2' => 'value2' - ] - ]) - ->setApiKey('Server-API-Key') - ->setDevicesToken(['deviceToken1','deviceToken2','deviceToken3'...]); -``` - -APN sample: - - $push->setMessage([ - 'aps' => [ - 'alert' => [ - 'title' => 'This is the title', - 'body' => 'This is the body' - ], - 'sound' => 'default' - +$push->setMessage([ + 'notification' => [ + 'title'=>'This is the title', + 'body'=>'This is the message', + 'sound' => 'default' ], - 'extraPayLoad' => [ - 'custom' => 'My custom data', + 'data' => [ + 'extraPayLoad1' => 'value1', + 'extraPayLoad2' => 'value2' ] - ]) + ]) + ->setApiKey('Server-API-Key') ->setDevicesToken(['deviceToken1','deviceToken2','deviceToken3'...]); +``` +APN sample: +```php +$push->setMessage([ + 'aps' => [ + 'alert' => [ + 'title' => 'This is the title', + 'body' => 'This is the body' + ], + 'sound' => 'default' + + ], + 'extraPayLoad' => [ + 'custom' => 'My custom data', + ] + ]) + ->setDevicesToken(['deviceToken1','deviceToken2','deviceToken3'...]); +``` or do it separately - - $push->setMessage([ - 'notification' => [ - 'title'=>'This is the title', - 'body'=>'This is the message', - 'sound' => 'default' - ], - 'data' => [ - 'extraPayLoad1' => 'value1', - 'extraPayLoad2' => 'value2' - ] - ]); - $push->setApiKey('Server-API-Key'); - $push->setDevicesToken(['deviceToken1' - ,'deviceToken2', - 'deviceToken3' - ]); - +```php +$push->setMessage([ + 'notification' => [ + 'title'=>'This is the title', + 'body'=>'This is the message', + 'sound' => 'default' + ], + 'data' => [ + 'extraPayLoad1' => 'value1', + 'extraPayLoad2' => 'value2' + ] + ]); +$push->setApiKey('Server-API-Key'); +$push->setDevicesToken(['deviceToken1' + ,'deviceToken2', + 'deviceToken3' +]); +``` If you want send the notification to only 1 device, you may pass the value as string. - - $push->setDevicesToken('deviceToken'); +```php +$push->setDevicesToken('deviceToken'); +``` ### Send the Notification Method send() can be also chained to the above methods. - - $push->setMessage([ - 'notification' => [ - 'title'=>'This is the title', - 'body'=>'This is the message', - 'sound' => 'default' - ], - 'data' => [ - 'extraPayLoad1' => 'value1', - 'extraPayLoad2' => 'value2' - ] - ]) - ->setApiKey('Server-API-Key') - ->setDevicesToken(['deviceToken1','deviceToken2','deviceToken3'...]) - ->send(); +```php +$push->setMessage([ + 'notification' => [ + 'title'=>'This is the title', + 'body'=>'This is the message', + 'sound' => 'default' + ], + 'data' => [ + 'extraPayLoad1' => 'value1', + 'extraPayLoad2' => 'value2' + ] + ]) + ->setApiKey('Server-API-Key') + ->setDevicesToken(['deviceToken1','deviceToken2','deviceToken3'...]) + ->send(); +``` ### Send the Notification by Topic (**FCM** only) @@ -345,7 +347,7 @@ $response = $push->setMessage(['message'=>'Hello World']) ### Understanding Gcm and Fcm Message Payload -#### Notification Message +#### Notification Message Add a `notification` key when setting the message in `setMessage` method. like follows: @@ -356,7 +358,7 @@ $push->setMessage([ 'body'=>'This is the message', 'sound' => 'default' ] - ); + ); ``` You may add some extra payload adding a `data` key when setting the message in `setMessage` method. @@ -375,7 +377,7 @@ $push->setMessage([ ]); ``` -#### Data Message +#### Data Message By default this package sends the notification as Data Message. So no need to add a `data` key. Just leave it without main keys. @@ -384,7 +386,7 @@ $push->setMessage([ 'title'=>'This is the title', 'body'=>'This is the message', 'myCustomVAlue' => 'value' - ]); + ]); ``` The above example is like you were sending the following: @@ -404,16 +406,18 @@ For more details, have a look at [gcm/fcm notification paypload support](https:/ ### Getting the Notification Response If you want to get the push service response, you can call the method `getFeedback`: - +```php $push->getFeedback(); +``` Or again, chain it to the above methods: - +```php $push->setMessage(['body'=>'This is the message','title'=>'This is the title']) ->setApiKey('Server-API-Key') ->setDevicesToken(['deviceToken1','deviceToken2','deviceToken3'...]) ->send() ->getFeedback(); +``` It will return an object with the response. @@ -422,7 +426,7 @@ It will return an object with the response. Any time you send a notification, it will check if APN server has any feedback for your certificate. If so, the responses are merged to our feedback like below: -``` +```php class stdClass#21 (4) { public $success => int(0) @@ -452,30 +456,88 @@ class stdClass#21 (4) { ### Get Unregistered Devices tokens After sending a notification, you may retrieve the list of unregistered tokens - - $push->getUnregisteredDeviceTokens(); +```php +$push->getUnregisteredDeviceTokens(); +``` This method returns an array of unregistered tokens from the Push service provider. If there isn't any unregistered token, it will return an empty array. ### Laravel Alias Facade After register the Alias Facade for this Package, you can use it like follows: - - PushNotification::setService('fcm') - ->setMessage([ - 'notification' => [ - 'title'=>'This is the title', - 'body'=>'This is the message', - 'sound' => 'default' - ], - 'data' => [ - 'extraPayLoad1' => 'value1', - 'extraPayLoad2' => 'value2' - ] - ]) - ->setApiKey('Server-API-Key') - ->setDevicesToken(['deviceToken1','deviceToken2','deviceToken3'...]) - ->send() - ->getFeedback(); +```php +PushNotification::setService('fcm') + ->setMessage([ + 'notification' => [ + 'title'=>'This is the title', + 'body'=>'This is the message', + 'sound' => 'default' + ], + 'data' => [ + 'extraPayLoad1' => 'value1', + 'extraPayLoad2' => 'value2' + ] + ]) + ->setApiKey('Server-API-Key') + ->setDevicesToken(['deviceToken1','deviceToken2','deviceToken3'...]) + ->send() + ->getFeedback(); +``` It would return the Push Feedback of the Notification sent. + +### Notification channels + +#### Formatting Push Notifications +If a notification supports being sent as an push message, you should define `toApn` `toFcm` `toGcm` methods on the notification class. This method will receive a `$notifiable` entity and should return a `Edujugon\PushNotification\Messages\PushMessage` instance: + +```php +public function toApn($notifiable) +{ + return new PushMessage('Hello world'); +} +``` + +#### Customizing The Title and Body +```php +public function toApn($notifiable) +{ + return (new PushMessage) + ->title('Hello world') + ->body('...'); +} +``` + +#### Customizing The Notification Sound +```php +public function toApn($notifiable) +{ + return (new PushMessage) + ->body('Hello world') + ->sound('default'); +} +``` + +#### Passing Service Config +```php +public function toApn($notifiable) +{ + return (new PushMessage) + ->body('Hello world') + ->config(['dry_run' => false]); +} +``` + +#### Routing Push Notifications +Just define `routeNotificationForApn` `routeNotificationForFcm` `routeNotificationForGcm` methods on the entity +```php +/** + * Route notifications for the Apn channel. + * + * @return string|array + */ +public function routeNotificationForApn() +{ + return $this->ios_push_token; +} +``` From 6918ae0e4e72823aceff752b15878e86cc37e7f5 Mon Sep 17 00:00:00 2001 From: Lynh Tran Date: Tue, 2 Jan 2018 12:05:00 +0700 Subject: [PATCH 05/45] Update readme --- readme.md | 111 +++++++++++++++++++++++++++++------------------------- 1 file changed, 60 insertions(+), 51 deletions(-) diff --git a/readme.md b/readme.md index 020f2b5..9770fad 100644 --- a/readme.md +++ b/readme.md @@ -39,22 +39,25 @@ composer require edujugon/push-notification Then you don't have to either register or add the alias, this package uses Package Auto-Discovery's feature, and should be available as soon as you install it via Composer. (Laravel < 5.5) Register the PushNotification service by adding it to the providers array. - - 'providers' => array( - ... - Edujugon\PushNotification\Providers\PushNotificationServiceProvider::class - ) +```php +'providers' => array( + ... + Edujugon\PushNotification\Providers\PushNotificationServiceProvider::class +) +``` (Laravel < 5.5) Let's add the Alias facade, add it to the aliases array. - - 'aliases' => array( - ... - 'PushNotification' => Edujugon\PushNotification\Facades\PushNotification::class, - ) +```php +'aliases' => array( + ... + 'PushNotification' => Edujugon\PushNotification\Facades\PushNotification::class, +) +``` Publish the package's configuration file to the application's own config directory - - php artisan vendor:publish --provider="Edujugon\PushNotification\Providers\PushNotificationServiceProvider" --tag="config" +``` +php artisan vendor:publish --provider="Edujugon\PushNotification\Providers\PushNotificationServiceProvider" --tag="config" +``` > Go to [laravel facade sample](https://github.com/edujugon/PushNotification#laravel-alias-facade) directly. @@ -69,13 +72,13 @@ The default configuration parameters for **GCM** and **FCM** are : * apiKey => Your ApiKey You can dynamically update those values or adding new ones calling the method setConfig like so: - - $push->setConfig([ - 'priority' => 'high', - 'dry_run' => true, - 'time_to_live' => 3 - ]); - +```php +$push->setConfig([ + 'priority' => 'high', + 'dry_run' => true, + 'time_to_live' => 3 +]); +``` The default configuration parameters for **APN** are: @@ -85,32 +88,37 @@ The default configuration parameters for **APN** are: * ```dry_run => false``` Also you can update those values and add more dynamically - - $push->setConfig([ - 'passPhrase' => 'NewPass', - 'custom' => 'MycustomValue', - 'dry_run' => true - ]); +```php +$push->setConfig([ + 'passPhrase' => 'NewPass', + 'custom' => 'MycustomValue', + 'dry_run' => true +]); +``` Even you may update the url of the Push Service dynamically like follows: - - $puhs->setUrl('http://newPushServiceUrl.com'); +```php +$push->setUrl('http://newPushServiceUrl.com'); +``` > Not update the url unless it's really necessary. ## Usage - - $push = new PushNotification; +```php +$push = new PushNotification; +``` By default it will use GCM as Push Service provider. For APN Service: - - $push = new PushNotification('apn'); +```php +$push = new PushNotification('apn'); +``` For FCM Service: - - $push = new PushNotification('fcm'); +```php +$push = new PushNotification('fcm'); +``` Now you may use any method what you need. Please see the API List. @@ -255,11 +263,11 @@ $push->setMessage([ 'title'=>'This is the title', 'body'=>'This is the message', 'sound' => 'default' - ], + ], 'data' => [ 'extraPayLoad1' => 'value1', 'extraPayLoad2' => 'value2' - ] + ] ]) ->setApiKey('Server-API-Key') ->setDevicesToken(['deviceToken1','deviceToken2','deviceToken3'...]); @@ -296,8 +304,9 @@ $push->setMessage([ ] ]); $push->setApiKey('Server-API-Key'); -$push->setDevicesToken(['deviceToken1' - ,'deviceToken2', +$push->setDevicesToken([ + 'deviceToken1', + 'deviceToken2', 'deviceToken3' ]); ``` @@ -315,11 +324,11 @@ $push->setMessage([ 'title'=>'This is the title', 'body'=>'This is the message', 'sound' => 'default' - ], + ], 'data' => [ 'extraPayLoad1' => 'value1', 'extraPayLoad2' => 'value2' - ] + ] ]) ->setApiKey('Server-API-Key') ->setDevicesToken(['deviceToken1','deviceToken2','deviceToken3'...]) @@ -357,7 +366,7 @@ $push->setMessage([ 'title'=>'This is the title', 'body'=>'This is the message', 'sound' => 'default' - ] + ] ); ``` @@ -369,11 +378,11 @@ $push->setMessage([ 'title'=>'This is the title', 'body'=>'This is the message', 'sound' => 'default' - ], + ], 'data' => [ 'extraPayLoad1' => 'value1', 'extraPayLoad2' => 'value2' - ] + ] ]); ``` @@ -397,7 +406,7 @@ $push->setMessage([ 'title'=>'This is the title', 'body'=>'This is the message', 'myCustomVAlue' => 'value' - ] + ] ]); ``` @@ -407,16 +416,16 @@ For more details, have a look at [gcm/fcm notification paypload support](https:/ If you want to get the push service response, you can call the method `getFeedback`: ```php - $push->getFeedback(); +$push->getFeedback(); ``` Or again, chain it to the above methods: ```php - $push->setMessage(['body'=>'This is the message','title'=>'This is the title']) - ->setApiKey('Server-API-Key') - ->setDevicesToken(['deviceToken1','deviceToken2','deviceToken3'...]) - ->send() - ->getFeedback(); +$push->setMessage(['body'=>'This is the message','title'=>'This is the title']) + ->setApiKey('Server-API-Key') + ->setDevicesToken(['deviceToken1','deviceToken2','deviceToken3'...]) + ->send() + ->getFeedback(); ``` It will return an object with the response. @@ -472,11 +481,11 @@ PushNotification::setService('fcm') 'title'=>'This is the title', 'body'=>'This is the message', 'sound' => 'default' - ], + ], 'data' => [ 'extraPayLoad1' => 'value1', 'extraPayLoad2' => 'value2' - ] + ] ]) ->setApiKey('Server-API-Key') ->setDevicesToken(['deviceToken1','deviceToken2','deviceToken3'...]) From aa6f235e658a4485e1a1c9d69fa97aed2a612c44 Mon Sep 17 00:00:00 2001 From: Lynh Tran Date: Tue, 2 Jan 2018 12:05:51 +0700 Subject: [PATCH 06/45] Revert "Update readme" This reverts commit 6918ae0e4e72823aceff752b15878e86cc37e7f5. --- readme.md | 111 +++++++++++++++++++++++++----------------------------- 1 file changed, 51 insertions(+), 60 deletions(-) diff --git a/readme.md b/readme.md index 9770fad..020f2b5 100644 --- a/readme.md +++ b/readme.md @@ -39,25 +39,22 @@ composer require edujugon/push-notification Then you don't have to either register or add the alias, this package uses Package Auto-Discovery's feature, and should be available as soon as you install it via Composer. (Laravel < 5.5) Register the PushNotification service by adding it to the providers array. -```php -'providers' => array( - ... - Edujugon\PushNotification\Providers\PushNotificationServiceProvider::class -) -``` + + 'providers' => array( + ... + Edujugon\PushNotification\Providers\PushNotificationServiceProvider::class + ) (Laravel < 5.5) Let's add the Alias facade, add it to the aliases array. -```php -'aliases' => array( - ... - 'PushNotification' => Edujugon\PushNotification\Facades\PushNotification::class, -) -``` + + 'aliases' => array( + ... + 'PushNotification' => Edujugon\PushNotification\Facades\PushNotification::class, + ) Publish the package's configuration file to the application's own config directory -``` -php artisan vendor:publish --provider="Edujugon\PushNotification\Providers\PushNotificationServiceProvider" --tag="config" -``` + + php artisan vendor:publish --provider="Edujugon\PushNotification\Providers\PushNotificationServiceProvider" --tag="config" > Go to [laravel facade sample](https://github.com/edujugon/PushNotification#laravel-alias-facade) directly. @@ -72,13 +69,13 @@ The default configuration parameters for **GCM** and **FCM** are : * apiKey => Your ApiKey You can dynamically update those values or adding new ones calling the method setConfig like so: -```php -$push->setConfig([ - 'priority' => 'high', - 'dry_run' => true, - 'time_to_live' => 3 -]); -``` + + $push->setConfig([ + 'priority' => 'high', + 'dry_run' => true, + 'time_to_live' => 3 + ]); + The default configuration parameters for **APN** are: @@ -88,37 +85,32 @@ The default configuration parameters for **APN** are: * ```dry_run => false``` Also you can update those values and add more dynamically -```php -$push->setConfig([ - 'passPhrase' => 'NewPass', - 'custom' => 'MycustomValue', - 'dry_run' => true -]); -``` + + $push->setConfig([ + 'passPhrase' => 'NewPass', + 'custom' => 'MycustomValue', + 'dry_run' => true + ]); Even you may update the url of the Push Service dynamically like follows: -```php -$push->setUrl('http://newPushServiceUrl.com'); -``` + + $puhs->setUrl('http://newPushServiceUrl.com'); > Not update the url unless it's really necessary. ## Usage -```php -$push = new PushNotification; -``` + + $push = new PushNotification; By default it will use GCM as Push Service provider. For APN Service: -```php -$push = new PushNotification('apn'); -``` + + $push = new PushNotification('apn'); For FCM Service: -```php -$push = new PushNotification('fcm'); -``` + + $push = new PushNotification('fcm'); Now you may use any method what you need. Please see the API List. @@ -263,11 +255,11 @@ $push->setMessage([ 'title'=>'This is the title', 'body'=>'This is the message', 'sound' => 'default' - ], + ], 'data' => [ 'extraPayLoad1' => 'value1', 'extraPayLoad2' => 'value2' - ] + ] ]) ->setApiKey('Server-API-Key') ->setDevicesToken(['deviceToken1','deviceToken2','deviceToken3'...]); @@ -304,9 +296,8 @@ $push->setMessage([ ] ]); $push->setApiKey('Server-API-Key'); -$push->setDevicesToken([ - 'deviceToken1', - 'deviceToken2', +$push->setDevicesToken(['deviceToken1' + ,'deviceToken2', 'deviceToken3' ]); ``` @@ -324,11 +315,11 @@ $push->setMessage([ 'title'=>'This is the title', 'body'=>'This is the message', 'sound' => 'default' - ], + ], 'data' => [ 'extraPayLoad1' => 'value1', 'extraPayLoad2' => 'value2' - ] + ] ]) ->setApiKey('Server-API-Key') ->setDevicesToken(['deviceToken1','deviceToken2','deviceToken3'...]) @@ -366,7 +357,7 @@ $push->setMessage([ 'title'=>'This is the title', 'body'=>'This is the message', 'sound' => 'default' - ] + ] ); ``` @@ -378,11 +369,11 @@ $push->setMessage([ 'title'=>'This is the title', 'body'=>'This is the message', 'sound' => 'default' - ], + ], 'data' => [ 'extraPayLoad1' => 'value1', 'extraPayLoad2' => 'value2' - ] + ] ]); ``` @@ -406,7 +397,7 @@ $push->setMessage([ 'title'=>'This is the title', 'body'=>'This is the message', 'myCustomVAlue' => 'value' - ] + ] ]); ``` @@ -416,16 +407,16 @@ For more details, have a look at [gcm/fcm notification paypload support](https:/ If you want to get the push service response, you can call the method `getFeedback`: ```php -$push->getFeedback(); + $push->getFeedback(); ``` Or again, chain it to the above methods: ```php -$push->setMessage(['body'=>'This is the message','title'=>'This is the title']) - ->setApiKey('Server-API-Key') - ->setDevicesToken(['deviceToken1','deviceToken2','deviceToken3'...]) - ->send() - ->getFeedback(); + $push->setMessage(['body'=>'This is the message','title'=>'This is the title']) + ->setApiKey('Server-API-Key') + ->setDevicesToken(['deviceToken1','deviceToken2','deviceToken3'...]) + ->send() + ->getFeedback(); ``` It will return an object with the response. @@ -481,11 +472,11 @@ PushNotification::setService('fcm') 'title'=>'This is the title', 'body'=>'This is the message', 'sound' => 'default' - ], + ], 'data' => [ 'extraPayLoad1' => 'value1', 'extraPayLoad2' => 'value2' - ] + ] ]) ->setApiKey('Server-API-Key') ->setDevicesToken(['deviceToken1','deviceToken2','deviceToken3'...]) From ed743e4cb190e3521390a042ddcefbefca42b14a Mon Sep 17 00:00:00 2001 From: Lynh Tran Date: Tue, 2 Jan 2018 12:09:19 +0700 Subject: [PATCH 07/45] Update readme --- readme.md | 79 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 35 deletions(-) diff --git a/readme.md b/readme.md index 020f2b5..793b1d6 100644 --- a/readme.md +++ b/readme.md @@ -39,22 +39,25 @@ composer require edujugon/push-notification Then you don't have to either register or add the alias, this package uses Package Auto-Discovery's feature, and should be available as soon as you install it via Composer. (Laravel < 5.5) Register the PushNotification service by adding it to the providers array. - - 'providers' => array( - ... - Edujugon\PushNotification\Providers\PushNotificationServiceProvider::class - ) +```php +'providers' => array( + ... + Edujugon\PushNotification\Providers\PushNotificationServiceProvider::class +) +``` (Laravel < 5.5) Let's add the Alias facade, add it to the aliases array. - - 'aliases' => array( - ... - 'PushNotification' => Edujugon\PushNotification\Facades\PushNotification::class, - ) +```php +'aliases' => array( + ... + 'PushNotification' => Edujugon\PushNotification\Facades\PushNotification::class, +) +``` Publish the package's configuration file to the application's own config directory - - php artisan vendor:publish --provider="Edujugon\PushNotification\Providers\PushNotificationServiceProvider" --tag="config" +``` +php artisan vendor:publish --provider="Edujugon\PushNotification\Providers\PushNotificationServiceProvider" --tag="config" +``` > Go to [laravel facade sample](https://github.com/edujugon/PushNotification#laravel-alias-facade) directly. @@ -69,12 +72,13 @@ The default configuration parameters for **GCM** and **FCM** are : * apiKey => Your ApiKey You can dynamically update those values or adding new ones calling the method setConfig like so: - - $push->setConfig([ - 'priority' => 'high', - 'dry_run' => true, - 'time_to_live' => 3 - ]); +```php +$push->setConfig([ + 'priority' => 'high', + 'dry_run' => true, + 'time_to_live' => 3 +]); +``` The default configuration parameters for **APN** are: @@ -85,32 +89,37 @@ The default configuration parameters for **APN** are: * ```dry_run => false``` Also you can update those values and add more dynamically - - $push->setConfig([ - 'passPhrase' => 'NewPass', - 'custom' => 'MycustomValue', - 'dry_run' => true - ]); +```php +$push->setConfig([ + 'passPhrase' => 'NewPass', + 'custom' => 'MycustomValue', + 'dry_run' => true +]); +``` Even you may update the url of the Push Service dynamically like follows: - - $puhs->setUrl('http://newPushServiceUrl.com'); +```php +$push->setUrl('http://newPushServiceUrl.com'); +``` > Not update the url unless it's really necessary. ## Usage - - $push = new PushNotification; +```php +$push = new PushNotification; +``` By default it will use GCM as Push Service provider. For APN Service: - - $push = new PushNotification('apn'); +```php +$push = new PushNotification('apn'); +``` For FCM Service: - - $push = new PushNotification('fcm'); +```php +$push = new PushNotification('fcm'); +``` Now you may use any method what you need. Please see the API List. @@ -504,7 +513,7 @@ public function toApn($notifiable) { return (new PushMessage) ->title('Hello world') - ->body('...'); + ->body('...'); } ``` @@ -514,7 +523,7 @@ public function toApn($notifiable) { return (new PushMessage) ->body('Hello world') - ->sound('default'); + ->sound('default'); } ``` @@ -524,7 +533,7 @@ public function toApn($notifiable) { return (new PushMessage) ->body('Hello world') - ->config(['dry_run' => false]); + ->config(['dry_run' => false]); } ``` From 0992f08641b19d56739deab8e8142b1e2def97f3 Mon Sep 17 00:00:00 2001 From: Lynh Tran Date: Tue, 2 Jan 2018 12:17:53 +0700 Subject: [PATCH 08/45] Update readme --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 793b1d6..446a7a9 100644 --- a/readme.md +++ b/readme.md @@ -498,7 +498,7 @@ It would return the Push Feedback of the Notification sent. ### Notification channels #### Formatting Push Notifications -If a notification supports being sent as an push message, you should define `toApn` `toFcm` `toGcm` methods on the notification class. This method will receive a `$notifiable` entity and should return a `Edujugon\PushNotification\Messages\PushMessage` instance: +If a notification supports being sent as an push message, you should define `toApn` and/or `toFcm`/`toGcm` methods on the notification class. This method will receive a `$notifiable` entity and should return a `Edujugon\PushNotification\Messages\PushMessage` instance: ```php public function toApn($notifiable) @@ -538,7 +538,7 @@ public function toApn($notifiable) ``` #### Routing Push Notifications -Just define `routeNotificationForApn` `routeNotificationForFcm` `routeNotificationForGcm` methods on the entity +Just define `routeNotificationForApn` and/or `routeNotificationForFcm`/`routeNotificationForGcm` methods on the entity ```php /** * Route notifications for the Apn channel. From 57d69699bfd76b19bc024a2d645a1a724de0cfae Mon Sep 17 00:00:00 2001 From: edujugon Date: Wed, 3 Jan 2018 21:37:16 +0100 Subject: [PATCH 09/45] Typo PHPDoc param data type --- src/Channels/PushChannel.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Channels/PushChannel.php b/src/Channels/PushChannel.php index 34998c4..0abac01 100644 --- a/src/Channels/PushChannel.php +++ b/src/Channels/PushChannel.php @@ -16,8 +16,7 @@ abstract class PushChannel /** * Create a new Apn channel instance. * - * @param \Edujugon\PushNotification\Facades\PushNotification $push - * @return void + * @param \Edujugon\PushNotification\PushNotification $push */ public function __construct(PushNotification $push) { From 11e028fad2f0078ee9f7a6983e023fe2cdfd261e Mon Sep 17 00:00:00 2001 From: edujugon Date: Wed, 3 Jan 2018 23:51:19 +0100 Subject: [PATCH 10/45] Fix typo push service name --- src/Channels/GcmChannel.php | 2 +- src/Channels/PushChannel.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Channels/GcmChannel.php b/src/Channels/GcmChannel.php index 1250d41..1b3626c 100644 --- a/src/Channels/GcmChannel.php +++ b/src/Channels/GcmChannel.php @@ -38,6 +38,6 @@ public function send($notifiable, Notification $notification) $data['data'] = $message->extra; } - return $this->push('gpn', $to, $data, $message); + $this->push('gcm', $to, $data, $message); } } diff --git a/src/Channels/PushChannel.php b/src/Channels/PushChannel.php index 0abac01..4d4a643 100644 --- a/src/Channels/PushChannel.php +++ b/src/Channels/PushChannel.php @@ -49,7 +49,7 @@ protected function push($service, $to, $data, PushMessage $message) $feedback = $this->push->send() ->getFeedback(); - broadcast(new NotificationPushed($this->push)); + event(new NotificationPushed($this->push)); return $feedback; } From 46e0ca90723c55cab8f103044944f8f3c2962b68 Mon Sep 17 00:00:00 2001 From: edujugon Date: Thu, 4 Jan 2018 00:08:47 +0100 Subject: [PATCH 11/45] Remove method return type --- src/Events/NotificationPushed.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Events/NotificationPushed.php b/src/Events/NotificationPushed.php index 87c7150..945971c 100644 --- a/src/Events/NotificationPushed.php +++ b/src/Events/NotificationPushed.php @@ -20,7 +20,6 @@ class NotificationPushed * Create a new event instance. * * @param \Edujugon\PushNotification\PushNotification $push - * @return void */ public function __construct(PushNotification $push) { From d7678484618b4eaf9b0e4cf05d2e211d5111c468 Mon Sep 17 00:00:00 2001 From: edujugon Date: Thu, 4 Jan 2018 00:10:48 +0100 Subject: [PATCH 12/45] Code refactoring on Channels --- src/Channels/ApnChannel.php | 32 +++++++------------- src/Channels/FcmChannel.php | 38 ++--------------------- src/Channels/GcmChannel.php | 32 +++++++------------- src/Channels/PushChannel.php | 58 +++++++++++++++++++++++++++++++++++- 4 files changed, 82 insertions(+), 78 deletions(-) diff --git a/src/Channels/ApnChannel.php b/src/Channels/ApnChannel.php index cb7ac48..47810c9 100644 --- a/src/Channels/ApnChannel.php +++ b/src/Channels/ApnChannel.php @@ -2,30 +2,20 @@ namespace Edujugon\PushNotification\Channels; -use Edujugon\PushNotification\Messages\PushMessage; -use Illuminate\Notifications\Notification; - class ApnChannel extends PushChannel { - /** - * Send the given notification. - * - * @param mixed $notifiable - * @param \Illuminate\Notifications\Notification $notification - * @return void - */ - public function send($notifiable, Notification $notification) + protected function pushServiceName() { - if (! $to = $notifiable->routeNotificationFor('Apn')) { - return; - } - - $message = $notification->toApn($notifiable); + return 'apn'; + } - if (is_string($message)) { - $message = new PushMessage($message); - } + protected function extraDataName() + { + return 'extraPayLoad'; + } + protected function buildData($message) + { $data = [ 'aps' => [ 'alert' => [ @@ -37,9 +27,9 @@ public function send($notifiable, Notification $notification) ]; if (! empty($message->extra)) { - $data['extraPayLoad'] = $message->extra; + $data[$this->extraDataName()] = $message->extra; } - return $this->push('apn', $to, $data, $message); + return $data; } } diff --git a/src/Channels/FcmChannel.php b/src/Channels/FcmChannel.php index 2e61c98..4a40bb3 100644 --- a/src/Channels/FcmChannel.php +++ b/src/Channels/FcmChannel.php @@ -2,42 +2,10 @@ namespace Edujugon\PushNotification\Channels; -use Edujugon\PushNotification\Messages\PushMessage; -use Illuminate\Notifications\Notification; - -class FcmChannel extends PushChannel +class FcmChannel extends GcmChannel { - /** - * Send the given notification. - * - * @param mixed $notifiable - * @param \Illuminate\Notifications\Notification $notification - * @return void - */ - public function send($notifiable, Notification $notification) + protected function pushServiceName() { - if (! $to = $notifiable->routeNotificationFor('Fcm')) { - return; - } - - $message = $notification->toFcm($notifiable); - - if (is_string($message)) { - $message = new PushMessage($message); - } - - $data = [ - 'notification' => [ - 'title' => $message->title, - 'body' => $message->body, - 'sound' => $message->sound, - ], - ]; - - if (! empty($message->extra)) { - $data['data'] = $message->extra; - } - - return $this->push('fcm', $to, $data, $message); + return 'fcm'; } } diff --git a/src/Channels/GcmChannel.php b/src/Channels/GcmChannel.php index 1b3626c..1a24cbd 100644 --- a/src/Channels/GcmChannel.php +++ b/src/Channels/GcmChannel.php @@ -2,30 +2,20 @@ namespace Edujugon\PushNotification\Channels; -use Edujugon\PushNotification\Messages\PushMessage; -use Illuminate\Notifications\Notification; - class GcmChannel extends PushChannel { - /** - * Send the given notification. - * - * @param mixed $notifiable - * @param \Illuminate\Notifications\Notification $notification - * @return void - */ - public function send($notifiable, Notification $notification) + protected function pushServiceName() { - if (! $to = $notifiable->routeNotificationFor('Gcm')) { - return; - } - - $message = $notification->toGcm($notifiable); + return 'gcm'; + } - if (is_string($message)) { - $message = new PushMessage($message); - } + protected function extraDataName() + { + return 'data'; + } + protected function buildData($message) + { $data = [ 'notification' => [ 'title' => $message->title, @@ -35,9 +25,9 @@ public function send($notifiable, Notification $notification) ]; if (! empty($message->extra)) { - $data['data'] = $message->extra; + $data[$this->extraDataName()] = $message->extra; } - $this->push('gcm', $to, $data, $message); + return $data; } } diff --git a/src/Channels/PushChannel.php b/src/Channels/PushChannel.php index 4d4a643..5225660 100644 --- a/src/Channels/PushChannel.php +++ b/src/Channels/PushChannel.php @@ -5,6 +5,7 @@ use Edujugon\PushNotification\Events\NotificationPushed; use Edujugon\PushNotification\Messages\PushMessage; use Edujugon\PushNotification\PushNotification; +use Illuminate\Notifications\Notification; abstract class PushChannel { @@ -23,6 +24,26 @@ public function __construct(PushNotification $push) $this->push = $push; } + /** + * Send the given notification. + * + * @param mixed $notifiable + * @param \Illuminate\Notifications\Notification $notification + * @return void + */ + public function send($notifiable, Notification $notification) + { + if (! $to = $notifiable->routeNotificationFor($this->notificationFor())) { + return; + } + + $message = $this->buildMessage($notifiable,$notification); + + $data = $this->buildData($message); + + $this->push($this->pushServiceName(), $to, $data, $message); + } + /** * Send the push notification. * @@ -49,8 +70,43 @@ protected function push($service, $to, $data, PushMessage $message) $feedback = $this->push->send() ->getFeedback(); - event(new NotificationPushed($this->push)); + if(function_exists('broadcast')) { + broadcast(new NotificationPushed($this->push)); + }elseif (function_exists('event')) { + event(new NotificationPushed($this->push)); + } return $feedback; } + + protected function buildMessage($notifiable,$notification) + { + $message = call_user_func_array([$notification,$this->getToMethod()], [$notifiable]); + + if (is_string($message)) { + $message = new PushMessage($message); + } + + return $message; + } + + /** + * @return string + */ + protected function getToMethod() + { + return "to" . ucfirst($this->pushServiceName()); + } + + /** + * @return string + */ + protected function notificationFor() + { + return ucfirst(strtolower($this->pushServiceName())); + } + + protected abstract function buildData($message); + protected abstract function pushServiceName(); + protected abstract function extraDataName(); } From fe885f3d623999d1d82837624f931e4b5cec66a7 Mon Sep 17 00:00:00 2001 From: Lynh Tran Date: Thu, 4 Jan 2018 09:38:30 +0700 Subject: [PATCH 13/45] Update docblock and CS fixes --- src/Channels/ApnChannel.php | 13 ++++++------ src/Channels/FcmChannel.php | 3 +++ src/Channels/GcmChannel.php | 13 ++++++------ src/Channels/PushChannel.php | 40 ++++++++++++++++++++++++++++-------- 4 files changed, 48 insertions(+), 21 deletions(-) diff --git a/src/Channels/ApnChannel.php b/src/Channels/ApnChannel.php index 47810c9..ed352e2 100644 --- a/src/Channels/ApnChannel.php +++ b/src/Channels/ApnChannel.php @@ -4,16 +4,17 @@ class ApnChannel extends PushChannel { + /** + * {@inheritdoc} + */ protected function pushServiceName() { return 'apn'; } - protected function extraDataName() - { - return 'extraPayLoad'; - } - + /** + * {@inheritdoc} + */ protected function buildData($message) { $data = [ @@ -27,7 +28,7 @@ protected function buildData($message) ]; if (! empty($message->extra)) { - $data[$this->extraDataName()] = $message->extra; + $data['extraPayLoad'] = $message->extra; } return $data; diff --git a/src/Channels/FcmChannel.php b/src/Channels/FcmChannel.php index 4a40bb3..77b3529 100644 --- a/src/Channels/FcmChannel.php +++ b/src/Channels/FcmChannel.php @@ -4,6 +4,9 @@ class FcmChannel extends GcmChannel { + /** + * {@inheritdoc} + */ protected function pushServiceName() { return 'fcm'; diff --git a/src/Channels/GcmChannel.php b/src/Channels/GcmChannel.php index 1a24cbd..78ebfa7 100644 --- a/src/Channels/GcmChannel.php +++ b/src/Channels/GcmChannel.php @@ -4,16 +4,17 @@ class GcmChannel extends PushChannel { + /** + * {@inheritdoc} + */ protected function pushServiceName() { return 'gcm'; } - protected function extraDataName() - { - return 'data'; - } - + /** + * {@inheritdoc} + */ protected function buildData($message) { $data = [ @@ -25,7 +26,7 @@ protected function buildData($message) ]; if (! empty($message->extra)) { - $data[$this->extraDataName()] = $message->extra; + $data['data'] = $message->extra; } return $data; diff --git a/src/Channels/PushChannel.php b/src/Channels/PushChannel.php index 5225660..2637374 100644 --- a/src/Channels/PushChannel.php +++ b/src/Channels/PushChannel.php @@ -37,7 +37,7 @@ public function send($notifiable, Notification $notification) return; } - $message = $this->buildMessage($notifiable,$notification); + $message = $this->buildMessage($notifiable, $notification); $data = $this->buildData($message); @@ -70,18 +70,25 @@ protected function push($service, $to, $data, PushMessage $message) $feedback = $this->push->send() ->getFeedback(); - if(function_exists('broadcast')) { + if (function_exists('broadcast')) { broadcast(new NotificationPushed($this->push)); - }elseif (function_exists('event')) { + } elseif (function_exists('event')) { event(new NotificationPushed($this->push)); } return $feedback; } - protected function buildMessage($notifiable,$notification) + /** + * Format the message. + * + * @param mixed $notifiable + * @param \Illuminate\Notifications\Notification $notification + * @return \Edujugon\PushNotification\Messages\PushMessage + */ + protected function buildMessage($notifiable, Notification $notification) { - $message = call_user_func_array([$notification,$this->getToMethod()], [$notifiable]); + $message = call_user_func_array([$notification, $this->getToMethod()], [$notifiable]); if (is_string($message)) { $message = new PushMessage($message); @@ -91,14 +98,18 @@ protected function buildMessage($notifiable,$notification) } /** + * Get the method name to get the push notification representation of the notification. + * * @return string */ protected function getToMethod() { - return "to" . ucfirst($this->pushServiceName()); + return 'to' . ucfirst($this->pushServiceName()); } /** + * Format push service name for routing notification. + * * @return string */ protected function notificationFor() @@ -106,7 +117,18 @@ protected function notificationFor() return ucfirst(strtolower($this->pushServiceName())); } - protected abstract function buildData($message); - protected abstract function pushServiceName(); - protected abstract function extraDataName(); + /** + * Build the push payload data. + * + * @param \Edujugon\PushNotification\Messages\PushMessage $message + * @return array + */ + abstract protected function buildData(PushMessage $message); + + /** + * Get push notification service name. + * + * @return string + */ + abstract protected function pushServiceName(); } From 1a68870a6a9aa256398b5975e2cb180bd23e7799 Mon Sep 17 00:00:00 2001 From: Lynh Tran Date: Thu, 4 Jan 2018 09:41:09 +0700 Subject: [PATCH 14/45] Add param signature --- src/Channels/ApnChannel.php | 4 +++- src/Channels/GcmChannel.php | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Channels/ApnChannel.php b/src/Channels/ApnChannel.php index ed352e2..5fa4e01 100644 --- a/src/Channels/ApnChannel.php +++ b/src/Channels/ApnChannel.php @@ -2,6 +2,8 @@ namespace Edujugon\PushNotification\Channels; +use Edujugon\PushNotification\Messages\PushMessage; + class ApnChannel extends PushChannel { /** @@ -15,7 +17,7 @@ protected function pushServiceName() /** * {@inheritdoc} */ - protected function buildData($message) + protected function buildData(PushMessage $message) { $data = [ 'aps' => [ diff --git a/src/Channels/GcmChannel.php b/src/Channels/GcmChannel.php index 78ebfa7..b65a4f1 100644 --- a/src/Channels/GcmChannel.php +++ b/src/Channels/GcmChannel.php @@ -2,6 +2,8 @@ namespace Edujugon\PushNotification\Channels; +use Edujugon\PushNotification\Messages\PushMessage; + class GcmChannel extends PushChannel { /** @@ -15,7 +17,7 @@ protected function pushServiceName() /** * {@inheritdoc} */ - protected function buildData($message) + protected function buildData(PushMessage $message) { $data = [ 'notification' => [ From 3938248c3b49ed24d19ab76ae545b4db17cb0226 Mon Sep 17 00:00:00 2001 From: edujugon Date: Wed, 10 Jan 2018 20:32:43 +0100 Subject: [PATCH 15/45] Code Refactoring Extract broadcasting action to a method --- src/Channels/PushChannel.php | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Channels/PushChannel.php b/src/Channels/PushChannel.php index 2637374..888e6dc 100644 --- a/src/Channels/PushChannel.php +++ b/src/Channels/PushChannel.php @@ -70,11 +70,7 @@ protected function push($service, $to, $data, PushMessage $message) $feedback = $this->push->send() ->getFeedback(); - if (function_exists('broadcast')) { - broadcast(new NotificationPushed($this->push)); - } elseif (function_exists('event')) { - event(new NotificationPushed($this->push)); - } + $this->broadcast(); return $feedback; } @@ -125,10 +121,23 @@ protected function notificationFor() */ abstract protected function buildData(PushMessage $message); + /** + * BroadCast NotificationPushed event + */ + protected function broadcast() + { + if (function_exists('broadcast')) { + broadcast(new NotificationPushed($this->push)); + } elseif (function_exists('event')) { + event(new NotificationPushed($this->push)); + } + } + /** * Get push notification service name. * * @return string */ abstract protected function pushServiceName(); + } From 7f0e4378016d2fecdf0925581af70eb83d302205 Mon Sep 17 00:00:00 2001 From: edujugon Date: Sat, 13 Jan 2018 17:53:44 +0100 Subject: [PATCH 16/45] Update dependency versions --- composer.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 3fc23c3..c295a54 100644 --- a/composer.json +++ b/composer.json @@ -10,9 +10,10 @@ } ], "require": { - "php" : ">=5.6.0", + "php" : ">=5.6.4", "guzzlehttp/guzzle": "^6.2", - "illuminate/support": "^5.2" + "illuminate/support": "^5.3", + "illuminate/notifications": "^5.3" }, "require-dev": { "phpunit/phpunit": "4.0.*" From a90ab164ec7031aabc1d34e2dbc78e8e5b144281 Mon Sep 17 00:00:00 2001 From: Jamie Couture Date: Mon, 15 Jan 2018 10:52:08 -0500 Subject: [PATCH 17/45] apn.php: avoid recursion on connection failure Currently when Apn.php attempts to connect to apple push services we attempt to re-try caught exceptions if one is thrown. However, in situations where a push certificate is invalid or expired we run into infinite recursion constantly re-trying the connection without providing any feedback. The following will set a limit on the number of times we may re-try. Configurable if users define 'connection_attempts'. Default is three attempts before giving up. Feedback will be set with the last known failure reason. Original behaviour can be achieved by explicitly setting 'connection_attempts' to zero in the setConfig() assoc-array. Signed-off-by: Jamie Couture --- readme.md | 17 ++++++++ src/Apn.php | 72 ++++++++++++++++++++++++++++++++-- tests/PushNotificationTest.php | 66 ++++++++++++++++++++++++++++++- 3 files changed, 151 insertions(+), 4 deletions(-) diff --git a/readme.md b/readme.md index 74d97b0..9dba56b 100644 --- a/readme.md +++ b/readme.md @@ -88,12 +88,14 @@ The default configuration parameters for **APN** are: * passPhrase => 'MyPassPhrase' * passFile => __DIR__ . '/iosCertificates/yourKey.pem' //Optional * dry_run => false +* connection_attempts => 3 //Optional Also you can update those values and add more dynamically $push->setConfig([ 'passPhrase' => 'NewPass', 'custom' => 'MycustomValue', + 'connection_attempts' => 3, 'dry_run' => true ]); @@ -103,6 +105,21 @@ Even you may update the url of the Push Service dynamically like follows: > Not update the url unless it's really necessary. +You can specify the number of client-side attempts to APN before giving +up. The default amount is 3 attempts. You can override this value by +specifying `connection_attempts` in `setConfig()` assoc-array. Keep in +mind the default number of requested attempts is 3. + +If you prefer to retry indefinitely, set `connection_attempts` to zero. + + $push->setConfig([ + 'passPhrase' => 'NewPass', + 'custom' => 'MycustomValue', + 'connection_attempts' => 0, + 'dry_run' => true + ]); + + ## Usage $push = new PushNotification; diff --git a/src/Apn.php b/src/Apn.php index a940134..853e945 100644 --- a/src/Apn.php +++ b/src/Apn.php @@ -6,6 +6,8 @@ class Apn extends PushService implements PushServiceInterface { + const MAX_ATTEMPTS = 3; + /** * Url for development purposes * @@ -39,6 +41,16 @@ class Apn extends PushService implements PushServiceInterface */ private $feedbackUrl; + /** + * The number of attempts to re-try before failing. + * Set to zero for unlimited attempts. + * + * @var int + */ + private $maxAttempts = self::MAX_ATTEMPTS; + + private $attempts = 0; + /** * Apn constructor. */ @@ -63,7 +75,7 @@ public function setConfig(array $config) parent::setConfig($config); $this->setProperGateway(); - + $this->setRetryAttemptsIfConfigured(); } /** @@ -86,6 +98,45 @@ private function setProperGateway() } } + /** + * Configure re-try attempts. + * + * @return void + */ + private function setRetryAttemptsIfConfigured() + { + if (isset($this->config['connection_attempts']) && + is_numeric($this->config['connection_attempts'])) + { + $this->maxAttempts = $this->config['connection_attempts']; + } + } + + /** + * Determines whether the connection attempts should be unlimited. + * + * @retorn bool + */ + private function isUnlimitedAttempts() + { + return $this->maxAttempts == 0; + } + + private function canRetry() + { + if ($this->isUnlimitedAttempts()) + return true; + + $this->attempts++; + return $this->attempts < $this->maxAttempts; + } + + private function resetAttempts() + { + $this->attempts = 0; + return $this; + } + /** * Provide the unregistered tokens of the notification sent. * @@ -183,7 +234,13 @@ private function openConnectionAPNS($ctx) $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx); }catch (\Exception $e){ //if stream socket can't be established, try again - return $this->openConnectionAPNS($ctx); + if ($this->canRetry()) + return $this->openConnectionAPNS($ctx); + + $response = ['success' => false, 'error' => 'Connection problem: ' . $e->getMessage() . PHP_EOL]; + $this->setFeedback(json_decode(json_encode($response), FALSE)); + + return false; } stream_set_blocking ($fp, 0); @@ -196,6 +253,8 @@ private function openConnectionAPNS($ctx) return false; } + + $this->resetAttempts(); return $fp; } @@ -301,7 +360,13 @@ public function apnsFeedback() { $apns = stream_socket_client($this->feedbackUrl, $errcode, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx); }catch (\Exception $e){ //if stream socket can't be established, try again - return $this->apnsFeedback(); + if ($this->canRetry()) + return $this->apnsFeedback(); + + $response = ['success' => false, 'error' => 'APNS feedback connection problem: ' . $e->getMessage() . PHP_EOL]; + $this->setFeedback(json_decode(json_encode($response), FALSE)); + + return false; } //Read the data on the connection: @@ -313,6 +378,7 @@ public function apnsFeedback() { } fclose($apns); + $this->resetAttempts(); return $feedback_tokens; } diff --git a/tests/PushNotificationTest.php b/tests/PushNotificationTest.php index 3a4528c..207752f 100644 --- a/tests/PushNotificationTest.php +++ b/tests/PushNotificationTest.php @@ -289,4 +289,68 @@ public function fake_unregisteredDevicesToken_with_apn_feedback_response_merged_ //var_dump($tokens); } -} \ No newline at end of file + + /** @test */ + public function apn_connection_attempts_default() { + $push = new PushNotification('apn'); + + $push->setConfig(['dry_run' => true]); + + $key = 'connection_attempts'; + $this->assertArrayNotHasKey($key, $push->config); + } + + /** @test */ + public function set_apn_connect_attempts_override_default() { + $push = new PushNotification('apn'); + + $expected = 0; + $push->setConfig([ + 'dry_run' => true, + 'connection_attempts' => $expected, + ]); + + $key = 'connection_attempts'; + $this->assertArrayHasKey($key, $push->config); + $this->assertEquals($expected, $push->config[$key]); + } + + /** @test */ + public function apn_connect_attempts_bailout_badcert() { + $push = new PushNotification('apn'); + + $tmp_name = tempnam(sys_get_temp_dir(), 'apn-tmp'); + $fh = fopen($tmp_name, 'w'); + fwrite($fh, 'badcert'); + fclose($fh); + + $expected = 0; + + // ZZZ: intentional failure use-case so let's not + // waste time attemping to push with a bad cert. + $push->setConfig([ + 'dry_run' => true, + 'connection_attempts' => 1, + 'certificate' => $tmp_name, + ]); + + $message = [ + 'aps' => [ + 'alert' => [ + 'title' => '1 Notification test', + 'body' => 'Just for testing purposes' + ], + 'sound' => 'default' + ] + ]; + + $push->setMessage($message) + ->setDevicesToken(['507e3adaf433ae3e6234f35c82f8a43ad0d84218bff08f16ea7be0869f066c0312']); + + $push = $push->send(); + $this->assertInstanceOf('stdClass', $push->getFeedback()); + + unlink($tmp_name); + } + +} From 47b797abb3c8669c567c4e3588127055946db563 Mon Sep 17 00:00:00 2001 From: edujugon Date: Sat, 20 Jan 2018 20:34:15 +0100 Subject: [PATCH 18/45] Code refactoring --- src/Apn.php | 68 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/src/Apn.php b/src/Apn.php index 853e945..b5146ff 100644 --- a/src/Apn.php +++ b/src/Apn.php @@ -115,13 +115,18 @@ private function setRetryAttemptsIfConfigured() /** * Determines whether the connection attempts should be unlimited. * - * @retorn bool + * @return bool */ private function isUnlimitedAttempts() { return $this->maxAttempts == 0; } + /** + * Check if can retry a connection + * + * @return bool + */ private function canRetry() { if ($this->isUnlimitedAttempts()) @@ -131,6 +136,11 @@ private function canRetry() return $this->attempts < $this->maxAttempts; } + /** + * Reset connection attempts + * + * @return $this + */ private function resetAttempts() { $this->attempts = 0; @@ -226,12 +236,24 @@ private function composeStreamSocket() */ private function openConnectionAPNS($ctx) { + $fp = false; // Open a connection to the APNS server try{ $fp = stream_socket_client( $this->url, $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx); + + stream_set_blocking ($fp, 0); + + if (!$fp) + { + $response = ['success' => false, 'error' => "Failed to connect: $err $errstr" . PHP_EOL]; + + $this->setFeedback(json_decode(json_encode($response), FALSE)); + + } + }catch (\Exception $e){ //if stream socket can't be established, try again if ($this->canRetry()) @@ -240,22 +262,10 @@ private function openConnectionAPNS($ctx) $response = ['success' => false, 'error' => 'Connection problem: ' . $e->getMessage() . PHP_EOL]; $this->setFeedback(json_decode(json_encode($response), FALSE)); - return false; + }finally { + $this->resetAttempts(); + return $fp; } - - stream_set_blocking ($fp, 0); - - if (!$fp) - { - $response = ['success' => false, 'error' => "Failed to connect: $err $errstr" . PHP_EOL]; - - $this->setFeedback(json_decode(json_encode($response), FALSE)); - - return false; - } - - $this->resetAttempts(); - return $fp; } /** @@ -358,6 +368,16 @@ public function apnsFeedback() { // Open a connection to the APNS server try{ $apns = stream_socket_client($this->feedbackUrl, $errcode, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx); + + //Read the data on the connection: + while(!feof($apns)) { + $data = fread($apns, 38); + if(strlen($data)) { + $feedback_tokens['apnsFeedback'][] = unpack("N1timestamp/n1length/H*devtoken", $data); + } + } + fclose($apns); + }catch (\Exception $e){ //if stream socket can't be established, try again if ($this->canRetry()) @@ -366,21 +386,11 @@ public function apnsFeedback() { $response = ['success' => false, 'error' => 'APNS feedback connection problem: ' . $e->getMessage() . PHP_EOL]; $this->setFeedback(json_decode(json_encode($response), FALSE)); - return false; + }finally { + $this->resetAttempts(); + return $feedback_tokens; } - //Read the data on the connection: - while(!feof($apns)) { - $data = fread($apns, 38); - if(strlen($data)) { - $feedback_tokens['apnsFeedback'][] = unpack("N1timestamp/n1length/H*devtoken", $data); - } - } - fclose($apns); - - $this->resetAttempts(); - return $feedback_tokens; - } /** From c6dfd40203794e9d2bc3b69c64792b5547033e6b Mon Sep 17 00:00:00 2001 From: edujugon Date: Sat, 24 Feb 2018 13:50:13 +0100 Subject: [PATCH 19/45] Update documentation Add more info about notification channels --- readme.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/readme.md b/readme.md index fc0549e..cdee55a 100644 --- a/readme.md +++ b/readme.md @@ -552,6 +552,15 @@ public function toApn($notifiable) } ``` +#### Add it to the notification channels +```php +public function via($notifiable) +{ + return [ApnChannel::class]; +} +``` +>Don't forget the use statement at the top of the class + #### Routing Push Notifications Just define `routeNotificationForApn` and/or `routeNotificationForFcm`/`routeNotificationForGcm` methods on the entity ```php From ee62270859e9fe3ba3682dda7b6ec2f861295964 Mon Sep 17 00:00:00 2001 From: Jeroen Date: Mon, 26 Feb 2018 10:35:18 +0100 Subject: [PATCH 20/45] Added badge option in APN example showcase the possibility to change badge number in APN example --- readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index cdee55a..f05f518 100644 --- a/readme.md +++ b/readme.md @@ -302,7 +302,8 @@ $push->setMessage([ ], 'extraPayLoad' => [ 'custom' => 'My custom data', - ] + ], + 'badge' => 1 ]) ->setDevicesToken(['deviceToken1','deviceToken2','deviceToken3'...]); ``` From 37cec6604bd93fc201c3d8838caedb673f3d69cc Mon Sep 17 00:00:00 2001 From: Jeroen Date: Mon, 26 Feb 2018 10:38:43 +0100 Subject: [PATCH 21/45] Update readme.md --- readme.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index f05f518..6831898 100644 --- a/readme.md +++ b/readme.md @@ -297,13 +297,14 @@ $push->setMessage([ 'title' => 'This is the title', 'body' => 'This is the body' ], - 'sound' => 'default' + 'sound' => 'default', + 'badge' => 1 ], 'extraPayLoad' => [ 'custom' => 'My custom data', ], - 'badge' => 1 + ]) ->setDevicesToken(['deviceToken1','deviceToken2','deviceToken3'...]); ``` From 1759dd4132f27cc518b497170140db9d7f91cb75 Mon Sep 17 00:00:00 2001 From: edujugon Date: Wed, 25 Apr 2018 21:54:55 +0200 Subject: [PATCH 22/45] Update readme --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index cdee55a..8be9ba1 100644 --- a/readme.md +++ b/readme.md @@ -63,7 +63,7 @@ php artisan vendor:publish --provider="Edujugon\PushNotification\Providers\PushN ### Configuration -The default configuration for all Push service providers is located in Config/config.php +After publishing the configuration, all the Push service config details are located in config/pushnotification.php The default configuration parameters for **GCM** and **FCM** are : From 7b7daf4b20313d2c79bc384ba5fe778167af1c18 Mon Sep 17 00:00:00 2001 From: edujugon Date: Wed, 25 Apr 2018 22:01:01 +0200 Subject: [PATCH 23/45] Small change remove unnecessary comma --- readme.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 6488908..f57a009 100644 --- a/readme.md +++ b/readme.md @@ -303,8 +303,7 @@ $push->setMessage([ ], 'extraPayLoad' => [ 'custom' => 'My custom data', - ], - + ] ]) ->setDevicesToken(['deviceToken1','deviceToken2','deviceToken3'...]); ``` From 0fd60a7b0ca2046bcd4ac38d7a623e68bac3d11f Mon Sep 17 00:00:00 2001 From: Kamil Kuklinski Date: Fri, 27 Apr 2018 10:07:40 +0100 Subject: [PATCH 24/45] Update readme.me Added info about dry_run parameter to make sure other developers won't make same mistake I did. --- readme.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/readme.md b/readme.md index f57a009..202c9e2 100644 --- a/readme.md +++ b/readme.md @@ -88,6 +88,8 @@ The default configuration parameters for **APN** are: * ```passFile => __DIR__ . '/iosCertificates/yourKey.pem' //Optional``` * ```dry_run => false``` +(Make sure to set `dry_run` to `true` if you're using development *.pem certificate, and `false` for production) + Also you can update those values and add more dynamically ```php $push->setConfig([ From 7ff54538e11ec4f68872495d5eca70574707eb84 Mon Sep 17 00:00:00 2001 From: Jason Kirow Date: Wed, 27 Jun 2018 14:23:12 -0400 Subject: [PATCH 25/45] Allow a badge attribute to be passed through to the Apn Channel. --- src/Channels/ApnChannel.php | 1 + src/Messages/PushMessage.php | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/Channels/ApnChannel.php b/src/Channels/ApnChannel.php index 5fa4e01..d729b8a 100644 --- a/src/Channels/ApnChannel.php +++ b/src/Channels/ApnChannel.php @@ -26,6 +26,7 @@ protected function buildData(PushMessage $message) 'body' => $message->body, ], 'sound' => $message->sound, + 'badge' => $message->badge, ], ]; diff --git a/src/Messages/PushMessage.php b/src/Messages/PushMessage.php index 13f1ee6..4187034 100644 --- a/src/Messages/PushMessage.php +++ b/src/Messages/PushMessage.php @@ -19,6 +19,11 @@ class PushMessage */ public $sound = 'default'; + /** + * @var integer + */ + public $badge; + /** * @var array */ @@ -79,6 +84,19 @@ public function sound($sound) return $this; } + /** + * Set the notification badge. + * + * @param integer $badge + * @return void + */ + public function badge($badge) + { + $this->badge = $badge; + + return $this; + } + /** * Set message extra data. * From 8cc96346ba8e44697d0bcb8436d93b7fdfe24eda Mon Sep 17 00:00:00 2001 From: Jason Kirow Date: Wed, 27 Jun 2018 15:27:49 -0400 Subject: [PATCH 26/45] Update Readme --- readme.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/readme.md b/readme.md index 202c9e2..f0e8447 100644 --- a/readme.md +++ b/readme.md @@ -545,6 +545,16 @@ public function toApn($notifiable) } ``` +#### Customizing The Badge Number +```php +public function toApn($notifiable) +{ + return (new PushMessage) + ->body('Hello world') + ->sound('default') + ->badge(7); +} + #### Passing Service Config ```php public function toApn($notifiable) From 27f83cc5c7af3286814fe682dabbf71695cce57e Mon Sep 17 00:00:00 2001 From: edujugon Date: Fri, 29 Jun 2018 17:15:36 +0200 Subject: [PATCH 27/45] typo and set correct return values --- src/Messages/PushMessage.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Messages/PushMessage.php b/src/Messages/PushMessage.php index 4187034..1974eb7 100644 --- a/src/Messages/PushMessage.php +++ b/src/Messages/PushMessage.php @@ -48,7 +48,7 @@ public function __construct($body = '') /** * Set the message body. * - * @param string $title + * @param string $body * @return $this */ public function body($body) @@ -75,7 +75,7 @@ public function title($title) * Set the notification sound. * * @param string $sound - * @return void + * @return $this */ public function sound($sound) { @@ -88,7 +88,7 @@ public function sound($sound) * Set the notification badge. * * @param integer $badge - * @return void + * @return $this */ public function badge($badge) { From f254f6f254ec5036a3f88b8bdcb43ef6ecb7e38b Mon Sep 17 00:00:00 2001 From: edujugon Date: Fri, 29 Jun 2018 17:18:41 +0200 Subject: [PATCH 28/45] small presentation fix --- readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.md b/readme.md index f0e8447..cffae7a 100644 --- a/readme.md +++ b/readme.md @@ -554,6 +554,7 @@ public function toApn($notifiable) ->sound('default') ->badge(7); } +``` #### Passing Service Config ```php From 466938c85b8cf2396b0f36aaffe0572a0b172db1 Mon Sep 17 00:00:00 2001 From: edujugon Date: Fri, 29 Jun 2018 17:28:46 +0200 Subject: [PATCH 29/45] Add a badge key to the data only if it has been provided and is numeric --- src/Channels/ApnChannel.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Channels/ApnChannel.php b/src/Channels/ApnChannel.php index d729b8a..f068d35 100644 --- a/src/Channels/ApnChannel.php +++ b/src/Channels/ApnChannel.php @@ -26,7 +26,6 @@ protected function buildData(PushMessage $message) 'body' => $message->body, ], 'sound' => $message->sound, - 'badge' => $message->badge, ], ]; @@ -34,6 +33,10 @@ protected function buildData(PushMessage $message) $data['extraPayLoad'] = $message->extra; } + if (is_numeric($message->badge)) { + $data['aps']['badge'] = $message->badge; + } + return $data; } } From 9c7abf56d8dd7b718944c1d22bd01b397c8f57bb Mon Sep 17 00:00:00 2001 From: edujugon Date: Sat, 1 Sep 2018 10:18:22 +0200 Subject: [PATCH 30/45] Throw exception if service is not defined in config file. This closes #23 --- src/Exceptions/PushNotificationException.php | 7 ++++++ src/PushService.php | 24 ++++++++++---------- 2 files changed, 19 insertions(+), 12 deletions(-) create mode 100644 src/Exceptions/PushNotificationException.php diff --git a/src/Exceptions/PushNotificationException.php b/src/Exceptions/PushNotificationException.php new file mode 100644 index 0000000..02f9cdd --- /dev/null +++ b/src/Exceptions/PushNotificationException.php @@ -0,0 +1,7 @@ + Date: Sun, 28 Oct 2018 10:16:41 +0100 Subject: [PATCH 31/45] Code refatoring * coding style (PSR-2) --- src/Apn.php | 150 ++++++++++-------- src/Channels/PushChannel.php | 1 - src/Contracts/PushServiceInterface.php | 14 +- src/Exceptions/PushNotificationException.php | 2 +- src/Facades/PushNotification.php | 11 +- src/Fcm.php | 8 +- src/Gcm.php | 55 +++---- .../PushNotificationServiceProvider.php | 3 +- src/PushNotification.php | 51 +++--- src/PushService.php | 9 +- tests/PushNotificationTest.php | 98 ++++++------ 11 files changed, 210 insertions(+), 192 deletions(-) diff --git a/src/Apn.php b/src/Apn.php index b5146ff..23ca60e 100644 --- a/src/Apn.php +++ b/src/Apn.php @@ -85,13 +85,12 @@ public function setConfig(array $config) */ private function setProperGateway() { - if(isset($this->config['dry_run'])) - { - if($this->config['dry_run']){ + if (isset($this->config['dry_run'])) { + if ($this->config['dry_run']) { $this->setUrl($this->sandboxUrl); $this->feedbackUrl = $this->feedbackSandboxUrl; - }else { + } else { $this->setUrl($this->productionUrl); $this->feedbackUrl = $this->feedbackProductionUrl; } @@ -106,8 +105,7 @@ private function setProperGateway() private function setRetryAttemptsIfConfigured() { if (isset($this->config['connection_attempts']) && - is_numeric($this->config['connection_attempts'])) - { + is_numeric($this->config['connection_attempts'])) { $this->maxAttempts = $this->config['connection_attempts']; } } @@ -129,10 +127,12 @@ private function isUnlimitedAttempts() */ private function canRetry() { - if ($this->isUnlimitedAttempts()) + if ($this->isUnlimitedAttempts()) { return true; + } $this->attempts++; + return $this->attempts < $this->maxAttempts; } @@ -144,6 +144,7 @@ private function canRetry() private function resetAttempts() { $this->attempts = 0; + return $this; } @@ -157,10 +158,12 @@ public function getUnregisteredDeviceTokens(array $devices_token) { $tokens = []; - if(! empty($this->feedback->tokenFailList)) - $tokens = $this->feedback->tokenFailList; - if(!empty($this->feedback->apnsFeedback)) - $tokens = array_merge($tokens,array_pluck($this->feedback->apnsFeedback,'devtoken')); + if (!empty($this->feedback->tokenFailList)) { + $tokens = $this->feedback->tokenFailList; + } + if (!empty($this->feedback->apnsFeedback)) { + $tokens = array_merge($tokens, array_pluck($this->feedback->apnsFeedback, 'devtoken')); + } return $tokens; } @@ -172,9 +175,12 @@ public function getUnregisteredDeviceTokens(array $devices_token) */ private function messageNoExistCertificate() { - $response = ['success' => false, 'error' => "Please, add your APN certificate to the iosCertificates folder." . PHP_EOL]; + $response = [ + 'success' => false, + 'error' => "Please, add your APN certificate to the iosCertificates folder." . PHP_EOL + ]; - $this->setFeedback(json_decode(json_encode($response), FALSE)); + $this->setFeedback(json_decode(json_encode($response))); } /** @@ -183,11 +189,9 @@ private function messageNoExistCertificate() */ private function existCertificate() { - if(isset($this->config['certificate'])) - { + if (isset($this->config['certificate'])) { $certificate = $this->config['certificate']; - if(!file_exists($certificate)) - { + if (!file_exists($certificate)) { $this->messageNoExistCertificate(); return false; } @@ -212,16 +216,18 @@ private function composeStreamSocket() $certificate = $this->config['certificate']; stream_context_set_option($ctx, 'ssl', 'local_cert', $certificate); - if(isset($this->config['passPhrase'])) - { + if (isset($this->config['passPhrase'])) { $passPhrase = $this->config['passPhrase']; - if(!empty($passPhrase)) stream_context_set_option($ctx, 'ssl', 'passphrase', $passPhrase); + if (!empty($passPhrase)) { + stream_context_set_option($ctx, 'ssl', 'passphrase', $passPhrase); + } } - if(isset($this->config['passFile'])) - { + if (isset($this->config['passFile'])) { $passFile = $this->config['passFile']; - if(file_exists($passFile)) stream_context_set_option($ctx, 'ssl', 'local_pk', $passFile); + if (file_exists($passFile)) { + stream_context_set_option($ctx, 'ssl', 'local_pk', $passFile); + } } return $ctx; @@ -239,30 +245,35 @@ private function openConnectionAPNS($ctx) $fp = false; // Open a connection to the APNS server - try{ + try { $fp = stream_socket_client( - $this->url, $err, - $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx); + $this->url, + $err, + $errstr, + 60, + STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, + $ctx + ); - stream_set_blocking ($fp, 0); + stream_set_blocking($fp, 0); - if (!$fp) - { + if (!$fp) { $response = ['success' => false, 'error' => "Failed to connect: $err $errstr" . PHP_EOL]; - $this->setFeedback(json_decode(json_encode($response), FALSE)); + $this->setFeedback(json_decode(json_encode($response))); } - }catch (\Exception $e){ + } catch (\Exception $e) { //if stream socket can't be established, try again - if ($this->canRetry()) + if ($this->canRetry()) { return $this->openConnectionAPNS($ctx); + } $response = ['success' => false, 'error' => 'Connection problem: ' . $e->getMessage() . PHP_EOL]; - $this->setFeedback(json_decode(json_encode($response), FALSE)); + $this->setFeedback(json_decode(json_encode($response))); - }finally { + } finally { $this->resetAttempts(); return $fp; } @@ -274,14 +285,16 @@ private function openConnectionAPNS($ctx) * @param array $message * @return \stdClass APN Response */ - public function send(array $deviceTokens,array $message) + public function send(array $deviceTokens, array $message) { /** * If there isn't certificate returns the feedback. * Feedback has been loaded in existCertificate method if no certificate found */ - if(!$this->existCertificate()) return $this->feedback; + if (!$this->existCertificate()) { + return $this->feedback; + } // Encode the payload as JSON $payload = json_encode($message); @@ -289,23 +302,23 @@ public function send(array $deviceTokens,array $message) //When sending a notification we prepare a clean feedback $feedback = $this->initializeFeedback(); - foreach ($deviceTokens as $token) - { + foreach ($deviceTokens as $token) { /** * Open APN connection */ $ctx = $this->composeStreamSocket(); $fp = $this->openConnectionAPNS($ctx); - if(!$fp) return $this->feedback; + if (!$fp) { + return $this->feedback; + } // Build the binary notification - //Check if the token is numeric no to get PHP Warnings with pack function. - if (ctype_xdigit($token)) { + //Check if the token is numeric not to get PHP Warnings with pack function. + if (ctype_xdigit($token)) { $msg = chr(0) . pack('n', 32) . pack('H*', $token) . pack('n', strlen($payload)) . $payload; - }else - { + } else { $feedback['tokenFailList'][] = $token; $feedback['failure'] += 1; continue; @@ -313,13 +326,13 @@ public function send(array $deviceTokens,array $message) $result = fwrite($fp, $msg, strlen($msg)); - if (!$result) - { + if (!$result) { $feedback['tokenFailList'][] = $token; $feedback['failure'] += 1; - }else + } else { $feedback['success'] += 1; + } // Close the connection to the server if ($fp) { @@ -336,18 +349,16 @@ public function send(array $deviceTokens,array $message) /** * Merge the apn feedback to our custom feedback if there is any. */ - if(!empty($apnsFeedback)) - { - $feedback = array_merge($feedback,$apnsFeedback); + if (!empty($apnsFeedback)) { + $feedback = array_merge($feedback, $apnsFeedback); - $feedback = $this->updateCustomFeedbackValues($apnsFeedback, $feedback,$deviceTokens); + $feedback = $this->updateCustomFeedbackValues($apnsFeedback, $feedback, $deviceTokens); } //Set the global feedback - $this->setFeedback(json_decode(json_encode($feedback), FALSE)); + $this->setFeedback(json_decode(json_encode($feedback))); return $this->feedback; - } /** @@ -360,37 +371,43 @@ public function apnsFeedback() { $feedback_tokens = array(); - if(!$this->existCertificate()) return $feedback_tokens; + if (!$this->existCertificate()) { + return $feedback_tokens; + } //connect to the APNS feedback servers $ctx = $this->composeStreamSocket(); // Open a connection to the APNS server - try{ + try { $apns = stream_socket_client($this->feedbackUrl, $errcode, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx); //Read the data on the connection: - while(!feof($apns)) { + while (!feof($apns)) { $data = fread($apns, 38); - if(strlen($data)) { + if (strlen($data)) { $feedback_tokens['apnsFeedback'][] = unpack("N1timestamp/n1length/H*devtoken", $data); } } fclose($apns); - }catch (\Exception $e){ + } catch (\Exception $e) { //if stream socket can't be established, try again - if ($this->canRetry()) + if ($this->canRetry()) { return $this->apnsFeedback(); + } - $response = ['success' => false, 'error' => 'APNS feedback connection problem: ' . $e->getMessage() . PHP_EOL]; - $this->setFeedback(json_decode(json_encode($response), FALSE)); + $response = [ + 'success' => false, + 'error' => 'APNS feedback connection problem: ' . $e->getMessage() . PHP_EOL + ]; - }finally { + $this->setFeedback(json_decode(json_encode($response))); + + } finally { $this->resetAttempts(); return $feedback_tokens; } - } /** @@ -402,18 +419,17 @@ public function apnsFeedback() { * * @return array $feedback */ - private function updateCustomFeedbackValues($apnsFeedback, $feedback,$deviceTokens) + private function updateCustomFeedbackValues($apnsFeedback, $feedback, $deviceTokens) { //Add failures amount based on apple feedback to our custom feedback $feedback['failure'] += count($apnsFeedback['apnsFeedback']); //apns tokens - $apnsTokens = array_pluck($apnsFeedback['apnsFeedback'],'devtoken'); + $apnsTokens = array_pluck($apnsFeedback['apnsFeedback'], 'devtoken'); - foreach ($deviceTokens as $token) - { - if(in_array($token, $apnsTokens)){ + foreach ($deviceTokens as $token) { + if (in_array($token, $apnsTokens)) { $feedback['success'] -= 1; $feedback['tokenFailList'][] = $token; } diff --git a/src/Channels/PushChannel.php b/src/Channels/PushChannel.php index 888e6dc..1642938 100644 --- a/src/Channels/PushChannel.php +++ b/src/Channels/PushChannel.php @@ -1,5 +1,4 @@ addRequestHeaders(); $data = $this->buildData($topic, $message, $isCondition); @@ -51,7 +49,7 @@ public function sendByTopic($topic,$message, $isCondition = false) } catch (\Exception $e) { $response = ['success' => false, 'error' => $e->getMessage()]; - $this->setFeedback(json_decode(json_encode($response), FALSE)); + $this->setFeedback(json_decode(json_encode($response))); } finally { return $this->feedback; @@ -70,6 +68,6 @@ protected function buildData($topic, $message, $isCondition) { $condition = $isCondition ? ['condition' => $topic] : ['to' => '/topics/' . $topic]; - return array_merge($condition , $this->buildMessage($message)); + return array_merge($condition, $this->buildMessage($message)); } } \ No newline at end of file diff --git a/src/Gcm.php b/src/Gcm.php index bdbbd82..533e7f4 100644 --- a/src/Gcm.php +++ b/src/Gcm.php @@ -35,7 +35,7 @@ public function __construct() } /** - * Provide the unregistered tokens of the notification sent. + * Provide the unregistered tokens of the sent notification. * * @param array $devices_token * @return array $tokenUnRegistered @@ -45,18 +45,17 @@ public function getUnregisteredDeviceTokens(array $devices_token) /** * If there is any failure sending the notification */ - if($this->feedback && isset($this->feedback->failure)) - { - + if ($this->feedback && isset($this->feedback->failure)) { $unRegisteredTokens = $devices_token; /** * Walk the array looking for any error. * If no error, unset it from all token list which will become the unregistered tokens array. */ - foreach ($this->feedback->results as $key => $message) - { - if(! isset($message->error)) unset( $unRegisteredTokens[$key] ); + foreach ($this->feedback->results as $key => $message) { + if (!isset($message->error)) { + unset($unRegisteredTokens[$key]); + } } return $unRegisteredTokens; @@ -72,14 +71,14 @@ public function getUnregisteredDeviceTokens(array $devices_token) * @param $message * @return array */ - protected function addRequestFields($deviceTokens, $message){ + protected function addRequestFields($deviceTokens, $message) + { $params = $this->cleanConfigParams(); $message = $this->buildMessage($message); - return array_merge($params,$message,['registration_ids' => $deviceTokens]); - + return array_merge($params, $message, ['registration_ids' => $deviceTokens]); } /** @@ -88,9 +87,10 @@ protected function addRequestFields($deviceTokens, $message){ */ protected function buildMessage($message) { - // if NO notification and data keys, then set Data Message as default. - if(!array_key_exists('data',$message) && !array_key_exists('notification',$message)) + // if no notification nor data keys, then set Data Message as default. + if (!array_key_exists('data', $message) && !array_key_exists('notification', $message)) { return ['data' => $message]; + } return $message; } @@ -100,16 +100,16 @@ protected function buildMessage($message) * * @return array */ - private function cleanConfigParams(){ - + private function cleanConfigParams() + { /** * Add the params you want to be removed from the push notification */ $paramsToBeRemoved = ['apiKey']; - return array_filter($this->config,function($key) use($paramsToBeRemoved){ - return !in_array($key,$paramsToBeRemoved); - },ARRAY_FILTER_USE_KEY); + return array_filter($this->config, function ($key) use ($paramsToBeRemoved) { + return !in_array($key, $paramsToBeRemoved); + }, ARRAY_FILTER_USE_KEY); } /** @@ -117,7 +117,8 @@ private function cleanConfigParams(){ * * @return array */ - protected function addRequestHeaders(){ + protected function addRequestHeaders() + { return [ 'Authorization' => 'key=' . $this->config['apiKey'], 'Content-Type:' =>'application/json' @@ -126,17 +127,19 @@ protected function addRequestHeaders(){ /** * Send Push Notification + * * @param array $deviceTokens * @param array $message + * * @return \stdClass GCM Response */ - public function send(array $deviceTokens,array $message) + public function send(array $deviceTokens, array $message) { - $fields = $this->addRequestFields($deviceTokens,$message); + $fields = $this->addRequestFields($deviceTokens, $message); $headers = $this->addRequestHeaders(); - try - { + + try { $result = $this->client->post( $this->url, [ @@ -151,14 +154,12 @@ public function send(array $deviceTokens,array $message) return $this->feedback; - }catch (\Exception $e) - { + } catch (\Exception $e) { $response = ['success' => false, 'error' => $e->getMessage()]; - $this->setFeedback(json_decode(json_encode($response), FALSE)); + $this->setFeedback(json_decode(json_encode($response))); return $this->feedback; } - } -} \ No newline at end of file +} diff --git a/src/Providers/PushNotificationServiceProvider.php b/src/Providers/PushNotificationServiceProvider.php index 82e3d81..41cd0d2 100644 --- a/src/Providers/PushNotificationServiceProvider.php +++ b/src/Providers/PushNotificationServiceProvider.php @@ -29,8 +29,7 @@ public function boot() */ public function register() { - $this->app->singleton('edujugonPushNotification',function($app) - { + $this->app->singleton('edujugonPushNotification', function ($app) { return new PushNotification(); }); } diff --git a/src/PushNotification.php b/src/PushNotification.php index 6264e30..6e7305f 100644 --- a/src/PushNotification.php +++ b/src/PushNotification.php @@ -1,7 +1,6 @@ servicesList)) $service = $this->defaultServiceName; + if (!array_key_exists($service, $this->servicesList)) { + $service = $this->defaultServiceName; + } $this->service = is_null($service) ? new $this->servicesList[$this->defaultServiceName] : new $this->servicesList[$service]; - } /** * Set the Push Service to be used. - * + * * @param $serviceName * @return $this */ - public function setService($serviceName){ + public function setService($serviceName) + { + if (!array_key_exists($serviceName, $this->servicesList)) { + $serviceName = $this->defaultServiceName; + } - if(!array_key_exists($serviceName,$this->servicesList)) $serviceName = $this->defaultServiceName; - $this->service = new $this->servicesList[$serviceName]; return $this; @@ -103,7 +105,9 @@ public function setDevicesToken($deviceTokens) public function setApiKey($api_key) { // if apn doesn't do anything - if(!$this->service instanceof Apn) $this->service->setApiKey($api_key) ; + if (!$this->service instanceof Apn) { + $this->service->setApiKey($api_key); + } return $this; } @@ -135,7 +139,7 @@ public function setUrl($url) /** *Get the unregistered tokens of the notification sent. - * + * * @return array $tokenUnRegistered */ public function getUnregisteredDeviceTokens() @@ -145,7 +149,7 @@ public function getUnregisteredDeviceTokens() /** * Give the Push Notification Feedback after sending a notification. - * + * * @return mixed */ public function getFeedback() @@ -158,12 +162,11 @@ public function getFeedback() * * @return $this */ - public function send(){ - - $this->service->send($this->deviceTokens,$this->message); + public function send() + { + $this->service->send($this->deviceTokens, $this->message); return $this; - } /** @@ -173,10 +176,11 @@ public function send(){ */ public function sendByTopic($topic, $isCondition = false) { - if($this->service instanceof Fcm) - $this->service->sendByTopic($topic, $this->message, $isCondition); + if ($this->service instanceof Fcm) { + $this->service->sendByTopic($topic, $this->message, $isCondition); + } - return $this; + return $this; } /** @@ -185,19 +189,16 @@ public function sendByTopic($topic, $isCondition = false) * @param $property * @return mixed / null */ - public function __get($property){ - - if(property_exists($this,$property)) - { + public function __get($property) + { + if (property_exists($this, $property)) { return $this->$property; } - if(property_exists($this->service,$property)) - { + if (property_exists($this->service, $property)) { return $this->service->$property; } return null; - } -} \ No newline at end of file +} diff --git a/src/PushService.php b/src/PushService.php index ba07044..06637d2 100644 --- a/src/PushService.php +++ b/src/PushService.php @@ -14,7 +14,7 @@ abstract class PushService protected $url = ''; /** - * Confing details + * Config details * By default priority is set to high and dry_run to false * * @var array @@ -49,7 +49,7 @@ public function setFeedback($feedback) */ public function setConfig(array $config) { - $this->config = array_replace($this->config,$config); + $this->config = array_replace($this->config, $config); } /** @@ -94,8 +94,9 @@ protected function initializeFeedback() * @param $property * @return mixed|null */ - public function __get($property){ - return property_exists($this,$property) ? $this->$property : null; + public function __get($property) + { + return property_exists($this, $property) ? $this->$property : null; } } \ No newline at end of file diff --git a/tests/PushNotificationTest.php b/tests/PushNotificationTest.php index 322ea11..e44bcdd 100644 --- a/tests/PushNotificationTest.php +++ b/tests/PushNotificationTest.php @@ -10,7 +10,7 @@ public function push_notification_instance_creation_without_argument_set_gcm_as_ { $push = new PushNotification(); - $this->assertInstanceOf('Edujugon\PushNotification\Gcm',$push->service); + $this->assertInstanceOf('Edujugon\PushNotification\Gcm', $push->service); } /** @test */ @@ -25,7 +25,7 @@ public function assert_send_method_returns_an_stdClass_instance() $push = $push->send(); - $this->assertInstanceOf('stdClass',$push->getFeedback()); + $this->assertInstanceOf('stdClass', $push->getFeedback()); } /** @test */ @@ -56,47 +56,47 @@ public function assert_unregistered_device_tokens_is_an_array() ->setMessage(['message' =>'hello world']) ->send(); - $this->assertInternalType('array',$push->getUnregisteredDeviceTokens()); - + $this->assertInternalType('array', $push->getUnregisteredDeviceTokens()); } /** @test */ - public function set_and_get_service_config(){ + public function set_and_get_service_config() + { /** GCM */ $push = new PushNotification(); $push->setConfig(['time_to_live' => 3]); - $this->assertArrayHasKey('time_to_live',$push->config); - $this->assertArrayHasKey('priority',$push->config); //default key - $this->assertInternalType('array',$push->config); + $this->assertArrayHasKey('time_to_live', $push->config); + $this->assertArrayHasKey('priority', $push->config); //default key + $this->assertInternalType('array', $push->config); /** APNS */ $pushAPN = new PushNotification('apn'); $pushAPN->setConfig(['time_to_live' => 3]); - $this->assertArrayHasKey('time_to_live',$pushAPN->config); - $this->assertArrayHasKey('certificate',$pushAPN->config); //default key - $this->assertInternalType('array',$pushAPN->config); + $this->assertArrayHasKey('time_to_live', $pushAPN->config); + $this->assertArrayHasKey('certificate', $pushAPN->config); //default key + $this->assertInternalType('array', $pushAPN->config); } /** @test */ - public function set_message_data(){ - + public function set_message_data() + { $push = new PushNotification(); $push->setMessage(['message' =>'hello world']); - $this->assertArrayHasKey('message',$push->message); - - $this->assertEquals('hello world',$push->message['message']); + $this->assertArrayHasKey('message', $push->message); + $this->assertEquals('hello world', $push->message['message']); } /** @test */ - public function send_method_in_apn_service(){ + public function send_method_in_apn_service() + { $push = new PushNotification('apn'); $message = [ @@ -119,8 +119,8 @@ public function send_method_in_apn_service(){ $push = $push->send(); //var_dump($push->getFeedback()); - $this->assertInstanceOf('stdClass',$push->getFeedback()); - $this->assertInternalType('array',$push->getUnregisteredDeviceTokens()); + $this->assertInstanceOf('stdClass', $push->getFeedback()); + $this->assertInternalType('array', $push->getUnregisteredDeviceTokens()); } /** @test */ @@ -141,11 +141,11 @@ public function apn_dry_run_option_update_the_apn_url() $push->setConfig(['dry_run'=>false]); - $this->assertEquals('ssl://gateway.push.apple.com:2195',$push->url); + $this->assertEquals('ssl://gateway.push.apple.com:2195', $push->url); $push->setConfig(['dry_run'=>true]); - $this->assertEquals('ssl://gateway.sandbox.push.apple.com:2195',$push->url); + $this->assertEquals('ssl://gateway.sandbox.push.apple.com:2195', $push->url); } @@ -161,9 +161,8 @@ public function fcm_assert_send_method_returns_an_stdClass_instance() $push = $push->send(); - $this->assertEquals('https://fcm.googleapis.com/fcm/send',$push->url); - $this->assertInstanceOf('stdClass',$push->getFeedback()); - + $this->assertEquals('https://fcm.googleapis.com/fcm/send', $push->url); + $this->assertInstanceOf('stdClass', $push->getFeedback()); } /** @test */ @@ -171,17 +170,16 @@ public function if_push_service_as_argument_is_not_valid_user_gcm_as_default() { $push = new PushNotification('asdf'); - $this->assertInstanceOf('Edujugon\PushNotification\Gcm',$push->service); - - + $this->assertInstanceOf('Edujugon\PushNotification\Gcm', $push->service); } + /** @test */ public function get_available_push_service_list() { $push = new PushNotification(); - $this->assertCount(3,$push->servicesList); - $this->assertInternalType('array',$push->servicesList); + $this->assertCount(3, $push->servicesList); + $this->assertInternalType('array', $push->servicesList); } /** @test */ @@ -189,10 +187,10 @@ public function if_argument_in_set_service_method_does_not_exist_set_the_service $push = new PushNotification(); $push->setService('asdf')->send(); - $this->assertInstanceOf('Edujugon\PushNotification\Gcm',$push->service); + $this->assertInstanceOf('Edujugon\PushNotification\Gcm', $push->service); $push->setService('fcm'); - $this->assertInstanceOf('Edujugon\PushNotification\Fcm',$push->service); + $this->assertInstanceOf('Edujugon\PushNotification\Fcm', $push->service); } /** @test */ @@ -207,14 +205,14 @@ public function get_feedback_after_sending_a_notification() ->send() ->getFeedback(); - $this->assertInstanceOf('stdClass',$response); + $this->assertInstanceOf('stdClass', $response); } /** @test */ public function apn_feedback() { - $push = new PushNotification('apn'); + $message = [ 'aps' => [ 'alert' => [ @@ -232,9 +230,8 @@ public function apn_feedback() ]); $push->send(); - $this->assertInstanceOf('stdClass',$push->getFeedback()); - $this->assertInternalType('array',$push->getUnregisteredDeviceTokens()); - + $this->assertInstanceOf('stdClass', $push->getFeedback()); + $this->assertInternalType('array', $push->getUnregisteredDeviceTokens()); } @@ -249,7 +246,7 @@ public function allow_apikey_from_config_file() ->send() ->getFeedback(); - $this->assertInstanceOf('stdClass',$response); + $this->assertInstanceOf('stdClass', $response); } @@ -277,15 +274,17 @@ public function fake_unregisteredDevicesToken_with_apn_feedback_response_merged_ ] ] ]; - $merge = array_merge($primary,$array); - $obj = json_decode(json_encode($merge), FALSE); + $merge = array_merge($primary, $array); + $obj = json_decode(json_encode($merge)); $tokens = []; - if(! empty($obj->tokenFailList)) + if (! empty($obj->tokenFailList)) { $tokens = $obj->tokenFailList; - if(!empty($obj->apnsFeedback)) - $tokens = array_merge($tokens,array_pluck($obj->apnsFeedback,'devtoken')); + } + if (!empty($obj->apnsFeedback)) { + $tokens = array_merge($tokens, array_pluck($obj->apnsFeedback, 'devtoken')); + } //var_dump($tokens); } @@ -300,7 +299,7 @@ public function send_a_notification_by_topic_in_fcm() ->sendByTopic('test') ->getFeedback(); - $this->assertInstanceOf('stdClass',$response); + $this->assertInstanceOf('stdClass', $response); } /** @test */ @@ -311,14 +310,15 @@ public function send_a_notification_by_condition_in_fcm() $response = $push->setMessage(['message'=>'Hello World']) ->setApiKey('asdfasdffasdfasdfasdf') ->setConfig(['dry_run' => false]) - ->sendByTopic("'dogs' in topics || 'cats' in topics",true) + ->sendByTopic("'dogs' in topics || 'cats' in topics", true) ->getFeedback(); - $this->assertInstanceOf('stdClass',$response); + $this->assertInstanceOf('stdClass', $response); } /** @test */ - public function apn_connection_attempts_default() { + public function apn_connection_attempts_default() + { $push = new PushNotification('apn'); $push->setConfig(['dry_run' => true]); @@ -328,7 +328,8 @@ public function apn_connection_attempts_default() { } /** @test */ - public function set_apn_connect_attempts_override_default() { + public function set_apn_connect_attempts_override_default() + { $push = new PushNotification('apn'); $expected = 0; @@ -343,7 +344,8 @@ public function set_apn_connect_attempts_override_default() { } /** @test */ - public function apn_connect_attempts_bailout_badcert() { + public function apn_connect_attempts_bailout_badcert() + { $push = new PushNotification('apn'); $tmp_name = tempnam(sys_get_temp_dir(), 'apn-tmp'); From 122895813028244756ea688f568fb6c34692fb60 Mon Sep 17 00:00:00 2001 From: edujugon Date: Tue, 6 Nov 2018 20:12:10 +0100 Subject: [PATCH 32/45] Using JSON_BIGINT_AS_STRING as bitmask to prevent large integers convertion to float type Issue reference #63 --- src/Gcm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gcm.php b/src/Gcm.php index 533e7f4..ea0c7da 100644 --- a/src/Gcm.php +++ b/src/Gcm.php @@ -150,7 +150,7 @@ public function send(array $deviceTokens, array $message) $json = $result->getBody(); - $this->setFeedback(json_decode($json)); + $this->setFeedback(json_decode($json , false , 512 , JSON_BIGINT_AS_STRING)); return $this->feedback; From 6c4df4d8cd3c78e569f22befa1eca40126ab16ef Mon Sep 17 00:00:00 2001 From: kolorob02 Date: Thu, 22 Nov 2018 11:02:24 +0600 Subject: [PATCH 33/45] added click action for both android and iOS --- src/Channels/ApnChannel.php | 1 + src/Channels/GcmChannel.php | 1 + src/Messages/PushMessage.php | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/src/Channels/ApnChannel.php b/src/Channels/ApnChannel.php index f068d35..6a731a1 100644 --- a/src/Channels/ApnChannel.php +++ b/src/Channels/ApnChannel.php @@ -25,6 +25,7 @@ protected function buildData(PushMessage $message) 'title' => $message->title, 'body' => $message->body, ], + 'category' => $message->category, 'sound' => $message->sound, ], ]; diff --git a/src/Channels/GcmChannel.php b/src/Channels/GcmChannel.php index b65a4f1..cfcddef 100644 --- a/src/Channels/GcmChannel.php +++ b/src/Channels/GcmChannel.php @@ -24,6 +24,7 @@ protected function buildData(PushMessage $message) 'title' => $message->title, 'body' => $message->body, 'sound' => $message->sound, + 'click_action' => $message->click_action, ], ]; diff --git a/src/Messages/PushMessage.php b/src/Messages/PushMessage.php index 1974eb7..ed2848a 100644 --- a/src/Messages/PushMessage.php +++ b/src/Messages/PushMessage.php @@ -19,6 +19,16 @@ class PushMessage */ public $sound = 'default'; + /** + * @var string + */ + public $click_action; + + /** + * @var string + */ + public $category; + /** * @var integer */ @@ -84,6 +94,32 @@ public function sound($sound) return $this; } + /** + * The action associated with a user click on the notification.(Android) + * + * @param string $click_action + * @return $this + */ + public function clickAction($click_action) + { + $this->click_action = $click_action; + + return $this; + } + + /** + * The action associated with a user click on the notification.(iOS) + * + * @param string $click_action + * @return $this + */ + public function category($category) + { + $this->category = $category; + + return $this; + } + /** * Set the notification badge. * From 4f8a6bb5a03d8bd013a41344428e4c1f01fe3ef1 Mon Sep 17 00:00:00 2001 From: kolorob02 Date: Thu, 22 Nov 2018 11:55:21 +0600 Subject: [PATCH 34/45] changed build data for gcm to enable triggering 'onMessageReceived' method when the application is in background --- src/Channels/GcmChannel.php | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/Channels/GcmChannel.php b/src/Channels/GcmChannel.php index cfcddef..4732438 100644 --- a/src/Channels/GcmChannel.php +++ b/src/Channels/GcmChannel.php @@ -19,14 +19,18 @@ protected function pushServiceName() */ protected function buildData(PushMessage $message) { - $data = [ - 'notification' => [ - 'title' => $message->title, - 'body' => $message->body, - 'sound' => $message->sound, - 'click_action' => $message->click_action, - ], - ]; + $data = []; + if($message->title != null || $message->body != null || $message->sound != null || $message->click_action) + { + $data = [ + 'notification' => [ + 'title' => $message->title, + 'body' => $message->body, + 'sound' => $message->sound, + 'click_action' => $message->click_action, + ], + ]; + } if (! empty($message->extra)) { $data['data'] = $message->extra; From d9e7bebe9fa663766673a56fdbd6e3d9af0b5d6b Mon Sep 17 00:00:00 2001 From: kolorob02 Date: Thu, 22 Nov 2018 12:06:10 +0600 Subject: [PATCH 35/45] loggin $data array in gcm channel Build Data --- src/Channels/PushChannel.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Channels/PushChannel.php b/src/Channels/PushChannel.php index 1642938..25b42c8 100644 --- a/src/Channels/PushChannel.php +++ b/src/Channels/PushChannel.php @@ -5,6 +5,7 @@ use Edujugon\PushNotification\Messages\PushMessage; use Edujugon\PushNotification\PushNotification; use Illuminate\Notifications\Notification; +use Illuminate\Support\Facades\Log; abstract class PushChannel { @@ -40,6 +41,8 @@ public function send($notifiable, Notification $notification) $data = $this->buildData($message); + Log::info($message); + $this->push($this->pushServiceName(), $to, $data, $message); } From 47db647d3b31217dcee25da843938e7557c6d5fd Mon Sep 17 00:00:00 2001 From: kolorob02 Date: Thu, 22 Nov 2018 12:10:24 +0600 Subject: [PATCH 36/45] logging data array in gcm channel build data method --- src/Channels/GcmChannel.php | 3 +++ src/Channels/PushChannel.php | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Channels/GcmChannel.php b/src/Channels/GcmChannel.php index 4732438..4e5e27e 100644 --- a/src/Channels/GcmChannel.php +++ b/src/Channels/GcmChannel.php @@ -3,6 +3,7 @@ namespace Edujugon\PushNotification\Channels; use Edujugon\PushNotification\Messages\PushMessage; +use Illuminate\Support\Facades\Log; class GcmChannel extends PushChannel { @@ -36,6 +37,8 @@ protected function buildData(PushMessage $message) $data['data'] = $message->extra; } + Log::alert(dd($data)); + return $data; } } diff --git a/src/Channels/PushChannel.php b/src/Channels/PushChannel.php index 25b42c8..1642938 100644 --- a/src/Channels/PushChannel.php +++ b/src/Channels/PushChannel.php @@ -5,7 +5,6 @@ use Edujugon\PushNotification\Messages\PushMessage; use Edujugon\PushNotification\PushNotification; use Illuminate\Notifications\Notification; -use Illuminate\Support\Facades\Log; abstract class PushChannel { @@ -41,8 +40,6 @@ public function send($notifiable, Notification $notification) $data = $this->buildData($message); - Log::info($message); - $this->push($this->pushServiceName(), $to, $data, $message); } From 5a78d7260b87d7c0ecc3faa0819a629f5f3cde4d Mon Sep 17 00:00:00 2001 From: kolorob02 Date: Thu, 22 Nov 2018 12:13:23 +0600 Subject: [PATCH 37/45] changed null check of $message->sound in gcm channel buildData method --- src/Channels/GcmChannel.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Channels/GcmChannel.php b/src/Channels/GcmChannel.php index 4e5e27e..78273a4 100644 --- a/src/Channels/GcmChannel.php +++ b/src/Channels/GcmChannel.php @@ -3,7 +3,6 @@ namespace Edujugon\PushNotification\Channels; use Edujugon\PushNotification\Messages\PushMessage; -use Illuminate\Support\Facades\Log; class GcmChannel extends PushChannel { @@ -21,7 +20,7 @@ protected function pushServiceName() protected function buildData(PushMessage $message) { $data = []; - if($message->title != null || $message->body != null || $message->sound != null || $message->click_action) + if($message->title != null || $message->body != null || $message->click_action) { $data = [ 'notification' => [ @@ -37,8 +36,6 @@ protected function buildData(PushMessage $message) $data['data'] = $message->extra; } - Log::alert(dd($data)); - return $data; } } From e62a6f06d4d3716eba62ee547fc08a79f62bf393 Mon Sep 17 00:00:00 2001 From: kolorob02 Date: Thu, 22 Nov 2018 12:17:52 +0600 Subject: [PATCH 38/45] fixed click_action null comparison in gcm channel buildData --- src/Channels/GcmChannel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Channels/GcmChannel.php b/src/Channels/GcmChannel.php index 78273a4..d53f6d7 100644 --- a/src/Channels/GcmChannel.php +++ b/src/Channels/GcmChannel.php @@ -20,7 +20,7 @@ protected function pushServiceName() protected function buildData(PushMessage $message) { $data = []; - if($message->title != null || $message->body != null || $message->click_action) + if($message->title != null || $message->body != null || $message->click_action != null) { $data = [ 'notification' => [ From 432ca1f0a2e44c8160c0bbdb4f6c86f6684b7107 Mon Sep 17 00:00:00 2001 From: edujugon Date: Sat, 8 Dec 2018 16:58:39 +0100 Subject: [PATCH 39/45] Use laravel helpers to access configuration variables. Fixes #71 --- src/PushService.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/PushService.php b/src/PushService.php index 06637d2..c6c8ff5 100644 --- a/src/PushService.php +++ b/src/PushService.php @@ -63,8 +63,11 @@ public function setConfig(array $config) */ public function initializeConfig($service) { - if (function_exists('config_path') && file_exists(config_path('pushnotification.php'))) { - $configuration = include(config_path('pushnotification.php')); + if (function_exists('config_path') && + file_exists(config_path('pushnotification.php')) && + function_exists('app') + ) { + $configuration = app('config')->get('pushnotification'); } else { $configuration = include(__DIR__ . '/Config/config.php'); } From 7f5d70ef522e455f211b4fa0d1507bdf21e61630 Mon Sep 17 00:00:00 2001 From: edujugon Date: Sun, 9 Dec 2018 13:27:42 +0100 Subject: [PATCH 40/45] [PSR-2] small fix --- src/Channels/GcmChannel.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Channels/GcmChannel.php b/src/Channels/GcmChannel.php index d53f6d7..5b6dc99 100644 --- a/src/Channels/GcmChannel.php +++ b/src/Channels/GcmChannel.php @@ -20,8 +20,7 @@ protected function pushServiceName() protected function buildData(PushMessage $message) { $data = []; - if($message->title != null || $message->body != null || $message->click_action != null) - { + if ($message->title != null || $message->body != null || $message->click_action != null) { $data = [ 'notification' => [ 'title' => $message->title, From f4bb9bcadb01409027d086d184af381cad5a36f5 Mon Sep 17 00:00:00 2001 From: edujugon Date: Sun, 16 Dec 2018 20:04:53 +0100 Subject: [PATCH 41/45] [Fix] Code styling PSR-2 --- src/Gcm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gcm.php b/src/Gcm.php index ea0c7da..46cb3a4 100644 --- a/src/Gcm.php +++ b/src/Gcm.php @@ -150,7 +150,7 @@ public function send(array $deviceTokens, array $message) $json = $result->getBody(); - $this->setFeedback(json_decode($json , false , 512 , JSON_BIGINT_AS_STRING)); + $this->setFeedback(json_decode($json, false, 512, JSON_BIGINT_AS_STRING)); return $this->feedback; From 68c4af876e0c7335ac89cebcb4ac3e9340b388a3 Mon Sep 17 00:00:00 2001 From: edujugon Date: Sun, 16 Dec 2018 20:06:15 +0100 Subject: [PATCH 42/45] Using JSON_BIGINT_AS_STRING as bitmask to prevent large integers convertion to float type. Fixes #63 --- src/Fcm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Fcm.php b/src/Fcm.php index 1c4c20a..c8eb7cf 100644 --- a/src/Fcm.php +++ b/src/Fcm.php @@ -44,7 +44,7 @@ public function sendByTopic($topic, $message, $isCondition = false) $json = $result->getBody(); - $this->setFeedback(json_decode($json)); + $this->setFeedback(json_decode($json, false, 512, JSON_BIGINT_AS_STRING)); } catch (\Exception $e) { $response = ['success' => false, 'error' => $e->getMessage()]; From 299674a9ece878c8b36196891337785be8f535c2 Mon Sep 17 00:00:00 2001 From: pascalvgemert Date: Mon, 28 Jan 2019 08:51:19 +0100 Subject: [PATCH 43/45] Fix badge support for FCM and GCM via channel --- src/Channels/GcmChannel.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Channels/GcmChannel.php b/src/Channels/GcmChannel.php index 5b6dc99..93cc125 100644 --- a/src/Channels/GcmChannel.php +++ b/src/Channels/GcmChannel.php @@ -29,6 +29,11 @@ protected function buildData(PushMessage $message) 'click_action' => $message->click_action, ], ]; + + // Set custom badge number when isset in PushMessage + if (! empty($message->badge)) { + $data['notification']['badge'] = $message->badge; + } } if (! empty($message->extra)) { From 1bd990fb683a89519298a0326c1a47700f69bc11 Mon Sep 17 00:00:00 2001 From: Eliyas Hossain Date: Sun, 12 May 2019 13:54:10 +0600 Subject: [PATCH 44/45] added icon property into fcm channel --- src/Channels/GcmChannel.php | 1 + src/Messages/PushMessage.php | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/Channels/GcmChannel.php b/src/Channels/GcmChannel.php index 93cc125..c80cd18 100644 --- a/src/Channels/GcmChannel.php +++ b/src/Channels/GcmChannel.php @@ -25,6 +25,7 @@ protected function buildData(PushMessage $message) 'notification' => [ 'title' => $message->title, 'body' => $message->body, + 'icon' => $message->icon, 'sound' => $message->sound, 'click_action' => $message->click_action, ], diff --git a/src/Messages/PushMessage.php b/src/Messages/PushMessage.php index ed2848a..30bdc0d 100644 --- a/src/Messages/PushMessage.php +++ b/src/Messages/PushMessage.php @@ -14,6 +14,11 @@ class PushMessage */ public $body; + /** + * @var string + */ + public $icon; + /** * @var string */ @@ -81,6 +86,19 @@ public function title($title) return $this; } + /** + * Set the message icon. + * + * @param string $icon + * @return $this + */ + public function icon($icon) + { + $this->icon = $icon; + + return $this; + } + /** * Set the notification sound. * From 9d1bc7a9e0af11522f4eb48a05157341b6d27b5c Mon Sep 17 00:00:00 2001 From: Eliyas Hossain Date: Mon, 13 May 2019 11:23:13 +0600 Subject: [PATCH 45/45] set icon property optional in gcm channel --- src/Channels/GcmChannel.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Channels/GcmChannel.php b/src/Channels/GcmChannel.php index c80cd18..8997f98 100644 --- a/src/Channels/GcmChannel.php +++ b/src/Channels/GcmChannel.php @@ -25,7 +25,6 @@ protected function buildData(PushMessage $message) 'notification' => [ 'title' => $message->title, 'body' => $message->body, - 'icon' => $message->icon, 'sound' => $message->sound, 'click_action' => $message->click_action, ], @@ -35,6 +34,11 @@ protected function buildData(PushMessage $message) if (! empty($message->badge)) { $data['notification']['badge'] = $message->badge; } + + // Set icon when isset in PushMessage + if (! empty($message->icon)) { + $data['notification']['icon'] = $message->icon; + } } if (! empty($message->extra)) {