firebase.module in Firebase Push Notification (FCM) 7
Same filename and directory in other branches
File
firebase.moduleView source
<?php
/**
* Implements hook_help().
*/
function firebase_help($path, $arg) {
switch ($path) {
case 'admin/help#firebase':
return '<p>' . t('Enables sending push notifications.') . '</p>';
}
}
/**
* Implements hook_menu().
*/
function firebase_menu() {
$items['admin/config/system/firebase'] = array(
'title' => 'Firebase Push Notification Configuration',
'description' => 'Configure Firebase Notification',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'firebase_form',
),
'access arguments' => array(
'administer site configuration',
),
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
/**
* Form callback: Firebase settings.
*
* @see firebase_menu()
*/
function firebase_form($form, &$form_state) {
$form = array();
$form['firebase_server_key'] = array(
'#type' => 'textarea',
'#title' => t('Firebase Server Key'),
'#description' => t('This is the server key. <em>Do not confuse with API Key</em>'),
'#default_value' => variable_get('firebase_server_key', ''),
'#required' => TRUE,
);
$form['firebase_endpoint'] = array(
'#type' => 'textfield',
'#title' => t('Firebase endpoint'),
'#description' => t('Google Firebase Cloud Messaging endpoint.'),
'#default_value' => variable_get('firebase_endpoint', 'https://fcm.googleapis.com/fcm/send'),
'#required' => TRUE,
);
return system_settings_form($form);
}
/**
* Sends the push notification.
*
* @param string $token
* Firebase token that identify each device.
* @param array $param
* Parameters for payload. Expected values are:
* - $param['title']
* Title of push message
* - $param['body']
* Body of push message
* Optional values are:
* - $param['icon']
* Icon to be displayed. If none is given, the App's icon will be used.
* - $param['sound']
* Sound to play. If none is given, the App's default will be used.
* - $param['priority']
* Set message priority.
* - $param['click_action']
* The action associated with a user click on the notification.
* - $param['content_available']
* If sending silent pushes for iOS, this must be equal to TRUE.
* - $param['data']
* Send extra information to device. Not displayed to users.
* - $param['badge']
* Badge number on App icon.
*
* @return bool
* TRUE if the push was sent successfully, and FALSE if not.
*/
function firebase_send($token, $param) {
// We absolutely need the token. If it was not provided, return early.
if (empty($token)) {
return FALSE;
}
if (!($response = _firebase_sendPushNotification($token, $param))) {
// Error connecting to Firebase API. For instance, timeout.
return FALSE;
}
if ($response['body']->success === 1 && $response['body']->failure === 0) {
return TRUE;
}
// Something went wrong. We didn't sent the push notification.
// Common errors:
// - Authentication Error
// The Server Key is invalid.
// - Invalid Registration Token
// The token (generated by app) is not recognized by Firebase.
// @see https://firebase.google.com/docs/cloud-messaging/http-server-ref#error-codes
$error_message = reset($response['body']->results)->error;
watchdog('firebase', 'Message failure: !error', array(
'!error' => $error_message,
));
return FALSE;
}
/**
* Execute the push notification.
*
* @param string $appToken
* Device token.
* @param array $param
* Parameters for payload.
*
* @return object
* Firebase's response.
*/
function _firebase_sendPushNotification($appToken, array $param) {
$headers = _firebase_buildHeaders();
// We receive our prepared payload from buildMessage.
// Contains the token and notification array.
$message = _firebase_buildMessage($appToken, $param);
$ch = curl_init(variable_get('firebase_endpoint', 'https://fcm.googleapis.com/fcm/send'));
// Setup curl with our headers and message.
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $message);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// Send the request to Firebase.
$response['body'] = curl_exec($ch);
$response['body'] = json_decode($response['body']);
curl_close($ch);
return $response;
}
/**
* Builds the push notification header.
*/
function _firebase_buildHeaders() {
return array(
'Content-Type: application/json',
'Authorization: key=' . variable_get('firebase_server_key', ''),
);
}
/**
* Builds the push notification body.
*
* @param string $appToken
* Device token.
* @param array $param
* Parameters for payload.
*
* @return array
* Prepared payload for push notification.
*/
function _firebase_buildMessage($appToken, array $param) {
// Parameters will be okay if we have at least the title and body.
// If we do NOT have minimum fields, we assume it is a silent push.
// Silent pushes need parameter data. So we check for $param['data'].
// If these conditions are not met, we set a default value, just to go
// through the push notification.
if (!_firebase_isParamValid($param)) {
return FALSE;
}
$mandatory = _firebase_addMandatoryFields($appToken);
$optional = _firebase_addOptionalFields($param);
$message = $mandatory + $optional;
return json_encode($message);
}
/**
* Adds mandatory fields to payload.
*
* @param string $token
* Device token.
*
* @return array
* Mandatory payload.
*/
function _firebase_addMandatoryFields($token) {
// This is the core notification body.
$message['to'] = $token;
$message['priority'] = 'high';
return $message;
}
/**
* Adds optional fields to payload.
*
* @param array $param
* Data for payload.
*
* @return array
* Optional payload.
*/
function _firebase_addOptionalFields($param) {
$message = [];
if (!empty($param['priority'])) {
$message['priority'] = $param['priority'];
}
if (!empty($param['title']) && !empty($param['body'])) {
$message['notification'] = [
'title' => $param['title'],
'body' => $param['body'],
];
}
// If an icon, sound or click_action are available,
// add them to notification body.
if (!empty($param['icon'])) {
$message['notification']['icon'] = $param['icon'];
}
if (!empty($param['sound'])) {
$message['notification']['sound'] = $param['sound'];
}
if (!empty($param['click_action'])) {
$message['notification']['click_action'] = $param['click_action'];
}
if (!empty($param['content_available'])) {
$message['content_available'] = $param['content_available'];
}
if (isset($param['badge'])) {
$message['notification']['badge'] = $param['badge'];
}
// Data is not displayed to app users. It is usually used to send
// some data to be processed by the app.
if (!empty($param['data'])) {
$message['data'] = $param['data'];
}
return $message;
}
/**
* Validate mandatory data on received parameters.
*
* @param array $param
* Params that builds Push notification payload.
*
* @return bool
* TRUE|FALSE - if mandatory data is present.
*/
function _firebase_isParamValid(array $param) {
// We either have the title and body OR
// it's a silent push - require $param['data'].
if (!empty($param['title']) && !empty($param['body'])) {
return TRUE;
}
if (isset($param['data']) && firebase_checkReservedKeywords($param['data'])) {
return TRUE;
}
return FALSE;
}
/**
* Validate reserved keywords on data.
*
* The key should not be a reserved word
* ("from" or any word starting with "google" or "gcm").
* Do not use any of the words defined here
* https://firebase.google.com/docs/cloud-messaging/http-server-ref.
*
* Not checking ALL reserved keywords. Just eliminating the common ones.
* Created this function to document this important restriction.
*
* @param array $data
* Params that builds Push notification payload.
*
* @return bool
* TRUE if keys are fine, and FALSE if not.
*/
function firebase_checkReservedKeywords($data) {
foreach ($data as $key => $value) {
if (preg_match('/(^from$)|(^gcm)|(^google)/', $key)) {
return FALSE;
}
}
return TRUE;
}
Functions
Name | Description |
---|---|
firebase_checkReservedKeywords | Validate reserved keywords on data. |
firebase_form | Form callback: Firebase settings. |
firebase_help | Implements hook_help(). |
firebase_menu | Implements hook_menu(). |
firebase_send | Sends the push notification. |
_firebase_addMandatoryFields | Adds mandatory fields to payload. |
_firebase_addOptionalFields | Adds optional fields to payload. |
_firebase_buildHeaders | Builds the push notification header. |
_firebase_buildMessage | Builds the push notification body. |
_firebase_isParamValid | Validate mandatory data on received parameters. |
_firebase_sendPushNotification | Execute the push notification. |