/home/edulekha/crm.edulekha.com/application/libraries/sms/App_sms.php
<?php
use GuzzleHttp\Client;
defined('BASEPATH') or exit('No direct script access allowed');
define('SMS_TRIGGER_INVOICE_OVERDUE', 'invoice_overdue_notice');
define('SMS_TRIGGER_INVOICE_DUE', 'invoice_due_notice');
define('SMS_TRIGGER_PAYMENT_RECORDED', 'invoice_payment_recorded');
define('SMS_TRIGGER_ESTIMATE_EXP_REMINDER', 'estimate_expiration_reminder');
define('SMS_TRIGGER_PROPOSAL_EXP_REMINDER', 'proposal_expiration_reminder');
define('SMS_TRIGGER_PROPOSAL_NEW_COMMENT_TO_CUSTOMER', 'proposal_new_comment_to_customer');
define('SMS_TRIGGER_PROPOSAL_NEW_COMMENT_TO_STAFF', 'proposal_new_comment_to_staff');
define('SMS_TRIGGER_CONTRACT_EXP_REMINDER', 'contract_expiration_reminder');
define('SMS_TRIGGER_CONTRACT_SIGN_REMINDER', 'contract_sign_reminder_to_customer');
define('SMS_TRIGGER_STAFF_REMINDER', 'staff_reminder');
define('SMS_TRIGGER_CONTRACT_NEW_COMMENT_TO_STAFF', 'contract_new_comment_to_staff');
define('SMS_TRIGGER_CONTRACT_NEW_COMMENT_TO_CUSTOMER', 'contract_new_comment_to_customer');
class App_sms
{
private static $gateways;
protected $client;
private $triggers = [];
protected $ci;
public static $trigger_being_sent;
public $test_mode = false;
public function __construct()
{
$this->ci = &get_instance();
$this->client = new Client(
[ 'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'verify' => false,
CURLOPT_RETURNTRANSFER => true,
]
);
$this->set_default_triggers();
}
public function add_gateway($id, $data = [])
{
if (!$this->is_initialized($id) || $this->is_options_page()) {
foreach ($data['options'] as $option) {
add_option($this->option_name($id, $option['name']), (isset($option['default_value']) ? $option['default_value'] : ''));
}
add_option($this->option_name($id, 'active'), 0);
add_option($this->option_name($id, 'initialized'), 1);
}
$data['id'] = $id;
self::$gateways[$id] = $data;
}
public function get_option($id, $option)
{
return get_option($this->option_name($id, $option));
}
public function get_gateway($id)
{
$gateway = isset(self::$gateways[$id]) ? self::$gateways[$id] : null;
return $gateway;
}
public function set_test_mode($value)
{
$this->test_mode = $value;
return $this;
}
public function get_gateways()
{
return hooks()->apply_filters('get_sms_gateways', self::$gateways);
}
public function get_trigger_value($trigger)
{
$oc_name = 'sms-trigger-' . $trigger . '-value';
$message = $this->ci->app_object_cache->get($oc_name);
if (!$message) {
$message = get_option($this->trigger_option_name($trigger));
$this->ci->app_object_cache->add($oc_name, $message);
}
return $message;
}
public function add_trigger($trigger)
{
$this->triggers = array_merge($this->triggers, $trigger);
}
public function get_available_triggers()
{
$triggers = hooks()->apply_filters('sms_gateway_available_triggers', $this->triggers);
foreach ($triggers as $trigger_id => $triger) {
if ($this->is_options_page()) {
add_option($this->trigger_option_name($trigger_id), '', 0);
}
$triggers[$trigger_id]['value'] = $this->get_trigger_value($trigger_id);
}
return $triggers;
}
public function trigger($trigger, $phone, $merge_fields = [])
{
if (empty($phone)) {
return false;
}
$gateway = $this->get_active_gateway();
if ($gateway !== false) {
$className = 'sms_' . $gateway['id'];
if ($this->is_trigger_active($trigger)) {
$message = $this->parse_merge_fields(
$merge_fields,
$this->get_trigger_value($trigger)
);
$message = clear_textarea_breaks($message);
static::$trigger_being_sent = $trigger;
$retval = $this->ci->{$className}->send($phone, $message, $trigger);
hooks()->do_action('sms_trigger_triggered', ['message' => $message, 'trigger' => $trigger, 'phone' => $phone]);
static::$trigger_being_sent = null;
return $retval;
}
}
return false;
}
/**
* Parse sms gateway merge fields
* We will use the email templates merge fields function because they are the same
* @param array $merge_fields merge fields
* @param string $message the message to bind the merge fields
* @return string
*/
public function parse_merge_fields($merge_fields, $message)
{
$template = new stdClass();
$template->message = $message;
$template->subject = '';
$template->fromname = '';
return parse_email_template_merge_fields($template, $merge_fields)->message;
}
public function option_name($id, $option)
{
return 'sms_' . $id . '_' . $option;
}
public function trigger_option_name($trigger)
{
return 'sms_trigger_' . $trigger;
}
public function is_any_trigger_active()
{
$triggers = $this->get_available_triggers();
$active = false;
foreach ($triggers as $trigger_id => $trigger_opts) {
if ($this->_is_trigger_message_empty($this->get_trigger_value($trigger_id))) {
$active = true;
break;
}
}
return $active;
}
protected function set_error($error, $log_message = true)
{
$GLOBALS['sms_error'] = $error;
if ($log_message) {
log_activity('Failed to send SMS via ' . get_class($this) . ': ' . $error);
}
return $this;
}
private function _is_trigger_message_empty($message)
{
if (trim($message) === '') {
return false;
}
return true;
}
public function is_trigger_active($trigger)
{
if ($trigger != '') {
if (!$this->_is_trigger_message_empty($this->get_trigger_value($trigger))) {
return false;
}
} else {
return $this->is_any_trigger_active();
}
return true;
}
public function get_active_gateway()
{
$active = false;
foreach (self::$gateways as $gateway) {
if ($this->get_option($gateway['id'], 'active') == '1') {
$active = $gateway;
break;
}
}
return $active;
}
/**
* Check if is settings page in admin area
* @return boolean
*/
private function is_options_page()
{
return $this->ci->input->get('group') == 'sms' && $this->ci->uri->segment(2) == 'settings';
}
/**
* Check if sms gateway is initialized and options are added into database
* @return boolean
*/
private function is_initialized($id)
{
return $this->get_option($id, 'initialized') == '' ? false : true;
}
/**
* Log success message
*
* @param string $number
* @param string $message
*
* @return void
*/
protected function logSuccess($number, $message)
{
return log_activity('SMS sent to ' . $number . ', Message: ' . $message);
}
private function set_default_triggers()
{
$customer_merge_fields = [
'{contact_firstname}',
'{contact_lastname}',
'{client_company}',
'{client_vat_number}',
'{client_id}',
];
$invoice_merge_fields = [
'{invoice_link}',
'{invoice_number}',
'{invoice_duedate}',
'{invoice_date}',
'{invoice_status}',
'{invoice_subtotal}',
'{invoice_total}',
'{invoice_amount_due}',
'{invoice_short_url}',
];
$proposal_merge_fields = [
'{proposal_number}',
'{proposal_id}',
'{proposal_subject}',
'{proposal_date}',
'{proposal_open_till}',
'{proposal_subtotal}',
'{proposal_total}',
'{proposal_proposal_to}',
'{proposal_link}',
'{proposal_short_url}',
];
$contract_merge_fields = [
'{contract_id}',
'{contract_subject}',
'{contract_datestart}',
'{contract_dateend}',
'{contract_contract_value}',
'{contract_link}',
'{contract_short_url}',
];
$triggers = [
SMS_TRIGGER_INVOICE_OVERDUE => [
'merge_fields' => array_merge($customer_merge_fields, $invoice_merge_fields, ['{total_days_overdue}']),
'label' => 'Invoice Overdue Notice',
'info' => 'Trigger when invoice overdue notice is sent to customer contacts.',
],
SMS_TRIGGER_INVOICE_DUE => [
'merge_fields' => array_merge($customer_merge_fields, $invoice_merge_fields),
'label' => 'Invoice Due Notice',
'info' => 'Trigger when invoice due notice is sent to customer contacts.',
],
SMS_TRIGGER_PAYMENT_RECORDED => [
'merge_fields' => array_merge($customer_merge_fields, $invoice_merge_fields, ['{payment_total}', '{payment_date}']),
'label' => 'Invoice Payment Recorded',
'info' => 'Trigger when invoice payment is recorded.',
],
SMS_TRIGGER_ESTIMATE_EXP_REMINDER => [
'merge_fields' => array_merge(
$customer_merge_fields,
[
'{estimate_link}',
'{estimate_number}',
'{estimate_date}',
'{estimate_status}',
'{estimate_subtotal}',
'{estimate_total}',
'{estimate_short_url}',
]
),
'label' => 'Estimate Expiration Reminder',
'info' => 'Trigger when expiration reminder should be send to customer contacts.',
],
SMS_TRIGGER_PROPOSAL_EXP_REMINDER => [
'merge_fields' => $proposal_merge_fields,
'label' => 'Proposal Expiration Reminder',
'info' => 'Trigger when expiration reminder should be send to proposal.',
],
SMS_TRIGGER_PROPOSAL_NEW_COMMENT_TO_CUSTOMER => [
'merge_fields' => $proposal_merge_fields,
'label' => 'New Comment on Proposal (to customer)',
'info' => 'Trigger when staff member comments on proposal, SMS will be sent to proposal number (customer/lead).',
],
SMS_TRIGGER_PROPOSAL_NEW_COMMENT_TO_STAFF => [
'merge_fields' => $proposal_merge_fields,
'label' => 'New Comment on Proposal (to staff)',
'info' => 'Trigger when customer/lead comments on proposal, SMS will be sent to proposal creator and assigned staff member.',
],
SMS_TRIGGER_CONTRACT_NEW_COMMENT_TO_CUSTOMER => [
'merge_fields' => array_merge($customer_merge_fields, $contract_merge_fields),
'label' => 'New Comment on Contract (to customer)',
'info' => 'Trigger when staff member add comment to contract, SMS will be sent customer contacts.',
],
SMS_TRIGGER_CONTRACT_NEW_COMMENT_TO_STAFF => [
'merge_fields' => $contract_merge_fields,
'label' => 'New Comment on Contract (to staff)',
'info' => 'Trigger when customer add comment to contract, SMS will be sent to contract creator.',
],
SMS_TRIGGER_CONTRACT_EXP_REMINDER => [
'merge_fields' => array_merge($customer_merge_fields, $contract_merge_fields),
'label' => 'Contract Expiration Reminder',
'info' => 'Trigger when expiration reminder should be send via Cron Job to customer contacts.',
],
SMS_TRIGGER_CONTRACT_SIGN_REMINDER => [
'merge_fields' => array_merge($customer_merge_fields, $contract_merge_fields),
'label' => 'Contract Sign Reminder',
'info' => 'Trigger when the contract is first time sent to the customer and automatically stopped when the contract is signed.',
],
SMS_TRIGGER_STAFF_REMINDER => [
'merge_fields' => [
'{staff_firstname}',
'{staff_lastname}',
'{staff_reminder_description}',
'{staff_reminder_date}',
'{staff_reminder_relation_name}',
'{staff_reminder_relation_link}',
],
'label' => 'Staff Reminder',
'info' => 'Trigger when staff is notified for a specific custom <a href="' . admin_url('misc/reminders') . '">reminder</a>.',
],
];
$this->triggers = hooks()->apply_filters('sms_triggers', $triggers);
}
}