Просмотр исходного кода

Ticket #4857 - Objects system for SMS sending (Twilio).

AntonLV 1 год назад
Родитель
Сommit
a70bb5e422

+ 48 - 0
inc/classes/BxDolSms.php

@@ -0,0 +1,48 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaCore UNA Core
+ * @{
+ */
+
+class BxDolSms extends BxDolFactoryObject
+{
+    protected function __construct($aObject, $oTemplate = null, $sDbClassName = 'BxDolSmsQuery')
+    {
+        parent::__construct($aObject, $oTemplate, $sDbClassName);
+    }
+
+    /**
+     * Get SMS provider object instance by object name
+     * @param $sObject object name
+     * @return object instance or false on error
+     */
+    static public function getObjectInstance($sObject = false, $oTemplate = false)
+    {
+        if(!$sObject)
+            $sObject = getParam('sys_sms_default');
+        if(!$sObject)
+            return false;
+
+        return parent::getObjectInstanceByClassNames($sObject, $oTemplate, 'BxDolSms', 'BxDolSmsQuery');
+    }
+
+    public function normalizePhone($sPhone){
+        $sPhone = trim($sPhone);
+        if(substr($sPhone, 0, 1) != '+')
+            $sPhone = '+' . $sPhone;
+
+        return $sPhone;
+    }
+
+    public function send($sTo, $sMessage, $sFrom = '') {}
+
+    protected function _writeLog($sString)
+    {
+        bx_log('sys_sms', $sString);
+    }
+}
+
+/** @} */

+ 27 - 0
inc/classes/BxDolSmsQuery.php

@@ -0,0 +1,27 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaCore UNA Core
+ * @{
+ */
+
+/**
+ * Database queries for SMS objects.
+ * @see BxDolSms
+ */
+class BxDolSmsQuery extends BxDolFactoryObjectQuery
+{
+    static public function getObject($sObject)
+    {
+        return parent::getObjectFromTable($sObject, 'sys_objects_sms');
+    }
+
+    static public function getObjects ()
+    {
+        return parent::getObjectsFromTable('sys_objects_sms');
+    }
+}
+
+/** @} */

+ 46 - 0
inc/classes/BxDolSmsTwilio.php

@@ -0,0 +1,46 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaCore UNA Core
+ * @{
+ */
+
+require_once BX_DIRECTORY_PATH_PLUGINS . 'twilio/sdk/src/Twilio/autoload.php';
+
+class BxDolSmsTwilio extends BxDolSms
+{
+    protected $_sSid;
+    protected $_sToken;
+    protected $_sFromNumber;
+
+    protected function __construct($aObject, $oTemplate = null, $sDbClassName = '')
+    {
+        parent::__construct($aObject, $oTemplate, $sDbClassName);
+
+        $this->_sSid = getParam('sys_sms_twilio_sid');
+        $this->_sToken = getParam('sys_sms_twilio_token');
+        $this->_sFromNumber = getParam('sys_sms_twilio_from_number');
+    }
+
+    public function send($sTo, $sMessage, $sFrom = '')
+    {
+        try {
+            $oClient = new Twilio\Rest\Client($this->_sSid, $this->_sToken);
+            $oClient->messages->create($this->normalizePhone($sTo), [
+                'body' => $sMessage, 
+                'from' => $sFrom != '' ? $this->normalizePhone($sFrom) : $this->normalizePhone($this->_sFromNumber)
+            ]);
+
+            return true;
+        }
+        catch (Exception $oException) {
+            $this->_writeLog($oException->getFile() . ':' . $oException->getLine() . ' ' . $oException->getMessage());
+
+            return false;
+        }
+    }
+}
+
+/** @} */

+ 0 - 78
inc/classes/BxDolTwilio.php

@@ -1,78 +0,0 @@
-<?php defined('BX_DOL') or die('hack attempt');
-/**
- * Copyright (c) UNA, Inc - https://una.io
- * MIT License - https://opensource.org/licenses/MIT
- *
- * @defgroup    UnaCore UNA Core
- * @{
- */
-
-require_once BX_DIRECTORY_PATH_PLUGINS . 'twilio/sdk/src/Twilio/autoload.php';
-
-class BxDolTwilio extends BxDolFactory implements iBxDolSingleton
-{
-    protected $_sSid;
-    protected $_sToken;
-    protected $_sFromNumber;
-    
-    protected function __construct()
-    {
-        if (isset($GLOBALS['bxDolClasses'][get_class($this)]))
-            trigger_error ('Multiple instances are not allowed for the class: ' . get_class($this), E_USER_ERROR);
-
-        parent::__construct();
-
-        $this->_sSid = getParam('sys_twilio_gate_sid');
-        $this->_sToken = getParam('sys_twilio_gate_token');
-        $this->_sFromNumber = getParam('sys_twilio_gate_from_number');
-    }
-
-    /**
-     * Prevent cloning the instance
-     */
-    public function __clone()
-    {
-        if (isset($GLOBALS['bxDolClasses'][get_class($this)]))
-            trigger_error('Clone is not allowed for the class: ' . get_class($this), E_USER_ERROR);
-    }
-
-    /**
-     * Get singleton instance of the class
-     */
-    public static function getInstance()
-    {
-        if(!isset($GLOBALS['bxDolClasses'][__CLASS__]))
-            $GLOBALS['bxDolClasses'][__CLASS__] = new BxDolTwilio();
-
-        return $GLOBALS['bxDolClasses'][__CLASS__];
-    }
-    
-    public function sendSms($sTo, $sMessage, $sFrom = '')
-    {
-        try {
-            $client = new Twilio\Rest\Client($this->_sSid, $this->_sToken);
-            $aParams = array('body' => $sMessage, 'from' => $sFrom != '' ? $this->normalizePhone($sFrom) : $this->normalizePhone($this->_sFromNumber));
-            $client->messages->create($this->normalizePhone($sTo), $aParams);
-            return true;
-        }
-        catch (Exception $oException) {
-            $this->writeLog($oException->getFile() . ':' . $oException->getLine() . ' ' . $oException->getMessage());
-            return false;
-        }
-    }
-    
-    public function normalizePhone($sPhone){
-		$sPhone = trim($sPhone);
-		if (substr($sPhone, 0, 1) != '+'){
-			$sPhone = '+' . $sPhone;	
-		}
-		return $sPhone;
-	}
-    
-    private function writeLog($sString)
-	{
-        bx_log('sys_twilio', $sString);
-	}
-}
-
-/** @} */

+ 25 - 5
install/sql/system.sql

@@ -76,6 +76,24 @@ CREATE TABLE `sys_objects_push` (
 INSERT INTO `sys_objects_push` (`object`, `title`, `override_class_name`, `override_class_file`) VALUES
 ('sys_onesignal', 'OneSignal', 'BxTemplPushOneSignal', '');
 
+
+-- --------------------------------------------------------
+
+
+CREATE TABLE `sys_objects_sms` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object` varchar(64) NOT NULL,
+  `title` varchar(255) NOT NULL,
+  `override_class_name` varchar(255) NOT NULL,
+  `override_class_file` varchar(255) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `object` (`object`)
+);
+
+INSERT INTO `sys_objects_sms` (`object`, `title`, `override_class_name`, `override_class_file`) VALUES
+('sys_twilio', 'Twilio', 'BxDolSmsTwilio', '');
+
+
 -- --------------------------------------------------------
 
 
@@ -712,13 +730,15 @@ INSERT INTO `sys_options`(`category_id`, `name`, `caption`, `value`, `type`, `ex
 --
 -- CATEGORY: Twilio gate settings
 --
-INSERT INTO `sys_options_categories`(`type_id`, `name`, `caption`, `hidden`, `order`) VALUES (@iTypeId, 'twilio_gate', '_adm_stg_cpt_category_twilio_gate', 0, 18);
+INSERT INTO `sys_options_categories`(`type_id`, `name`, `caption`, `hidden`, `order`) VALUES (@iTypeId, 'sms', '_adm_stg_cpt_category_sms', 0, 18);
 SET @iCategoryId = LAST_INSERT_ID();
 
 INSERT INTO `sys_options`(`category_id`, `name`, `caption`, `value`, `type`, `extra`, `check`, `check_error`, `order`) VALUES
-(@iCategoryId, 'sys_twilio_gate_sid', '_adm_stg_cpt_option_sys_twilio_gate_sid', '', 'digit', '', '', '', 1),
-(@iCategoryId, 'sys_twilio_gate_token', '_adm_stg_cpt_option_sys_twilio_gate_token', '', 'digit', '', '', '', 2),
-(@iCategoryId, 'sys_twilio_gate_from_number', '_adm_stg_cpt_option_sys_twilio_gate_from_number', '', 'digit', '', '', '', 3);
+(@iCategoryId, 'sys_sms_default', '_adm_stg_cpt_option_sys_sms_default', '', 'select', 'a:3:{s:6:"module";s:6:"system";s:6:"method";s:23:"get_options_sms_default";s:5:"class";s:13:"TemplServices";}', '', '', 1),
+
+(@iCategoryId, 'sys_sms_twilio_sid', '_adm_stg_cpt_option_sys_sms_twilio_sid', '', 'digit', '', '', '', 11),
+(@iCategoryId, 'sys_sms_twilio_token', '_adm_stg_cpt_option_sys_sms_twilio_token', '', 'digit', '', '', '', 12),
+(@iCategoryId, 'sys_sms_twilio_from_number', '_adm_stg_cpt_option_sys_sms_twilio_from_number', '', 'digit', '', '', '', 13);
 
 
 --
@@ -6299,7 +6319,7 @@ CREATE TABLE `sys_objects_logs` (
 
 INSERT INTO `sys_objects_logs` (`object`, `module`, `logs_storage`, `title`, `active`, `class_name`, `class_file`) VALUES
 ('sys_debug', 'system', 'Auto', '_sys_log_debug', 1, '', ''),
-('sys_twilio', 'system', 'Auto', '_sys_log_twilio', 1, '', ''),
+('sys_sms', 'system', 'Auto', '_sys_log_sms', 1, '', ''),
 ('sys_push', 'system', 'Auto', '_sys_log_push', 1, '', ''),
 ('sys_payments', 'system', 'Auto', '_sys_log_payments', 1, '', ''),
 ('sys_cron_jobs', 'system', 'Auto', '_sys_log_cron_jobs', 0, '', ''),

+ 2 - 3
member.php

@@ -51,9 +51,8 @@ if (isset($_POST['ID'])) { // login form is submitted
         $sId = trim($oForm->getCleanValue('ID'));
         $oAccount = BxDolAccount::getInstance($sId);
         $aAccountInfo = $oAccount->getInfo();
-        if (
-            (getParam('sys_account_activation_2fa_enable') == 'on' && getParam('sys_twilio_gate_sid') != '' && getParam('sys_twilio_gate_token') != '' && getParam('sys_twilio_gate_from_number') != '') 
-            && (getParam('sys_account_activation_2fa_lifetime') == 0 || (time() - $aAccountInfo['logged'] > getParam('sys_account_activation_2fa_lifetime')))){
+        if((getParam('sys_account_activation_2fa_enable') == 'on' && getParam('sys_sms_default') != '') 
+            && (getParam('sys_account_activation_2fa_lifetime') == 0 || (time() - $aAccountInfo['logged'] > getParam('sys_account_activation_2fa_lifetime')))) {
             $oSession = BxDolSession::getInstance();
             $oSession->setValue(BX_ACCOUNT_SESSION_KEY_FOR_2FA_LOGIN_ACCOUNT_ID, trim($oForm->getCleanValue('ID')));
             $oSession->setValue(BX_ACCOUNT_SESSION_KEY_FOR_2FA_LOGIN_IS_REMEMBER, $oForm->getRememberMe());

+ 11 - 11
modules/boonex/english/data/langs/system/en.xml

@@ -1529,7 +1529,7 @@
     <string name="_adm_stg_cpt_category_storage"><![CDATA[Storage]]></string>
     <string name="_adm_stg_cpt_category_system"><![CDATA[System]]></string>
     <string name="_adm_stg_cpt_category_templates"><![CDATA[Templates]]></string>
-    <string name="_adm_stg_cpt_category_twilio_gate"><![CDATA[Twilio]]></string>
+    <string name="_adm_stg_cpt_category_sms"><![CDATA[SMS Sending]]></string>
     <string name="_adm_stg_cpt_category_location"><![CDATA[Location]]></string>
     <string name="_adm_stg_cpt_category_social_settings"><![CDATA[Social]]></string>
     <string name="_adm_stg_cpt_category_api_general"><![CDATA[General]]></string>
@@ -1676,7 +1676,6 @@
     <string name="_adm_stg_cpt_option_sys_per_page_search_keyword_plural"><![CDATA[Site Search Results]]></string>
     <string name="_adm_stg_inf_option_sys_per_page_search_keyword_plural"><![CDATA[Set the maximum number of results displayed per page in Site Search]]></string>
     <string name="_adm_stg_cpt_option_sys_push_default"><![CDATA[Provider]]></string>
-    
     <string name="_adm_stg_cpt_option_sys_push_app_id"><![CDATA[OneSignal App ID]]></string>
     <string name="_adm_stg_cpt_option_sys_push_rest_api"><![CDATA[REST API Key]]></string>
     <string name="_adm_stg_cpt_option_sys_push_short_name"><![CDATA[Short name (required only for http sites. It must match the Subdomain you entered on the Web Push settings on the OneSignal dashboard)]]></string>
@@ -1684,9 +1683,10 @@
     <string name="_adm_stg_cpt_option_sys_push_queue_time"><![CDATA[Push queue execution flag]]></string>
     <string name="_adm_stg_cpt_option_sys_push_queue_send_per_start"><![CDATA[Number of messages to send from Push queue per run]]></string>
     <string name="_adm_stg_cpt_option_sys_push_queue_send_per_start_to_recipient"><![CDATA[Number of messages to send from Push queue per run to some recipient]]></string>
-    <string name="_adm_stg_cpt_option_sys_twilio_gate_sid"><![CDATA[Account SID]]></string>
-    <string name="_adm_stg_cpt_option_sys_twilio_gate_token"><![CDATA[Auth token]]></string>
-    <string name="_adm_stg_cpt_option_sys_twilio_gate_from_number"><![CDATA[Default 'From' number for SMS]]></string>    
+    <string name="_adm_stg_cpt_option_sys_sms_default"><![CDATA[Provider]]></string>
+    <string name="_adm_stg_cpt_option_sys_sms_twilio_sid"><![CDATA[Twilio: Account SID]]></string>
+    <string name="_adm_stg_cpt_option_sys_sms_twilio_token"><![CDATA[Twilio: Auth token]]></string>
+    <string name="_adm_stg_cpt_option_sys_sms_twilio_from_number"><![CDATA[Twilio: Default 'From' number for SMS]]></string>    
     <string name="_adm_stg_cpt_option_sys_nominatim_server"><![CDATA[Nominatim server URL]]></string>    
     <string name="_adm_stg_cpt_option_sys_nominatim_email"><![CDATA[Nominatim email to identify requests]]></string>
     <string name="_adm_stg_cpt_option_sys_recaptcha_key_private"><![CDATA[reCAPTCHA/hCaptcha private key]]></string>
@@ -3098,7 +3098,7 @@ If it is not enabled then please consider implement this optimization, since it
 	<string name="_sys_loading"><![CDATA[Loading...]]></string>
 	<string name="_sys_location_country"><![CDATA[<i class="sys-icon location-arrow"></i> {0}]]></string>
 	<string name="_sys_location_country_city"><![CDATA[<i class="sys-icon location-arrow"></i> {2}, {1}, {0}]]></string>
-    <string name="_sys_location_country_city_street"><![CDATA[<i class="sys-icon location-arrow"></i> {4} {3}, {2}, {1}, {0} ]]></string>
+        <string name="_sys_location_country_city_street"><![CDATA[<i class="sys-icon location-arrow"></i> {4} {3}, {2}, {1}, {0} ]]></string>
 	<string name="_sys_location_determining"><![CDATA[Determining location...]]></string>
 	<string name="_sys_location_geolocation_not_supported_by_browser"><![CDATA[Geolocation is not supported by this browser]]></string>
 	<string name="_sys_location_undefined"><![CDATA[Location undefined]]></string>
@@ -3115,12 +3115,12 @@ If it is not enabled then please consider implement this optimization, since it
     <string name="_sys_location_status_undef"><![CDATA[Address is undefined]]></string>
     <string name="_sys_location_status_ok"><![CDATA[Address found]]></string>
     <string name="_sys_location_status_fail"><![CDATA[Address not found]]></string>
-	<string name="_sys_log_debug"><![CDATA[System: debug]]></string>
-    <string name="_sys_log_twilio"><![CDATA[System: Twilio]]></string>
+    <string name="_sys_log_debug"><![CDATA[System: debug]]></string>
+    <string name="_sys_log_sms"><![CDATA[System: SMS]]></string>
     <string name="_sys_log_push"><![CDATA[System: PUSH]]></string>
-	<string name="_sys_log_payments"><![CDATA[System: Payments]]></string>
-	<string name="_sys_log_cron_jobs"><![CDATA[System: Cron jobs]]></string>
-	<string name="_sys_log_transcoder"><![CDATA[System: Transcoder]]></string>
+    <string name="_sys_log_payments"><![CDATA[System: Payments]]></string>
+    <string name="_sys_log_cron_jobs"><![CDATA[System: Cron jobs]]></string>
+    <string name="_sys_log_transcoder"><![CDATA[System: Transcoder]]></string>
     <string name="_sys_macros_malformed"><![CDATA[Error: malformed macros]]></string>
     <string name="_sys_macros_unsafe"><![CDATA[Error: unsafe macros]]></string>
     <string name="_sys_macros_output_not_displayable"><![CDATA[Error: output isn't displayable]]></string>

+ 6 - 5
modules/boonex/russian/data/langs/system/ru.xml

@@ -1506,7 +1506,7 @@
     <string name="_adm_stg_cpt_category_storage"><![CDATA[Дисковое пространство]]></string>
     <string name="_adm_stg_cpt_category_system"><![CDATA[Система]]></string>
     <string name="_adm_stg_cpt_category_templates"><![CDATA[Темы]]></string>
-    <string name="_adm_stg_cpt_category_twilio_gate"><![CDATA[Twilio]]></string>
+    <string name="_adm_stg_cpt_category_sms"><![CDATA[Отправка СМС]]></string>
     <string name="_adm_stg_cpt_category_location"><![CDATA[Местоположение]]></string>
     <string name="_adm_stg_cpt_category_social_settings"><![CDATA[Социальные]]></string>
     <string name="_adm_stg_cpt_category_api_general"><![CDATA[Общие]]></string>
@@ -1659,9 +1659,10 @@
     <string name="_adm_stg_cpt_option_sys_push_queue_time"><![CDATA[Флаг выполнения Push очереди]]></string>
     <string name="_adm_stg_cpt_option_sys_push_queue_send_per_start"><![CDATA[Количество сообщенией, отправляемое из Push очереди при каждом запуске]]></string>
     <string name="_adm_stg_cpt_option_sys_push_queue_send_per_start_to_recipient"><![CDATA[Количество сообщенией, отправляемое из Push очереди одному и тому же получателю при каждом запуске]]></string>
-    <string name="_adm_stg_cpt_option_sys_twilio_gate_sid"><![CDATA[Account SID]]></string>
-    <string name="_adm_stg_cpt_option_sys_twilio_gate_token"><![CDATA[Auth token]]></string>
-    <string name="_adm_stg_cpt_option_sys_twilio_gate_from_number"><![CDATA[Номер для отправки SMS по умолчанию]]></string>
+    <string name="_adm_stg_cpt_option_sys_sms_default"><![CDATA[Поставщик]]></string>
+    <string name="_adm_stg_cpt_option_sys_sms_twilio_sid"><![CDATA[Twilio: SID учетной записи]]></string>
+    <string name="_adm_stg_cpt_option_sys_sms_twilio_token"><![CDATA[Twilio: Токен аутентификации]]></string>
+    <string name="_adm_stg_cpt_option_sys_sms_twilio_from_number"><![CDATA[Twilio: Номер для отправки SMS по умолчанию]]></string>
     <string name="_adm_stg_cpt_option_sys_nominatim_server"><![CDATA[Nominatim сервер (URL)]]></string>    
     <string name="_adm_stg_cpt_option_sys_nominatim_email"><![CDATA[Nominatim Email адрес (чтобы идентифицировать запросы)]]></string>
     <string name="_adm_stg_cpt_option_sys_recaptcha_key_private"><![CDATA[reCAPTCHA/hCaptcha - приватный ключ]]></string>
@@ -3092,7 +3093,7 @@
     <string name="_sys_location_status_ok"><![CDATA[Адрес найден]]></string>
     <string name="_sys_location_status_fail"><![CDATA[Адрес не найден]]></string>
     <string name="_sys_log_debug"><![CDATA[Система: отладка]]></string>
-    <string name="_sys_log_twilio"><![CDATA[Система: Twilio]]></string>
+    <string name="_sys_log_sms"><![CDATA[Система: SMS]]></string>
     <string name="_sys_log_push"><![CDATA[Система: PUSH]]></string>
     <string name="_sys_log_payments"><![CDATA[Система: Платежи]]></string>
     <string name="_sys_log_cron_jobs"><![CDATA[System: Задания Cron]]></string>

+ 11 - 6
template/scripts/BxBaseServiceAccount.php

@@ -459,12 +459,12 @@ class BxBaseServiceAccount extends BxDol
                      * @hook @ref hook-account-before_confirm_phone_send_sms
                      */
                     bx_alert('account', 'before_confirm_phone_send_sms', $oAccount->id(), bx_get_logged_profile_id(), [
-                        'phone_number' => $sPhoneNumber, 
-                        'sms_text' => $sActivationText, 
+                        'phone_number' => &$sPhoneNumber, 
+                        'sms_text' => &$sActivationText, 
                         'override_result' => &$mixedResult
                     ]);
 
-                    if ($mixedResult === null && !BxDolTwilio::getInstance()->sendSms($sPhoneNumber,  $sActivationText))
+                    if ($mixedResult === null && ($oSms = BxDolSms::getObjectInstance()) !== false && !$oSms->send($sPhoneNumber,  $sActivationText))
                         return MsgBox(_t("_sys_txt_confirm_phone_send_sms_error_occured"));
 
                     $oSession->setValue(BX_ACCOUNT_SESSION_KEY_FOR_PHONE_ACTIVATEION_CODE, $sActivationCode);
@@ -652,6 +652,7 @@ class BxBaseServiceAccount extends BxDol
             $oForm->setValid(false);
         }
 
+        $sResultMsg = '';
         if ($oForm->isSubmittedAndValid()) {
             $sEmail = $oForm->getCleanValue('email');
             $sPhone = $oForm->getCleanValue('phone');
@@ -690,10 +691,14 @@ class BxBaseServiceAccount extends BxDol
                  *      - `override_result` - [mixed] by ref, can be object, can be overridden in hook processing
                  * @hook @ref hook-account-before_forgot_password_send_sms
                  */
-                bx_alert('account', 'before_forgot_password_send_sms', $aAccountInfo['id'], false, array('phone_number' => &$sPhone, 'sms_text' => &$sSmsText, 'override_result' => &$mixedOverrideResult));
+                bx_alert('account', 'before_forgot_password_send_sms', $aAccountInfo['id'], false, [
+                    'phone_number' => &$sPhone, 
+                    'sms_text' => &$sSmsText, 
+                    'override_result' => &$mixedOverrideResult
+                ]);
+
                 if ($mixedOverrideResult === null) {
-                    $oTwilio = BxDolTwilio::getInstance();
-                    if($oTwilio->sendSms($sPhone,  $sSmsText))
+                    if(($oSms = BxDolSms::getObjectInstance()) !== false && $oSms->send($sPhone,  $sSmsText))
                         $sResultMsg = MsgBox(_t("_sys_txt_forgot_pasword_check_phone"));
                     else
                         $sResultMsg = MsgBox(_t("_sys_txt_forgot_pasword_error_occured"));

+ 12 - 10
template/scripts/BxBaseServiceLogin.php

@@ -264,8 +264,8 @@ class BxBaseServiceLogin extends BxDol
                 $oAccount->updatePhone($sNewPhoneNumber);
             $sActivationCode = rand(1000, 9999);
             $sActivationText =_t('_sys_txt_login_2fa_sms_text', $sActivationCode);
-            $ret = null;
-            
+
+            $mixedOverrideResult = null;
             /**
              * @hooks
              * @hookdef hook-account-before_2fa_send_sms 'account', 'before_2fa_send_sms' - hook after user performed login
@@ -279,18 +279,20 @@ class BxBaseServiceLogin extends BxDol
              *      - `override_result` - [string] the password after encription, to save in db
              * @hook @ref hook-account-before_2fa_send_sms
              */
-            bx_alert('account', 'before_2fa_send_sms', $oAccount->id(), false, array('phone_number' => $sPhoneNumber, 'sms_text' => $sActivationText, 'override_result' => &$ret));
-            if ($ret === null) 
-            {
-                $oTwilio = BxDolTwilio::getInstance();
-                if(!$oTwilio->sendSms($sNewPhoneNumber, $sActivationText)){
-                    return MsgBox(_t('_sys_txt_login_2fa_sms_error_occured'));
-                }
-            }
+            bx_alert('account', 'before_2fa_send_sms', $oAccount->id(), false, [
+                'phone_number' => &$sPhoneNumber, 
+                'sms_text' => &$sActivationText, 
+                'override_result' => &$mixedOverrideResult
+            ]);
+
+            if($mixedOverrideResult === null && ($oSms = BxDolSms::getObjectInstance()) !== false && !$oSms->sendSms($sNewPhoneNumber, $sActivationText))
+                return MsgBox(_t('_sys_txt_login_2fa_sms_error_occured'));
+
             $oSession = BxDolSession::getInstance();
             $oSession->setValue(BX_ACCOUNT_SESSION_KEY_FOR_PHONE_ACTIVATEION_CODE, $sActivationCode);
             header('Location: ' . bx_absolute_url(BxDolPermalinks::getInstance()->permalink('page.php?i=login-step3')));
         }
+
         return '<div class="bx-def-padding-sec-bottom">' . _t("_sys_txt_login_2fa_description") . '</div>' .$oForm->getCode();
     }
     

+ 13 - 0
template/scripts/BxBaseServices.php

@@ -1262,6 +1262,19 @@ class BxBaseServices extends BxDol implements iBxDolProfileService
         return $aResults;
     }
 
+    public function serviceGetOptionsSmsDefault()
+    {
+        $aResults = [
+            '' => _t('_None')
+        ];
+
+        $aObjects = BxDolSmsQuery::getObjects();
+        foreach($aObjects as $aObject)
+            $aResults[$aObject['object']] = $aObject['title'];
+
+        return $aResults;
+    }
+
     public function serviceGetOptionsSocketsFieldDefault()
     {
         $aResults = [];