Commit 71bdb2b5 authored by Richard Weinhold's avatar Richard Weinhold 🔨
Browse files

adds sendRaw method to core class and Handlers

- sendRaw() allows to push raw payload without defaults and minimal
  preprocessing to servers
parent 4a361a66
......@@ -7,6 +7,9 @@ namespace ricwein\PushNotification\Handler;
use ricwein\PushNotification\PushHandler;
/**
* PushHandler for Apple Push Notification Service
*/
class APNSHandler extends PushHandler {
/**
......@@ -18,18 +21,90 @@ class APNSHandler extends PushHandler {
'passphrase' => null,
];
/**
* build binary notification-package
* @param string $deviceToken
* @param string $payload json
* @param array $arbitrary additional settings
* @param int $version push-version (1/2)
* @return string
* @throws \UnexpectedValueException
*/
protected function _buildNotification($deviceToken, $payload, array $arbitrary = [], $version = 1) {
// set default arbitrary settings
$arbitrary = array_merge([
'expire' => 0,
'messageID' => 0,
'priority' => 10,
], $arbitrary);
// cleanup device tokens
$deviceToken = str_replace(' ', '', trim($deviceToken, '<> '));
// build notification
if ((int) $version === 1) {
$notification = pack('C', 1); // Command 1
$notification .= pack('N', (int) $arbitrary['messageID']); // notification id
$notification .= pack('N', ($arbitrary['expire'] > 0 ? time() + $arbitrary['expire'] : 0)); // expiration timestamps
$notification .= pack('nH*', 32, $deviceToken); // device-token
$notification .= pack('n', strlen($payload)) . $payload; // payload
return $notification;
} elseif ((int) $version === 2) {
// build notification
$notification = pack('CnH*', 1, 32, $deviceToken); // device-token
$notification .= pack('CnA*', 2, strlen($payload), $payload); // payload
$notification .= pack('CnN', 3, 4, (int) $arbitrary['messageID']); // notification id
$notification .= pack('CnN', 4, 4, ($arbitrary['expire'] > 0 ? time() + $arbitrary['expire'] : 0)); // expiration timestamps
$notification .= pack('CnC', 5, 1, (int) $arbitrary['priority']); // notification priority
// pack notification into frame
$frame = pack('C', 2); // Command 2
$frame .= pack('N', strlen($notification)) . $notification; // notification
return $frame;
}
throw new \UnexpectedValueException('Unknown Command Version', 500);
}
/**
* send notification to Apples APNS servers
* @param string $message
* @param array $payload (optional)
* @param array $payload
* @param array $devices
* @return bool
* @throws \UnexpectedValueException|\RuntimeException
*/
public function send($message, array $payload = [], array $devices) {
// build payload
$payload = array_merge(['aps' => [
'alert' => trim(stripslashes($message)),
'badge' => 1,
'sound' => 'default',
]], $payload);
return $this->sendRaw($payload, $devices);
}
/**
* build and send Notification from raw payload
* @param array $payload
* @param array $devices
* @return bool
* @throws \UnexpectedValueException|\RuntimeException
*/
public function sendRaw(array $payload, array $devices) {
// set default values
$result = true;
$arbitrary = ['command' => 1];
// handle arbitrary settings
// extract arbitrary settings
foreach (['expire', 'messageID', 'priority', 'command'] as $key) {
if (isset($payload[$key])) {
$arbitrary[$key] = (int) abs($payload[$key]);
......@@ -39,13 +114,6 @@ class APNSHandler extends PushHandler {
}
}
// build payload
$payload = array_merge(['aps' => [
'alert' => trim(stripslashes($message)),
'badge' => 1,
'sound' => 'default',
]], $payload);
// open context
$ctx = stream_context_create();
......@@ -54,7 +122,10 @@ class APNSHandler extends PushHandler {
if (empty($certpath) || $certpath === DIRECTORY_SEPARATOR || !is_file($certpath)) {
throw new \UnexpectedValueException('Invalid cert-file: ' . $certpath, 500);
}
stream_context_set_option($ctx, 'ssl', 'local_cert', $certpath);
if (!stream_context_set_option($ctx, 'ssl', 'local_cert', $certpath)) {
throw new \UnexpectedValueException('unable to set cert-file', 500);
}
// set cert passphrase if given
if ($this->_server['passphrase'] !== null) {
......@@ -84,56 +155,7 @@ class APNSHandler extends PushHandler {
@fclose($stream);
return $result;
}
/**
* build binary notification-package
* @param string $device
* @param string $payload json
* @param int $expiration (optional)
* @param array $arbitrary additional settings
* @param int $version push-version (1/2)
* @return string
*/
protected function _buildNotification($deviceToken, $payload, array $arbitrary = [], $version = 1) {
// set default arbitrary settings
$arbitrary = array_merge([
'expire' => 0,
'messageID' => 0,
'priority' => 10,
], $arbitrary);
// cleanup device tokens
$deviceToken = str_replace(' ', '', trim($deviceToken, '<> '));
// build notification
if ((int) $version === 1) {
$notification = pack('C', 1); // Command 1
$notification .= pack('N', (int) $arbitrary['messageID']); // notification id
$notification .= pack('N', ($arbitrary['expire'] > 0 ? time() + $arbitrary['expire'] : 0)); // expiration timestamps
$notification .= pack('nH*', 32, $deviceToken); // device-token
$notification .= pack('n', strlen($payload)) . $payload; // payload
return $notification;
} elseif ((int) $version === 2) {
// build notification
$notification = pack('CnH*', 1, 32, $deviceToken); // device-token
$notification .= pack('CnA*', 2, strlen($payload), $payload); // payload
$notification .= pack('CnN', 3, 4, (int) $arbitrary['messageID']); // notification id
$notification .= pack('CnN', 4, 4, ($arbitrary['expire'] > 0 ? time() + $arbitrary['expire'] : 0)); // expiration timestamps
$notification .= pack('CnC', 5, 1, (int) $arbitrary['priority']); // notification priority
// pack notification into frame
$frame = pack('C', 2); // Command 2
$frame .= pack('N', strlen($notification)) . $notification; // notification
return $frame;
}
throw new \UnexpectedValueException('Unknown Command Version', 500);
}
}
......@@ -7,6 +7,9 @@ namespace ricwein\PushNotification\Handler;
use ricwein\PushNotification\PushHandler;
/**
* PushHandler for Google Cloud Messaging
*/
class GCMHandler extends PushHandler {
/**
......@@ -20,7 +23,7 @@ class GCMHandler extends PushHandler {
/**
* send notification to Googles GCM servers
* @param string $message
* @param array $payload (optional)
* @param array $payload
* @param array $devices
* @return bool
*/
......@@ -28,12 +31,27 @@ class GCMHandler extends PushHandler {
// build payload
$payload = [
'registration_ids' => $devices,
'data' => array_merge([
'message' => $message,
'data' => array_merge([
'message' => trim(stripslashes($message)),
], $payload),
];
return $this->sendRaw($payload, $devices);
}
/**
* build and send Notification from raw payload
* @param array $payload
* @param array $devices
* @return bool
* @throws \RuntimeException
*/
public function sendRaw(array $payload, array $devices) {
$payload = array_merge([
'registration_ids' => $devices,
], $payload);
// init http-headers
$headers = [
'Authorization: key=' . $this->_server['token'],
......@@ -75,6 +93,7 @@ class GCMHandler extends PushHandler {
// decode response and check if sending to all devices succeeded
$result = @json_decode($result, true);
return (isset($result['success']) && (int) $result['success'] === count($devices));
}
}
......@@ -7,6 +7,9 @@ namespace ricwein\PushNotification\Handler;
use ricwein\PushNotification\PushHandler;
/**
* PushHandler for Windows push Notification Services
*/
class WNSHandler extends PushHandler {
/**
......@@ -19,8 +22,10 @@ class WNSHandler extends PushHandler {
];
/**
* @param $deviceID
* @param $deviceSecret
* @param int $clientID
* @param string $clientSecret
* @return string
* @throws \Exception
*/
public function requestOAuthToken($clientID, $clientSecret) {
// init http-headers
......@@ -76,10 +81,13 @@ class WNSHandler extends PushHandler {
}
/**
* @param $message
* @param string $message
* @param array $data
* @return string
*/
protected static function _buildPayload($message, array $data = []) {
protected static function _buildPayloadXML($message, array $data = []) {
$message = trim(stripslashes($message));
if (isset($data['title']) && !isset($data['image'])) {
return '<?xml version="1.0" encoding="utf-8"?>' .
'<toast>' .
......@@ -120,20 +128,44 @@ class WNSHandler extends PushHandler {
'</binding>' .
'</visual>' .
'</toast>';
}}
}
}
/**
* send notification to Microsofts live.com WNS servers
* @param string $message
* @param array $payload (optional)
* @param array $payload
* @param array $devices
* @return bool
* @throws \RuntimeException
*/
public function send($message, array $payload = [], array $devices) {
$result = true;
// buil xml-payload
$xml = static::_buildPayload($message, $payload);
$payload['xml'] = static::_buildPayloadXML($message, $payload);
return $this->sendRaw($payload, $devices);
}
/**
* build and send Notification from raw payload
* @param array $payload
* @param array $devices
* @return bool
* @throws \RuntimeException|\UnexpectedValueException
*/
public function sendRaw(array $payload, array $devices) {
$result = true;
// buil xml-payload
if (isset($payload['xml'])) {
$xml = $payload['xml'];
} elseif (isset($payload['message'])) {
$xml = static::_buildPayloadXML($payload['message'], $payload);
} else {
throw new \UnexpectedValueException('missing \'messages\' or \'xml\' key for WNS payload', 500);
}
// open curl connection
$curl = curl_init();
......@@ -187,7 +219,6 @@ class WNSHandler extends PushHandler {
$response = curl_getinfo($curl);
$result = $result && ((int) $response['http_code'] === 200);
}
// remeber to close the connection when finished
......
......@@ -5,6 +5,9 @@
namespace ricwein\PushNotification;
/**
* PushHandler, providing base push operations
*/
abstract class PushHandler {
/**
......@@ -16,8 +19,8 @@ abstract class PushHandler {
];
/**
* @param string $serverToken (optional)
* @param string $url (optional)
* @param string $serverToken
* @param string $url
*/
public function __construct($serverToken = null, $url = null) {
if ($serverToken !== null) {
......@@ -53,6 +56,11 @@ abstract class PushHandler {
return $this;
}
/**
* check and prepare internal configuration for sending
* @return bool
* @throws \UnexpectedValueException
*/
public function prepare() {
if (empty($this->_server['token'])) {
throw new \UnexpectedValueException('server token not set', 500);
......@@ -64,11 +72,21 @@ abstract class PushHandler {
}
/**
* build payload and send via push-handler to servers
* build default PushNotification and send via PushHandler to servers
* @param string $message
* @param array $payload
* @param array $devices
* @param array $data (optional)
* @return bool
* @throws \UnexpectedValueException|\RuntimeException
*/
abstract public function send($message, array $payload = [], array $devices);
/**
* build and send Notification from raw payload
* @param array $payload
* @param array $devices
* @return bool
* @throws \UnexpectedValueException|\RuntimeException
*/
abstract public function send($message, array $data = [], array $devices);
abstract public function sendRaw(array $payload, array $devices);
}
......@@ -7,6 +7,9 @@ namespace ricwein\PushNotification;
use ricwein\PushNotification\PushHandler;
/**
* PushNotification core
*/
class PushNotification {
/**
......@@ -20,7 +23,7 @@ class PushNotification {
protected $_devices = [];
/**
* @param PushHandler $handler (optional)
* @param PushHandler $handler
*/
public function __construct(PushHandler $handler = null) {
if ($handler !== null) {
......@@ -38,9 +41,9 @@ class PushNotification {
}
/**
* build payload and send via push-handler to servers
* build payload and send via PushHandler to servers
* @param string $message
* @param array $payload (optional)
* @param array $payload
* @return bool
*/
public function send($message, array $payload = []) {
......@@ -50,6 +53,22 @@ class PushNotification {
return $this->_handler->send($message, $payload, $this->_devices);
}
/**
* send raw payload via PushHandler to servers
* @param array $payload
* @return bool
*/
public function sendRaw(array $payload = []) {
if (!$this->_prepare()) {
return false;
}
return $this->_handler->sendRaw($payload, $this->_devices);
}
/**
* prepare PushHandler for sending
* @return bool
*/
protected function _prepare() {
if (count($this->_devices) === 0) {
return false;
......@@ -73,6 +92,7 @@ class PushNotification {
* @param string $name
* @param mixed $arguments
* @return $this
* @throws \Exception
*/
public function __call($name, $arguments) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment