engagements.module
Search API
This is the primary module file for the engagements module.
File
modules/engagements/engagements.moduleView source
- <?php
-
- /**
- * @file
- * This is the primary module file for the engagements module.
- */
-
-
-
-
-
- /**
- * Implement hook_menu
- */
- function engagements_menu()
- {
- $items = array();
-
- $items["engagements"] = array(
- "title" => t("Engagements"),
- "page_callback" => "engagements_display_main",
- "access_arguments" => array("can_view_engagements"),
- "tab_family" => "system",
- "page_settings" => array(
- "display_currently_advising" => TRUE,
- ),
- "weight" => 20,
- "type" => MENU_TYPE_TAB,
- );
-
-
- $items['engagements-track/%/%/pixel.gif'] = array(
- 'page_callback' => 'engagements_handle_tracking_pixel_request',
- 'page_arguments' => array(1, 2),
- 'access_callback' => TRUE,
- 'type' => MENU_TYPE_CALLBACK,
- );
-
-
- $items['engagements-handle-incoming-sms'] = array(
- 'page_callback' => 'engagements_handle_incoming_sms',
- 'access_callback' => TRUE,
- 'type' => MENU_TYPE_CALLBACK,
- );
-
-
-
-
- $items["admin/config/imap"] = array(
- "title" => "Engagements - IMAP settings",
- "description" => "Configure IMAP settings for Engagements",
- "page_callback" => "fp_render_form",
- "page_arguments" => array("engagements_imap_settings_form", "system_settings"),
- "access_arguments" => array("administer_engagements"),
- "page_settings" => array(
- "menu_icon" => fp_get_module_path('system') . "/icons/cog.png",
- "menu_links" => array(
- 0 => array(
- "text" => "Admin Console",
- "path" => "admin-tools/admin",
- "query" => "de_catalog_year=%DE_CATALOG_YEAR%",
- ),
- ),
- ),
- "type" => MENU_TYPE_NORMAL_ITEM,
- "tab_parent" => "admin-tools/admin",
- );
-
-
- $items["admin/config/sms"] = array(
- "title" => "Engagements - SMS settings",
- "description" => "Configure SMS settings for Engagements",
- "page_callback" => "fp_render_form",
- "page_arguments" => array("engagements_sms_settings_form", "system_settings"),
- "access_arguments" => array("administer_engagements"),
- "page_settings" => array(
- "menu_icon" => fp_get_module_path('system') . "/icons/cog.png",
- "menu_links" => array(
- 0 => array(
- "text" => "Admin Console",
- "path" => "admin-tools/admin",
- "query" => "de_catalog_year=%DE_CATALOG_YEAR%",
- ),
- ),
- ),
- "type" => MENU_TYPE_NORMAL_ITEM,
- "tab_parent" => "admin-tools/admin",
- );
-
-
-
- $items["admin-tools/mass-sms"] = array(
- "title" => "Send Mass Text Messages",
- "description" => "Send a text message to multiple recipients.",
- "page_callback" => "fp_render_form",
- "page_arguments" => array("engagements_mass_sms_form"),
- "access_arguments" => array("can_send_mass_sms"),
- "page_settings" => array(
- "menu_icon" => fp_get_module_path('system') . "/icons/transmit_go.png",
- "menu_links" => array(
- 0 => array(
- "text" => "Admin Tools",
- "path" => "admin-tools",
- "query" => "de_catalog_year=%DE_CATALOG_YEAR%",
- ),
- ),
- ),
- "type" => MENU_TYPE_NORMAL_ITEM,
- );
-
-
-
-
- $items["advisee-engagements"] = array(
- "title" => "Engagements Received%ENGAGEMENTS_ADVISEE_ALERTS_COUNT%",
- "page_callback" => "engagements_display_advisee_engagements_page",
- "access_arguments" => array('can_view_engagements'),
- "type" => MENU_TYPE_TAB,
- 'tab_family' => 'alerts',
- 'weight' => 15,
- "page_settings" => array(
- "menu_links" => array(
- 0 => array(
- "text" => "Dashboard",
- "path" => "main",
- ),
- ),
- ),
- );
-
-
-
-
-
-
- return $items;
- }
-
-
- /**
- * implements hook_menu_handle_replacement_pattern
- */
- function engagements_menu_handle_replacement_pattern($str) {
-
- if (strstr($str, "%ENGAGEMENTS_ADVISEE_ALERTS_COUNT%")) {
- // Get our count.
- $alert_counts = fp_get_alert_count_by_type();
-
- $c = intval($alert_counts['engagements']['engagement']['unread']);
-
- $x = "";
- if ($c > 0) {
- $x .= " ($c)";
- }
-
- $str = str_replace("%ENGAGEMENTS_ADVISEE_ALERTS_COUNT%", $x, $str);
- }
-
- return $str;
- }
-
-
- /**
- * Implements hook_get_count_for_alert_type
- *
- * Set and Return back "unread" (not in content_last_access)
- *
- */
- function engagements_get_alert_count_by_type($account = NULL) {
- global $user;
- if ($account === NULL) $account = $user;
-
- if ($account->id == 0) return FALSE;
-
-
- $rtn = array();
-
- $rtn['engagement']['total'] = 0;
- $rtn['engagement']['read'] = 0;
- $rtn['engagement']['unread'] = 0;
-
-
-
- $already_counted = array();
-
- // We need to know this user's list of advisees.
- $advisees = advise_get_advisees($account->cwid);
-
- $advisee_line = "";
- if ($advisees && count($advisees) > 0) {
-
- $advisees_list = "'" . join("','", $advisees) . "'";
-
- $advisee_line = " AND b.field__student_id IN (" . $advisees_list . ") ";
-
-
- /*
- $total_count = db_result(db_query("SELECT COUNT(*) as mycount
- FROM content__engagement b,
- content n
- WHERE n.type = ?
- AND b.vid = n.vid
- AND b.cid = n.cid
- AND n.published = 1
- AND n.delete_flag = 0
- AND field__direction = 'received'
- AND field__engagement_type IN ('email', 'txt_msg')
- AND (field__manual_entry IS NULL OR field__manual_entry != 'Y')
- $advisee_line ", array('engagement')));
- */
-
- $total_count = 0;
- $res = db_query("SELECT b.cid
- FROM content__engagement b,
- content n
- WHERE n.type = ?
- AND b.vid = n.vid
- AND b.cid = n.cid
- AND n.published = 1
- AND n.delete_flag = 0
- AND field__direction = 'received'
- AND field__engagement_type IN ('email', 'txt_msg')
- AND (field__manual_entry IS NULL OR field__manual_entry != 'Y')
- $advisee_line ", array('engagement'));
- while($cur = db_fetch_array($res)) {
- $cid = $cur['cid'];
- $already_counted[$cid] = $cid;
- $total_count++;
- }
-
-
-
- $read_count = db_result(db_query("SELECT COUNT(*) as mycount
- FROM content_last_access a,
- content__engagement b,
- content n
- WHERE n.type = ?
- AND n.published = 1
- AND b.vid = n.vid
- AND b.cid = n.cid
- AND n.delete_flag = 0
- AND n.cid = a.cid
- AND field__direction = 'received'
- AND field__engagement_type IN ('email', 'txt_msg')
- AND (field__manual_entry IS NULL OR field__manual_entry != 'Y')
- $advisee_line
- AND a.user_id = ?", array('engagement', $account->id)));
-
-
- $rtn['engagement']['total'] = intval($total_count);
- $rtn['engagement']['read'] = intval($read_count);
- $rtn['engagement']['unread'] = $total_count - $read_count;
-
- } // if advisees
-
- // We should ALSO get these students to show up when we're the recipient of a text number, regardless of if they are
- // considered our "advisee" or not.
- $numbers = engagements_get_user_notify_sms_receipt_values($account->id);
-
- if ($numbers && is_array($numbers) && count($numbers) > 0) {
- // Were there any txt messages sent to these number, which we have not read?
- $numbers_line = "";
- $numbers_list = "'" . join("','", $numbers) . "'";
-
- $numbers_line = " AND b.field__to_sms_phone IN (" . $numbers_list . ") ";
-
- // So, we should also search for results where we received at these numbers, regardless of if the user was our advisee or not.
-
- $total_count = 0;
- $res = db_query("SELECT b.cid
- FROM content__engagement b,
- content n
- WHERE n.type = ?
- AND b.vid = n.vid
- AND b.cid = n.cid
- AND n.published = 1
- AND n.delete_flag = 0
- AND field__direction = 'received'
- AND field__engagement_type IN ('email', 'txt_msg')
- AND (field__manual_entry IS NULL OR field__manual_entry != 'Y')
- $numbers_line ", array('engagement'));
- while($cur = db_fetch_array($res)) {
- $cid = $cur['cid'];
- if (!in_array($cid, $already_counted)) {
- $already_counted[$cid] = $cid;
- $total_count++;
- }
- }
-
-
- $read_count = db_result(db_query("SELECT COUNT(*) as mycount
- FROM content_last_access a,
- content__engagement b,
- content n
- WHERE n.type = ?
- AND n.published = 1
- AND b.vid = n.vid
- AND b.cid = n.cid
- AND n.delete_flag = 0
- AND n.cid = a.cid
- AND field__direction = 'received'
- AND field__engagement_type IN ('email', 'txt_msg')
- AND (field__manual_entry IS NULL OR field__manual_entry != 'Y')
- $numbers_line
- AND a.user_id = ?", array('engagement', $account->id)));
-
-
- $rtn['engagement']['total'] += intval($total_count);
- $rtn['engagement']['read'] += intval($read_count);
- $rtn['engagement']['unread'] += ($total_count - $read_count);
-
-
-
- } // if numbers
-
-
-
-
- if (count($rtn) == 0) return FALSE;
-
- return $rtn;
-
- } // engagements_get_alert_count_by_type
-
-
-
-
-
-
- function engagements_display_advisee_engagements_page() {
- global $user;
- $rtn = "";
- fp_set_title('');
-
- fp_add_css(fp_get_module_path('alerts') . '/css/style.css');
-
- $rtn .= "<p>" . t("This screen shows engagements/communications (emails and text messages) which advisees have sent, but not those which you or any other
- faculty/staff member has sent. To see the complete history of engagements with an advisee, visit the advisee's
- Engagements tab.") . "</p>";
-
-
- $student_ids = advise_get_advisees($user->cwid);
- $student_line = "''";
- if ($student_ids && count($student_ids) > 0) {
- $student_line = "'" . join("','", $student_ids) . "'";
- }
-
- if ($student_line) {
- $student_line = " field__student_id IN ($student_line) ";
- }
-
-
- // We also want to show messages sent to us which might not have been from an advisee, but we are a designated recipient anyway.
- $numbers = engagements_get_user_notify_sms_receipt_values($user->id);
- $numbers_line = "";
- $numbers_list = "''";
- if ($numbers && is_array($numbers) && count($numbers) > 0) {
- // Were there any txt messages sent to these number, which we have not read?
- $numbers_line = "";
- $numbers_list = "'" . join("','", $numbers) . "'";
- }
-
- $numbers_line = " field__to_sms_phone IN (" . $numbers_list . ") ";
-
-
- $table_headers = array();
- $table_headers[] = array("label" => "Actions");
- $table_headers[] = array("label" => "Student");
- $table_headers[] = array("label" => "Type");
- $table_headers[] = array("label" => "Details/Preview");
- $table_headers[] = array("label" => "Updated", "field" => "n.updated");
-
- $limit = 25;
-
- // Set our initial sort, if none is already set.
- theme_table_header_sortable_set_initial_sort('n.updated', 'DESC');
-
- $phones = engagements_get_from_phones();
-
- $rtn .= "<table border='0' class='advisees-alerts'>";
- // Draw our our table headers, with links....
- $rtn .= theme_table_header_sortable($table_headers);
- // Get our order by clause based on selected table header, if any.
- $order_by = theme_table_header_sortable_order_by($table_headers);
-
-
- // Now, we are going to search for alerts about these students, in the form of a pager query.
- // Query for alerts for this student. We will be using a pager_query, so we can display a complete history, if we wish.
- $res = pager_query("SELECT DISTINCT(a.cid) FROM content__engagement a, content n
- WHERE a.vid = n.vid
- AND a.cid = n.cid
- AND n.delete_flag = 0
- AND n.published = 1
- AND field__direction = 'received'
- AND ($student_line OR $numbers_line)
- AND field__engagement_type IN ('email', 'txt_msg')
- AND (field__manual_entry IS NULL OR field__manual_entry != 'Y')
- GROUP BY a.cid
- $order_by", $filter_params, $limit, 0, "SELECT COUNT(DISTINCT(a.cid)) FROM content__engagement a, content n
- WHERE a.vid = n.vid
- AND a.cid = n.cid
- AND n.delete_flag = 0
- AND n.published = 1
- AND field__direction = 'received'
- AND ($student_line OR $numbers_line)
- AND field__engagement_type IN ('email', 'txt_msg')
- AND (field__manual_entry IS NULL OR field__manual_entry != 'Y')
- GROUP BY a.cid
- $order_by");
- while ($cur = db_fetch_object($res)) {
- $cid = $cur->cid;
- $content = content_load($cid);
-
- $updated = format_date($content->updated, 'short');
-
- $student_id = $content->field__student_id['value'];
- $student_name = fp_get_student_name($student_id, TRUE);
-
- $extra_class = "";
- // If this content hasn't been read by this user, mark as "unread"
- if (!content_get_last_access($cid)) {
- $extra_class .= " unread";
- }
-
- $student_url = fp_url('student-profile', "current_student_id=$student_id");
- $view_url = fp_url("content/$cid", "window_mode=popup&content_tabs=false");
- $dtitle = t("View Engagement");
- $view_link = "<a href='javascript:fpOpenLargeIframeDialog(\"$view_url\",\"$dtitle\");' title='" . t("View") . "' class='action-link' ><i class='fa fa-eye'></i></a>";
-
- $student_profile_link = "<a href='$student_url' title='" . t("Student Profile") . "' class='action-link'><i class='fa fa-user'></i></a>";
-
- $disp_preview = "";
-
- if ($content->field__engagement_type['value'] == "txt_msg") {
- $msg = trim(filter_markup($content->field__engagement_msg['value'], 'plain'));
- if (strstr($msg, "~~")) {
- $temp = explode("~~", $msg);
- $msg = $temp[0];
- }
-
- $desc = "";
- $details = engagements_get_sms_from_history($content->field__external_msg_id['value']);
- if ($details) {
- $to = $details['to_number'];
- $pretty_to_number = engagements_convert_to_pretty_phone_number($to);
- $desc = @$phones['lines'][$details['to_number']]['description'];
- if (!$desc) $desc = @$phones['lines'][$details['from_number']]['description'];
- if ($desc) $desc = " / $desc";
- }
- $disp_preview = "$pretty_to_number$desc: $msg";
-
- } // txt_msg
- else if ($content->field__engagement_type['value'] == 'email') {
- $disp_preview = trim(filter_markup($content->field__engagement_msg['value'], 'plain'));
- }
-
- if (strlen($disp_preview) > 60) {
- $disp_preview = trim(substr($disp_preview, 0, 57)) . "...";
- }
-
-
- $disp_type = $content->field__engagement_type['display_value'];
-
-
-
- $rtn .= "
- <tr class='{$content->field__alert_status['value']} $extra_class'>
- <td class='actions'>$view_link $edit_link $remove_link $student_profile_link</td>
- ";
- $rtn .= "<td class='student'>$student_name</td>";
- $rtn .= "
- <td class='short-desc'><div class='short-desc-wrapper'>$disp_type</div></td>
- <td class='short-desc'><div class='short-desc-wrapper'>$disp_preview</div></td>
- <td class='updated'>$updated</td>
- </tr>
- ";
- } // while cur
-
-
- $rtn .= "</table>";
-
- $rtn .= theme_pager(array(t('« newest'), t('‹ newer'), '', t('older ›'), t('oldest »')));
-
-
-
-
-
-
-
- return $rtn;
- } // engagements_display_advisee_engagements_page
-
-
-
-
-
-
-
-
-
-
-
- function engagements_mass_sms_form()
- {
- global $user;
- $form = array();
-
- fp_add_css(fp_get_module_path('engagements') . '/css/style.css');
-
-
- $form['mark_top'] = array(
- 'value' => "<p>" . t("Use this form to send the same SMS (txt) message to multiple recipients at a time. <strong>Recipients must be either students
- or faculty/staff at your institution, with their mobile numbers already in the database</strong>. Your messages will
- be queued, and sent out approximately one per second.") . "</p>",
- );
-
-
-
- if (isset($_SESSION['mass_sms_batch_data'])) {
- $html = "";
- $html .= "<div class='mass-sms-batch-results'>";
-
- $message = $_SESSION['mass_sms_batch_data']['message'];
- if (strlen($message) > 160) $message = substr($message, 0, 160) . "...<em>" . t("trimmed") . "</em>";
- $message = nl2br($message);
-
- $last_timestamp = $_SESSION["mass_sms_batch_data"]["last_timestamp"];
- $last_batch_id = $_SESSION["mass_sms_batch_data"]["batch_id"];
- $html .= t("The last mass batch of txt messages were sent on %time.", array('%time' => format_date(convert_time($last_timestamp)))) . "<br><br>
- " . t("The message sent was:") . "
- <div class='mass-msg-sent-trunc'>$message</div>";
- $html .= "<p>" . t("You may download a CSV of results relating to this session for the next hour by clicking the following link (valid for 1 hour):") . "</p>";
- $html .= "<p>" . l(t("Download CSV"), "stats/download-csv-from-batch/$last_batch_id", "filename=" . urlencode("mass_sms_results__" . $last_timestamp), array('class' => 'button')) . "
- " . t("Note: Row 2 of this CSV shows the actual message that was sent. It is not repeated per-row, to save space.") . "</p>";
-
-
- $html .= "</div>";
-
- $form['mark_last_batch'] = array(
- 'type' => 'markup',
- 'value' => $html,
- );
- }
-
-
-
-
-
-
-
-
-
- $form['from_number'] = array(
- 'label' => t("Select which mass-text phone number this will be coming from:"),
- 'type' => 'select',
- 'options' => engagements_get_from_phones_for_fapi(FALSE, $user, TRUE),
- 'required' => TRUE,
- 'hide_please_select' => TRUE,
- );
-
- $form['message'] = array(
- 'type' => 'textarea',
- 'label' => t('Your message:'),
- 'maxlength' => 1600,
- 'required' => TRUE,
- 'description' => t("To insert emoji in Windows, press <span style='padding-left: 10px; padding-right: 10px; font-size: 1.3em;'><i class='fa fa-windows'></i> + .</span> <em>(Windows key + period)</em>
- <br><br>
- Keep in mind that pricing is based on 160-chars = 1 message segment.
- <br><b>Important:</b> Your message <u>will NOT</u> have any
- header attached. It would be a good idea to begin by stating what unit/department/school you are sending from.
- <br> Ex: <em>From the UFP President's Office: Welcome students to the new term...</em>
- <br><b>Important:</b> Your message <u>WILL automatically</u> have a message appended letting the user know they can reply with STOP to opt-out of receiving text messages."),
- );
-
-
- $form['recipients'] = array(
- 'type' => 'textarea',
- 'label' => t('Recipients:'),
- 'rows' => 20,
- 'required' => TRUE,
- 'description' => t("List the recipients you wish to send your message, one per line. You may enter a valid phone number, CWID, or email address.
- The mobile phone number that is on record for the user with the entered CWID or email address is the one which will be used. Invalid phone numbers
- or users missing phone numbers will be skipped, with a report of skipped users displayed after this routine is run.
- <br>Ex:
- <br> 100556
- <br> 100557
- <br> 100558
- <br> tom431@demo.edu
- <br> 555-123-4567 "),
- );
-
-
- $form['password'] = array(
- 'label' => t("Enter the Mass SMS password:"),
- 'type' => 'password',
- 'description' => t("To prevent accidental submissions, please enter the Mass SMS password. This is a word or phrase which is configured on the Engagements SMS settings
- screen. If you do not know this password, ask your system administrator."),
- );
-
-
- $form['submit_btn'] = array(
- 'type' => 'submit',
- 'value' => t("Submit"),
- 'spinner' => TRUE,
- 'suffix' => "<a href='javascript:history.go(-1);'>" . t("Cancel") . "</a>",
- );
-
- return $form;
- } // mass_sms_form
-
-
-
- function engagements_mass_sms_form_validate($form, $form_state)
- {
- $values = $form_state['values'];
-
- $pass = $values['password'];
-
- if ($pass !== variable_get('sms_mass_sms_password', 'changeMe')) {
- form_error('password', t("Sorry, but you did not enter the correct Mass SMS password. Please try again."));
- }
- }
-
-
- /**
- * Our submit function. Our main task is simply to set off a batch routine.
- */
- function engagements_mass_sms_form_submit($form, $form_state)
- {
-
-
- $values = $form_state['values'];
- $recipients = trim($values['recipients']);
- $message = trim($values['message']);
- $from_number = trim($values['from_number']);
-
- // Start a batch operation.
-
-
- // Okay, set up the batch....
- $batch = array(
- "operation" => array("engagements_mass_sms_perform_batch_operation", array($recipients, $message, $from_number)),
- "title" => t("Sending Mass Text Messages"),
- "progress_message" => "Attempting to send to recipient @current of @total",
- "display_percent" => TRUE,
- );
-
- // Set the batch...
- batch_set($batch);
- } // ... mass_sms_form_submit
-
-
- function engagements_mass_sms_perform_batch_operation(&$batch, $recipients, $message, $from_number)
- {
-
- // if this is our first time through, let's init our values.
- if (!isset($batch["results"]["total"])) {
- // Our first time through. Let's start up.
-
- $batch['recipients'] = array();
- $batch['not_found'] = array();
- $batch['rejected'] = array();
- $batch['date_sent_ts'] = time();
- $batch['date_sent'] = format_date(convert_time(time()));
- $batch['csv'] = "";
- $batch['message'] = $message;
- $safe_message = str_replace('"', "'", $message);
- $num_segments = ceil(strlen($message) / 160);
- // Create headers for the csv
- $batch['csv'] .= "From Number,To Entered Value,Recipient Mobile Number,Recipient Cwid,Recipient User Type,SMS Status,Message,Num Segments,MessageSid,Date Sent\n";
- // Second row states the message, so we don't have to repeat it each row.
- $batch['csv'] .= "000,Sending msg:,0,0,0,0,\"$safe_message\",$num_segments,0,0\n";
- $batch['csv'] .= "--,--,--,--,--,--,--,--,--,--\n";
-
- $lines = explode("\n", $recipients);
-
- $batch["results"] = array();
- $batch["results"]["total"] = count($lines);
- $batch["results"]["current"] = 0;
- $batch["results"]["finished"] = FALSE;
- } // if.... (this is our first time through)
-
-
-
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- // Actually go through our lines of recipients, try to find their number, and send!
- ////////////////////////////////////////////
- $current = $batch["results"]["current"];
- $total = $batch["results"]["total"];
-
- $limit = 1; // How many numbers to process this time through
- $c = 0; // count of records.
-
-
- $lines = explode("\n", $recipients);
-
- for ($t = $current; $t < count($lines); $t++) {
-
- if ($c >= $limit) {
- break;
- }
-
- $line = trim($lines[$t]);
- if (!$line) {
- $c++;
- continue;
- }
- // Whatever this is, let's try to get a valid phone number out of it.
-
- $num = $cwid = $user_type = $user_name = "";
-
- $user_type = 'student';
-
- // First, we were given a CWID?
- $test = db_get_user_id_from_cwid($line, 'student');
- if (!$test) {
- $test = db_get_user_id_from_cwid($line, 'faculty');
- $user_type = 'faculty';
- }
-
- if (!$test) {
- $user_type = '';
- // Okay, it was NOT a CWID. Is this an email address?
- if (strstr($line, '@')) {
- $test = db_get_user_id_from_email($line, 'student');
- $user_type = 'student';
- if (!$test) {
- $test = db_get_user_id_from_email($line, 'faculty');
- $user_type = 'faculty';
- }
- }
- }
-
- if (!$test) {
- $user_type = '';
- // Okay, this was not an email address either. Perhaps this is simply a phone number all by itself?
- $num = engagements_convert_to_valid_phone_number($line);
- if (!$num) {
- // Okay, we are going to have to give up-- this was not a valid number, nor anything else we might try
- // to search for.
- $batch['not_found'][] = $line;
- // add to csv
- $batch['csv'] .= "\"$from_number\",\"$line\",\"\",\"\",\"\",\"user/number not found\",\"\",\"\",\"\",\"\"\n";
- $c++;
- continue;
- } else {
- // Figure out what user_id this phone number belongs to.
- // TODO: This bit of code means it can only be sent to current users, and not non-users. Perhaps that should be a setting?
- $test = db_result(db_query("SELECT user_id FROM user_attributes WHERE `name` = 'mobile_phone' AND `value` = ? LIMIT 1", array($num)));
- }
- }
-
-
- if ($test) {
- $user_type = 'student';
- // This means that we found a user_id. Let's get their mobile_phone number from their user attributes.
- $num = engagements_convert_to_valid_phone_number(user_get_attribute($test, 'mobile_phone', ''));
- $test_account = fp_load_user($test);
- if ($test_account && !$test_account->is_student) {
- $user_type = 'faculty';
- }
- // Let's also get their CWID.
- $cwid = db_get_cwid_from_user_id($test);
- // And let's get their name.
- $user_name = $test_account->l_name . ", " . $test_account->f_name;
- }
-
- if (!$num || $num == "") {
- // Okay, we are going to have to give up-- this was not a valid number
- $batch['not_found'][] = $line;
- $batch['csv'] .= "\"$from_number\",\"$line\",\"$cwid\",\"$user_type\",\"\",\"user has no valid mobile number\",\"\",\"\",\"\",\"\"\n";
- $c++;
- continue;
- }
-
- // If we made it here, then we have a valid recipient! Let's put it into an array called details.
- $details = array(
- 'num' => $num,
- 'user_id' => $test,
- 'cwid' => $cwid,
- 'user_type' => $user_type,
- 'user_name' => $user_name,
- 'line' => $line,
- );
-
- // Has the user opted-out of receiving our txt messages?
- if (!engagements_can_send_sms_to_number($num)) {
- $batch['opt_out'][] = $line;
- $batch['csv'] .= "\"$from_number\",\"$line\",\"$cwid\",\"$user_type\",\"\",\"user opted-out of receiving text\",\"\",\"\",\"\",\"\"\n";
- $c++;
- continue;
- }
-
- // Send our message to this number, record it as an engagement as well.
- $num_segments = ceil(strlen($message) / 160);
- $status = "sent";
-
- $external_msg_id = engagements_send_sms_to_number($num, $message, $details['cwid'], $from_number);
- if (!$external_msg_id) {
- $batch['rejected'][] = $num;
- $status = "rejected";
- } else {
- // We can create an engagement for this SMS. We will make use of our engagements_handle_incoming_sms function.
- $vars = array(
- 'MessageSid' => $external_msg_id,
- 'From' => $from_number,
- 'To' => $num,
- 'Body' => $message,
- 'NumMedia' => 0,
- 'NumSegements' => $num_segments,
- 'direction' => 'outbound-api',
- 'date_sent_ts' => $batch['date_sent_ts'],
- );
-
- engagements_handle_incoming_sms($vars);
- }
-
- $safe_message_sid = (string) $external_msg_id;
-
- $batch['csv'] .= "\"$from_number\",\"{$details['line']}\",\"$num\",\"{$details['cwid']}\",\"{$details['user_type']}\",\"$status\",\"\",\"$num_segments\",\"$safe_message_sid\",\"{$batch['date_sent']}\"\n";
-
-
- $c++;
- } // foreach
-
-
- // Update our $batch results variables
- $batch["results"]["current"] = $current + $c;
-
- if ($batch["results"]["current"] >= $total) {
- // We are finished!
- $batch["results"]["finished"] = TRUE;
- }
-
- // Add the information to the SESSION so we can call on it later.
- $_SESSION['mass_sms_batch_data'] = $batch;
- $_SESSION["mass_sms_batch_data"]["last_timestamp"] = time();
- } // . batch operation
-
-
-
-
-
-
-
-
-
-
- /**
- * Configure the imap settings used by Engagements
- */
- function engagements_imap_settings_form()
- {
- $form = array();
-
-
- $form['mark_top'] = array(
- 'value' => '<p>Configure the connection to your IMAP server here.</p>',
- );
-
- $form['imap_host'] = array(
- 'type' => 'textfield',
- 'label' => t('Host'),
- 'value' => variable_get('imap_host', ''),
- 'description' => 'Ex: mail.example.com',
- );
-
- $form['imap_port'] = array(
- 'type' => 'textfield',
- 'label' => t('Port'),
- 'value' => variable_get('imap_port', ''),
- 'size' => 10,
- 'description' => 'Ex: 143, 993',
- );
-
- $form['imap_secure'] = array(
- 'type' => 'select',
- 'label' => t('Security'),
- 'value' => variable_get('imap_secure', ''),
- 'options' => array('none' => 'none', 'tls' => 'TLS', 'ssl' => 'SSL'),
- 'description' => 'Ex: TLS',
- );
-
- $form['imap_username'] = array(
- 'type' => 'textfield',
- 'label' => t('Username'),
- 'value' => variable_get('imap_username', ''),
- 'description' => '',
- );
-
- $form['imap_password'] = array(
- 'type' => 'textfield',
- 'label' => t('Password'),
- 'value' => variable_get('imap_password', ''),
- 'description' => t('Note: The password will be stored within the database, in the Variables table.
- Make sure you take the necessary precautions to ensure the security of your database.'),
- );
-
-
-
-
- // TODO: folder names to look in?
- // TODO: other settings on deleting messages once read, etc?
-
-
-
- return $form;
- } // engagements_imap_settings_form
-
-
-
-
- /**
- * Configure the various SMS settings
- */
- function engagements_sms_settings_form()
- {
-
-
-
-
- $form = array();
-
-
- $form['mark_signalwire_top'] = array(
- 'value' => "<fieldset><legend>Settings for SignalWire</legend>
- <p>The following settings are for the service SignalWire. You must already have a SignalWire account
- set up to use.</p>",
- );
-
- $form['sms_project_id'] = array(
- 'label' => 'Project ID',
- 'type' => 'textfield',
- 'value' => variable_get('sms_project_id', ''),
- 'description' => t("This is the project id (from SignalWire)."),
- );
-
- $form['sms_auth_token'] = array(
- 'label' => 'Auth Token',
- 'type' => 'textfield',
- 'value' => variable_get('sms_auth_token', ''),
- 'description' => t("Given by the API settings in signalwire"),
- );
-
-
- $form['sms_space_url'] = array(
- 'label' => 'Space URL',
- 'type' => 'textfield',
- 'value' => variable_get('sms_space_url', ''),
- 'description' => t("The URL you use to access your region of signalwire. example.signalwire.com. No http:// or such."),
- );
-
-
- $form['sms_from_phone'] = array(
- 'label' => 'From Phone number(s):',
- 'type' => 'textarea',
- 'rows' => 3,
- 'value' => variable_get('sms_from_phone', '555-555-1234'),
- 'description' => t("These are the phone numbers from your SignalWire account.
- <br>Enter them one per line, with a tilda (~) between the number
- and a brief line description, like so:
- <br> 555-123-4567 ~ Brief Description ~ default
- <br> 555-222-1111 ~ Brief Description2
- <br>Notice that the 'default' designation lets FlightPath know what is the default number which standard notifications
- will be sent from. If no default is set, the first number will be used.
- <br><strong>Important:</strong> Do not send mass txt messages from these numbers unless your campaign is set to do so. These
- numbers will not appear as options to send mass txt messages."),
- );
-
-
- $form['sms_mass_phone'] = array(
- 'label' => 'Mass Text Phone number(s):',
- 'type' => 'textarea',
- 'rows' => 3,
- 'value' => variable_get('sms_mass_phone', '800-555-1234'),
- 'description' => t("These are phone numbers from your SignalWire account, specifically belonging to a campaign for marketting or otherwise
- mass text messages. At the time of this writing, toll-free numbers do not need to belong to such a campaign. These
- will be the only numbers which appear as options to send mass txt messages to."),
- );
-
-
- $form['sms_header'] = array(
- 'label' => 'SMS Header:',
- 'type' => 'textfield',
- 'value' => variable_get('sms_header', '(@initials) from @name:'),
- 'description' => t("All SMS text messages sent from FlightPath will begin with this header, in order to help the student
- understand the who the sender of the message is.
- <br>You may leave blank to disable (not recommended),
- or use the following replacement patterns:
- <ul>
- <li><b>@initials</b> - The sender's school initials. Ex: ULM or UD</li>
- <li><b>@school</b> - The sender's school name. Ex: University of Idaho (this is only applicable if you have the Schools module enabled.)</li>
- <li><b>@name</b> - The first and last name of the sending user OR for automated messages, it will simply say FlightPath (or whatever your system has been named).</li>
- <li><b>@line-desc</b> - This is the line description for the number the message is being sent from.</li>
- <li><b>@line-desc-trimmed</b> - This is a trimmed (to no more than 20 chars) of the line description for the number the message is being sent from.
- </ul>"),
- );
-
-
- $form['sms_mass_sms_password'] = array(
- 'label' => 'Mass SMS Password:',
- 'type' => 'textfield',
- 'value' => variable_get('sms_mass_sms_password', 'changeMe'),
- 'description' => t("Before a user may use the Send Mass Text Messages feature (to sent o many recipients), they must enter this password to protect against accidental submissions."),
- );
-
-
- $form['mark_signalwire_bottom'] = array(
- 'value' => "</fieldset><br><br>",
- );
-
-
-
-
- return $form;
- } // engagements_sms_settings_form
-
-
-
- function engagements_sms_replace_patterns($str, $from_mobile = "", $account = NULL)
- {
- global $user;
- if ($account == NULL) $account = $user;
- $school_id = 0;
- $school_name = "";
- if (function_exists('schools_menu')) {
- $school_id = schools_get_school_id_for_user($account->id);
- $school_name = schools_get_school_name_for_id($school_id);
- }
-
- $name = $account->f_name . " " . $account->l_name;
-
- $line_desc = $line_desc_trimmed = t("Num/Dept Description");
-
-
- $phones = engagements_get_from_phones();
-
- if ($from_mobile == "") $from_mobile = $phones['default']['num']; // use default if it was left blank
- if ($from_mobile) {
- $line_desc = @$phones['lines'][$from_mobile]['description'];
- $line_desc_trimmed = substr($line_desc, 0, 20);
- }
-
- $str = str_ireplace("@initials", variable_get_for_school('school_initials', '', $school_id), $str);
- $str = str_ireplace("@school", $school_name, $str);
- $str = str_ireplace("@name", $name, $str);
- $str = str_ireplace("@line-desc-trimmed", $line_desc_trimmed, $str);
- $str = str_ireplace("@line-desc", $line_desc, $str);
-
-
- return $str;
- } // ...sms_replace_patterns
-
-
-
-
- /**
- * Get the available "from phone" numbers in an organized array structure.
- */
- function engagements_get_from_phones($bool_mass_text_numbers = FALSE)
- {
- $rtn = array();
- $val = variable_get('sms_from_phone', '555-555-1234');
- if ($bool_mass_text_numbers) {
- $val = variable_get('sms_mass_phone', '800-555-1234');
- }
-
-
- $bool_default_set = FALSE;
- $first_num = "";
-
- $lines = explode("\n", $val);
- foreach ($lines as $line) {
- $line = trim($line);
- if ($line == "") continue;
-
- $temp = explode("~", $line);
- $num = engagements_convert_to_valid_phone_number(trim($temp[0]));
- $desc = @trim($temp[1]);
- $default = @trim(strtolower($temp[2]));
-
- if ($desc == '') $desc = $num;
- if ($first_num == '') $first_num = $num;
-
-
- $rtn['lines'][$num] = array(
- 'num' => $num,
- 'description' => $desc,
- 'default' => $default,
- );
-
- if ($default == 'default') {
- $rtn['default'] = $rtn['lines'][$num];
- $bool_default_set = TRUE;
- }
- }
-
- // Default not set, so use the first number.
- if (!$bool_default_set) {
- $rtn['default'] = $rtn['lines'][$first_num];
- }
-
-
-
- return $rtn;
- }
-
-
-
-
- function engagements_get_sms_from_history($message_sid)
- {
- $res = db_query("SELECT * FROM sms_history WHERE message_sid = ? ORDER BY mid DESC LIMIT 1", array($message_sid));
- $cur = db_fetch_array($res);
-
- if ($cur) return $cur;
-
- return FALSE;
- }
-
-
- /**
- * Implements hook_cron
- *
- * One of the things we want to do is check on all of our SMS messages.
- *
- * We will also want to check our imap messages
- *
- */
- function engagements_cron()
- {
-
-
-
- $last_sms_check = intval(variable_get('engagements_sms_get_all_last_check', 0));
- $last_imap_check = variable_get('engagements_imap_get_all_last_check', 0);
-
-
-
- // only check every X minutes at most.
- // TODO: Maybe this is a setting?
- $sms_check_against = strtotime("NOW - 30 MINUTES");
- if ($sms_check_against >= $last_sms_check) {
- engagements_sms_get_all_messages(); // refreshes sms information for messages we've sent and received
- }
-
- // Check for imap messages in a similar way as the SMS messages.
- engagements_imap_get_all_received_messages();
- } // hook_cron
-
-
- /**
- * This catches incoming sms messages from POST, but can also be used by our "sms_get_all_messages" function, but it is also used by the
- * sms_get_all_messages to save/update information.
- *
- * TODO: Have a way to handle incoming calls, too, so we can charge correctly.
- *
- */
- function engagements_handle_incoming_sms($vars = array())
- {
-
- // If we did not supply a set of variables, use the POST superglobal
- if (count($vars) === 0) $vars = $_POST;
-
- watchdog("engagements_sms", "Received from vars (possibly POST): <pre>" . print_r($vars, TRUE) . '</pre>', array(), WATCHDOG_DEBUG);
-
- $message_sid = $vars['MessageSid'];
- $from_mobile = engagements_convert_to_valid_phone_number($vars['From']);
- $to_mobile = engagements_convert_to_valid_phone_number($vars['To']);
- $system_name = variable_get("system_name", "FlightPath");
-
- $body = $vars['Body'];
-
- $num_media = intval($vars['NumMedia']);
- $num_segments = intval($vars['NumSegments']);
- $price = 0; // We know this is an SMS, so this is the price per segment inbound (SignalWire does not charge us for basic SMS inbound).
- if ($num_media > 0) {
- $price = 0.01; // Contained at least one piece of media, so price increases. This is SignalWire's price.
- }
- $direction = "inbound";
- $fp_price = engagements_get_fp_price($price, $direction, $num_segments);
-
- $date_sent_ts = time(); // the time we received it.
- if (isset($vars['date_sent_ts'])) {
- $date_sent_ts = $vars['date_sent_ts'];
- }
-
- if (isset($vars['direction'])) {
- $direction = $vars['direction'];
- }
-
- $content = NULL;
-
- $link = $alert_link = "";
-
- // Figure out what user this came from/to!
- $from_cwid = $from_user_id = $to_user_id = "";
- $user_id = db_result(db_query("SELECT user_id FROM user_attributes WHERE `name` = 'mobile_phone' AND `value` = ?", array($from_mobile)));
- if ($user_id) {
- $from_cwid = db_get_cwid_from_user_id($user_id);
- $from_user_id = $user_id;
- }
-
- $to_cwid = "";
- $user_id = db_result(db_query("SELECT user_id FROM user_attributes WHERE `name` = 'mobile_phone' AND `value` = ?", array($to_mobile)));
- if ($user_id) {
- $to_cwid = db_get_cwid_from_user_id($user_id);
- $to_user_id = $user_id;
- }
-
-
- $dir = "received";
- $fac_cwid = $to_cwid;
- $stu_cwid = $from_cwid;
- if (strstr($direction, 'outbound')) {
- $dir = 'sent';
- $fac_cwid = $from_cwid;
- $stu_cwid = $to_cwid;
- }
-
- // Did we receive STOP?
- if ($dir == 'received') {
- if (trim(strtoupper($body)) === 'STOP') {
- engagements_handle_sms_stop($from_user_id, $from_cwid, $from_mobile, $to_mobile);
- }
- // UNSTOP or SUBSCRIBE?
- if (trim(strtoupper($body)) === 'UNSTOP' || trim(strtoupper($body)) === 'SUBSCRIBE') {
- engagements_handle_sms_unstop($from_user_id, $from_cwid, $from_mobile, $to_mobile);
- }
-
- // We do not return. Go ahead and let it create an engagement below, so the
- // advisor can see that this happened.
-
- }
-
-
- if (trim($stu_cwid) != "") {
- // create an engagement content node for this student!
-
- $content = new stdClass();
- $content->type = 'engagement';
- $content->cid = "new";
- $content->published = 1;
- $content->delete_flag = 0;
- $content->title = "Engagement: txt_msg re: student $stu_cwid"; // required
-
- $content->field__activity_datetime['value'] = date('Y-m-d H:i:s', $date_sent_ts);
- $content->field__faculty_id['value'] = $fac_cwid;
- $content->field__student_id['value'] = $stu_cwid;
- $content->field__engagement_type['value'] = 'txt_msg';
- $content->field__direction['value'] = $dir;
- $content->field__from_sms_phone['value'] = $from_mobile;
- $content->field__to_sms_phone['value'] = $to_mobile;
-
- content_save($content);
- $cid = $content->cid;
-
- $media_filenames = "";
-
- // Handle retreiving and saving media.
- if ($num_media > 0) { // Do we have any media?
- for ($t = 0; $t < $num_media; $t++) {
- $media_url = $vars["MediaUrl$t"];
- $media_type = $vars["MediaContentType$t"];
-
- $ext = engagements_get_file_extension_from_mime_type($media_type);
- if (!$ext || $ext == "html" || $ext == "htm") continue; // skip if its not a type we care about.
-
- // Create a new random filename to save it as.
- $filename = 'sms__' . $from_mobile . '_' . time() . '_' . mt_rand(1, 9999) . '.' . $ext;
- $tmp_name = sha1($filename . mt_rand(1,9999) . time() . mt_rand(1,9999));
-
- $file_contents = file_get_contents($media_url);
-
- // Save to our temporary location on the server.
- $test = file_put_contents(sys_get_temp_dir() . '/' . $tmp_name, $file_contents);
- if (!$test) {
- watchdog('engagements_sms', 'Unable to write media file at temp location: ' . sys_get_temp_dir(), array(), 'error');
- fpm('Unable to write media file at temp location:' . sys_get_temp_dir() . '. Permissions issue?');
- continue;
- }
-
-
- $file = array(
- 'name' => $filename,
- 'type' => $media_type,
- 'tmp_name' => $tmp_name,
- );
-
- // This function will handle encryption of files automatically.
- $fid = content_add_new_uploaded_file($file, $cid, FALSE);
- $media_filenames .= $filename . ',';
- } // for t (media)
-
- $media_filenames = rtrim($media_filenames, ',');
- } // if num media > 0
-
-
-
-
- // if we have media, add to the end of body.
- if ($media_filenames) {
- $body .= "~~MEDIA~~$media_filenames~~END_MEDIA~~";
- }
-
- $content->field__engagement_msg['value'] = $body;
- $content->field__external_msg_id['value'] = $message_sid;
-
- $content->field__visibility['value'] = 'public';
-
- content_save($content);
-
- } // We have a student to attach this to.
-
-
-
- if ($dir != "sent") { // meaning, we RECEIVED this message.
- $already_notified_users = array();
-
- $student_name = fp_get_student_name($stu_cwid, TRUE);
- $base_url = $GLOBALS['fp_system_settings']['base_url'];
- $link = $base_url . "/engagements?current_student_id=$stu_cwid";
-
- $phones = engagements_get_from_phones();
- $desc = "";
- $to = $to_mobile;
- $pretty_to_number = engagements_convert_to_pretty_phone_number($to);
- $desc = @$phones['lines'][$to]['description'];
- if (!$desc) $desc = @$phones['lines'][$from_mobile]['description'];
- if ($desc) $desc = " $desc";
-
- if (trim($stu_cwid) != "") {
- // Create a new "activity record" that the student has sent a txt message
- $acontent = new stdClass();
- $acontent->type = 'activity_record';
- $acontent->cid = "new";
- $acontent->published = 1;
- $acontent->delete_flag = 0;
- $acontent->title = t('Student sent a text message to ') . $pretty_to_number . " / " . $desc;
- $acontent->field__student_id['value'] = $stu_cwid;
- $acontent->field__activity_type['value'] = 'comment';
- content_save($acontent);
-
- // Notify the advisor(s).
-
- $tmsg = "$student_name has submitted a text message to $system_name
- (To: $pretty_to_number / $desc).
- <br><br>\n\n
- To view, visit the student's Engagements tab by logging in and following this link:<br>\n
- <a href='$link'>$link</a>";
-
- $advisors = advise_get_advisors_for_student($stu_cwid);
- foreach ($advisors as $c => $afaculty_id) {
- $account_user_id = db_get_user_id_from_cwid($afaculty_id, 'faculty');
- if ($account_user_id) {
- notify_send_notification_to_user($account_user_id, $tmsg, $content->cid, 'engagement');
- $already_notified_users[] = $account_user_id;
- }
- } // foreach advisors
-
- }
-
-
- /*
- * TODO: Only do this if we have a setting set?
- * TODO: Note: don't send the full message, but instead send link to an alert that we create for the recipient? We'd have to do this in the foreach loop below.
- *
- if (trim($stu_cwid) == "") {
- // Meaning, we couldn't find this student in our system!
- // TODO: Create an alert for the recipient which does show the full txt message. The notification provides a link to the alert. We'd do this in
- // TODO: the foreach loop below.
- $tmsg .= "A text message has been received for $system_name. (To: $pretty_to_number / $desc).<br><br> No student could be found which is
- associated with the sending number ($from_mobile).<br><br>Message body:<br>---------<br>
- $body<br><br>Message SID:$message_sid.";
-
- }
- */
-
-
-
- // Notify other users who might have been assigned to receive notifications
- $to_be_notified = engagements_get_users_to_be_notified_for_sms_on_number($to_mobile);
- foreach ($to_be_notified as $account_user_id) {
- if (in_array($account_user_id, $already_notified_users)) continue;
-
- if (trim($stu_cwid) == "") {
- // Meaning, we couldn't find this student in our system!
- // TODO: Create an alert for the recipient which does show the full txt message. The notification provides a link to the alert.
- $alert = new stdClass();
- $alert->type = 'alert';
- $alert->cid = "new";
- $alert->published = 1;
- $alert->delete_flag = 0;
- $alert->title = t('Unrecognized sender sent a text message to ') . $pretty_to_number . " / " . $desc;
- $alert->field__alert_msg['value'] = $body;
- $alert->field__alert_status['value'] = 'open';
- $alert->field__visibility['value'] = 'faculty';
- $alert->field__target_faculty_id['value'] = db_get_cwid_from_user_id($account_user_id);
- $alert->field__student_id['value'] = "N/A";
- $alert->field__exclude_advisor['value'] = 1;
-
- content_save($alert);
-
- $alert_link = $base_url . "/content/$alert->cid?content_crumbs=alerts";
-
- $tmsg = "A text message has been received for $system_name. (To: $pretty_to_number / $desc).<br><br> No student could be found which is
- associated with the sending number ($from_mobile).<br><br>Message SID: $message_sid.
- <br><br>To view the full message, view the Alert by logging in and clicking here:
- <a href='$alert_link'>$alert_link</a>";
-
- notify_send_notification_to_user($account_user_id, $tmsg, $alert->cid, 'alert');
- }
- else {
- // We DO have a student this came from. Let this user know normally.
- $tmsg = "$student_name has submitted a text message to $system_name (To: $pretty_to_number / $desc).
- <br><br>\n\n
- To view, visit the student's Engagements tab by logging in and following this link:<br>\n
- <a href='$link'>$link</a>";
- notify_send_notification_to_user($account_user_id, $tmsg, $content->cid, 'engagement');
- }
- } //foreach to_be_notified
-
-
- } // dir != sent (we received this text)
-
-
-
-
-
-
-
-
- // Write our data to our sms_history table.
- db_query(
- "INSERT INTO sms_history (`message_sid`, sw_type, `body`, `from_number`, `to_number`, `sw_price`, `fp_price`, `from_cwid`, `to_cwid`, `updated`, `direction`,
- `media_filenames`, `date_sent`, price_processed, num_segments, delivery_status, err_code, err_message, err_friendly_message)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ",
- array($message_sid, 'sms', $body, $from_mobile, $to_mobile, $price, $fp_price, $from_cwid, $to_cwid, time(), $direction,
- $media_filenames, $date_sent_ts, 1, $num_segments, @$vars['display_status'], @$vars['err_code'], @$vars['err_message'], @$vars['err_friendly_message'])
- );
- } // engagements_handle_incoming_sms
-
-
-
-
- /**
- * This function is called by engagements_handle_incoming_sms, when we receive 'STOP' from the user.
- * We must add them to our "sms_do_not_txt" table, and send a reply letting them know how to re-subscribe in the future.
- */
- function engagements_handle_sms_stop($user_id = 0, $cwid = '', $phone_number = '', $from_fp_phone_number = '') {
-
- if ($user_id === 0) {
- // Try to figure out what the user_id is based on the phone number.
- $test = db_result(db_query("SELECT user_id FROM user_attributes WHERE name = 'mobile_phone' AND value = ?", array($from_fp_phone_number)));
- $test = intval($test);
- if ($test > 0) $user_id = $test;
- }
-
- $phone_number = engagements_convert_to_valid_phone_number($phone_number);
- if (!$phone_number) {
- // watchdog that there was an error because phone number not valid.
- watchdog('engagements_sms', "User tried to opt-out of sms, but invalid phone number: $user_id, $cwid, $phone_number", array(), WATCHDOG_ERROR);
- return FALSE;
- }
-
- if ($user_id) {
- // Get current notification method for this user.
- $prev_notification_method = user_get_setting($user_id, 'default_notification_method', 'email');
- // Set their new defailt_notification_method to just email.
- user_set_setting($user_id, 'default_notification_method', 'email');
- // also set an opt-out setting value here, so the user can change it from within flightpath.
- user_set_setting($user_id, "sms_opt_out__" . $phone_number, 'yes');
- }
-
- // Save everything to do_not_txt table. (First, delete anything already there for this phone_number, which is the most important to keep track of)
- db_query('DELETE FROM sms_do_not_txt WHERE phone_number = ?', array($phone_number));
- db_query("INSERT INTO sms_do_not_txt (user_id, cwid, phone_number, prev_notification_method, updated)
- VALUES (?, ?, ?, ?, ?)", array($user_id, $cwid, $phone_number, $prev_notification_method, time()));
-
- // Send final sms back to number telling them how to re-enable.
- $msg = t("You have opted-out of receiving text messages from @flightpath. To re-subscribe, text UNSTOP or SUBSCRIBE.\n\nYou may also log into @flightpath and edit your notification settings.",
- array("@flightpath" => variable_get("system_name", "FlightPath")));
-
- engagements_send_sms_to_number($phone_number, $msg, '', $from_fp_phone_number, FALSE);
-
-
- watchdog('engagements_sms', "User opted-out of sms: $user_id, $cwid, $phone_number");
- } // engagements_handle_sms_stop
-
-
- /**
- * User opted-IN to receiving txt messages.
- */
- function engagements_handle_sms_unstop($user_id = 0, $cwid = '', $phone_number = '', $from_fp_phone_number = '') {
-
- if ($user_id === 0) {
- // Try to figure out what the user_id is based on the phone number.
- $test = db_result(db_query("SELECT user_id FROM user_attributes WHERE name = 'mobile_phone' AND value = ?", array($from_fp_phone_number)));
- $test = intval($test);
- if ($test > 0) $user_id = $test;
- }
-
- $phone_number = engagements_convert_to_valid_phone_number($phone_number);
-
- if (!$phone_number) {
- // watchdog that there was an error because phone number not valid.
- watchdog('engagements_sms', "User tried to opt-in to sms, but invalid phone number: $user_id, $cwid, $phone_number", array(), WATCHDOG_ERROR);
- return FALSE;
- }
-
- if ($user_id) {
- // Get current notification method for this user.
- $notification_method = db_result(db_query("SELECT prev_notification_method FROM sms_do_not_txt WHERE phone_number = ?", array($phone_number)));
- if ($notification_method) {
- // Set their new defailt_notification_method to just email.
- user_set_setting($user_id, 'default_notification_method', $notification_method);
- }
- // also set our opt-out setting value here, so the user can change it from within flightpath.
- user_set_setting($user_id, "sms_opt_out__" . $phone_number, 'no');
- }
-
- // Save everything to do_not_txt table. (First, delete anything already there for this phone_number, which is the most important to keep track of)
- db_query('DELETE FROM sms_do_not_txt WHERE phone_number = ?', array($phone_number));
-
- // Send final sms back to number telling them how to re-enable.
- $msg = t("You have opted-in to receiving text messages from @flightpath.\nReply STOP to opt-out.\n\nYou may also log into @flightpath and edit your notification settings.",
- array("@flightpath" => variable_get("system_name", "FlightPath")));
-
- engagements_send_sms_to_number($phone_number, $msg, '', $from_fp_phone_number, FALSE);
-
-
- watchdog('engagements_sms', "User opted-out of sms: $user_id, $cwid, $phone_number");
-
- }
-
-
-
-
- function engagements_can_send_sms_to_number($phone_number) {
- $phone_number = engagements_convert_to_valid_phone_number($phone_number);
- if (!$phone_number) return FALSE;
-
- $mid = db_result(db_query("SELECT mid FROM sms_do_not_txt WHERE phone_number = ?", array($phone_number)));
-
- // We found an entry in this table, so NO, we cannot txt this number.
- if ($mid) return FALSE;
-
- // else
- return TRUE;
-
-
- }
-
-
- /**
- *
- */
- function engagements_get_signalwire_sms_error_codes_array() {
- $rtn = array(
- "10002" => "Trial account does not support this feature",
- "11200" => "HTTP Retrieval Failure",
- "11751" => "MMS -> Media exceeds mobile operator size limit",
- "12100" => "Document Parse Failure",
- "12300" => "Invalid Content-Type",
- "13221" => "Dial -> Number: Invalid Method Value",
- "15002" => "Call Progress: Queue Timeout",
- "21210" => "'From' phone number not verified",
- "21217" => "A call or SMS is placed to a destination which does not represent a valid phone number",
- "21219" => "'To' phone number not verified",
- "21601" => "Phone number is not a valid SMS-capable inbound phone number",
- "21602" => "Message body is required",
- "21603" => "The source 'From' phone number is required to send an SMS",
- "21604" => "The destination 'To' phone number is required to send an SMS",
- "21610" => "Attempt to send to unsubscribed recipient",
- "21611" => "This 'From' number has exceeded the maximum number of queued messages",
- "21617" => "The concatenated message body exceeds the 1600 character limit",
- "21620" => "Invalid media URL(s)",
- "21623" => "Number of media files exceeds allowed limit",
- "30002" => "Account suspended",
- "30003" => "Unreachable destination handset",
- "30004" => "Message blocked or opted out",
- "30005" => "Unknown destination handset",
- "30006" => "Landline or unreachable carrier",
- "30007" => "Message marked as spam",
- "30008" => "Unknown error",
- "30010" => "Message price exceeds max price",
- "30022" => "Campaign Registry Throughput Limit Exceeded",
- );
-
-
-
-
- return $rtn;
- }
-
-
-
- /**
- * Retrieve all messages, update the ones which don't have prices associated with them yet.
- *
- * We will also be getting voice calls & prices too for our log table.
- */
- function engagements_sms_get_all_messages()
- {
-
- require_once(fp_get_module_path('engagements', TRUE, FALSE) . '/lib/signalwire/vendor/autoload.php');
-
- $vars = array();
-
- $error_codes = engagements_get_signalwire_sms_error_codes_array();
-
- // project id, auth tolen, space url
- $project_id = variable_get('sms_project_id', '');
-
- if ($project_id == "") {
- return FALSE;
- }
-
- $auth_token = variable_get('sms_auth_token', '');
- $space_url = variable_get('sms_space_url', '');
-
- $client = new SignalWire\Rest\Client($project_id, $auth_token, array("signalwireSpaceUrl" => $space_url));
-
- // Get all messages so we can update our table.
-
- // We only care about messages sent TODAY, since we theoretically already got them yesterday
- $check_since = date('Y-m-d', strtotime("NOW - 3 HOURS")); // We will get messages from 3 hours in the past and today,
- // (in case it's close to ***midnight***)
- // to make sure we don't miss anything. The idea being that we have a cron
- // running frequently enough that this gives us lots of chances to retrieve information.
-
- $messages = $client->messages->read(array('dateSentAfter' => $check_since));
- foreach ($messages as $record) {
- //fpm(ppm($record, TRUE));
- // fpm($record->status);
-
- watchdog('engagements_debug', "In engagements_sms_get_all_messages(). Reviewing message: <pre>" . print_r($record, TRUE) . "</pre>", array(), WATCHDOG_DEBUG);
-
- $status = strtolower(trim($record->status));
- $error_message = $record->errorMessage;
- $error_code = intval($record->errorCode);
-
- if ($error_code == 12100 || $error_code == 11200) {
- // We don't care about these code, as they appear on EVERY message.
- $error_code = NULL;
- $status = NULL;
- }
-
- if ($error_code) {
- $friendly_error_message = @$error_codes[$error_code];
- }
- $message_sid = $record->sid;
-
- $vars['MessageSid'] = $message_sid;
-
- // Should we update any details about this message? Price, errors, etc?
- $test = engagements_get_sms_from_history($message_sid);
- if ($test && (floatval($record->price) != floatval($test['sw_price']) || trim($error_code) != trim($test['err_code']))) {
-
- // update prices
- $price = $record->price;
- //$fp_price = engagements_get_fp_price($price, $test['direction'], intval($test['num_segments']));
- $fp_price = 0; // no longer using this field.
-
- watchdog('engagements_debug', "In engagements_sms_get_all_messages(). Updating sms_history table.", array(), WATCHDOG_DEBUG);
-
- db_query("UPDATE sms_history
- SET sw_price = ?, fp_price = ?, price_processed = 1, delivery_status = ?, err_code = ?, err_message = ?, err_friendly_message = ?
- WHERE mid = ?", array($price, $fp_price, $status, $error_code, $error_message, $friendly_error_message, $test['mid']));
-
- // Meaning, we already have this one saved, and now that we've updated it, we can continue.
- continue;
- } // if test and we have things to update
- else if ($test) {
- // meaning, we already have this one saved. Skip it.
- continue;
- }
-
- $from_mobile = engagements_convert_to_valid_phone_number($record->from);
- $to_mobile = engagements_convert_to_valid_phone_number($record->to);
-
- $body = $record->body;
-
- $date_sent = $record->dateSent; // this is a Datetime object
- $date_sent_ts = strtotime($date_sent->format("Y-m-d H:i:s"));
-
- $direction = $record->direction;
- $num_segments = intval($record->numSegments);
-
-
- $vars['From'] = $from_mobile;
- $vars['To'] = $to_mobile;
- $vars['Body'] = $body;
- $vars['date_sent_ts'] = $date_sent_ts;
- $vars['direction'] = $direction;
- $vars['NumSegements'] = $num_segments;
- $vars['delivery_status'] = $status;
- $vars['err_code'] = $error_code;
- $vars['err_message'] = $error_message;
- $vars['err_friendly_message'] = $friendly_error_message;
-
- $vars['NumMedia'] = 0;
-
- // Is there media?
- if (intval($record->numMedia) > 0) {
-
- $vars['NumMedia'] = intval($record->numMedia);
-
- // List all media for this message.
- $allmedia = $client->messages($message_sid)->media->read();
- $c = 0;
- foreach ($allmedia as $mitem) {
-
- $media_sid = $mitem->sid;
- $content_type = $mitem->contentType;
-
- $vars['MediaContentType' . $c] = $content_type;
- $vars['MediaUrl' . $c] = "https://$space_url/api/laml/2010-04-01/Accounts/$project_id/Messages/$message_sid/Media/$media_sid";
-
-
- $c++;
- } // foreach media
-
-
- } // there was media!
-
-
- watchdog('engagements_debug', "In engagements_sms_get_all_messages(). Sending to engagements_handle_incoming_sms: <pre>" . print_r($vars, TRUE) . "</pre>", array(), WATCHDOG_DEBUG);
-
- // Save this message using our "handle_incoming_sms" function.
- engagements_handle_incoming_sms($vars);
- } // foreach messages
-
-
- //////////////////////////////////////////////////////////////
-
-
- $body = "";
- // Now, we also want to get a list of all calls and their prices too.
- $calls = $client->calls->read(array('startTimeAfter', $check_since));
-
-
-
- foreach ($calls as $record) {
-
-
- watchdog('engagements_debug', "In engagements_sms_get_all_messages(). Reviewing CALL: <pre>" . print_r($record, TRUE) . "</pre>", array(), WATCHDOG_DEBUG);
-
- $sid = $record->sid;
-
- // Do we already have this in our table? If so, skip.
- $test = engagements_get_sms_from_history($sid);
- if ($test) continue; // We've already recorded this, so skip.
-
- $date_sent = $record->startTime; // this is a Datetime object
- $date_sent_ts = strtotime($date_sent->format("Y-m-d H:i:s"));
-
-
- $to_mobile = engagements_convert_to_valid_phone_number($record->to);
- $from_mobile = engagements_convert_to_valid_phone_number($record->from);
-
- // Figure out what user this came from/to!
- $from_cwid = "";
- $user_id = db_result(db_query("SELECT user_id FROM user_attributes WHERE `name` = 'mobile_phone' AND `value` = ?", array($from_mobile)));
- if ($user_id) {
- $from_cwid = db_get_cwid_from_user_id($user_id);
- }
-
- $to_cwid = "";
- $user_id = db_result(db_query("SELECT user_id FROM user_attributes WHERE `name` = 'mobile_phone' AND `value` = ?", array($to_mobile)));
- if ($user_id) {
- $to_cwid = db_get_cwid_from_user_id($user_id);
- }
-
- $duration = $record->duration;
- $direction = $record->direction;
- $price = $record->price;
- $fp_price = engagements_get_fp_price($price, $direction, 1, 'call');
-
-
- // Write our data to our sms_history table.
- db_query(
- "INSERT INTO sms_history (`message_sid`, sw_type, `body`, `from_number`, `to_number`, `sw_price`, `fp_price`, `from_cwid`, `updated`, `direction`,
- `media_filenames`, `date_sent`, price_processed, num_segments)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ",
- array($sid, 'call', $body, $from_mobile, $to_mobile, $price, $fp_price, $from_cwid, time(), $direction, '', $date_sent_ts, 1, $duration)
- );
-
- watchdog("engagements_sms", "Documented call to $to_mobile.", array(), WATCHDOG_DEBUG);
-
- } //foreach calls as record
-
-
-
-
-
- // Record the last time we called this function.
- variable_set('engagements_sms_get_all_last_check', time());
- } // function
-
-
-
-
-
-
-
-
-
-
- /**
- * figure out the price we will charge.
- */
- function engagements_get_fp_price($price, $direction, $num_segments = 1, $type = 'sms')
- {
-
- $rtn = 0;
-
- if ($num_segments == 0) {
- $num_segments = 1;
- }
-
- if (strstr($direction, 'outbound')) {
- $rtn = 0.0033 * $num_segments;
- }
-
- if ($price == 0.01) {
- $rtn = 0.015;
- }
-
- if ($type == 'call') {
- $rtn = 0.005;
- }
-
-
- // Guess at 15% over, if we don't know.
- $new_price = $price * 1.15; // generic; add 15%.
-
- // Return the LARGER of the two prices.
- if ($new_price > $rtn) {
- return $new_price;
- }
-
- return $rtn;
- }
-
-
-
-
- // From: https://stackoverflow.com/questions/16511021/convert-mime-type-to-file-extension-php
- /**
- * This function will look at the mime type (aka content type) to figure out what the
- * file extension should be. This is useful when retrieving txt message media.
- *
- * We will only have the ones we think students might actually try to txt to their teachers.
- */
- function engagements_get_file_extension_from_mime_type($mime)
- {
- $mime_map = array(
- 'video/3gpp2' => '3g2',
- 'video/3gp' => '3gp',
- 'video/3gpp' => '3gp',
- 'application/x-compressed' => '7zip',
- 'audio/x-acc' => 'aac',
- 'audio/ac3' => 'ac3',
- 'application/postscript' => 'ai',
- 'audio/x-aiff' => 'aif',
- 'audio/aiff' => 'aif',
- 'audio/x-au' => 'au',
- 'video/x-msvideo' => 'avi',
- 'video/msvideo' => 'avi',
- 'video/avi' => 'avi',
- 'application/x-troff-msvideo' => 'avi',
- //'application/macbinary' => 'bin',
- //'application/mac-binary' => 'bin',
- //'application/x-binary' => 'bin',
- //'application/x-macbinary' => 'bin',
- 'image/bmp' => 'bmp',
- 'image/x-bmp' => 'bmp',
- 'image/x-bitmap' => 'bmp',
- 'image/x-xbitmap' => 'bmp',
- 'image/x-win-bitmap' => 'bmp',
- 'image/x-windows-bmp' => 'bmp',
- 'image/ms-bmp' => 'bmp',
- 'image/x-ms-bmp' => 'bmp',
- 'application/bmp' => 'bmp',
- 'application/x-bmp' => 'bmp',
- 'application/x-win-bitmap' => 'bmp',
- //'application/cdr' => 'cdr',
- //'application/coreldraw' => 'cdr',
- //'application/x-cdr' => 'cdr',
- //'application/x-coreldraw' => 'cdr',
- //'image/cdr' => 'cdr',
- //'image/x-cdr' => 'cdr',
- //'zz-application/zz-winassoc-cdr' => 'cdr',
- //'application/mac-compactpro' => 'cpt',
- //'application/pkix-crl' => 'crl',
- //'application/pkcs-crl' => 'crl',
- //'application/x-x509-ca-cert' => 'crt',
- //'application/pkix-cert' => 'crt',
- 'text/css' => 'css',
- 'text/x-comma-separated-values' => 'csv',
- 'text/comma-separated-values' => 'csv',
- 'application/vnd.msexcel' => 'csv',
- 'application/x-director' => 'dcr',
- 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx',
- 'application/vnd.oasis.opendocument.text' => 'odt',
- 'application/x-dvi' => 'dvi',
- 'message/rfc822' => 'eml',
- //'application/x-msdownload' => 'exe',
- 'video/x-f4v' => 'f4v',
- 'audio/x-flac' => 'flac',
- 'video/x-flv' => 'flv',
- 'image/gif' => 'gif',
- 'application/gpg-keys' => 'gpg',
- 'application/x-gtar' => 'gtar',
- 'application/x-gzip' => 'gzip',
- 'application/mac-binhex40' => 'hqx',
- 'application/mac-binhex' => 'hqx',
- 'application/x-binhex40' => 'hqx',
- 'application/x-mac-binhex40' => 'hqx',
- 'text/html' => 'html',
- 'image/x-icon' => 'ico',
- 'image/x-ico' => 'ico',
- 'image/vnd.microsoft.icon' => 'ico',
- 'text/calendar' => 'ics',
- 'application/java-archive' => 'jar',
- 'application/x-java-application' => 'jar',
- 'application/x-jar' => 'jar',
- 'image/jp2' => 'jp2',
- 'video/mj2' => 'jp2',
- 'image/jpx' => 'jp2',
- 'image/jpm' => 'jp2',
- 'image/jpeg' => 'jpg',
- 'image/pjpeg' => 'jpeg',
- 'application/x-javascript' => 'js',
- 'application/json' => 'json',
- 'text/json' => 'json',
- //'application/vnd.google-earth.kml+xml' => 'kml',
- //'application/vnd.google-earth.kmz' => 'kmz',
- 'text/x-log' => 'log',
- 'audio/x-m4a' => 'm4a',
- 'audio/mp4' => 'm4a',
- 'application/vnd.mpegurl' => 'm4u',
- 'audio/midi' => 'mid',
- 'application/vnd.mif' => 'mif',
- 'video/quicktime' => 'mov',
- 'video/x-sgi-movie' => 'movie',
- 'audio/mpeg' => 'mp3',
- 'audio/mpg' => 'mp3',
- 'audio/mpeg3' => 'mp3',
- 'audio/mp3' => 'mp3',
- 'video/mp4' => 'mp4',
- 'video/mpeg' => 'mpeg',
- 'application/oda' => 'oda',
- 'audio/ogg' => 'ogg',
- 'video/ogg' => 'ogg',
- 'application/ogg' => 'ogg',
- 'font/otf' => 'otf',
- 'application/x-pkcs10' => 'p10',
- 'application/pkcs10' => 'p10',
- 'application/x-pkcs12' => 'p12',
- 'application/x-pkcs7-signature' => 'p7a',
- 'application/pkcs7-mime' => 'p7c',
- 'application/x-pkcs7-mime' => 'p7c',
- 'application/x-pkcs7-certreqresp' => 'p7r',
- 'application/pkcs7-signature' => 'p7s',
- 'application/pdf' => 'pdf',
- 'application/octet-stream' => 'pdf',
- 'application/x-x509-user-cert' => 'pem',
- 'application/x-pem-file' => 'pem',
- 'application/pgp' => 'pgp',
- //'application/x-httpd-php' => 'php',
- //'application/php' => 'php',
- //'application/x-php' => 'php',
- //'text/php' => 'php',
- //'text/x-php' => 'php',
- //'application/x-httpd-php-source' => 'php',
- 'image/png' => 'png',
- 'image/x-png' => 'png',
- 'application/powerpoint' => 'ppt',
- 'application/vnd.ms-powerpoint' => 'ppt',
- 'application/vnd.ms-office' => 'ppt',
- 'application/msword' => 'doc',
- 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'pptx',
- 'application/x-photoshop' => 'psd',
- 'image/vnd.adobe.photoshop' => 'psd',
- 'audio/x-realaudio' => 'ra',
- 'audio/x-pn-realaudio' => 'ram',
- 'application/x-rar' => 'rar',
- 'application/rar' => 'rar',
- 'application/x-rar-compressed' => 'rar',
- 'audio/x-pn-realaudio-plugin' => 'rpm',
- 'application/x-pkcs7' => 'rsa',
- 'text/rtf' => 'rtf',
- 'text/richtext' => 'rtx',
- 'video/vnd.rn-realvideo' => 'rv',
- 'application/x-stuffit' => 'sit',
- 'application/smil' => 'smil',
- 'text/srt' => 'srt',
- 'image/svg+xml' => 'svg',
- 'application/x-shockwave-flash' => 'swf',
- 'application/x-tar' => 'tar',
- 'application/x-gzip-compressed' => 'tgz',
- 'image/tiff' => 'tiff',
- 'font/ttf' => 'ttf',
- 'text/plain' => 'txt',
- 'text/x-vcard' => 'vcf',
- 'application/videolan' => 'vlc',
- 'text/vtt' => 'vtt',
- 'audio/x-wav' => 'wav',
- 'audio/wave' => 'wav',
- 'audio/wav' => 'wav',
- 'application/wbxml' => 'wbxml',
- 'video/webm' => 'webm',
- 'image/webp' => 'webp',
- 'audio/x-ms-wma' => 'wma',
- 'application/wmlc' => 'wmlc',
- 'video/x-ms-wmv' => 'wmv',
- 'video/x-ms-asf' => 'wmv',
- 'font/woff' => 'woff',
- 'font/woff2' => 'woff2',
- 'application/xhtml+xml' => 'xhtml',
- 'application/excel' => 'xl',
- 'application/msexcel' => 'xls',
- 'application/x-msexcel' => 'xls',
- 'application/x-ms-excel' => 'xls',
- 'application/x-excel' => 'xls',
- 'application/x-dos_ms_excel' => 'xls',
- 'application/xls' => 'xls',
- 'application/x-xls' => 'xls',
- 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx',
- 'application/vnd.ms-excel' => 'xlsx',
- 'application/xml' => 'xml',
- 'text/xml' => 'xml',
- 'text/xsl' => 'xsl',
- 'application/xspf+xml' => 'xspf',
- 'application/x-compress' => 'z',
- 'application/x-zip' => 'zip',
- 'application/zip' => 'zip',
- 'application/x-zip-compressed' => 'zip',
- 'application/s-compressed' => 'zip',
- 'multipart/x-zip' => 'zip',
- //'text/x-scriptzsh' => 'zsh',
- );
-
- return isset($mime_map[$mime]) ? $mime_map[$mime] : FALSE;
- }
-
-
-
-
-
-
- /**
- * Connect to our imap server, download all received messages from students (or others).
- * We will then delete them, so they don't get read twice.
- */
- function engagements_imap_get_all_received_messages()
- {
-
- $host = variable_get('imap_host', '');
- $port = variable_get('imap_port', '');
- $secure = variable_get('imap_secure', '');
-
- $mailbox_server = "{" . "$host:$port/$secure" . "}";
- $username = variable_get('imap_username', '');
- $password = variable_get('imap_password', '');
-
- if ($username == "") {
- return FALSE;
- }
-
-
- watchdog('imap', "Attempting to connect to imap server.", array(), WATCHDOG_DEBUG);
- $mbox = imap_open($mailbox_server, $username, $password);
- if (!$mbox) {
- watchdog('imap', "Could not connect to imap server!", array(), WATCHDOG_ERROR);
- fp_add_message("Could not connect to IMAP server.", 'error', TRUE);
- }
-
- // We need to get the name of the "Trash" folder, which might contain a lot of weird extra stuff in the name.
- // TODO: Maybe save in a cached field so we don't have to retrieve every time it runs? But, that gets cleared when we clear the cache.
- $mailboxes = imap_list($mbox, $mailbox_server, "*");
- $trash_box_name = "Trash";
- foreach ($mailboxes as $boxname) {
- if (stristr($boxname, "trash")) {
- $trash_box_name = str_replace($mailbox_server, "", $boxname);
- break;
- }
- }
-
-
-
- $mbox_check = imap_check($mbox);
-
- // Fetch an overview for all messages in INBOX, by going from 1 to the max number messages.
- $result = imap_fetch_overview($mbox, "1:{$mbox_check->Nmsgs}", 0);
-
- foreach ($result as $overview) {
- $msgno = $overview->msgno;
- $subject = $overview->subject;
- $udate = $overview->udate; // udate is apparently already in UTC, which is what we want.
-
- watchdog('imap', "Gettign message $msgno. Subject: $subject. Udate: $udate.", array(), WATCHDOG_DEBUG);
-
- // We need to get our ONLY the email address from the From field, which
- // might look like: Richard Peacock <richard.peacock@school.domain.co.com>
- // We will use a regular expression to figure it out. From: https://stackoverflow.com/questions/33865113/extract-email-address-from-string-php
- $ofrom = $overview->from;
- preg_match_all("/[\._a-zA-Z0-9-]+@[\._a-zA-Z0-9-]+/i", $ofrom, $matches);
- $from_email = $matches[0][0]; // Since this is a FROM email, we assume there's only one sender.
-
- $body = _engagements_imap_get_body($mbox, $msgno);
-
- watchdog('imap', "Found Body: $body", array(), WATCHDOG_DEBUG);
-
- // match the from email to a student
- $student_user_id = db_get_user_id_from_email($from_email, 'student');
- if ($student_user_id) {
-
- watchdog('imap', "Found from student $student_user_id, creating engagement content.", array(), WATCHDOG_DEBUG);
-
- // create this as an engagement for this student.
- $account = fp_load_user($student_user_id);
- $student_cwid = $account->cwid;
-
- $content = new stdClass();
- $content->type = 'engagement';
- $content->cid = "new";
- $content->published = 1;
- $content->delete_flag = 0;
- $content->title = $subject; // required
-
- $content->field__activity_datetime['value'] = date('Y-m-d H:i:s', $udate);
- $content->field__student_id['value'] = $student_cwid;
- $content->field__engagement_type['value'] = 'email';
- $content->field__direction['value'] = 'received';
-
- $content->field__engagement_msg['value'] = $body;
-
- content_save($content);
- $cid = $content->cid;
-
- $attachments = _engagements_imap_get_attachments($mbox, $msgno, fp_get_machine_readable($from_email), $cid);
-
- // save attachements along with the engagement, if there are any
- if (count($attachments) > 0) {
-
- $fid_line = "";
- foreach ($attachments as $adetails) {
- $fid = $adetails['fid'];
- $fid_line .= $fid . ",";
- }
- $fid_line = rtrim($fid_line, ",");
- $content->field__attachment['value'] = $fid_line;
- }
-
-
- $content->field__visibility['value'] = 'public';
-
- content_save($content);
-
- // if received, create an activity record.
- // Create a new "activity record" that the student has sent an email message
-
- $acontent = new stdClass();
- $acontent->type = 'activity_record';
- $acontent->cid = "new";
- $acontent->published = 1;
- $acontent->delete_flag = 0;
- $acontent->title = t('Student replied to email message.');
- $acontent->field__student_id['value'] = $student_cwid;
- $acontent->field__activity_type['value'] = 'mail';
- content_save($acontent);
-
- // Notify the advisor(s).
- // get list of all advisors for this student, and send notifications.
- $advisors = advise_get_advisors_for_student($student_cwid);
- foreach ($advisors as $c => $afaculty_id) {
- $account_user_id = db_get_user_id_from_cwid($afaculty_id, 'faculty');
- if ($account_user_id) {
- $student_name = fp_get_student_name($student_cwid, TRUE);
- $base_url = $GLOBALS['fp_system_settings']['base_url'];
- $link = $base_url . "/engagements?current_student_id=$student_cwid";
- $tmsg = "";
- $tmsg .= "$student_name has submitted an email to FlightPath.<br><br>\n\n
- To view, visit the student's Engagements tab by logging in and following this link:<br>\n
- <a href='$link'>$link</a>";
-
- notify_send_notification_to_user($account_user_id, $tmsg, $content->cid, 'engagement');
- }
- }
- } // if student_user_id
-
-
-
- // We are now finished with this email, so we can move it to our trash folder.
- //imap_mail_move($mbox, $msgno, $trash_box_name);
- imap_delete($mbox, $msgno);
- } // foreach result as overview
-
- // Delete all mail marked for deletion...
- imap_expunge($mbox);
-
- watchdog('imap', "Closing connection to imap server.", array(), WATCHDOG_DEBUG);
- // Close connection, we're done.
- imap_close($mbox);
-
-
- // Record the last time we called this function.
- variable_set('engagements_imap_get_all_last_check', time());
- } // end of function
-
-
-
- // From https://stackoverflow.com/questions/2649579/downloading-attachments-to-directory-with-imap-in-php-randomly-works
- /**
- * $inbox is the imap link. email_number is msg_no.
- */
- function _engagements_imap_get_attachments($inbox, $email_number, $from_email_machine_readable, $cid = 0)
- {
-
- /* get information specific to this email */
- $overview = imap_fetch_overview($inbox, $email_number, 0);
- $message = imap_fetchbody($inbox, $email_number, 2);
- $structure = imap_fetchstructure($inbox, $email_number);
-
- $attachments = array();
- if (isset($structure->parts) && count($structure->parts)) {
- for ($i = 0; $i < count($structure->parts); $i++) {
- $attachments[$i] = array(
- 'is_attachment' => false,
- 'filename' => '',
- 'name' => '',
- 'subtype' => '',
- 'attachment' => ''
- );
-
- if ($structure->parts[$i]->ifdparameters) {
- foreach ($structure->parts[$i]->dparameters as $object) {
- if (strtolower($object->attribute) == 'filename') {
- $attachments[$i]['is_attachment'] = TRUE;
- $attachments[$i]['filename'] = $object->value;
- $attachments[$i]['subtype'] = $structure->parts[$i]->subtype;
- }
- }
- }
-
- if ($structure->parts[$i]->ifparameters) {
- foreach ($structure->parts[$i]->parameters as $object) {
- if (strtolower($object->attribute) == 'name') {
- $attachments[$i]['is_attachment'] = true;
- $attachments[$i]['name'] = $object->value;
- $attachments[$i]['subtype'] = $structure->parts[$i]->subtype;
- }
- }
- }
-
- if ($attachments[$i]['is_attachment']) {
- $attachments[$i]['attachment'] = imap_fetchbody($inbox, $email_number, $i + 1);
- if ($structure->parts[$i]->encoding == 3) { // 3 = BASE64
- $attachments[$i]['attachment'] = base64_decode($attachments[$i]['attachment']);
- } elseif ($structure->parts[$i]->encoding == 4) { // 4 = QUOTED-PRINTABLE
- $attachments[$i]['attachment'] = quoted_printable_decode($attachments[$i]['attachment']);
- }
- }
- } // for($i = 0; $i < count($structure->parts); $i++)
- } // if(isset($structure->parts) && count($structure->parts))
-
-
-
- $rtn = array();
-
- if (count($attachments) != 0) {
- foreach ($attachments as $c => $at) {
- if ($at['is_attachment'] == TRUE) {
-
-
- // Create a new random filename to save it as.
- $filename = 'email__' . $from_email_machine_readable . '_' . time() . '_' . mt_rand(1, 9999); // We will figure out the ext (from mimetype) later.
- $tmp_name = sha1($filename . time() . mt_rand(1,99999) . mt_rand(1,99999));
-
- // Save to our temporary location on the server.
- $test = file_put_contents(sys_get_temp_dir() . '/' . $tmp_name, $at['attachment']);
- if (!$test) {
- watchdog('engagements_email', 'Unable to write media file at temp location: ' . sys_get_temp_dir(), array(), 'error');
- fpm('Unable to write media file at temp location:' . sys_get_temp_dir() . '. Permissions issue?');
- continue;
- }
-
-
- // Next, we want to rename it to have the proper file extension, as best we can tell.
- $ext = strtolower($at['subtype']); // if we can't figure it out, use this.
- // Attempt to figure out the mimetype....
- $finfo = finfo_open(FILEINFO_MIME_TYPE);
- $mimetype = finfo_file($finfo, sys_get_temp_dir() . '/' . $tmp_name);
- $temp = explode(";", $mimetype);
- $mimetype = strtolower(trim($temp[0]));
-
- $new_ext = engagements_get_file_extension_from_mime_type($mimetype);
- if ($new_ext) {
- $ext = $new_ext;
- }
-
- $filename .= ".$ext"; // the filename doesn't have its extension already for whatever reason.
-
- $file = array(
- 'name' => $filename,
- 'type' => $mimetype,
- 'tmp_name' => $tmp_name,
- );
-
- $fid = content_add_new_uploaded_file($file, $cid, FALSE);
- // TODO: Possibly rename filename based on if it is encrypted or not?
-
- $rtn[] = array(
- 'fid' => $fid,
- 'filename' => $filename,
- 'mimetime' => $mimetype,
- 'ext' => $ext,
- );
- } // if is_attachment == TRUE
- } // foreach
- }
-
- return $rtn;
- } // ... imap_get_attachments
-
-
- // From: https://stackoverflow.com/questions/4272551/extract-body-text-from-email-php
- function _engagements_imap_get_body($imapLink, $msgno)
- {
-
- $obj_structure = imap_fetchstructure($imapLink, $msgno);
- // Recherche de la section contenant le corps du message et extraction du contenu
- $obj_section = $obj_structure;
-
-
-
- //$text = imap_fetchbody($imapLink, $msgno, $section);
-
- // So it turns out the $section for HTML can be 1.2, but it might also be just "2" in simple messages.
- // Try to get HTML first....
- $text = trim(imap_fetchbody($imapLink, $msgno, 1.2));
- if ($text == "") {
- $text = trim(imap_fetchbody($imapLink, $msgno, 2));
- }
- if ($text == "") {
- $text = trim(imap_fetchbody($imapLink, $msgno, 1.1));
- }
- if ($text == "") {
- $text = trim(imap_fetchbody($imapLink, $msgno, 1));
- }
-
-
- // Décodage éventuel
- if ($obj_section->encoding == 3) {
- $text = imap_base64($text);
- } else if ($obj_section->encoding == 4) {
- $text = imap_qprint($text);
- }
- // Encodage éventuel
- foreach ($obj_section->parameters as $obj_param) {
- if (($obj_param->attribute == "charset") && (mb_strtoupper($obj_param->value) != "UTF-8")) {
- $text = utf8_encode($text);
- break;
- }
- }
-
-
-
- $text = filter_markup($text, 'basic');
-
- // Sometimes, emails contain odd encoding. Ex: =C2=A0, which is apparently a non-breaking space. Let's convert just in case.
- // From: https://stackoverflow.com/questions/12682208/parsing-email-body-with-7bit-content-transfer-encoding-php
- // and: https://github.com/geerlingguy/Imap/blob/c4b54e52576bf71a93045d2a4581589eab9a00b6/JJG/Imap.php#L398
- // Manually convert common encoded characters into their UTF-8 equivalents.
- $characters = array(
- '=20' => ' ', // space.
- '=2C' => ',', // comma.
- '=E2=80=99' => "'", // single quote.
- '=C2=A0' => ' ', // non-breaking space.
- '=0A' => "\r\n", // line break.
- '=0D' => "\r\n", // carriage return.
- '=A0' => ' ', // non-breaking space.
- "=\r\n" => '', // joined line.
- '=E2=80=A6' => '…', // ellipsis.
- '=E2=80=A2' => '•', // bullet.
- '=E2=80=93' => '–', // en dash.
- '=E2=80=94' => '—', // em dash.
- );
-
- // Loop through the encoded characters and replace any that are found.
- foreach ($characters as $key => $value) {
- $text = str_replace($key, $value, $text);
- }
-
-
-
- return $text;
- }
-
-
-
-
-
-
-
-
- /**
- * The user has opened an email with a tracking pixel. We will now record that
- * it was opened in our engagements_tracking table.
- *
- * We also need to actually render the pixel to the browser.
- */
- function engagements_handle_tracking_pixel_request($cid, $token)
- {
-
- // Record in database
- // Fist, get the current count, if it exists.
- $res = db_query("SELECT * FROM engagements_tracking WHERE cid = ? AND token = ?", array($cid, $token));
- $cur = db_fetch_array($res);
- if ($cur['cid'] != $cid || $cur['token'] != $token) {
- // Means it was not generated, this might be a malicious attempt or an old token or something.
- die;
- }
- $opens = intval($cur['opens']) + 1;
- db_query('UPDATE engagements_tracking
- SET opens = ?,
- updated = ?
- WHERE cid = ? AND token = ?', array($opens, time(), $cid, $token));
-
- watchdog('engagements_track', "Tracking request for: $cid - $token");
-
-
- // Create a new "activity record" that the student has viewed this email.
- $email_content = content_load($cid);
-
- // Create a new actvity_record.
- $content = new stdClass();
- $content->type = 'activity_record';
- $content->cid = "new";
- $content->published = 1;
- $content->delete_flag = 0;
- $content->title = t('Student opened email titled "@et".', array("@et" => $email_content->title));
- $content->field__student_id['value'] = $email_content->field__student_id['value'];
- $content->field__activity_type['value'] = 'mail';
- content_save($content);
-
-
-
- // Render pixel to browser and die. We will be using the 1x1.gif file in our assets folder.
- // Output the image to browser
- header('Content-Type: image/gif');
- $im = imagecreatefromgif(fp_get_module_path('engagements', TRUE, FALSE) . '/assets/1x1.gif');
- imagegif($im);
- imagedestroy($im);
- die;
- } // engagements_handle_tracking_pixel_request
-
-
-
-
-
-
-
- function engagements_perm()
- {
- $rtn = array(
- 'administer_engagements' => array(
- 'title' => 'Administer Engagements',
- 'description' => t('The user can edit the system config settings for the Engagements module. Only give to admin users.'),
- "admin_restricted" => TRUE, // means only appears for admin (user_id == 1)
- ),
- 'can_view_engagements' => array(
- 'title' => 'Can view Engagements',
- 'description' => t('The user may view engagements (only "everyone" by default)'),
- ),
- 'can_view_faculty_engagements' => array(
- 'title' => 'View "Faculty/Staff" Engagements',
- 'description' => t('The user is allowed to view engagements marked visible for "Faculty/Staff".'),
- ),
- 'can_send_email_engagements' => array(
- 'title' => t('Can send email engagements to students'),
- ),
- 'can_log_engagements' => array(
- 'title' => t('Can log engagements with students'),
- ),
- 'can_send_txt_engagements' => array(
- 'title' => t('Can send txt message engagements to students'),
- 'description' => t("<b>Important:</b> Be sure to also select the specific phone number/permissions below."),
- ),
- );
-
- // set up other permissions for each SMS line we have.
- $phones = engagements_get_from_phones();
- foreach ($phones['lines'] as $num => $details) {
- $pretty_num = engagements_convert_to_pretty_phone_number($num);
- $desc = filter_markup($details['description'], "plain");
- $desc = str_replace("'", "", $desc);
- $desc = str_replace('"', "", $desc);
-
- $rtn["can_send_sms_from_$num"] = array(
- "title" => t("Can send txt messages from @pretty", array("@pretty" => $pretty_num)),
- "description" => t("The user may send SMS (txt) messages from @pretty - %desc phone line.", array("@pretty" => $pretty_num, "%desc" => $desc)),
- );
- }
-
- $rtn['can_send_mass_sms'] = array(
- 'title' => t("Send mass txt messages"),
- 'description' => t("The user may access and send mass SMS (txt) messages to lists of recipients from the designated mass text lines.
- Only give to trusted users."),
- );
-
-
- return $rtn;
- }
-
-
-
-
-
-
- /**
- * For use with the content module. We will register our custom content type(s)
- * for use with this module.
- */
- function engagements_content_register_content_type()
- {
-
- $arr = array();
-
- $arr['engagement'] = array(
- 'title' => 'Engagement',
- 'description' => 'This is a content type meant to track a students activities and communications in the system.',
- 'settings' => array(
- 'title' => array(
- 'label' => t('Subject'),
- 'weight' => 65,
- ),
- ),
- );
-
-
- // If we are in a popup (dialog)...
- if (@$_GET['window_mode'] == 'popup') {
- // We want to make sure we redirect to our handler URL, which will close the dialog.
- $arr['engagement']['settings']['#redirect'] = array(
- 'path' => 'content-dialog-handle-after-save',
- 'query' => '',
- );
- }
-
-
-
-
- $fields = array();
-
-
- $fields['faculty_id'] = array(
- 'type' => 'textfield',
- 'label' => 'Faculty/Staff',
- 'weight' => 5,
- );
-
-
- $fields['from_sms_phone'] = array(
- 'type' => 'select',
- 'label' => t('From Text Phone Line:'),
- 'hide_please_select' => TRUE,
- 'options' => array(),
- 'weight' => 7,
- );
-
- $fields['student_id'] = array(
- 'type' => 'textfield',
- 'label' => 'Student',
- 'weight' => 10,
- );
-
-
- $fields['activity_datetime'] = array(
- 'type' => 'datetime-local',
- 'label' => 'Date/Time',
- 'value' => 'now',
- 'format_date' => 'short',
- 'weight' => 12,
- );
-
-
- $fields['engagement_type'] = array(
- 'type' => 'select',
- 'options' => array(
- 'phone' => t('Phone Call'),
- 'email' => t('Email'),
- 'in_person' => t('In-Person Meeting'),
- 'video_chat' => t('Video Chat'),
- 'txt_msg' => t('Txt Message'),
- 'social_media' => t('Social Media'),
- 'other' => t('Other'),
- ),
- 'label' => 'Type',
- 'required' => TRUE,
- 'hide_please_select' => TRUE,
- 'weight' => 40,
- );
-
- $fields['direction'] = array(
- 'type' => 'select',
- 'label' => t('Direction'),
- 'required' => TRUE,
- 'hide_please_select' => TRUE,
- 'options' => array(
- 'sent' => t("Sent"),
- 'received' => t('Received'),
- ),
- 'weight' => 50,
- );
-
-
- $fields['phone_outcome'] = array(
- 'type' => 'select',
- 'label' => t('Phone Outcome'),
- 'hide_please_select' => TRUE,
- 'options' => array(
- 'connected' => t("Connected"),
- 'no_answer' => t('No Answer'),
- 'voicemail' => t('Left Voicemail'),
- 'busy' => t('Busy'),
- 'wrong_number' => t('Wrong Number'),
- ),
- 'weight' => 60,
- );
-
-
- $fields['engagement_msg'] = array(
- 'type' => 'textarea',
- 'label' => t('Message'),
- 'filter' => 'basic',
- 'weight' => 70,
- );
-
-
- $fields['attachment'] = array(
- 'type' => 'file',
- 'label' => t('Attach File(s)'),
- 'weight' => 80,
- 'limit' => 999, // essentially, infinite.
- );
-
-
- $fields['visibility'] = array(
- 'type' => 'radios',
- 'label' => 'Visible to:',
- 'options' => array('public' => 'Anyone (incl. student)', 'faculty' => 'Faculty/Staff only'),
- 'weight' => 90,
- );
-
-
- $fields['manual_entry'] = array(
- 'type' => 'hidden',
- 'value' => '',
- );
-
- $fields['to_sms_phone'] = array(
- 'type' => 'hidden',
- 'value' => '',
- );
-
-
-
- $fields['external_msg_id'] = array(
- 'type' => 'hidden',
- 'value' => '',
- );
-
-
-
- $arr['engagement']['fields'] = $fields;
-
-
-
- return $arr;
- } // hook_content_register_content_type
-
-
-
- /**
- * Converts the string into a plain phone number, then tests to see if it is valid or not.
- * RETURNS FALSE if not valid, otherwise, returns the converted phone number. This will be a valid
- * number for use with our SMS service. (in the US anyway).
- */
- function engagements_convert_to_valid_phone_number($num)
- {
-
- // Remove any non-numeric characters from the num.
- $num = preg_replace("/\D/", '', $num);
-
- // The number should be 10 characters.
- if (strlen($num) == 10) return $num;
-
- if (strlen($num) == 11) {
- // Maybe it starts with a "1", which is not necessary.
- if (substr($num, 0, 1) == "1") {
- return substr($num, 1, 10); // ditch the first character.
- }
- }
-
- // Bad number, return false.
- return FALSE;
- }
-
-
- // From: https://stackoverflow.com/questions/4708248/formatting-phone-numbers-in-php
- function engagements_convert_to_pretty_phone_number($phoneNumber, $bool_convert_to_valid_first = TRUE)
- {
-
-
- if ($bool_convert_to_valid_first) {
- $phoneNumber = engagements_convert_to_valid_phone_number($phoneNumber);
- if (!$phoneNumber) return FALSE;
- }
-
-
- $phoneNumber = preg_replace('/[^0-9]/', '', $phoneNumber);
-
- if (strlen($phoneNumber) > 10) {
- $countryCode = substr($phoneNumber, 0, strlen($phoneNumber) - 10);
- $areaCode = substr($phoneNumber, -10, 3);
- $nextThree = substr($phoneNumber, -7, 3);
- $lastFour = substr($phoneNumber, -4, 4);
-
- $phoneNumber = '+' . $countryCode . ' (' . $areaCode . ') ' . $nextThree . '-' . $lastFour;
- } else if (strlen($phoneNumber) == 10) {
- $areaCode = substr($phoneNumber, 0, 3);
- $nextThree = substr($phoneNumber, 3, 3);
- $lastFour = substr($phoneNumber, 6, 4);
-
- $phoneNumber = '(' . $areaCode . ') ' . $nextThree . '-' . $lastFour;
- } else if (strlen($phoneNumber) == 7) {
- $nextThree = substr($phoneNumber, 0, 3);
- $lastFour = substr($phoneNumber, 3, 4);
-
- $phoneNumber = $nextThree . '-' . $lastFour;
- }
-
- return $phoneNumber;
- }
-
-
-
-
-
-
- /**
- * Implements hook_form_alter
- *
- * We want to make various modifications to our form, based on what we are trying to do to it. We may also
- * want to add in some custom javascript as well.
- *
- */
- function engagements_form_alter(&$form, $form_id)
- {
-
- global $user;
-
- if ($form_id == 'content_edit_content_form') {
- if (@$form['type']['value'] == 'engagement') {
-
- $db = get_global_database_handler();
-
- fp_add_js(fp_get_module_path("engagements") . "/js/engagements.js");
- fp_add_css(fp_get_module_path("engagements") . "/css/style.css");
-
- // If this is a NEW form, then check for values in the URL to auto-fill.
- if ($form['cid']['value'] === 'new') {
-
- if (!isset($_GET['engagement_type']) || $_GET['engagement_type'] == '' || $_GET['engagement_type'] == 'new') {
- // This means we are logging a NEW engagement, and not trying to send a txt or email. We need to
- // set our manual_entry value to something meaningful.
- $form['manual_entry']['value'] = 'Y';
- }
-
- if (isset($_GET['engagement_type']) && $_GET['engagement_type'] != '' && $_GET['engagement_type'] != 'new') {
-
- $form['engagement_type']['value'] = $_GET['engagement_type'];
-
-
- // Since we are setting the type, we do not want to display it as an option.
- $form['engagement_type']['attributes'] = array('class' => 'hidden');
- // There are other fields we do not wish to display as well:
- $form['direction']['attributes'] = array('class' => 'hidden');
- $form['activity_datetime']['attributes'] = array('class' => 'hidden');
- }
-
- $initials = variable_get_for_school("school_initials", "DEMO", $user->school_id);
-
- if (isset($_GET['faculty_id'])) {
- $form['faculty_id']['value'] = $_GET['faculty_id'];
-
- $form['faculty_id']['attributes'] = array('class' => 'hidden');
- $form['mark_from'] = array(
- 'type' => 'markup',
- 'value' => "<div class='engagement-field-mark engagement-from'><label>" . t("From") . ":</label>
- " . $db->get_faculty_name($form['faculty_id']['value']) . "
- </div>",
- 'weight' => $form['faculty_id']['weight'],
- );
- }
-
-
- if (isset($_GET['student_id'])) {
- $form['student_id']['value'] = $_GET['student_id'];
-
-
- $initials = variable_get_for_school("school_initials", "DEMO", db_get_school_id_for_student_id($_GET['student_id']));
-
-
- $form['student_id']['attributes'] = array('class' => 'hidden');
- $extra_mark = "";
-
- if ($form['engagement_type']['value'] == 'email') {
- $extra_mark = fp_get_student_email($form['student_id']['value']);
-
- // TODO: The EMAIL header may need to be a setting with replacement values
- $form['engagement_msg']['prefix'] = t("Your message will automatically begin with <strong>(@initials) from @name:</strong>", array("@initials" => $initials, "@name" => $db->get_faculty_name($form['faculty_id']['value'])));
- }
-
-
- $student_user_id = db_get_user_id_from_cwid($_GET['student_id'], 'student');
- $student_account = fp_load_user($student_user_id);
- if ($form['engagement_type']['value'] == 'txt_msg') {
-
-
- // Since this is a txt message, the textare has a max num of characters (1600)
- $form['engagement_msg']['maxlength'] = 1600;
-
-
- // Add in select list of the phone numbers we are allowed to select from.
- $from_options = engagements_get_from_phones_for_fapi(FALSE, $user);
- $form['from_sms_phone']['options'] = $from_options;
- if (count($from_options) == 0) {
- $form['from_sms_phone']['suffix'] .= "<h3>" . t("Note: You do
- not have permission to send txt messages from any number.
- See your system administrator for access.") . "</h3>";
-
- $form['from_sms_phone']['attributes']['readonly'] = "readonly";
- $form['from_sms_phone']['attributes']['class'] .= " readonly";
- $form['from_sms_phone']['attributes']['disabled'] .= "disabled";
-
- $form['engagement_msg']['attributes']['readonly'] = "readonly";
- $form['engagement_msg']['attributes']['class'] .= " readonly";
- $form['engagement_msg']['attributes']['disabled'] .= "disabled";
-
- $form['submit_submit']['attributes']['disabled'] = 'disabled';
- $form['submit_submit']['attributes']['class'] .= ' button-disabled';
- }
- $form['from_sms_phone']['required'] = TRUE;
-
- // get student phone number
- $extra_mark = "(NO MOBILE NUMBER AVAILABLE)";
-
-
- $mobile_phone = user_get_attribute($student_user_id, "mobile_phone");
- if ($mobile_phone) {
- $extra_mark = engagements_convert_to_pretty_phone_number($mobile_phone, TRUE);
- } else {
- // Mobile phone was never found, so disable submit and message box.
-
- $form['engagement_msg']['attributes']['readonly'] = 'readonly';
- $form['engagement_msg']['attributes']['class'] .= ' readonly';
-
- $form['submit_submit']['attributes']['disabled'] = 'disabled';
- $form['submit_submit']['attributes']['class'] .= ' button-disabled';
- $form['submit_submit']['suffix'] = "<strong>" . t('NOTE: Cannot send a text message as there is no mobile phone number for this recipient.') . "</strong>";
- }
-
- if (trim($mobile_phone) != "" && !engagements_can_send_sms_to_number($mobile_phone)) {
- // Meaning, the user has opted-out! Disable fields and let the user know.
- $form['engagement_msg']['attributes']['readonly'] = 'readonly';
- $form['engagement_msg']['attributes']['class'] .= ' readonly';
-
- $form['submit_submit']['attributes']['disabled'] = 'disabled';
- $form['submit_submit']['attributes']['class'] .= ' button-disabled';
- $form['submit_submit']['suffix'] = "<strong>" . t('NOTE: Cannot send a text message as this recipient has opted-out of receving text messages. Try email or calling instead.') . "</strong>";
-
-
- }
-
-
- // The header needs to be a setting with replacement values
- $sms_header = engagements_sms_replace_patterns(variable_get('sms_header', '(@initials) from @name:'), "", $user);
-
- $form['engagement_msg']['prefix'] = t("Your message will automatically begin with <strong>@header</strong>", array("@header" => $sms_header));
- $form['engagement_msg']['description'] = t("To insert emoji in Windows, press <span style='padding-left: 10px; padding-right: 10px; font-size: 1.3em;'><i class='fa fa-windows'></i> + .</span> <em>(Windows key + period)</em>");
-
-
- $form['attachment']['attributes'] = array('class' => 'hidden');
- }
-
-
- $form['mark_to'] = array(
- 'type' => 'markup',
- 'value' => "<div class='engagement-field-mark engagement-to'><label>" . t("To") . ":</label>
- " . $db->get_student_name($form['student_id']['value'], TRUE) . "<span class='engagement-student-extra-mark'>$extra_mark</span>
- </div>",
- 'weight' => $form['student_id']['weight'],
- );
- }
-
-
-
-
- // Always set the published = TRUE, and hide.
- $form['published']['value'] = TRUE;
- $form['published']['attributes'] = array('class' => 'hidden');
-
-
-
-
- // Add a validate handler to form, so we can name sure email or mobile phone numbers are valid.
- $form['#validate_handlers'][] = 'engagements_send_email_or_txt_form_validate';
-
- // Add a submit handler to form, so we can send email or txt messages
- $form['#submit_handlers'][] = 'engagements_send_email_or_txt_form_submit';
- } // cid == new
-
-
-
-
- if ($form['engagement_type']['value'] != 'txt_msg') {
- // If this is anything OTHER than a txt_msg, we will show the tinymce editor for the Message
- $form['engagement_msg']['type'] = 'textarea_editor';
- // Also get rid of the sms number field.
- $form['from_sms_phone'] = array(
- 'type' => 'hidden',
- 'value' => '',
- 'required' => FALSE,
- );
- }
-
- if ($form['engagement_type']['value'] != 'txt_msg' && $form['engagement_type']['value'] != 'email') {
- // Set visibility to 'faculty' by default.
- $form['visibility']['value'] = 'faculty';
- } else {
- $form['visibility']['value'] = 'public';
- $form['visibility']['attributes'] = array('class' => 'hidden');
- }
- } // form type == engagement
- } // content_edit_content_form
-
-
-
-
-
-
-
-
-
-
-
- } // hook_form_alter
-
-
- /**
- * Get an array of numbers which the user should be notified of when they receive an SMS.
- */
- function engagements_get_user_notify_sms_receipt_values($user_id = NULL) {
- global $user;
-
- $rtn = array();
-
- if ($user_id === NULL) {
- $user_id = $user->id;
- }
- $options = engagements_get_from_phones_for_fapi(TRUE);
-
- foreach ($options as $num => $val) {
- $test = user_get_setting($user_id, "notify_sms_receipt__" . $num);
- if (intval($test) === intval($num)) {
- $rtn[$num] = $num;
- }
- }
- return $rtn;
- }
-
-
- /**
- * Returns an array of all the user who should receive notifications when
- * we receive an SMS at a particular number.
- */
- function engagements_get_users_to_be_notified_for_sms_on_number($num) {
- $rtn = array();
-
- $res = db_query("SELECT user_id FROM user_settings
- WHERE name = ?", array('notify_sms_receipt__' . $num));
- while ($cur = db_fetch_array($res)) {
- $rtn[$cur['user_id']] = intval($cur['user_id']);
- }
-
-
- return $rtn;
- }
-
-
-
-
- /**
- * Returns back the phone lines available.
- *
- * If bool_return_all == FALSE, it means we will first check to make sure the user (specified by account) has permission
- * to send sms for that number.
- *
- */
- function engagements_get_from_phones_for_fapi($bool_return_all = TRUE, $account = NULL, $bool_only_mass_text_numbers = FALSE)
- {
- global $user;
- $rtn = array();
-
- if ($account == NULL) $account = $user;
-
- $phones = engagements_get_from_phones($bool_only_mass_text_numbers);
- $default = $phones['default']['num'];
- $rtn[$default] = t("[Default] ") . engagements_convert_to_pretty_phone_number($default) . ' - ' . $phones['default']['description'];
-
- foreach ($phones['lines'] as $num => $details) {
-
- if (!isset($rtn[$details['num']])) {
- $rtn[$details['num']] = engagements_convert_to_pretty_phone_number($details['num']) . " - " . $details['description'];
- }
- }
-
-
-
- // if bool_return_all != TRUE, then make sure the account has permissing to send from each number. If not, remove it.
- foreach ($rtn as $num => $details) {
- if (!$bool_return_all) {
- if (!$bool_only_mass_text_numbers && !user_has_permission("can_send_sms_from_$num", $account)) {
- unset($rtn[$num]);
- }
- }
- }
-
-
-
- return $rtn;
- } // engagements_get_from_phones_for_fapi()
-
-
-
-
-
-
-
- function engagements_send_email_or_txt_form_validate($form, &$form_state)
- {
-
- $values = $form_state['values'];
-
- ////////
- // TODO: I am not sure I even need to get the cid here... delete it?
- $cid = NULL;
- if (isset($form_state['content_object']) && is_object($form_state['content_object'])) {
- $cid = $form_state['content_object']->cid; // At this point, the content has already been saved, so we know its cid.
- }
- ////////
-
-
- $engagement_type = $values['engagement_type'];
-
- $manual_entry = @trim(strtoupper($values['manual_entry']));
-
- if ($engagement_type != 'email' && $engagement_type != 'txt_msg') {
- return; // we are not interested, harmlessly return.
- }
-
- $student_id = $values['student_id'];
- $faculty_id = $values['faculty_id'];
- $msg = $values['engagement_msg'];
-
- $from_number = trim($values['from_sms_phone']);
-
- $db = get_global_database_handler();
-
- if ($engagement_type == 'email' && $manual_entry != 'Y') {
- $student_email = fp_get_student_email($student_id);
- if (!filter_var($student_email, FILTER_VALIDATE_EMAIL)) { // take advantage of pho built-in email validator
- form_error('engagement_msg', t("Sorry, but the email provided for the student appears to be invalid."));
- return;
- }
- } // type == 'email'
-
-
- if ($engagement_type == 'txt_msg' && $manual_entry != 'Y') {
-
- $student_user_id = db_get_user_id_from_cwid($student_id, 'student');
-
-
- $temp = user_get_attribute($student_user_id, 'mobile_phone');
- $mobile_phone = engagements_convert_to_valid_phone_number(trim($temp));
-
- if (!$mobile_phone) {
- form_error('engagement_msg', t('Sorry, but the mobile phone number provided for the student appears to be invalid.'));
- return;
- }
- } // type == 'txt_msg'
-
-
- } // engagements_send_email_or_txt_form_validate
-
-
-
-
-
-
- function engagements_send_email_or_txt_form_submit($form, &$form_state)
- {
-
- global $user;
-
- $values = $form_state['values'];
- $cid = $form_state['content_object']->cid; // At this point, the content has already been saved, so we know its cid.
- $content = $form_state['content_object'];
- $engagement_type = $values['engagement_type'];
-
- $manual_entry = @trim(strtoupper($values['manual_entry']));
-
- if ($engagement_type != 'email' && $engagement_type != 'txt_msg') {
- return; // we are not interested, harmlessly return.
- }
-
- $db = get_global_database_handler();
- $student_id = $values['student_id'];
- $faculty_id = $values['faculty_id'];
- $faculty_name = $db->get_faculty_name($faculty_id);
-
- $initials = variable_get("school_initials", "DEMO");
-
- $initials = variable_get_for_school("school_initials", "DEMO", db_get_school_id_for_student_id($student_id));
-
- // get the "from_number"
- $from_number = $values['from_sms_phone'];
-
- // this needs to be a setting with replacement values!
- // Add header to msg...
- $header = engagements_sms_replace_patterns(variable_get('sms_header', '(@initials) from @name:'), $from_number, $user);
-
- $msg = $values['engagement_msg'];
-
- $db = get_global_database_handler();
-
- if ($engagement_type == 'email' && $manual_entry != 'Y') {
- $student_email = fp_get_student_email($student_id);
-
- $subject = $values['title'];
-
- // Add our tracking pixel to the end of the email msg (but not what is saved to our database).
- // We will use that to tell how many times the message gets opened.
- $tracking_img_url = engagements_create_new_tracking_img_url($cid);
-
-
- $msg .= "<br><br>----<br>You may respond directly to this email. It will be stored with FlightPath for $faculty_name to then review.";
-
- $msg .= "\n\n<img src='$tracking_img_url'>";
-
-
- // Were there any attachments with this content?
-
- $attachments = array();
- $attachment_csv = trim(@$content->field__attachment['value']);
- if ($attachment_csv) {
- $temp = explode(",", $attachment_csv);
- foreach ($temp as $fid) {
- if ($fid == "") continue;
- $file = content_get_uploaded_file($fid);
- if ($file) {
- // Handle encrypted files
- $fcont = file_get_contents($file['full_filename']); // the full_filename already contains the path to the file
- if (intval($file['is_encrypted']) === 1) {
- $fcont = encryption_decrypt($fcont);
- }
- $attachments[$file['original_filename']] = $fcont;
- }
- }
- }
-
-
-
- smtp_mail($student_email, $subject, $header . "<br><br>" . $msg, TRUE, $attachments, TRUE); // the TRUE sends as HTML.
- fp_add_message(t("Email has been successfully sent."));
- } // type == 'email'
-
-
- $mobile_phone = '';
-
- if ($engagement_type == 'txt_msg' && $manual_entry != 'Y') {
-
- $student_user_id = db_get_user_id_from_cwid($student_id, 'student');
-
- $temp = user_get_attribute($student_user_id, 'mobile_phone');
- $mobile_phone = engagements_convert_to_valid_phone_number(trim($temp));
- // Since we have passed validation, we will assume we have a valid phone number for this student.
-
- // Send the message!
- $external_msg_id = engagements_send_sms_to_number($mobile_phone, $header . "\n" . $msg, $student_id, $from_number);
-
- if ($external_msg_id) {
- fp_add_message(t("Text Message has been successfully sent."));
- // save the external_msg_id with the content.
- $content->field__external_msg_id['value'] = $external_msg_id;
-
- $content->field__to_sms_phone['value'] = $mobile_phone;
- $content->field__from_sms_phone['value'] = $from_number;
-
- $content->log = "[AUTO] Updating external_msg_id";
- content_save($content);
- }
- } // type == 'txt_msg'
-
- if ($manual_entry != 'Y') {
- watchdog("engagements", "sent $engagement_type to $student_id ($mobile_phone)");
- }
- else {
- watchdog("engagements", "logged $engagement_type to $student_id");
- }
-
- watchdog("engagements", "$engagement_type message to $student_id: $header <br> $msg", array(), WATCHDOG_DEBUG);
- } // ... send email or txt form submit
-
-
-
- /**
- * Actually send a text message. Will drupal_set_message() as an error if there is a problem, and return FALSE.
- * Returns TRUE on success, no drupal_set_message is printed.
- */
- function engagements_send_sms_to_number($to_number, $body, $to_cwid = "", $from_number = "default", $bool_send_opt_out_message = TRUE)
- {
-
- $to_number = engagements_convert_to_valid_phone_number($to_number);
-
- require_once(fp_get_module_path('engagements', TRUE, FALSE) . '/lib/signalwire/vendor/autoload.php');
-
- //use SignalWire\Rest\Client;
-
- // project id, auth tolen, space url
- $project_id = variable_get('sms_project_id', '');
- $auth_token = variable_get('sms_auth_token', '');
- $space_url = variable_get('sms_space_url', '');
-
- $from_phone = $from_number;
- $phones = engagements_get_from_phones();
- if ($from_phone == "default") {
- $from_phone = engagements_convert_to_valid_phone_number($phones['default']['num']);
- }
-
- if ($bool_send_opt_out_message) {
- // We must include a "text STOP to opt-out" type message to the bottom of every notification.
- // TODO: May be a setting instead, on the signalwire settings page
- $body .= "\n\n" . "Text STOP to opt-out of txt messages.";
- }
-
-
-
-
- // project id, auth tolen, space url
- $client = new SignalWire\Rest\Client($project_id, $auth_token, array("signalwireSpaceUrl" => $space_url));
- $external_msg_id = FALSE;
-
- try {
-
- $message = $client->messages
- ->create(
- "+1" . $to_number, // to
- array(
- "from" => "+1" . $from_phone, // my signalwire account phone number
- "body" => $body
- )
- );
-
- $external_msg_id = $message->sid;
-
- // save message information to our sms_history table.
-
- $record = $message;
-
- $message_sid = $record->sid;
-
- $from_mobile = engagements_convert_to_valid_phone_number($record->from);
- $body = $record->body;
- $num_segments = intval($record->numSegments);
-
- $date_sent = $record->dateCreated; // Since we just created it, just dateCreated instead of dateSent.
- $throw_away = print_r($date_sent, TRUE); // Not sure why, but I have to do this in order for the data field to populate.
-
- //$date_sent_ts = strtotime($date_sent->date); // Was causing a mysql error all of a sudden. Just use current time.
- $date_sent_ts = time();
-
- // The price is not available right now, so we will set it...
- $price = 0.0013 * $num_segments;
- //$fp_price = engagements_get_fp_price($price);
- $fp_price = 0.0033 * $num_segments;
-
-
- $direction = $record->direction;
-
- // Write our data to our sms_history table.
- db_query(
- "INSERT INTO sms_history (`message_sid`, `sw_type`, `body`, `from_number`, `to_number`, `sw_price`, `fp_price`, `to_cwid`, `updated`, `direction`, `media_filenames`, `date_sent`, price_processed, num_segments)
- VALUES (?, 'sms', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ",
- array($message_sid, $body, $from_mobile, $to_number, $price, $fp_price, $to_cwid, time(), $direction, '', $date_sent_ts, 0, $num_segments)
- );
- } catch (Exception $e) {
- fp_add_message("An error has occured while trying to send a text message to <em>$to_number</em>. The
- error has been logged. Please have the technical administrator investigate. Error message:" . $e->getMessage(), "error");
- watchdog("engagements_sms", "An error has occured while trying to send a text message to <em>$to_number</em>. Error: " . $e->getMessage() . ". The complete
- error is: <pre>" . print_r($e, true) . "</pre>", array(), WATCHDOG_ERROR);
- return FALSE;
- }
-
- watchdog("engagements_sms", "SMS message sent successfully to $to_number. External_msg_id = " . $external_msg_id);
-
- return $external_msg_id;
- } // engagements_send_sms_to_number
-
-
-
-
-
-
- /**
- * Generates a URL to our tracking pixel, based on the cid included.
- */
- function engagements_create_new_tracking_img_url($cid)
- {
-
- $token = hash('sha512', ($cid . microtime() . mt_rand(9, 99999) . mt_rand(9, 99999)));
- $url = $GLOBALS['fp_system_settings']['base_url'] . '/' . fp_url("engagements-track/$cid/$token/pixel.gif", '', FALSE);
-
- // Write to database
- db_query('INSERT INTO engagements_tracking (cid, token, opens, updated)
- VALUES (?, ?, ?, ?)', array($cid, $token, 0, time()));
-
-
- return $url;
- }
-
-
-
-
-
-
- /**
- * displays the main Engagements tab, which shows the history of past engagements.
- */
- function engagements_display_main()
- {
- global $user, $current_student_id;
-
- $faculty_id = 0;
- if ($user->is_faculty) {
- $faculty_id = $user->cwid;
- }
-
- fp_set_title('');
-
- fp_add_css(fp_get_module_path("engagements") . "/css/style.css");
- fp_add_js(fp_get_module_path("engagements") . "/js/engagements.js");
- fp_add_js(fp_get_module_path("advise") . "/js/advise.js");
-
- $types = content_get_types();
-
- $icons = array(
- 'phone' => 'fa-phone',
- 'email' => 'fa-envelope',
- 'txt_msg' => 'fa-comment',
- 'note' => 'fa-file-text',
- 'in_person' => 'fa-user',
- 'social_media' => 'fa-cloud',
- 'other' => 'fa-asterisk',
- 'video_chat' => 'fa-video-camera',
- 'reminder' => 'fa-thumb-tack',
- );
-
-
- $rtn = "";
- $rtn .= "<div id='engagements-list-page'>";
-
- $rtn .= "<div class='add-engagements-buttons'>";
- if (user_has_permission('can_send_email_engagements')) {
- $rtn .= "<a href='javascript:engagementsNewEngagementDialog(\"email\",\"New Email\",\"$current_student_id\",\"$faculty_id\");' class='button'><i class='fa fa-envelope-o'></i> New Email</a>";
- }
- if (user_has_permission('can_send_txt_engagements')) {
- $rtn .= "<a href='javascript:engagementsNewEngagementDialog(\"txt_msg\",\"New Text Message\",\"$current_student_id\",\"$faculty_id\");' class='button'><i class='fa fa-comment-o'></i> New TXT</a>";
- }
- if (user_has_permission('can_log_engagements')) {
- $rtn .= "<a href='javascript:engagementsNewEngagementDialog(\"\",\"Log New Engagement\",\"$current_student_id\",\"$faculty_id\");' class='button'><i class='fa fa-plus'></i> Log New Engagement</a>";
- }
-
- $rtn .= "</div> <!-- add-engagements-buttons -->
- <div class='clear'></div>
- ";
-
-
- $rtn .= fp_render_section_title("Recent Engagements");
-
- $rtn .= "<div class='engagements-list'>";
-
-
-
- $res = pager_query("SELECT DISTINCT(a.cid) FROM content__engagement a, content n
- WHERE field__student_id = ?
- AND a.vid = n.vid
- AND a.cid = n.cid
- AND n.delete_flag = 0
- AND n.published = 1
- ORDER BY a.vid DESC, field__activity_datetime DESC", array($current_student_id), 5, 0, "SELECT COUNT(DISTINCT(a.cid)) FROM content__engagement a, content n
- WHERE field__student_id = ?
- AND a.vid = n.vid
- AND a.cid = n.cid
- AND n.delete_flag = 0
- AND n.published = 1");
-
- while ($cur = db_fetch_object($res)) {
- $cid = $cur->cid;
- $content = content_load($cid);
-
- // is this "faculty" visibility? If so, do we have access to view?
- if ($content->field__visibility['value'] == 'faculty' && !user_has_permission('can_view_faculty_engagements')) {
- continue;
- }
-
- $visibility_icon = "";
-
- if ($content->field__visibility['value'] == 'faculty') {
- $visibility_icon = "<i class='fa fa-lock' title='Visibile to Faculty/Staff only'></i>";
- }
-
-
- $icon = $icons[$content->field__engagement_type['value']];
-
- $type = $content->field__engagement_type['value'];
- $direction = $content->field__direction['value'];
- $msg = $content->field__engagement_msg['display_value'];
- $manual_entry = $content->field__manual_entry['value'];
-
- $external_msg_id = @trim($content->field__external_msg_id['value']);
-
-
- $pre_description = "";
-
- $sms_extra_details = $sms_delivery_details = "";
-
- if ($type == 'txt_msg' && $external_msg_id) {
-
- $phones = engagements_get_from_phones();
- $details = engagements_get_sms_from_history($external_msg_id);
- if ($details) {
- $desc = @$phones['lines'][$details['to_number']]['description'];
- if (!$desc) $desc = @$phones['lines'][$details['from_number']]['description'];
-
- $sms_extra_details = "<span class='sms-extra-details'>";
- $sms_extra_details .= t("(%desc)", array('%desc' => $desc));
- $sms_extra_details .= "</span>";
-
- if (isset($details['delivery_status']) && $details['delivery_status'] == 'undelivered') {
-
- $moreinfo = "";
-
- $moreinfo .= "<p>" . t("We're sorry, but this message was not delivered.
- Usually this happens when the recipient's carrier (ex: AT&T, Verizon, etc) marks the message as 'spam' and refuses to deliver
- it to the user. <strong>Unfortunately, this is something which is outside the control of @fp.</strong>
- <br><br>
- This may also be due to the user's phone being invalid, disconnected, or incapable of receiving SMS text messages.
- <br><br>
- Your IT/@fp administrator may be able to log into your
- SMS vendor account for more information.
- <br><br>
- Note: the recipient <strong><u>did not receive this message</u></strong>. Please try again via email or another
- communication route.", array("@fp" => variable_get("system_name", "FlightPath"))) . "</p>";
-
- $moreinfo = base64_encode($moreinfo);
- $sms_delivery_details .= "<div class='sms-undelivered-error'><i class='fa fa-warning'></i> " . t("Undelivered by phone carrier network - %msg", array("%msg" => @$details['err_friendly_message'])) . "
- <a href='javascript:fp_alert(\"$moreinfo\",\"base64\");' title='" . t("More information") . "'><i class='fa fa-question-circle'></i></a></div>";
- }
-
- }
- }
-
-
-
- if ($manual_entry == 'Y') {
- // This was a manually logged engagement.
- $edit_link = "";
- // Is the user allowed to EDIT this manual engagement?
- if (content_user_access("edit", $content->cid)) {
- $edit_link = "<a href='javascript:fpOpenLargeIframeDialog(\"" . fp_url("content/$cid/edit", "window_mode=popup&content_tabs=false") . "\",\"Edit Alert\");' title='Edit' class='action-link'><i class='fa fa-pencil'></i></a>";
- }
-
- $pre_description .= t("Logged:") . " $edit_link ";
- }
-
-
-
- ///////////
- // This section we can instead query the content_files table for this cid.
- if ($type == 'txt_msg') {
- $ttemp = array('','');
- if (strstr($msg, "~~MEDIA~~") && strstr($msg, "~~END_MEDIA~~")) {
- $temp = explode("~~MEDIA~~", $msg);
- $msg = $temp[0]; // get rid of the media part of the msg.
- $ttemp = explode("~~END_MEDIA~~", $temp[1]);
- }
-
- $res2 = db_query("SELECT * FROM content_files WHERE cid = ? ORDER BY cid", array($cid));
- while ($cur2 = db_fetch_array($res2)) {
- $fid = $cur2['fid'];
- $file = content_get_uploaded_file($fid);
- $img_tag = "<img src='{$file['url']}' style='max-width: 200px; height: auto;'>";
- $msg .= "<div class='media-attached'><a href='{$file['url']}' target='_BLANK'>
- $img_tag
- </a></div>";
- }
- $msg .= $ttemp[1]; // in case there was anything AFTER ~~END_MEDIA~~
- }
-
-
-
- /*
- // If the $msg contains ~~MEDIA~~ and ~~END_MEDIA~~ then we can assume there are filenames after it, which we assume to be images that got
- // text messaged. Add them.
-
- $files = explode(",", $temp[1]);
- foreach ($files as $filename) {
- $ttemp = explode("~~END_MEDIA~~", $filename);
- $filename = $ttemp[0];
- $path = base_path() . '/custom/files/content_uploads/' . $filename;
-
- $img_tag = "<img src='$path' style='max-width: 200px; height: auto;'>";
-
- $ext_temp = explode(".", $filename);
- $ext = strtolower(@$ext_temp[count($ext_temp) - 1]);
-
- $image_exts = array("gif", "tiff", "jpg", "jpeg", "png", "bmp");
- if (!in_array($ext, $image_exts)) {
- $mime_icon = content_get_fontawesome_icon_for_mimetype("", $ext);
- $img_tag = "<div class='atached-file'><i class='fa $mime_icon'></i>" . " " . t("View %ext attachment in new window", array("%ext" => $ext)) . "</div>";
- }
-
- $msg .= "<div class='media-attached'><a href='$path' target='_BLANK'>
- $img_tag
- </a></div>" . $ttemp[1]; // add on the </p> at the end if its there.
- }
- } // contains ~~MEDIA~~
- */
-
-
- ////////////
-
-
-
- $header_desc_extra = "";
- if ($type == 'email' && $direction == 'sent' && $manual_entry != 'Y') {
- //$header_desc_extra = " Opens: 1";
- $num_opens = intval(db_result(db_query("SELECT opens FROM engagements_tracking WHERE cid = ?", array($content->cid))));
- $header_desc_extra = "<span class='header-desc-extra'>Opens: $num_opens</span>";
- }
-
-
- $fid_csv = @trim($content->field__attachment['value']);
- if ($fid_csv) {
- // were there any attachments?
- $attachment_icon = "";
- if ($fid_csv) {
- $attachment_icon = "<i class='fa fa-paperclip'></i> ";
- $attachments = array();
- $attachment_csv = trim(@$content->field__attachment['value']);
- // TODO: An option here would be to just query the content_files table for this cid.
-
-
- if ($attachment_csv) {
- $temp = explode(",", $attachment_csv);
- $msg .= "<label>" . t("Attached File(s):") . "</label><div class='attached-files'>";
- foreach ($temp as $fid) {
- if ($fid == "") continue;
- $file = content_get_uploaded_file($fid);
- if ($file) {
- $mime_icon = content_get_fontawesome_icon_for_mimetype($file['mimetype'], $file['ext']);
- $msg .= "<div class='attached-file'><a href='{$file['url']}'><i class='fa $mime_icon'></i> {$file['original_filename']}</a></div>";
- }
- }
- $msg .= "</div>";
- }
-
-
- }
-
- // We need a random id to assign to this email body.
- $bodyid = "bid_" . md5(microtime() . mt_rand(9, 99999) . mt_rand(9, 9999));
-
-
- // If the msg body is too long, let it be expandable.
- $more_link = $less_link = "";
- if (strlen($msg) > 500) {
- $more_link = "<a href='javascript:engagementsExpandBody(\"$bodyid\");' class='more-body-link' id='more_$bodyid'>More</a>";
- $less_link = "<a href='javascript:engagementsShrinkBody(\"$bodyid\");' class='less-body-link' id='less_$bodyid' style='display:none;'>Less</a>";
- }
-
- $msg = "<div class='email-subject'>{$attachment_icon}Subject: $content->title</div><div class='email-body' id='$bodyid'>$msg</div>$more_link$less_link";
- }
-
-
-
- $author_user_id = intval($content->user_id);
- $author_account = fp_load_user($author_user_id);
- $author_name = $author_account->f_name . " " . $author_account->l_name;
-
- $act_feed_extra_class = "";
- if ($content->field__from_sms_phone['value']) {
- $act_feed_extra_class .= " activity-feed-from-sms-" . engagements_convert_to_valid_phone_number(fp_get_machine_readable($content->field__from_sms_phone['value']));
- }
-
- if ($content->field__to_sms_phone['value']) {
- $act_feed_extra_class .= " activity-feed-to-sms-" . engagements_convert_to_valid_phone_number(fp_get_machine_readable($content->field__to_sms_phone['value']));
- }
-
-
- $rtn .= "<div class='activity-feed-teaser activity-feed-teaser-$direction activity-feed-teaser-type-$type $act_feed_extra_class'>
- <div class='activity-header-content'>
- <span class='header-icon'><i class='fa $icon'></i></span>
- <span class='header-description'>
- <span class='pre-description'>$pre_description</span>
- {$content->field__engagement_type['display_value']}
- </span>$sms_extra_details
- <span class='header-phone-outcome'>: {$content->field__direction['display_value']} $header_desc_extra</span>
- $sms_delivery_details
- <span class='header-edit'></span>
- <span class='header-date-time'>" . $content->field__activity_datetime['display_value'] . "</span>
- <span class='header-author'>$author_name</span>
- <span class='header-visibility'>$visibility_icon</span>
- </div>
- <div class='activity-contents'>
- <div class='activity-comment'>
- $msg
- </div>
- </div>
- </div>
- <div class='clear'></div>";
-
- // mark this content as "read" since it appeared on the screen.
- content_set_last_access($content->cid);
-
- } // while cur
-
-
-
- // Display the pager that was generated by the pager_query above!
- $rtn .= theme_pager(array(t('« newest'), t('‹ newer'), '', t('older ›'), t('oldest »')));
-
- $rtn .= "</div>"; // engagements-list
-
-
-
- $rtn .= "</div>"; // engagements-list-page
-
- // Let's set our breadcrumbs
- $db = get_global_database_handler();
- $crumbs = array();
- $crumbs[] = array(
- 'text' => 'Students',
- 'path' => 'student-search',
- );
- $crumbs[] = array(
- 'text' => $db->get_student_name($current_student_id) . " ({$current_student_id})",
- 'path' => 'student-profile',
- 'query' => "current_student_id={$current_student_id}",
- );
- fp_set_breadcrumbs($crumbs);
-
-
-
- watchdog("engagements", "view $current_student_id");
-
-
- return $rtn;
- } // engagements_display_main
-
Functions
Name | Description |
---|---|
engagements_can_send_sms_to_number | |
engagements_content_register_content_type | For use with the content module. We will register our custom content type(s) for use with this module. |
engagements_convert_to_pretty_phone_number | |
engagements_convert_to_valid_phone_number | Converts the string into a plain phone number, then tests to see if it is valid or not. RETURNS FALSE if not valid, otherwise, returns the converted phone number. This will be a valid number for use with our SMS service. (in the US anyway). |
engagements_create_new_tracking_img_url | Generates a URL to our tracking pixel, based on the cid included. |
engagements_cron | Implements hook_cron |
engagements_display_advisee_engagements_page | |
engagements_display_main | displays the main Engagements tab, which shows the history of past engagements. |
engagements_form_alter | Implements hook_form_alter |
engagements_get_alert_count_by_type | Implements hook_get_count_for_alert_type |
engagements_get_file_extension_from_mime_type | This function will look at the mime type (aka content type) to figure out what the file extension should be. This is useful when retrieving txt message media. |
engagements_get_fp_price | figure out the price we will charge. |
engagements_get_from_phones | Get the available "from phone" numbers in an organized array structure. |
engagements_get_from_phones_for_fapi | Returns back the phone lines available. |
engagements_get_signalwire_sms_error_codes_array | |
engagements_get_sms_from_history | |
engagements_get_users_to_be_notified_for_sms_on_number | Returns an array of all the user who should receive notifications when we receive an SMS at a particular number. |
engagements_get_user_notify_sms_receipt_values | Get an array of numbers which the user should be notified of when they receive an SMS. |
engagements_handle_incoming_sms | This catches incoming sms messages from POST, but can also be used by our "sms_get_all_messages" function, but it is also used by the sms_get_all_messages to save/update information. |
engagements_handle_sms_stop | This function is called by engagements_handle_incoming_sms, when we receive 'STOP' from the user. We must add them to our "sms_do_not_txt" table, and send a reply letting them know how to re-subscribe in the future. |
engagements_handle_sms_unstop | User opted-IN to receiving txt messages. |
engagements_handle_tracking_pixel_request | The user has opened an email with a tracking pixel. We will now record that it was opened in our engagements_tracking table. |
engagements_imap_get_all_received_messages | Connect to our imap server, download all received messages from students (or others). We will then delete them, so they don't get read twice. |
engagements_imap_settings_form | Configure the imap settings used by Engagements |
engagements_mass_sms_form | |
engagements_mass_sms_form_submit | Our submit function. Our main task is simply to set off a batch routine. |
engagements_mass_sms_form_validate | |
engagements_mass_sms_perform_batch_operation | |
engagements_menu | Implement hook_menu |
engagements_menu_handle_replacement_pattern | implements hook_menu_handle_replacement_pattern |
engagements_perm | |
engagements_send_email_or_txt_form_submit | |
engagements_send_email_or_txt_form_validate | |
engagements_send_sms_to_number | Actually send a text message. Will drupal_set_message() as an error if there is a problem, and return FALSE. Returns TRUE on success, no drupal_set_message is printed. |
engagements_sms_get_all_messages | Retrieve all messages, update the ones which don't have prices associated with them yet. |
engagements_sms_replace_patterns | |
engagements_sms_settings_form | Configure the various SMS settings |
_engagements_imap_get_attachments | $inbox is the imap link. email_number is msg_no. |
_engagements_imap_get_body |