View source
<?php
define('SMS_USER_PENDING', 1);
define('SMS_USER_CONFIRMED', 2);
define('SMS_USER_MAX_CHARS', 140);
require_once 'sms_user.actions.inc';
require_once 'sms_user.rules.inc';
function sms_user_perm() {
return array(
'receive sms',
'edit own sms number',
);
}
function sms_user_menu() {
$items = array();
$items['admin/smsframework/sms_user'] = array(
'title' => 'SMS User',
'description' => 'Edit options for SMS and user integration.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'sms_user_admin_settings',
),
'access arguments' => array(
'administer sms',
),
'file' => 'sms_user.admin.inc',
);
$items['user/%user/edit/mobile'] = array(
'title' => 'Mobile',
'page callback' => 'sms_user_settings',
'page arguments' => array(
1,
),
'type' => MENU_LOCAL_TASK,
'access callback' => 'sms_user_edit_access',
'access arguments' => array(
1,
),
'tab_parent' => 'user/%/edit',
);
return $items;
}
function sms_user_edit_access($account) {
return user_edit_access($account) && user_access('receive sms', $account);
}
function sms_user_send($uid, $message) {
$account = user_load($uid);
if (user_access('receive sms', $account)) {
if ($account->sms_user[0]['status'] == 2) {
return sms_send($account->sms_user[0]['number'], $message, $account->sms_user[0]['gateway']);
}
else {
return FALSE;
}
}
else {
drupal_set_message(t("User %user is not enabled to receive SMS, see 'receive sms' permission", array(
'%user' => $account->name,
)), 'status', TRUE);
}
}
function sms_user_get_uid($number, $status = NULL) {
$sql = "SELECT uid FROM {sms_user} WHERE number = '%s'";
$arguments = array(
$number,
);
if (isset($status)) {
$sql .= " AND status = %d";
$arguments[] = $status;
}
$data = db_fetch_array(db_query($sql, $arguments));
return $data['uid'];
}
function sms_user_sms_send(&$number, &$message, &$options, &$gateway) {
if (variable_get('sms_user_sleep', 1) && ($uid = sms_user_get_uid($number))) {
$account = user_load(array(
'uid' => $uid,
'status' => 1,
));
if (!empty($account->sms_user['sleep_enabled']) && _sms_user_sleep_active($account)) {
unset($gateway['send']);
watchdog('sms', 'Message was not sent to @user due to sleep settings.', array(
'@user' => $account->name,
));
}
}
}
function _sms_user_sleep_active($account) {
if (!empty($account->timezone_name)) {
$timezone = new DateTimeZone($account->timezone_name);
$date = new DateTime();
$date
->setTimezone($timezone);
$current_hour = $date
->format('G');
}
else {
$current_hour = date('G');
}
if ($account->sms_user['sleep_start_time'] <= $current_hour && $account->sms_user['sleep_end_time'] > $current_hour) {
return TRUE;
}
return FALSE;
}
function sms_user_settings($account) {
switch (isset($account->sms_user) ? $account->sms_user['status'] : 0) {
case 0:
$output = drupal_get_form('sms_user_settings_add_form', $account);
break;
case SMS_USER_PENDING:
$output = drupal_get_form('sms_user_settings_confirm_form', $account);
break;
case SMS_USER_CONFIRMED:
$output = drupal_get_form('sms_user_settings_reset_form', $account);
break;
}
if (variable_get('sms_user_sleep', 1)) {
$output .= drupal_get_form('sms_user_settings_sleep_form', $account);
}
return $output;
}
function sms_user_settings_add_form(&$form_state, $account) {
$form = sms_send_form();
$form['uid'] = array(
'#type' => 'hidden',
'#value' => $account->uid,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Confirm number'),
);
return $form;
}
function sms_user_settings_add_form_validate($form, &$form_state) {
if ($error = sms_user_validate_number($form_state['values']['number'])) {
form_set_error('number', $error);
}
if (empty($form_state['values']['gateway'])) {
$form_state['values']['gateway'] = array();
}
}
function sms_user_settings_add_form_submit($form, &$form_state, $account = NULL) {
if (!$account) {
$account = user_load(array(
'uid' => $form_state['values']['uid'],
));
}
sms_user_send_confirmation($account, $form_state['values']['number'], $form_state['values']['gateway']);
}
function sms_user_settings_confirm_form(&$form_state, $account) {
$form['uid'] = array(
'#type' => 'hidden',
'#value' => $account->uid,
);
$form['number'] = array(
'#type' => 'item',
'#title' => t('Mobile phone number'),
'#value' => $account->sms_user['number'],
);
$form['confirm_code'] = array(
'#type' => 'textfield',
'#title' => t('Confirmation code'),
'#description' => t('Enter the confirmation code sent by SMS to your mobile phone.'),
'#size' => 4,
'#maxlength' => 4,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Confirm number'),
);
$form['reset'] = array(
'#type' => 'submit',
'#value' => t('Delete & start over'),
'#access' => user_access('edit own sms number'),
);
return $form;
}
function sms_user_settings_confirm_form_validate($form, &$form_state) {
if ($form_state['clicked_button']['#value'] == t('Confirm number')) {
$account = user_load(array(
'uid' => $form_state['values']['uid'],
));
if ($form_state['values']['confirm_code'] != $account->sms_user['code']) {
form_set_error('confirm_code', t('The confirmation code is invalid.'));
}
}
}
function sms_user_settings_confirm_form_submit($form, &$form_state) {
$account = user_load(array(
'uid' => $form_state['values']['uid'],
));
if ($form_state['clicked_button']['#value'] == t('Delete & start over')) {
sms_user_delete($account->uid);
}
else {
$data = array(
'number' => $account->sms_user['number'],
'status' => SMS_USER_CONFIRMED,
'gateway' => $account->sms_user['gateway'],
);
user_save($account, array(
'sms_user' => $data,
), 'mobile');
if (module_exists('rules')) {
rules_invoke_event('sms_user_validated', $account);
}
}
}
function sms_user_settings_reset_form(&$form_state, $account) {
$form['uid'] = array(
'#type' => 'hidden',
'#value' => $account->uid,
);
$form['sms_user']['number'] = array(
'#type' => 'item',
'#title' => t('Your mobile phone number'),
'#value' => $account->sms_user['number'],
'#description' => t('Your mobile phone number has been confirmed.'),
);
$form['reset'] = array(
'#type' => 'submit',
'#value' => t('Delete & start over'),
'#access' => user_access('edit own sms number'),
);
return $form;
}
function sms_user_settings_reset_form_submit($form, &$form_state) {
$account = user_load(array(
'uid' => $form_state['values']['uid'],
));
sms_user_delete($account->uid);
if (module_exists('rules')) {
rules_invoke_event('sms_user_removed', $account);
}
drupal_set_message(t('Your mobile information has been removed'), 'status');
}
function sms_user_settings_sleep_form(&$form_state, $account) {
$form['uid'] = array(
'#type' => 'hidden',
'#value' => $account->uid,
);
$form['sleep'] = array(
'#type' => 'fieldset',
'#title' => t('Sleep Time'),
'#collapsible' => TRUE,
);
$form['sleep']['sleep_enabled'] = array(
'#type' => 'checkbox',
'#title' => t('Disable messages between these hours'),
'#description' => t('If enabled, you will not receive messages between the specified hours.'),
'#default_value' => isset($account->sms_user['sleep_enabled']) ? $account->sms_user['sleep_enabled'] : NULL,
);
if (strpos(variable_get('date_format_short', 'm/d/Y - H:i'), 'g')) {
$format = 'g A';
}
else {
$format = 'H:00';
}
$hour = 0;
while ($hour < 24) {
$options[$hour] = date($format, mktime($hour));
$hour++;
}
$form['sleep']['sleep_start_time'] = array(
'#type' => 'select',
'#multiple' => FALSE,
'#options' => $options,
'#default_value' => isset($account->sms_user['sleep_start_time']) ? $account->sms_user['sleep_start_time'] : NULL,
);
$form['sleep']['sleep_end_time'] = array(
'#type' => 'select',
'#multiple' => FALSE,
'#options' => $options,
'#default_value' => isset($account->sms_user['sleep_end_time']) ? $account->sms_user['sleep_end_time'] : NULL,
);
$form['sleep']['save'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
return $form;
}
function sms_user_settings_sleep_form_submit($form, &$form_state) {
$account = user_load(array(
'uid' => $form_state['values']['uid'],
));
$data = $account->sms_user;
$data['sleep_enabled'] = $form_state['values']['sleep_enabled'];
$data['sleep_start_time'] = $form_state['values']['sleep_start_time'];
$data['sleep_end_time'] = $form_state['values']['sleep_end_time'];
user_save($account, array(
'sms_user' => $data,
), 'mobile');
drupal_set_message(t('The changes have been saved.'), 'status');
}
function sms_user_send_confirmation($account, $number, $options) {
$code = rand(1000, 9999);
$number = sms_formatter($number);
$data = array(
'number' => $number,
'status' => SMS_USER_PENDING,
'code' => $code,
'gateway' => $options,
);
user_save($account, array(
'sms_user' => $data,
), 'mobile');
sms_send($number, _sms_user_confirm_message($code), $options);
}
function sms_user_validate_number(&$number) {
if ($error = sms_validate_number($number)) {
return $error;
}
elseif (sms_user_get_uid($number)) {
return t('This phone number is already registered to another user.');
}
}
function sms_user_user($op, &$edit, &$account, $category = NULL) {
global $user;
switch ($op) {
case 'load':
return sms_user_load($edit, $account, $category);
case 'update':
case 'insert':
return sms_user_save($edit, $account, $category);
case 'view':
if (user_access('receive sms', $account) && ($user->uid == $account->uid || user_access('administer smsframework'))) {
if (isset($account->sms_user['status']) && $account->sms_user['status'] == SMS_USER_PENDING) {
drupal_set_message(t('You need to confirm your mobile number, <a href="@mobile_url">enter the confirmation code sent to your mobile</a>.', array(
'@mobile_url' => url('user/' . $account->uid . '/edit/mobile'),
)));
}
$account->content['sms'] = array(
'#type' => 'user_profile_category',
'#title' => t('Mobile'),
);
$account->content['sms']['number'] = array(
'#type' => 'user_profile_item',
'#title' => t(''),
'#value' => isset($account->sms_user['number']) ? $account->sms_user['number'] : '',
);
}
break;
case 'register':
return sms_user_register();
case 'delete':
return sms_user_delete($account->uid);
case 'validate':
if (!empty($edit['sms_user']) && (variable_get('sms_user_registration_form', 0) == 2 || strlen($edit['sms_user']['number']))) {
if ($error = sms_user_validate_number($edit['sms_user']['number'])) {
form_set_error('sms_user][number', $error);
}
}
break;
case 'login':
if (!$account->access && !empty($account->sms_user['number']) && $account->sms_user['status'] != SMS_USER_CONFIRMED) {
sms_user_send_confirmation($account, $account->sms_user['number'], $account->sms_user['gateway']);
drupal_set_message(t('A confirmation message has been sent to your mobile phone. Please !link.', array(
'!link' => l(t('confirm your number'), 'user/' . $account->uid . '/edit/mobile'),
)), 'status');
}
break;
case 'categories':
$categories['mobile'] = array(
'name' => 'mobile',
'title' => t('Mobile'),
'weight' => 10,
);
return $categories;
}
}
function sms_user_load(&$edit, &$account, $category) {
$result = db_query("SELECT number, status, code, gateway FROM {sms_user} WHERE uid = %d", $account->uid);
$account->sms_user = array();
while ($data = db_fetch_array($result)) {
$user_data = unserialize($account->data);
$account->sms_user = $user_data['sms_user'];
$account->sms_user['number'] = $data['number'];
$account->sms_user['status'] = $data['status'];
$account->sms_user['code'] = $data['code'];
$account->sms_user['gateway'] = unserialize($data['gateway']);
}
$account->sms_user[0] = $account->sms_user;
}
function sms_user_save(&$edit, &$account, $category) {
if (($category == 'mobile' || $category == 'account') && $edit['sms_user']) {
$number = $edit['sms_user'];
$db_values = array(
$number['number'],
$number['status'],
isset($number['code']) ? $number['code'] : NULL,
serialize($number['gateway']),
);
db_query("UPDATE {sms_user} SET number = '%s', status = %d, code = '%s', gateway = '%s'\n WHERE uid = %d AND number = '%s'", array_merge($db_values, array(
$account->uid,
$number['number'],
)));
if ($number['number'] && !db_affected_rows()) {
db_query("INSERT INTO {sms_user} (number, status, code, gateway, uid)\n VALUES ('%s', %d, '%s', '%s', %d)", array_merge($db_values, array(
$account->uid,
)));
}
$edit['sms_user']['number'] = NULL;
$edit['sms_user']['status'] = NULL;
$edit['sms_user']['code'] = NULL;
$edit['sms_user']['gateway'] = NULL;
}
}
function sms_user_delete($uid, $number = FALSE) {
$db_args = array(
$uid,
);
if ($number == FALSE) {
$number_where = '';
}
else {
$number_where = "AND number = '%s'";
$db_args[] = $number;
}
db_query("DELETE FROM {sms_user} WHERE uid = %d {$number_where}", $db_args);
}
function _sms_user_confirm_message($code) {
$text_format = variable_get('sms_user_confirmation_message', '[site-name] confirmation code: [confirm-code]');
$text = token_replace_multiple($text_format, array(
'sms_user' => array(
'confirm-code' => $code,
),
));
return $text;
}
function sms_user_register() {
if (variable_get('sms_user_registration_form', 0)) {
$form['sms_user'] = array(
'#type' => 'fieldset',
'#title' => t('Mobile settings'),
'#description' => t('You will receive a message to confirm your mobile information upon login.'),
'#collapsible' => TRUE,
'#tree' => TRUE,
);
$required = FALSE;
if (variable_get('sms_user_registration_form', 0) == 2) {
$required = TRUE;
}
$form['sms_user'] += sms_send_form($required);
return $form;
}
}
function sms_user_token_values($type, $object = NULL, $options = array()) {
global $user;
$values = array();
switch ($type) {
case 'sms_user':
$values['confirm-code'] = $object['confirm-code'];
$values['mobile-url'] = url("user/{$user->uid}/edit/mobile", array(
'absolute' => TRUE,
));
break;
}
return $values;
}
function sms_user_token_list($type = 'all') {
$tokens = array();
if ($type == 'sms_user') {
$tokens['sms_user']['confirm-code'] = t('The mobile confirmation code for the user.');
$tokens['sms_user']['mobile-url'] = t('The URL for the user\'s mobile settings page.');
}
return $tokens;
}
function sms_user_sms_incoming($op, $number, $message, $options) {
global $user;
switch ($op) {
case 'pre process':
if ($account = sms_user_authenticate($number)) {
$metadata = array(
'login' => TRUE,
'number' => $number,
'message' => $message,
'options' => $options,
);
sms_user_login_metadata($account->uid, $metadata);
$edit = array();
user_module_invoke('login', $edit, $account);
}
elseif (variable_get('sms_user_registration_enabled', 0) && $number) {
if ($account = sms_user_register_new_user($number, $message, $options)) {
if ($message = variable_get('sms_user_new_account_message', '')) {
sms_user_send($account->uid, $message);
}
}
}
break;
case 'post process':
sms_user_logout();
break;
}
}
function sms_user_login_metadata($uid = NULL, $metadata = NULL, $reset = FALSE) {
static $accounts = array();
if ($reset) {
$accounts = array();
}
if (!isset($uid)) {
return $accounts;
}
if (isset($metadata)) {
$accounts[$uid] = $metadata;
return TRUE;
}
elseif (isset($accounts[$uid])) {
return $accounts[$uid];
}
else {
return FALSE;
}
}
function sms_user_register_new_user($number, $message, $options) {
global $user;
$edit = array();
$mail = isset($options['sms_email_gateway_from']) ? $options['sms_email_gateway_from'] : '';
$edit['sms_user'] = array(
'number' => $number,
'status' => 0,
'code' => '',
'gateway' => '',
);
if ($mail && ($account = user_load(array(
'mail' => $mail,
)))) {
$account = user_save($account, $edit);
}
else {
$edit['mail'] = $edit['init'] = $mail;
if (variable_get('sms_user_allow_password', 0)) {
$lines = explode("\n", $message);
$words = explode(" ", $lines[0]);
foreach ($words as $word) {
if (trim($word)) {
$edit['pass'] = preg_replace('/\\s+/', '-', $word);
break;
}
}
}
if (!$edit['pass']) {
$edit['pass'] = user_password();
}
$edit['name'] = substr(md5($number . strval(time())), 0, 10);
$edit['status'] = variable_get('user_register', 1) == 1;
$account = user_save('', $edit);
}
if (is_object($account)) {
$user = $account;
$metadata = array(
'register' => TRUE,
'number' => $number,
'message' => $message,
'options' => $options,
);
sms_user_login_metadata($account->uid, $metadata);
$edit = array();
user_module_invoke('login', $edit, $account);
return $account;
}
return FALSE;
}
function sms_user_authenticate($number) {
global $user;
$uid = sms_user_get_uid($number);
if ($account = user_load(array(
'uid' => $uid,
'status' => 1,
))) {
$user = $account;
watchdog('sms', '%name was authenticated using SMS.', array(
'%name' => $user->name,
));
return $user;
}
}
function sms_user_logout() {
global $user;
session_destroy();
$user = drupal_anonymous_user();
}
function sms_user_views_api() {
return array(
'api' => 2,
);
}