You are here

sms.module in SMS Framework 5

The core of the SMS Framework. Provides gateway managment and API for sending and receiving SMS messages.

File

sms.module
View source
<?php

/**
 * @file
 * The core of the SMS Framework. Provides gateway managment and API for
 * sending and receiving SMS messages.
 */

/**
 * Sends a message using the active gateway.
 * 
 * @param $number
 *   The destination number.
 * 
 * @param $message
 *   The text of the messsage to send.
 * 
 * @param $options
 *   An array of dditional properties as defined by gateway modules.
 */
function sms_send($number, $message, $options = array()) {
  $gateway = sms_default_gateway();
  foreach (module_implements('sms_send') as $module) {
    $function = $module . '_sms_send';
    $function($number, $message, $options, $gateway);
  }
  if (function_exists($gateway['send'])) {
    $response = $gateway['send']($number, $message, $options);
  }
  return sms_handle_result($response, $number, $message);
}

/**
 * Callback for incoming messages. Allows gateways modules to pass messages in
 * a standard format for processing.
 * 
 * @param $number
 *   The sender's mobile number.
 * 
 * @param $message
 *   The content of the text message.
 */
function sms_incoming($number, $message, $options = array()) {

  // Execute three phases
  module_invoke_all('sms_incoming', 'pre process', $number, $message, $options);
  module_invoke_all('sms_incoming', 'process', $number, $message, $options);
  module_invoke_all('sms_incoming', 'post process', $number, $message, $options);
}

/**
 * Returns the current default gateway.
 */
function sms_default_gateway() {
  return sms_gateways('gateway', variable_get('sms_default_gateway', 'log'));
}

/**
 * Implementation of hook_gateway_info().
 */
function sms_gateway_info() {
  return array(
    'log' => array(
      'name' => t('Log only'),
      'send' => 'sms_send_log',
    ),
  );
}
function sms_send_log($number, $message, $options) {
  watchdog('sms', t('SMS message sent to %number with the text: @message', array(
    '%number' => $number,
    '@message' => $message,
  )), WATCHDOG_INFO);
  return array(
    'status' => TRUE,
  );
}

/**
 * Implementation of hook_menu().
 */
function sms_menu($may_cache) {
  $items = array();
  if ($may_cache) {
    $items[] = array(
      'path' => 'admin/smsframework',
      'title' => t('SMS Framework'),
      'description' => t('Control how your site uses SMS.'),
      'position' => 'right',
      'callback' => 'system_admin_menu_block_page',
      'access' => user_access('administer smsframework'),
    );
    $items[] = array(
      'path' => 'admin/smsframework/gateways',
      'title' => t('Gateway configuration'),
      'description' => t('Configure gateways and chose the default gateway.'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array(
        'sms_admin_default_form',
      ),
      'access' => user_access('administer smsframework'),
    );
    $items[] = array(
      'path' => 'admin/smsframework/gateways/edit',
      'callback' => 'drupal_get_form',
      'callback arguments' => array(
        'sms_admin_gateway_form',
      ),
      'access' => user_access('administer smsframework'),
      'type' => MENU_CALLBACK,
    );
  }
  return $items;
}

/**
 * Implementation of hook_perm().
 */
function sms_perm() {
  return array(
    'administer smsframework',
  );
}

/**
 * Form for selecting the default gateway.
 */
function sms_admin_default_form() {
  $gateways = sms_gateways();
  foreach ($gateways as $identifier => $gateway) {
    $active = $identifier == variable_get('sms_default_gateway', 'log');
    $options[$identifier] = '';
    $form[$gateway['name']]['id'] = array(
      '#value' => $identifier,
    );
    if (function_exists($gateway['configure form'])) {
      $form[$gateway['name']]['configure'] = array(
        '#value' => l(t('configure'), 'admin/smsframework/gateways/edit/' . $identifier),
      );
    }
    else {
      $form[$gateway['name']]['configure'] = array(
        '#value' => t('No configuration options'),
      );
    }
  }
  $form['default'] = array(
    '#type' => 'radios',
    '#options' => $options,
    '#default_value' => variable_get('sms_default_gateway', 'log'),
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Set default gateway'),
  );
  return $form;
}
function sms_admin_default_form_submit($form_id, $form_values) {

  // Process form submission to set the default gateway
  if ($form_values['default']) {
    drupal_set_message(t('Default gateway updated.'));
    variable_set('sms_default_gateway', $form_values['default']);
  }
}
function theme_sms_admin_default_form($form) {
  $rows = array();
  foreach ($form as $name => $element) {
    if (isset($element['id']) && is_array($element['id'])) {
      $rows[] = array(
        drupal_render($form['default'][$element['id']['#value']]),
        check_plain($name),
        drupal_render($element['configure']),
      );
      unset($form[$name]);
    }
  }
  $header = array(
    t('Default'),
    t('Name'),
    array(
      'data' => t('Operations'),
      'colspan' => 1,
    ),
  );
  $output .= theme('table', $header, $rows);
  $output .= drupal_render($form);
  return $output;
}

/**
 * Gateway configuration form. Loads form from gateway.
 */
function sms_admin_gateway_form($gateway_id = NULL) {
  $gateway = sms_gateways('gateway', $gateway_id);
  if ($gateway && function_exists($gateway['configure form'])) {
    drupal_set_title(t('@gateway configuration', array(
      '@gateway' => $gateway['name'],
    )));
    $form = $gateway['configure form']($gateway['configuration']);
    $form['submit'] = array(
      '#type' => 'submit',
      '#value' => t('Save'),
    );
    $form['gateway'] = array(
      '#type' => 'value',
      '#value' => $gateway,
    );
    return $form;
  }
}

/**
 * Validation for gateway configuration. If the gateway defines a validation
 * function it uses that.
 */
function sms_admin_gateway_form_validate($form_id, $form_values) {

  // Pass validation to gateway
  $function = $form_values['gateway']['configure form'] . '_validate';
  if (function_exists($function)) {
    $function($function, $form_values);
  }
}

/**
 * Save the gateway settings.
 */
function sms_admin_gateway_form_submit($form_id, $form_values) {
  $gateway = $form_values['gateway'];

  // Remove uneccesary values
  unset($form_values['op'], $form_values['submit'], $form_values['gateway'], $form_values['form_token'], $form_values['form_id']);
  variable_set('sms_' . $gateway['identifier'] . '_settings', $form_values);
  drupal_set_message(t('The gateway settings have been saved.'));
  return 'admin/smsframework/gateways';
}

/**
 * Get a list of all gateways
 *
 * @param $op
 *   The format in which to return the list. When set to 'gateway' or 'name',
 *   only the specified gateway is returned. When set to 'gateways' or 'names',
 *   all gateways are returned.
 *
 * @param $gateway
 *   A gateway identifier string that indicates the gateway to return. Leave at default
 *   value (NULL) to return all gateways.
 *
 * @return
 *   Either an array of all gateways or a single gateway, in a variable format.
 **/
function sms_gateways($op = 'gateways', $gateway = NULL) {
  list($_gateways, $_names) = _gateways_build();
  switch ($op) {
    case 'gateways':
      return $_gateways;
    case 'gateway':
      $return = $_gateways[$gateway];
      $return['identifier'] = $gateway;
      return $return;
    case 'names':
      return $_names;
    case 'name':
      return $_names[$gateway];
  }
}
function _gateways_build() {
  $_gateways = array();
  $_names = array();
  $gateway_array = module_invoke_all('gateway_info');
  foreach ($gateway_array as $identifier => $info) {
    $info['configuration'] = variable_get('sms_' . $identifier . '_settings', '');
    $_gateways[$identifier] = $info;
    $_names[$identifier] = $info['name'];
  }
  asort($_names);
  return array(
    $_gateways,
    $_names,
  );
}
function sms_handle_result($result, $number, $message) {
  if ($result['status']) {
    return TRUE;
  }
  else {
    $error_message = 'Sending SMS to %number failed.';
    $variables['%number'] = $number;
    if ($result['message']) {
      $error_message .= ' The gateway said ' . $result['message'];
      if (!empty($result['variables'])) {
        $variables = array_merge($variables, $result['variables']);
      }
    }
    watchdog('sms', $error_message, $variables, WATCHDOG_ERROR);
    return FALSE;
  }
}
function sms_number_format($number) {
  $gateway = sms_default_gateway();
  if ($gateway['number_formatter'] && function_exists($gateway['number_formatter'])) {
    return $gateway['number_formatter']($number_formatter);
  }
  else {
    return $number;
  }
}
function sms_formatter($number) {

  // Remove non-number characters
  $number = preg_replace("/[^0-9]/", '', $number);
  if (strlen($number) > 16) {
    if ($number[0] == 1) {
      $number = ltrim($number, 1);
    }
    else {
      return FALSE;
    }
  }
  elseif (strlen($number) < 10) {
    return FALSE;
  }
  return $number;
}

/**
 * Generates a SMS sending form and adds gateway defined elements. The form
 * array that is returned can be merged with an existing form using
 * array_merge().
 * 
 * @param $required
 *   Specify if the user is required to provide information for the fields.
 * 
 * @return $form
 */
function sms_send_form($required = FALSE) {
  $gateway = sms_default_gateway();
  $form['number'] = array(
    '#type' => 'textfield',
    '#title' => t('Phone number'),
    '#size' => 40,
    '#maxlength' => 255,
    '#required' => $required,
  );

  // Add gateway defined fields
  if (function_exists($gateway['send form'])) {
    $form['gateway']['#tree'] = TRUE;
    $form['gateway'] = array_merge($gateway['send form']($required), $form['gateway']);
  }
  return $form;
}
function sms_send_form_validate($form_id, &$form_values) {
  if (!sms_formatter($form_values['number'])) {
    form_set_error('number', t('You must enter a valid phone number.'));
  }
}
function sms_validate_number(&$number) {
  if (!strlen($number) || !($number = sms_formatter($number))) {
    return t('The phone number is invalid.');
  }

  // Allow the active gateway to provide number validation
  $gateway = sms_default_gateway();
  if (function_exists($gateway['validate number']) && ($error = $gateway['validate number']($number))) {
    return $error;
  }
}

/**
 * Performs a simple send on submit. 
 */
function sms_send_form_submit($form_id, $form_values) {
  $form_values['number'] = sms_formatter($form_values['number']);
  sms_send($form_values['number'], $form_values['message'], $form_values['gateway']);
}

Functions

Namesort descending Description
sms_admin_default_form Form for selecting the default gateway.
sms_admin_default_form_submit
sms_admin_gateway_form Gateway configuration form. Loads form from gateway.
sms_admin_gateway_form_submit Save the gateway settings.
sms_admin_gateway_form_validate Validation for gateway configuration. If the gateway defines a validation function it uses that.
sms_default_gateway Returns the current default gateway.
sms_formatter
sms_gateways Get a list of all gateways
sms_gateway_info Implementation of hook_gateway_info().
sms_handle_result
sms_incoming Callback for incoming messages. Allows gateways modules to pass messages in a standard format for processing.
sms_menu Implementation of hook_menu().
sms_number_format
sms_perm Implementation of hook_perm().
sms_send Sends a message using the active gateway.
sms_send_form Generates a SMS sending form and adds gateway defined elements. The form array that is returned can be merged with an existing form using array_merge().
sms_send_form_submit Performs a simple send on submit.
sms_send_form_validate
sms_send_log
sms_validate_number
theme_sms_admin_default_form
_gateways_build