Edit File: DownstreamResponse.php
<?php namespace LaravelFCM\Response; use Monolog\Logger; use Monolog\Handler\StreamHandler; use Psr\Http\Message\ResponseInterface; /** * Class DownstreamResponse. */ class DownstreamResponse extends BaseResponse implements DownstreamResponseContract { const MULTICAST_ID = 'multicast_id'; const CANONICAL_IDS = 'canonical_ids'; const RESULTS = 'results'; const MISSING_REGISTRATION = 'MissingRegistration'; const MESSAGE_ID = 'message_id'; const REGISTRATION_ID = 'registration_id'; const NOT_REGISTERED = 'NotRegistered'; const INVALID_REGISTRATION = 'InvalidRegistration'; const UNAVAILABLE = 'Unavailable'; const DEVICE_MESSAGE_RATE_EXCEEDED = 'DeviceMessageRateExceeded'; const INTERNAL_SERVER_ERROR = 'InternalServerError'; /** * @internal * * @var int */ protected $numberTokensSuccess = 0; /** * @internal * * @var int */ protected $numberTokensFailure = 0; /** * @internal * * @var int */ protected $numberTokenModify = 0; /** * @internal * * @var */ protected $messageId; /** * @internal * * @var array */ protected $tokensToDelete = []; /** * @internal * * @var array */ protected $tokensToModify = []; /** * @internal * * @var array */ protected $tokensToRetry = []; /** * @internal * * @var array */ protected $tokensWithError = []; /** * @internal * * @var bool */ protected $hasMissingToken = false; /** * @internal * * @var array */ private $tokens; /** * DownstreamResponse constructor. * * @param \Psr\Http\Message\ResponseInterface $response * @param $tokens */ public function __construct(ResponseInterface $response, $tokens) { $this->tokens = is_string($tokens) ? [$tokens] : $tokens; parent::__construct($response); } /** * Parse the response. * * @param $responseInJson */ protected function parseResponse($responseInJson) { $this->parse($responseInJson); if ($this->needResultParsing($responseInJson)) { $this->parseResult($responseInJson); } if ($this->logEnabled) { $this->logResponse(); } } /** * @internal * * @param $responseInJson */ private function parse($responseInJson) { if (array_key_exists(self::MULTICAST_ID, $responseInJson)) { $this->messageId; } if (array_key_exists(self::SUCCESS, $responseInJson)) { $this->numberTokensSuccess = $responseInJson[self::SUCCESS]; } if (array_key_exists(self::FAILURE, $responseInJson)) { $this->numberTokensFailure = $responseInJson[self::FAILURE]; } if (array_key_exists(self::CANONICAL_IDS, $responseInJson)) { $this->numberTokenModify = $responseInJson[self::CANONICAL_IDS]; } } /** * @internal * * @param $responseInJson */ private function parseResult($responseInJson) { foreach ($responseInJson[self::RESULTS] as $index => $result) { if (!$this->isSent($result)) { if (!$this->needToBeModify($index, $result)) { if (!$this->needToBeDeleted($index, $result) && !$this->needToResend($index, $result) && !$this->checkMissingToken($result)) { $this->needToAddError($index, $result); } } } } } /** * @internal * * @param $responseInJson * * @return bool */ private function needResultParsing($responseInJson) { return array_key_exists(self::RESULTS, $responseInJson) && ($this->numberTokensFailure > 0 || $this->numberTokenModify > 0); } /** * @internal * * @param $results * * @return bool */ private function isSent($results) { return array_key_exists(self::MESSAGE_ID, $results) && !array_key_exists(self::REGISTRATION_ID, $results); } /** * @internal * * @param $index * @param $result * * @return bool */ private function needToBeModify($index, $result) { if (array_key_exists(self::MESSAGE_ID, $result) && array_key_exists(self::REGISTRATION_ID, $result)) { if ($this->tokens[$index]) { $this->tokensToModify[$this->tokens[$index]] = $result[self::REGISTRATION_ID]; } return true; } return false; } /** * @internal * * @param $index * @param $result * * @return bool */ private function needToBeDeleted($index, $result) { if (array_key_exists(self::ERROR, $result) && (in_array(self::NOT_REGISTERED, $result) || in_array(self::INVALID_REGISTRATION, $result))) { if ($this->tokens[$index]) { $this->tokensToDelete[] = $this->tokens[$index]; } return true; } return false; } /** * @internal * * @param $index * @param $result * * @return bool */ private function needToResend($index, $result) { if (array_key_exists(self::ERROR, $result) && (in_array(self::UNAVAILABLE, $result) || in_array(self::DEVICE_MESSAGE_RATE_EXCEEDED, $result) || in_array(self::INTERNAL_SERVER_ERROR, $result))) { if ($this->tokens[$index]) { $this->tokensToRetry[] = $this->tokens[$index]; } return true; } return false; } /** * @internal * * @param $result * * @return bool */ private function checkMissingToken($result) { $hasMissingToken = (array_key_exists(self::ERROR, $result) && in_array(self::MISSING_REGISTRATION, $result)); $this->hasMissingToken = (bool) ($this->hasMissingToken | $hasMissingToken); return $hasMissingToken; } /** * @internal * * @param $index * @param $result */ private function needToAddError($index, $result) { if (array_key_exists(self::ERROR, $result)) { if ($this->tokens[$index]) { $this->tokensWithError[$this->tokens[$index]] = $result[self::ERROR]; } } } /** * @internal */ protected function logResponse() { $logger = new Logger('Laravel-FCM'); $logger->pushHandler(new StreamHandler(storage_path('logs/laravel-fcm.log'))); $logMessage = 'notification send to '.count($this->tokens).' devices'.PHP_EOL; $logMessage .= 'success: '.$this->numberTokensSuccess.PHP_EOL; $logMessage .= 'failures: '.$this->numberTokensFailure.PHP_EOL; $logMessage .= 'number of modified token : '.$this->numberTokenModify.PHP_EOL; $logger->info($logMessage); } /** * Merge two response. * * @param DownstreamResponse $response */ public function merge(DownstreamResponse $response) { $this->numberTokensSuccess += $response->numberSuccess(); $this->numberTokensFailure += $response->numberFailure(); $this->numberTokenModify += $response->numberModification(); $this->tokensToDelete = array_merge($this->tokensToDelete, $response->tokensToDelete()); $this->tokensToModify = array_merge($this->tokensToModify, $response->tokensToModify()); $this->tokensToRetry = array_merge($this->tokensToRetry, $response->tokensToRetry()); $this->tokensWithError = array_merge($this->tokensWithError, $response->tokensWithError()); } /** * Get the number of device reached with success. * * @return int */ public function numberSuccess() { return $this->numberTokensSuccess; } /** * Get the number of device which thrown an error. * * @return int */ public function numberFailure() { return $this->numberTokensFailure; } /** * Get the number of device that you need to modify their token. * * @return int */ public function numberModification() { return $this->numberTokenModify; } /** * get token to delete. * * remove all tokens returned by this method in your database * * @return array */ public function tokensToDelete() { return $this->tokensToDelete; } /** * get token to modify. * * key: oldToken * value: new token * * find the old token in your database and replace it with the new one * * @return array */ public function tokensToModify() { return $this->tokensToModify; } /** * Get tokens that you should resend using exponential backoff. * * @return array */ public function tokensToRetry() { return $this->tokensToRetry; } /** * Get tokens that thrown an error. * * key : token * value : error * * In production, remove these tokens from you database * * @return array */ public function tokensWithError() { return $this->tokensWithError; } /** * check if missing tokens was given to the request * If true, remove all the empty token in your database. * * @return bool */ public function hasMissingToken() { return $this->hasMissingToken; } }
Back to File Manager