Commit 2f4ff362 authored by Adam Kwiatkowski's avatar Adam Kwiatkowski
Browse files

Initial commit

parents
File added
<?php
require_once "messagemedia/vendor/autoload.php";
use MessageMediaMessagesLib\Models;
use MessageMediaMessagesLib\Exceptions;
require_once "packages/phonenumber/src/PhoneNumber.php";
require_once "packages/phonenumber/vendor/autoload.php";
use Brick\PhoneNumber\PhoneNumber;
use Brick\PhoneNumber\PhoneNumberParseException;
/**
*
* @package CRM
* @copyright LLC (c) 2019-2020
* $Id$
*
*/
class au_com_devapp_messagemedia extends CRM_SMS_Provider {
/**
* api type to use to send a message
* @var string
*/
protected $_apiType = 'http';
/**
* provider details
* @var string
*/
protected $_providerInfo = [];
/**
* Curl handle resource id
*
*/
protected $_ch;
public $_apiURL = '';
/**
* We only need one instance of this object. So we use the singleton
* pattern and cache the instance in this variable
*
* @var object
* @static
*/
static private $_singleton = [];
/**
* Constructor
*
* Create and auth a Media Message session.
*
* @param array $provider
* @param bool $skipAuth
*
* @return void
*/
public function __construct($provider = [], $skipAuth = FALSE) {
// initialize vars
$this->_apiType = CRM_Utils_Array::value('api_type', $provider, 'http');
$this->_providerInfo = $provider;
if ($skipAuth) {
return TRUE;
}
}
/**
* singleton function used to manage this object.
*
* @param array $providerParams
* @param bool $force
*
* @return object
* @static
*/
public static function &singleton($providerParams = [], $force = FALSE) {
$providerID = CRM_Utils_Array::value('provider_id', $providerParams);
$skipAuth = $providerID ? FALSE : TRUE;
$cacheKey = (int) $providerID;
if (!isset(self::$_singleton[$cacheKey]) || $force) {
$provider = [];
if ($providerID) {
$provider = CRM_SMS_BAO_Provider::getProviderInfo($providerID);
}
self::$_singleton[$cacheKey] = new au_com_devapp_messagemedia(
$provider,
$skipAuth
);
}
return self::$_singleton[$cacheKey];
}
/**
* Send SMS.
*
* @param array $header
* @param string $message
*
* @return object
* @access public
*/
public function sendSMS($recipient, $header, $message) {
$authUserName = $this->_providerInfo['username'];
$authPassword = $this->_providerInfo['password'];
/* You can change this to true when the above keys are HMAC */
$useHmacAuthentication = FALSE;
$client = new MessageMediaMessagesLib\MessageMediaMessagesClient(
$authUserName,
$authPassword,
$useHmacAuthentication
);
$messagesController = $client->getMessages();
$body = new Models\SendMessagesRequest;
$body->messages = [];
$body->messages[0] = new Models\Message;
if (isset($this->_providerInfo['api_params']['From'])) {
$body->messages[0]->sourceNumber = $this->_providerInfo['api_params']['From'];
$body->messages[0]->sourceNumberType = Models\SourceNumberTypeEnum::INTERNATIONAL;
}
$body->messages[0]->destinationNumber = $recipient;
$body->messages[0]->content = $message;
$body->messages[0]->metadata = [
'contact_id' => $header['contact_id'],
'parent_activity_id' => $header['parent_activity_id'],
];
$body->messages[0]->deliveryReport = TRUE;
/*
$body->messages[0]->callbackUrl = CRM_Utils_System::url(
'civicrm/sms/callback',
'provider=au.com.devapp.messagemedia',
TRUE
);
*/
$response = $messagesController->sendMessages($body);
return $response;
}
public function formatPhoneNumber(&$recipient, $params) {
try {
$defaultCountryISO = CRM_Core_BAO_Country::defaultContactCountry();
if ($defaultCountryISO == 'AU' && strpos($recipient, '04') === 0) {
// Do nothing
}
else {
$this->getContactCountry($defaultCountryISO, $params['contact_id']);
}
$recipient = PhoneNumber::parse($recipient, $defaultCountryISO)->__toString();
}
catch (PhoneNumberParseException $e) {
throw new Exception(ts('Invalid phone number.'));
}
}
public function getContactCountry(&$defaultCountryISO, $contactId) {
try {
$result = civicrm_api3('Address', 'getvalue', [
'return' => 'country_id.iso_code',
'contact_id' => $contactId,
'is_primary' => 1,
]);
$defaultCountryISO = $result;
}
catch (Exception $e) {
}
}
/**
* Send an SMS Message via the API Server.
*
* @param array $recipient
* @param string $header
* @param string $message
* @param int $jobID
*/
public function send($recipient, $header, $message, $jobID = NULL) {
try {
$this->formatPhoneNumber($recipient, $header);
if (array_key_exists('is_test', $this->_providerInfo['api_params'])
&& $this->_providerInfo['api_params']['is_test'] == 1
) {
$responses = ['data' => 'Your message is successfully sent to:' . rand()];
}
else {
$error = '';
$responses = NULL;
try {
$responses = $this->sendSMS($recipient, $header, $message);
}
catch (Exceptions\SendMessages400Response $e) {
$error = 'Caught SendMessages400Response: ' . $e->getMessage();
}
catch (MessageMediaMessagesLib\APIException $e) {
$error = 'Caught APIException: ' . $e->getMessage();
}
}
}
catch (Exception $e) {
$error = $e->getMessage();
}
if (!empty($responses)) {
$messageId = $responses->messages[0]->messageId;
$activity = $this->createActivity($messageId, $message, $header, $jobID);
$success[] = ts("Successfully delivered to {$recipient}.");
if (!empty($header['parent_activity_id'])) {
civicrm_api3('Activity', 'create', [
'parent_id' => $header['parent_activity_id'],
'id' => $activity->id,
]);
}
}
elseif (!empty($error)) {
if (!empty($header['parent_activity_id'])) {
civicrm_api3('Activity', 'create', [
'id' => $header['parent_activity_id'],
'status_id' => 'Cancelled',
'details' => sprintf($error),
]);
$targetID = CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_ActivityContact', 'record_type_id', 'Activity Targets');
$activityTargetParams = [
'activity_id' => $header['parent_activity_id'],
'contact_id' => $header['contact_id'],
'record_type_id' => $targetID,
];
CRM_Activity_BAO_ActivityContact::create($activityTargetParams);
}
return PEAR::raiseError($error, NULL, PEAR_ERROR_RETURN);
}
return TRUE;
}
/**
* Process Inbound sms.
*
*/
public function inbound() {
$like = "";
$fromPhone = $this->retrieve('from', 'String');
$fromPhone = $this->formatPhone($this->stripPhone($fromPhone), $like, "like");
$to = $this->retrieve('to', 'String');
$to = $this->formatPhone($this->stripPhone($to), $like, "like");
$message = $this->retrieve('message', 'String');
$refId = $this->retrieve('ref', 'String');
return parent::processInbound($fromPhone, $message, $to, $refId);
}
}
<?xml version="1.0"?>
<extension key="au.com.devapp.messagemedia" type="module">
<file>messagemedia</file>
<name>Message Media SMS</name>
<description>SMS Integration with Message Media</description>
<license>AGPL-3.0</license>
<maintainer>
<author>DevApp</author>
<email>civicrm@devapp.com.au</email>
</maintainer>
<urls>
<url desc="Main Extension Page">https://www.devapp.com.au</url>
<url desc="Documentation">https://www.devapp.com.au</url>
<url desc="Support">https://www.devapp.com.au</url>
<url desc="Licensing">http://www.gnu.org/licenses/agpl-3.0.html</url>
</urls>
<releaseDate>2019-06-22</releaseDate>
<version>1.0</version>
<develStage>stable</develStage>
<compatibility>
<ver>5.13</ver>
</compatibility>
<comments>Requires MessageMedia Account from https://messagemedia.com/au/civicrm/</comments>
<civix>
<namespace>CRM/MessageMedia</namespace>
</civix>
</extension>
<?php
// AUTO-GENERATED FILE -- Civix may overwrite any changes made to this file
/**
* The ExtensionUtil class provides small stubs for accessing resources of this
* extension.
*/
class CRM_Messagemedia_ExtensionUtil {
const SHORT_NAME = "messagemedia";
const LONG_NAME = "au.com.devapp.messagemedia";
const CLASS_PREFIX = "CRM_Messagemedia";
/**
* Translate a string using the extension's domain.
*
* If the extension doesn't have a specific translation
* for the string, fallback to the default translations.
*
* @param string $text
* Canonical message text (generally en_US).
* @param array $params
* @return string
* Translated text.
* @see ts
*/
public static function ts($text, $params = array()) {
if (!array_key_exists('domain', $params)) {
$params['domain'] = array(self::LONG_NAME, NULL);
}
return ts($text, $params);
}
/**
* Get the URL of a resource file (in this extension).
*
* @param string|NULL $file
* Ex: NULL.
* Ex: 'css/foo.css'.
* @return string
* Ex: 'http://example.org/sites/default/ext/org.example.foo'.
* Ex: 'http://example.org/sites/default/ext/org.example.foo/css/foo.css'.
*/
public static function url($file = NULL) {
if ($file === NULL) {
return rtrim(CRM_Core_Resources::singleton()->getUrl(self::LONG_NAME), '/');
}
return CRM_Core_Resources::singleton()->getUrl(self::LONG_NAME, $file);
}
/**
* Get the path of a resource file (in this extension).
*
* @param string|NULL $file
* Ex: NULL.
* Ex: 'css/foo.css'.
* @return string
* Ex: '/var/www/example.org/sites/default/ext/org.example.foo'.
* Ex: '/var/www/example.org/sites/default/ext/org.example.foo/css/foo.css'.
*/
public static function path($file = NULL) {
// return CRM_Core_Resources::singleton()->getPath(self::LONG_NAME, $file);
return __DIR__ . ($file === NULL ? '' : (DIRECTORY_SEPARATOR . $file));
}
/**
* Get the name of a class within this extension.
*
* @param string $suffix
* Ex: 'Page_HelloWorld' or 'Page\\HelloWorld'.
* @return string
* Ex: 'CRM_Foo_Page_HelloWorld'.
*/
public static function findClass($suffix) {
return self::CLASS_PREFIX . '_' . str_replace('\\', '_', $suffix);
}
}
use CRM_Messagemedia_ExtensionUtil as E;
/**
* (Delegated) Implements hook_civicrm_config().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_config
*/
function _messagemedia_civix_civicrm_config(&$config = NULL) {
static $configured = FALSE;
if ($configured) {
return;
}
$configured = TRUE;
$template =& CRM_Core_Smarty::singleton();
$extRoot = dirname(__FILE__) . DIRECTORY_SEPARATOR;
$extDir = $extRoot . 'templates';
if (is_array($template->template_dir)) {
array_unshift($template->template_dir, $extDir);
}
else {
$template->template_dir = array($extDir, $template->template_dir);
}
$include_path = $extRoot . PATH_SEPARATOR . get_include_path();
set_include_path($include_path);
}
/**
* (Delegated) Implements hook_civicrm_xmlMenu().
*
* @param $files array(string)
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_xmlMenu
*/
function _messagemedia_civix_civicrm_xmlMenu(&$files) {
foreach (_messagemedia_civix_glob(__DIR__ . '/xml/Menu/*.xml') as $file) {
$files[] = $file;
}
}
/**
* Implements hook_civicrm_install().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_install
*/
function _messagemedia_civix_civicrm_install() {
_messagemedia_civix_civicrm_config();
if ($upgrader = _messagemedia_civix_upgrader()) {
$upgrader->onInstall();
}
}
/**
* Implements hook_civicrm_postInstall().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_postInstall
*/
function _messagemedia_civix_civicrm_postInstall() {
_messagemedia_civix_civicrm_config();
if ($upgrader = _messagemedia_civix_upgrader()) {
if (is_callable(array($upgrader, 'onPostInstall'))) {
$upgrader->onPostInstall();
}
}
}
/**
* Implements hook_civicrm_uninstall().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_uninstall
*/
function _messagemedia_civix_civicrm_uninstall() {
_messagemedia_civix_civicrm_config();
if ($upgrader = _messagemedia_civix_upgrader()) {
$upgrader->onUninstall();
}
}
/**
* (Delegated) Implements hook_civicrm_enable().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_enable
*/
function _messagemedia_civix_civicrm_enable() {
_messagemedia_civix_civicrm_config();
if ($upgrader = _messagemedia_civix_upgrader()) {
if (is_callable(array($upgrader, 'onEnable'))) {
$upgrader->onEnable();
}
}
}
/**
* (Delegated) Implements hook_civicrm_disable().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_disable
* @return mixed
*/
function _messagemedia_civix_civicrm_disable() {
_messagemedia_civix_civicrm_config();
if ($upgrader = _messagemedia_civix_upgrader()) {
if (is_callable(array($upgrader, 'onDisable'))) {
$upgrader->onDisable();
}
}
}
/**
* (Delegated) Implements hook_civicrm_upgrade().
*
* @param $op string, the type of operation being performed; 'check' or 'enqueue'
* @param $queue CRM_Queue_Queue, (for 'enqueue') the modifiable list of pending up upgrade tasks
*
* @return mixed based on op. for 'check', returns array(boolean) (TRUE if upgrades are pending)
* for 'enqueue', returns void
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_upgrade
*/
function _messagemedia_civix_civicrm_upgrade($op, CRM_Queue_Queue $queue = NULL) {
if ($upgrader = _messagemedia_civix_upgrader()) {
return $upgrader->onUpgrade($op, $queue);
}
}
/**
* @return CRM_Messagemedia_Upgrader
*/
function _messagemedia_civix_upgrader() {
if (!file_exists(__DIR__ . '/CRM/Messagemedia/Upgrader.php')) {
return NULL;
}
else {
return CRM_Messagemedia_Upgrader_Base::instance();
}
}
/**
* Search directory tree for files which match a glob pattern
*
* Note: Dot-directories (like "..", ".git", or ".svn") will be ignored.
* Note: In Civi 4.3+, delegate to CRM_Utils_File::findFiles()
*
* @param $dir string, base dir
* @param $pattern string, glob pattern, eg "*.txt"
* @return array(string)
*/
function _messagemedia_civix_find_files($dir, $pattern) {
if (is_callable(array('CRM_Utils_File', 'findFiles'))) {
return CRM_Utils_File::findFiles($dir, $pattern);
}
$todos = array($dir);
$result = array();
while (!empty($todos)) {
$subdir = array_shift($todos);
foreach (_messagemedia_civix_glob("$subdir/$pattern") as $match) {
if (!is_dir($match)) {
$result[] = $match;
}
}
if ($dh = opendir($subdir)) {
while (FALSE !== ($entry = readdir($dh))) {
$path = $subdir . DIRECTORY_SEPARATOR . $entry;
if ($entry{0} == '.') {
}
elseif (is_dir($path)) {
$todos[] = $path;
}
}
closedir($dh);
}
}
return $result;
}
/**
* (Delegated) Implements hook_civicrm_managed().
*
* Find any *.mgd.php files, merge their content, and return.
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_managed
*/
function _messagemedia_civix_civicrm_managed(&$entities) {
$mgdFiles = _messagemedia_civix_find_files(__DIR__, '*.mgd.php');
foreach ($mgdFiles as $file) {
$es = include $file;
foreach ($es as $e) {
if (empty($e['module'])) {
$e['module'] = E::LONG_NAME;
}
$entities[] = $e;
if (empty($e['params']['version'])) {
$e['params']['version'] = '3';
}
}
}
}
/**
* (Delegated) Implements hook_civicrm_caseTypes().
*
* Find any and return any files matching "xml/case/*.xml"
*
* Note: This hook only runs in CiviCRM 4.4+.
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_caseTypes
*/
function _messagemedia_civix_civicrm_caseTypes(&$caseTypes) {
if (!is_dir(__DIR__ . '/xml/case')) {
return;
}
foreach (_messagemedia_civix_glob(__DIR__ . '/xml/case/*.xml') as $file) {
$name = preg_replace('/\.xml$/', '', basename($file));
if ($name != CRM_Case_XMLProcessor::mungeCaseType($name)) {
$errorMessage = sprintf("Case-type file name is malformed (%s vs %s)", $name, CRM_Case_XMLProcessor::mungeCaseType($name));
CRM_Core_Error::fatal($errorMessage);
// throw new CRM_Core_Exception($errorMessage);
}
$caseTypes[$name] = array(
'module' => E::LONG_NAME,
'name' => $name,
'file' => $file,
);
}
}
/**
* (Delegated) Implements hook_civicrm_angularModules().
*
* Find any and return any files matching "ang/*.ang.php"
*
* Note: This hook only runs in CiviCRM 4.5+.
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_angularModules
*/
function _messagemedia_civix_civicrm_angularModules(&$angularModules) {
if (!is_dir(__DIR__ . '/ang')) {
return;
}
$files = _messagemedia_civix_glob(__DIR__ . '/ang/*.ang.php');
foreach ($files as $file) {
$name = preg_replace(':\.ang\.php$:', '', basename($file));
$module = include $file;