View source
<?php
namespace Drupal\push_notifications;
class PushNotificationsBroadcasterGcm implements PushNotificationsBroadcasterInterface {
const PUSH_NOTIFICATIONS_GCM_SERVER_POST_URL = 'https://android.googleapis.com/gcm/send';
protected $tokens;
protected $payload;
protected $countAttempted = 0;
protected $countSuccess = 0;
protected $success = FALSE;
protected $message;
private $tokenBundles;
public function __construct() {
}
public function setTokens($tokens) {
$this->tokens = $tokens;
}
public function setMessage($message) {
$this->message = $message;
$this->payload = array(
'alert' => $message,
);
}
public function sendBroadcast() {
if (empty($this->tokens) || empty($this->payload)) {
throw new \Exception('No tokens or payload set.');
}
$this->tokenBundles = ceil(count($this->tokens) / 1000);
$this->countAttempted = count($this->tokens);
for ($i = 0; $i < $this->tokenBundles; $i++) {
try {
$bundledTokens = array_slice($this->tokens, $i * 1000, 1000, FALSE);
$result = $this
->sendTokenBundle($bundledTokens);
$this
->processResult($result, $bundledTokens);
} catch (\Exception $e) {
\Drupal::logger('push_notifications')
->error($e
->getMessage());
}
}
$this->success = TRUE;
}
public function getResults() {
return array(
'network' => PUSH_NOTIFICATIONS_NETWORK_ID_ANDROID,
'payload' => $this->payload,
'count_attempted' => $this->countAttempted,
'count_success' => $this->countSuccess,
'success' => $this->success,
);
}
private function sendTokenBundle($tokens) {
$data = array();
foreach ($this->payload as $key => $value) {
if ($key != 'alert') {
$data['data'][$key] = $value;
}
}
$data['registration_ids'] = $tokens;
$data['collapse_key'] = (string) time();
$data['data']['message'] = $this->message;
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, self::PUSH_NOTIFICATIONS_GCM_SERVER_POST_URL);
curl_setopt($curl, CURLOPT_HTTPHEADER, $this
->getHeaders());
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_POST, TRUE);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
$response_raw = curl_exec($curl);
$info = curl_getinfo($curl);
curl_close($curl);
$response = FALSE;
if (isset($response_raw)) {
$response = json_decode($response_raw);
}
return array(
'info' => $info,
'response' => $response,
'response_raw' => $response_raw,
);
}
private function processResult($result, $tokens) {
if ($result['info']['http_code'] != 200) {
throw new \Exception('Connection could not be authorized with Google Play. Check your API key.');
}
if ($result['info']['http_code'] == 200 && !empty($result['response']->failure)) {
\Drupal::logger('push_notifications')
->notice("Google's Server returned an error: @response_raw", array(
'@response_raw' => $result['response_raw'],
));
foreach ($result['response']->results as $token_index => $message_result) {
if (!empty($message_result->error)) {
if ($message_result->error == 'NotRegistered' || $message_result->error == 'InvalidRegistration') {
$entity_type = 'push_notifications_token';
$query = \Drupal::entityQuery($entity_type)
->condition('token', $tokens[$token_index]);
$entity_ids = $query
->execute();
$entityTypeManager = \Drupal::entityTypeManager()
->getStorage($entity_type);
$entity = $entityTypeManager
->load(array_shift($entity_ids));
$entity
->delete();
\Drupal::logger('push_notifications')
->notice("GCM token not valid anymore. Removing token @token", array(
'@$token' => $tokens[$token_index],
));
}
}
}
}
if ($result['info']['http_code'] == 200 && !empty($result['response']->success)) {
$this->countSuccess += $result['response']->success;
}
}
private function getHeaders() {
$headers = array();
$headers[] = 'Content-Type:application/json';
$headers[] = 'Authorization:key=' . \Drupal::config('push_notifications.gcm')
->get('api_key');
return $headers;
}
}