apns-php
 All Data Structures Files Functions Variables Groups Pages
ApnsPHP_Push Class Reference

The Push Notification Provider. More...

Inheritance diagram for ApnsPHP_Push:
Inheritance graph
Collaboration diagram for ApnsPHP_Push:
Collaboration graph

Public Member Functions

void add (ApnsPHP_Message $message)
 Adds a message to the message queue. More...
 
array getErrors (boolean $bEmpty=true)
 Returns messages not delivered to the end user because one (or more) error occurred. More...
 
array getQueue (boolean $bEmpty=true)
 Returns messages in the message queue. More...
 
integer getSendRetryTimes ()
 Get the send retry time value. More...
 
void send ()
 Sends all messages in the message queue to Apple Push Notification Service. More...
 
void setSendRetryTimes (integer $nRetryTimes)
 Set the send retry times value. More...
 
- Public Member Functions inherited from ApnsPHP_Abstract
void __construct (integer $nEnvironment, string $sProviderCertificateFile)
 Constructor. More...
 
void connect ()
 Connects to Apple Push Notification service server. More...
 
boolean disconnect ()
 Disconnects from Apple Push Notifications service server. More...
 
string getCertificateAuthority ()
 Get the Root Certification Authority file path. More...
 
integer getConnectRetryInterval ()
 Get the connect retry interval. More...
 
integer getConnectRetryTimes ()
 Get the connect retry time value. More...
 
integer getConnectTimeout ()
 Get the connection timeout. More...
 
ApnsPHP_Log_Interface getLogger ()
 Get the Logger instance. More...
 
integer getSocketSelectTimeout ()
 Get the TCP socket select timeout. More...
 
integer getWriteInterval ()
 Get the write interval. More...
 
void setConnectRetryInterval (integer $nRetryInterval)
 Set the connect retry interval. More...
 
void setConnectRetryTimes (integer $nRetryTimes)
 Set the connect retry times value. More...
 
void setConnectTimeout (integer $nTimeout)
 Set the connection timeout. More...
 
void setLogger (ApnsPHP_Log_Interface $logger)
 Set the Logger instance to use for logging purpose. More...
 
void setProviderCertificatePassphrase (string $sProviderCertificatePassphrase)
 Set the Provider Certificate passphrase. More...
 
void setRootCertificationAuthority (string $sRootCertificationAuthorityFile)
 Set the Root Certification Authority file. More...
 
void setSocketSelectTimeout (integer $nSelectTimeout)
 Set the TCP socket select timeout. More...
 
void setWriteInterval (integer $nWriteInterval)
 Set the write interval. More...
 

Data Fields

const COMMAND_PUSH = 1
 integer Payload command. More...
 
const ERROR_RESPONSE_COMMAND = 8
 integer Error-response command code. More...
 
const ERROR_RESPONSE_SIZE = 6
 integer Error-response packet size. More...
 
const STATUS_CODE_INTERNAL_ERROR = 999
 integer Status code for internal error (not Apple). More...
 
- Data Fields inherited from ApnsPHP_Abstract
const CONNECT_RETRY_INTERVAL = 1000000
 integer Default connect retry interval in micro seconds. More...
 
const DEVICE_BINARY_SIZE = 32
 integer Device token length. More...
 
const ENVIRONMENT_PRODUCTION = 0
 integer Production environment. More...
 
const ENVIRONMENT_SANDBOX = 1
 integer Sandbox environment. More...
 
const SOCKET_SELECT_TIMEOUT = 1000000
 integer Default socket select timeout in micro seconds. More...
 
const WRITE_INTERVAL = 10000
 integer Default write interval in micro seconds. More...
 

Protected Member Functions

string _getBinaryNotification (string $sDeviceToken, string $sPayload, integer $nMessageID=0, integer $nExpire=604800)
 Generate a binary notification from a device token and a JSON-encoded payload. More...
 
array _parseErrorMessage (string $sErrorMessage)
 Parses the error message. More...
 
array null _readErrorMessage ()
 Reads an error message (if present) from the main stream. More...
 
void _removeMessageFromQueue (integer $nMessageID, boolean $bError=false)
 Remove a message from the message queue. More...
 
boolean _updateQueue (array $aErrorMessage=null)
 Checks for error message and deletes messages successfully sent from message queue. More...
 
- Protected Member Functions inherited from ApnsPHP_Abstract
boolean _connect ()
 Connects to Apple Push Notification service server. More...
 
void _log (string $sMessage)
 Logs a message through the Logger. More...
 

Protected Attributes

 $_aErrorResponseMessages
 array Error-response messages. More...
 
array $_aErrors = array()
 Error container. More...
 
array $_aMessageQueue = array()
 Message queue. More...
 
 $_aServiceURLs
 array Service URLs environments. More...
 
integer $_nSendRetryTimes = 3
 Send retry times. More...
 
- Protected Attributes inherited from ApnsPHP_Abstract
array $_aServiceURLs = array()
 Container for service URLs environments. More...
 
resource $_hSocket
 SSL Socket. More...
 
ApnsPHP_Log_Interface $_logger
 Logger. More...
 
integer $_nConnectRetryInterval
 Connect retry interval in micro seconds. More...
 
integer $_nConnectRetryTimes = 3
 Connect retry times. More...
 
integer $_nConnectTimeout
 Connect timeout in seconds. More...
 
integer $_nEnvironment
 Active environment. More...
 
integer $_nSocketSelectTimeout
 Socket select timeout in micro seconds. More...
 
integer $_nWriteInterval
 Write interval in micro seconds. More...
 
string $_sProviderCertificateFile
 Provider certificate file with key (Bundled PEM). More...
 
string $_sProviderCertificatePassphrase
 Provider certificate passphrase. More...
 
string $_sRootCertificationAuthorityFile
 Root certification authority file. More...
 

Detailed Description

The Push Notification Provider.

The class manages a message queue and sends notifications payload to Apple Push Notification Service.

Definition at line 33 of file Push.php.

Member Function Documentation

string _getBinaryNotification ( string  $sDeviceToken,
string  $sPayload,
integer  $nMessageID = 0,
integer  $nExpire = 604800 
)
protected

Generate a binary notification from a device token and a JSON-encoded payload.

See Also
http://tinyurl.com/ApplePushNotificationBinary
Parameters
$sDeviceTokenThe device token.
$sPayloadThe JSON-encoded payload.
$nMessageID[optional] Message unique ID.
$nExpire[optional] Seconds, starting from now, that identifies when the notification is no longer valid and can be discarded. Pass a negative value (-1 for example) to request that APNs not store the notification at all. Default is 86400 * 7, 7 days.
Returns
A binary notification.

Definition at line 263 of file Push.php.

Referenced by add().

264  {
265  $nTokenLength = strlen($sDeviceToken);
266  $nPayloadLength = strlen($sPayload);
267 
268  $sRet = pack('CNNnH*', self::COMMAND_PUSH, $nMessageID, $nExpire > 0 ? time() + $nExpire : 0, self::DEVICE_BINARY_SIZE, $sDeviceToken);
269  $sRet .= pack('n', $nPayloadLength);
270  $sRet .= $sPayload;
271 
272  return $sRet;
273  }

Here is the caller graph for this function:

array _parseErrorMessage ( string  $sErrorMessage)
protected

Parses the error message.

Parameters
$sErrorMessageThe Error Message.
Returns
Array with command, statusCode and identifier keys.

Definition at line 281 of file Push.php.

Referenced by _readErrorMessage().

282  {
283  return unpack('Ccommand/CstatusCode/Nidentifier', $sErrorMessage);
284  }

Here is the caller graph for this function:

array null _readErrorMessage ( )
protected

Reads an error message (if present) from the main stream.

If the error message is present and valid the error message is returned, otherwhise null is returned.

Returns
Return the error message array.

Definition at line 293 of file Push.php.

References _parseErrorMessage().

Referenced by _updateQueue().

294  {
295  $sErrorResponse = @fread($this->_hSocket, self::ERROR_RESPONSE_SIZE);
296  if ($sErrorResponse === false || strlen($sErrorResponse) != self::ERROR_RESPONSE_SIZE) {
297  return;
298  }
299  $aErrorResponse = $this->_parseErrorMessage($sErrorResponse);
300  if (!is_array($aErrorResponse) || empty($aErrorResponse)) {
301  return;
302  }
303  if (!isset($aErrorResponse['command'], $aErrorResponse['statusCode'], $aErrorResponse['identifier'])) {
304  return;
305  }
306  if ($aErrorResponse['command'] != self::ERROR_RESPONSE_COMMAND) {
307  return;
308  }
309  $aErrorResponse['time'] = time();
310  $aErrorResponse['statusMessage'] = 'None (unknown)';
311  if (isset($this->_aErrorResponseMessages[$aErrorResponse['statusCode']])) {
312  $aErrorResponse['statusMessage'] = $this->_aErrorResponseMessages[$aErrorResponse['statusCode']];
313  }
314  return $aErrorResponse;
315  }
array _parseErrorMessage(string $sErrorMessage)
Parses the error message.
Definition: Push.php:281

Here is the call graph for this function:

Here is the caller graph for this function:

void _removeMessageFromQueue ( integer  $nMessageID,
boolean  $bError = false 
)
protected

Remove a message from the message queue.

Parameters
$nMessageIDThe Message ID.
$bError[optional] Insert the message in the Error container.
Exceptions
ApnsPHP_Push_Exceptionif the Message ID is not valid or message does not exists.

Definition at line 371 of file Push.php.

Referenced by send().

372  {
373  if (!is_numeric($nMessageID) || $nMessageID <= 0) {
374  throw new ApnsPHP_Push_Exception(
375  'Message ID format is not valid.'
376  );
377  }
378  if (!isset($this->_aMessageQueue[$nMessageID])) {
379  throw new ApnsPHP_Push_Exception(
380  "The Message ID {$nMessageID} does not exists."
381  );
382  }
383  if ($bError) {
384  $this->_aErrors[$nMessageID] = $this->_aMessageQueue[$nMessageID];
385  }
386  unset($this->_aMessageQueue[$nMessageID]);
387  }
Exception class.

Here is the caller graph for this function:

boolean _updateQueue ( array  $aErrorMessage = null)
protected

Checks for error message and deletes messages successfully sent from message queue.

Parameters
$aErrorMessage[optional] The error message. It will anyway always be read from the main stream. The latest successful message sent is the lowest between this error message and the message that was read from the main stream.
See Also
_readErrorMessage()
Returns
True if an error was received.

Definition at line 327 of file Push.php.

References ApnsPHP_Abstract::_log(), _readErrorMessage(), ApnsPHP_Abstract::connect(), and ApnsPHP_Abstract::disconnect().

Referenced by send().

328  {
329  $aStreamErrorMessage = $this->_readErrorMessage();
330  if (!isset($aErrorMessage) && !isset($aStreamErrorMessage)) {
331  return false;
332  } else if (isset($aErrorMessage, $aStreamErrorMessage)) {
333  if ($aStreamErrorMessage['identifier'] <= $aErrorMessage['identifier']) {
334  $aErrorMessage = $aStreamErrorMessage;
335  unset($aStreamErrorMessage);
336  }
337  } else if (!isset($aErrorMessage) && isset($aStreamErrorMessage)) {
338  $aErrorMessage = $aStreamErrorMessage;
339  unset($aStreamErrorMessage);
340  }
341 
342  $this->_log('ERROR: Unable to send message ID ' .
343  $aErrorMessage['identifier'] . ': ' .
344  $aErrorMessage['statusMessage'] . ' (' . $aErrorMessage['statusCode'] . ').');
345 
346  $this->disconnect();
347 
348  foreach($this->_aMessageQueue as $k => &$aMessage) {
349  if ($k < $aErrorMessage['identifier']) {
350  unset($this->_aMessageQueue[$k]);
351  } else if ($k == $aErrorMessage['identifier']) {
352  $aMessage['ERRORS'][] = $aErrorMessage;
353  } else {
354  break;
355  }
356  }
357 
358  $this->connect();
359 
360  return true;
361  }
array null _readErrorMessage()
Reads an error message (if present) from the main stream.
Definition: Push.php:293
void connect()
Connects to Apple Push Notification service server.
Definition: Abstract.php:328
boolean disconnect()
Disconnects from Apple Push Notifications service server.
Definition: Abstract.php:356
void _log(string $sMessage)
Logs a message through the Logger.
Definition: Abstract.php:414

Here is the call graph for this function:

Here is the caller graph for this function:

void add ( ApnsPHP_Message  $message)

Adds a message to the message queue.

Parameters
$messageThe message.

Definition at line 93 of file Push.php.

References _getBinaryNotification(), ApnsPHP_Message::getExpiry(), ApnsPHP_Message::getPayload(), ApnsPHP_Message::getRecipient(), and ApnsPHP_Message::getRecipientsNumber().

94  {
95  $sMessagePayload = $message->getPayload();
96  $nRecipients = $message->getRecipientsNumber();
97 
98  $nMessageQueueLen = count($this->_aMessageQueue);
99  for ($i = 0; $i < $nRecipients; $i++) {
100  $nMessageID = $nMessageQueueLen + $i + 1;
101  $this->_aMessageQueue[$nMessageID] = array(
102  'MESSAGE' => $message,
103  'BINARY_NOTIFICATION' => $this->_getBinaryNotification(
104  $message->getRecipient($i),
105  $sMessagePayload,
106  $nMessageID,
107  $message->getExpiry()
108  ),
109  'ERRORS' => array()
110  );
111  }
112  }
integer getRecipientsNumber()
Get the number of recipients.
Definition: Message.php:107
string getPayload()
Convert the message in a JSON-encoded payload.
Definition: Message.php:397
string getRecipient(integer $nRecipient=0)
Get a recipient.
Definition: Message.php:92
string _getBinaryNotification(string $sDeviceToken, string $sPayload, integer $nMessageID=0, integer $nExpire=604800)
Generate a binary notification from a device token and a JSON-encoded payload.
Definition: Push.php:263
integer getExpiry()
Get the expiry value.
Definition: Message.php:458

Here is the call graph for this function:

array getErrors ( boolean  $bEmpty = true)

Returns messages not delivered to the end user because one (or more) error occurred.

Parameters
$bEmpty[optional] Empty message container.
Returns
Array of messages not delivered because one or more errors occurred.

Definition at line 240 of file Push.php.

References $_aErrors.

241  {
242  $aRet = $this->_aErrors;
243  if ($bEmpty) {
244  $this->_aErrors = array();
245  }
246  return $aRet;
247  }
array $_aErrors
Error container.
Definition: Push.php:63
array getQueue ( boolean  $bEmpty = true)

Returns messages in the message queue.

When a message is successful sent or reached the maximum retry time is removed from the message queue and inserted in the Errors container. Use the getErrors() method to retrive messages with delivery error(s).

Parameters
$bEmpty[optional] Empty message queue.
Returns
Array of messages left on the queue.

Definition at line 223 of file Push.php.

References $_aMessageQueue.

224  {
225  $aRet = $this->_aMessageQueue;
226  if ($bEmpty) {
227  $this->_aMessageQueue = array();
228  }
229  return $aRet;
230  }
array $_aMessageQueue
Message queue.
Definition: Push.php:62
integer getSendRetryTimes ( )

Get the send retry time value.

Returns
Send retry times.

Definition at line 83 of file Push.php.

References $_nSendRetryTimes.

84  {
86  }
integer $_nSendRetryTimes
Send retry times.
Definition: Push.php:55
void send ( )

Sends all messages in the message queue to Apple Push Notification Service.

Exceptions
ApnsPHP_Push_Exceptionif not connected to the service or no notification queued.

Definition at line 120 of file Push.php.

References ApnsPHP_Abstract::_log(), _removeMessageFromQueue(), and _updateQueue().

121  {
122  if (!$this->_hSocket) {
123  throw new ApnsPHP_Push_Exception(
124  'Not connected to Push Notification Service'
125  );
126  }
127 
128  if (empty($this->_aMessageQueue)) {
129  throw new ApnsPHP_Push_Exception(
130  'No notifications queued to be sent'
131  );
132  }
133 
134  $this->_aErrors = array();
135  $nRun = 1;
136  while (($nMessages = count($this->_aMessageQueue)) > 0) {
137  $this->_log("INFO: Sending messages queue, run #{$nRun}: $nMessages message(s) left in queue.");
138 
139  $bError = false;
140  foreach($this->_aMessageQueue as $k => &$aMessage) {
141  if (function_exists('pcntl_signal_dispatch')) {
142  pcntl_signal_dispatch();
143  }
144 
145  $message = $aMessage['MESSAGE'];
146  $sCustomIdentifier = (string)$message->getCustomIdentifier();
147  $sCustomIdentifier = sprintf('[custom identifier: %s]', empty($sCustomIdentifier) ? 'unset' : $sCustomIdentifier);
148 
149  $nErrors = 0;
150  if (!empty($aMessage['ERRORS'])) {
151  foreach($aMessage['ERRORS'] as $aError) {
152  if ($aError['statusCode'] == 0) {
153  $this->_log("INFO: Message ID {$k} {$sCustomIdentifier} has no error ({$aError['statusCode']}), removing from queue...");
154  $this->_removeMessageFromQueue($k);
155  continue 2;
156  } else if ($aError['statusCode'] > 1 && $aError['statusCode'] <= 8) {
157  $this->_log("WARNING: Message ID {$k} {$sCustomIdentifier} has an unrecoverable error ({$aError['statusCode']}), removing from queue without retrying...");
158  $this->_removeMessageFromQueue($k, true);
159  continue 2;
160  }
161  }
162  if (($nErrors = count($aMessage['ERRORS'])) >= $this->_nSendRetryTimes) {
163  $this->_log(
164  "WARNING: Message ID {$k} {$sCustomIdentifier} has {$nErrors} errors, removing from queue..."
165  );
166  $this->_removeMessageFromQueue($k, true);
167  continue;
168  }
169  }
170 
171  $nLen = strlen($aMessage['BINARY_NOTIFICATION']);
172  $this->_log("STATUS: Sending message ID {$k} {$sCustomIdentifier} (" . ($nErrors + 1) . "/{$this->_nSendRetryTimes}): {$nLen} bytes.");
173 
174  $aErrorMessage = null;
175  if ($nLen !== ($nWritten = (int)@fwrite($this->_hSocket, $aMessage['BINARY_NOTIFICATION']))) {
176  $aErrorMessage = array(
177  'identifier' => $k,
178  'statusCode' => self::STATUS_CODE_INTERNAL_ERROR,
179  'statusMessage' => sprintf('%s (%d bytes written instead of %d bytes)',
180  $this->_aErrorResponseMessages[self::STATUS_CODE_INTERNAL_ERROR], $nWritten, $nLen
181  )
182  );
183  }
184  usleep($this->_nWriteInterval);
185 
186  $bError = $this->_updateQueue($aErrorMessage);
187  if ($bError) {
188  break;
189  }
190  }
191 
192  if (!$bError) {
193  $read = array($this->_hSocket);
194  $null = NULL;
195  $nChangedStreams = @stream_select($read, $null, $null, 0, $this->_nSocketSelectTimeout);
196  if ($nChangedStreams === false) {
197  $this->_log('ERROR: Unable to wait for a stream availability.');
198  break;
199  } else if ($nChangedStreams > 0) {
200  $bError = $this->_updateQueue();
201  if (!$bError) {
202  $this->_aMessageQueue = array();
203  }
204  } else {
205  $this->_aMessageQueue = array();
206  }
207  }
208 
209  $nRun++;
210  }
211  }
void _removeMessageFromQueue(integer $nMessageID, boolean $bError=false)
Remove a message from the message queue.
Definition: Push.php:371
void _log(string $sMessage)
Logs a message through the Logger.
Definition: Abstract.php:414
Exception class.
boolean _updateQueue(array $aErrorMessage=null)
Checks for error message and deletes messages successfully sent from message queue.
Definition: Push.php:327

Here is the call graph for this function:

void setSendRetryTimes ( integer  $nRetryTimes)

Set the send retry times value.

If the client is unable to send a payload to to the server retries at least for this value. The default send retry times is 3.

Parameters
$nRetryTimesSend retry times.

Definition at line 73 of file Push.php.

74  {
75  $this->_nSendRetryTimes = (int)$nRetryTimes;
76  }

Field Documentation

$_aErrorResponseMessages
protected
Initial value:
= array(
0 => 'No errors encountered',
1 => 'Processing error',
2 => 'Missing device token',
3 => 'Missing topic',
4 => 'Missing payload',
5 => 'Invalid token size',
6 => 'Invalid topic size',
7 => 'Invalid payload size',
8 => 'Invalid token',
self::STATUS_CODE_INTERNAL_ERROR => 'Internal error'
)

array Error-response messages.

Definition at line 42 of file Push.php.

array $_aErrors = array()
protected

Error container.

Definition at line 63 of file Push.php.

Referenced by getErrors().

array $_aMessageQueue = array()
protected

Message queue.

Definition at line 62 of file Push.php.

Referenced by getQueue().

$_aServiceURLs
protected
Initial value:
= array(
'tls://gateway.push.apple.com:2195',
'tls://gateway.sandbox.push.apple.com:2195'
)

array Service URLs environments.

Definition at line 57 of file Push.php.

integer $_nSendRetryTimes = 3
protected

Send retry times.

Definition at line 55 of file Push.php.

Referenced by getSendRetryTimes().

const COMMAND_PUSH = 1

integer Payload command.

Definition at line 35 of file Push.php.

const ERROR_RESPONSE_COMMAND = 8

integer Error-response command code.

Definition at line 38 of file Push.php.

const ERROR_RESPONSE_SIZE = 6

integer Error-response packet size.

Definition at line 37 of file Push.php.

const STATUS_CODE_INTERNAL_ERROR = 999

integer Status code for internal error (not Apple).

Definition at line 40 of file Push.php.


The documentation for this class was generated from the following file: