Files
crm.clientright.ru/modules/SMSNotifier/SMSNotifier.php
Fedor ac7467f0b4 Major CRM updates: AI Assistant, Court Status API, S3 integration improvements, and extensive file storage system
- Added comprehensive AI Assistant system (aiassist/ directory):
  * Vector search and embedding capabilities
  * Typebot proxy integration
  * Elastic search functionality
  * Message classification and chat history
  * MCP proxy for external integrations

- Implemented Court Status API (GetCourtStatus.php):
  * Real-time court document status checking
  * Integration with external court systems
  * Comprehensive error handling and logging

- Enhanced S3 integration:
  * Improved file backup system with metadata
  * Batch processing capabilities
  * Enhanced error logging and recovery
  * Copy operations with URL fixing

- Added Telegram contact creation API
- Improved error logging across all modules
- Enhanced callback system for AI responses
- Extensive backup file storage with timestamps
- Updated documentation and README files

- File storage improvements:
  * Thousands of backup files with proper metadata
  * Fix operations for broken file references
  * Project-specific backup and recovery systems
  * Comprehensive file integrity checking

Total: 26,461+ files added/modified including AWS SDK, vendor dependencies, and extensive backup system.
2025-10-16 11:17:21 +03:00

447 lines
17 KiB
PHP

<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once dirname(__FILE__) . '/SMSNotifierBase.php';
include_once dirname(__FILE__) . '/ext/SMSProvider.php';
include_once dirname(__FILE__) . '/ext/ISMSProvider.php';
include_once 'include/Zend/Json.php';
class SMSNotifier extends SMSNotifierBase {
/**
* Check if there is active server configured.
*
* @return true if activer server is found, false otherwise.
*/
static function checkServer() {
$provider = SMSNotifierManager::getActiveProviderInstance();
return ($provider !== false);
}
/**
* Send SMS (Creates SMS Entity record, links it with related CRM record and triggers provider to send sms)
*
* @param String $message
* @param Array $tonumbers
* @param Integer $ownerid User id to assign the SMS record
* @param mixed $linktoids List of CRM record id to link SMS record
* @param String $linktoModule Modulename of CRM record to link with (if not provided lookup it will be calculated)
*/
//SalesPlatform.ru begin
static function sendsms($message, $tonumbers, $ownerid = false, $linktoids = false, $linktoModule = false, $recipientsTemplate = null) {
//static function sendsms($message, $tonumbers, $ownerid = false, $linktoids = false, $linktoModule = false) {
//SalesPlatform.ru end
global $current_user, $adb;
//SalesPlatform.ru begin
if(empty($tonumbers)) {
return;
}
//SalesPlatform.ru end
if($ownerid === false) {
if(isset($current_user) && !empty($current_user)) {
$ownerid = $current_user->id;
} else {
$ownerid = 1;
}
}
$moduleName = 'SMSNotifier';
$focus = CRMEntity::getInstance($moduleName);
$focus->column_fields['message'] = $message;
$focus->column_fields['assigned_user_id'] = $ownerid;
$focus->save($moduleName);
if($linktoids !== false) {
if($linktoModule !== false) {
//SalesPlatform.ru begin
self::spHandleSendSMS($focus, $moduleName, $focus->id, $linktoModule, $linktoids, $recipientsTemplate);
//relateEntities($focus, $moduleName, $focus->id, $linktoModule, $linktoids);
//SalesPlatform.ru end
} else {
// Link modulename not provided (linktoids can belong to mix of module so determine proper modulename)
$linkidsetypes = $adb->pquery( "SELECT setype,crmid FROM vtiger_crmentity WHERE crmid IN (".generateQuestionMarks($linktoids) . ")", array($linktoids) );
if($linkidsetypes && $adb->num_rows($linkidsetypes)) {
while($linkidsetypesrow = $adb->fetch_array($linkidsetypes)) {
//SalesPlatform.ru begin
self::spHandleSendSMS($focus, $moduleName, $focus->id, $linkidsetypesrow['setype'], $linkidsetypesrow['crmid'], $recipientsTemplate);
//relateEntities($focus, $moduleName, $focus->id, $linkidsetypesrow['setype'], $linkidsetypesrow['crmid']);
//SalesPlatform.ru end
}
}
}
}
$responses = self::fireSendSMS($message, $tonumbers);
$status = ISMSProvider::MSG_STATUS_DISPATCHED;
foreach ($responses as $response) {
if ($response['error']) {
$status = ISMSProvider::MSG_STATUS_FAILED;
}
}
$focus->processFireSendSMSResponse($responses);
return $focus->id;
}
//SalesPlatform.ru begin
private static function spHandleSendSMS($smsNotifierEntity, $smsNotifierModuleName, $smsRecordId, $linkToModule, $linkToIds, $recipientsTemplate) {
$smsRelatedModules = Vtiger_Relation_Model::getAllRelations(Vtiger_Module_Model::getInstance($smsNotifierModuleName));
$relatedModulesNames = array();
foreach($smsRelatedModules as $relatedModule) {
$relatedModulesNames[] = $relatedModule->getRelationModuleName();
}
if(in_array($linkToModule, $relatedModulesNames)) {
relateEntities($smsNotifierEntity, $smsNotifierModuleName, $smsRecordId, $linkToModule, $linkToIds);
self::updateLastSMSDate($linkToModule, $linkToIds);
} else {
self::spHandleIndirectlySendSMS($relatedModulesNames, $smsNotifierEntity, $smsNotifierModuleName, $smsRecordId, $linkToModule, $linkToIds, $recipientsTemplate);
}
}
private static function spHandleIndirectlySendSMS($relatedModulesNames, $smsNotifierEntity, $smsNotifierModuleName, $smsRecordId, $linkToModule, $linkToIds, $recipientsTemplate) {
$recordModel = Vtiger_Record_Model::getInstanceById($linkToIds, $linkToModule);
/* Get real recipients of sms */
$matches = array();
$relatedRecordsIdToModuleMap = array();
$recipientsVariables = explode(",", $recipientsTemplate);
foreach($recipientsVariables as $recipientTemplate) {
if(preg_match_all('/\\$\w+|\((\w+) : \(([_\w]+)\) (\w+)\)/', $recipientTemplate, $matches)) {
self::addRelateEntitiesIdToModuleMap($relatedRecordsIdToModuleMap, $relatedModulesNames, $recordModel, $linkToModule, $matches);
}
}
/* Relate sms to entities */
foreach($relatedRecordsIdToModuleMap as $recordId => $recordModuleName) {
relateEntities($smsNotifierEntity, $smsNotifierModuleName, $smsRecordId, $recordModuleName, $recordId);
self::updateLastSMSDate($recordModuleName, $recordId);
}
}
private static function addRelateEntitiesIdToModuleMap(&$relatedRecordsIdToModuleMap, $relatedModulesNames, $recordModel, $linkToModule, $matches) {
list($fullMatch, $referenceField, $referenceModule, $fieldName) = $matches;
$referenceField = $referenceField[0];
$referenceModule = $referenceModule[0];
$fieldName = $fieldName[0];
if(in_array($referenceModule, $relatedModulesNames)) {
$referenceRecordsIds = array((int) $recordModel->get($referenceField));
/* Special for Events Contacts handling */
if($linkToModule === "Events" && $referenceModule === "Contacts") {
$referenceRecordsIds = array();
foreach(explode(";", $_REQUEST['contactidlist']) as $contactId) {
$referenceRecordsIds[] = (int) $contactId;
}
}
foreach($referenceRecordsIds as $referenceRecordId) {
if($referenceRecordId > 0) {
/* Check for deleted and add to map */
$db = PearDatabase::getInstance();
$result = $db->pquery("SELECT deleted FROM vtiger_crmentity WHERE crmid=?", array($referenceRecordId));
if($resultRow = $db->fetchByAssoc($result) && (int) $resultRow['deleted'] == 0 &&
!array_key_exists($referenceRecordId, $relatedRecordsIdToModuleMap)) {
$referenceRecordModel = Vtiger_Record_Model::getInstanceById($referenceRecordId, $referenceModule);
if($referenceRecordModel->get($fieldName) != null) {
$relatedRecordsIdToModuleMap[$referenceRecordId] = $referenceModule;
}
}
}
}
}
}
//SalesPlatform.ru end
/**
* Detect the related modules based on the entity relation information for this instance.
*/
function detectRelatedModules() {
global $adb, $current_user;
// Pick the distinct modulenames based on related records.
$result = $adb->pquery("SELECT distinct setype FROM vtiger_crmentity WHERE crmid in (
SELECT relcrmid FROM vtiger_crmentityrel INNER JOIN vtiger_crmentity ON vtiger_crmentity.crmid=vtiger_crmentityrel.crmid
WHERE vtiger_crmentity.crmid = ? AND vtiger_crmentity.deleted=0)", array($this->id));
$relatedModules = array();
// Calculate the related module access (similar to getRelatedList API in DetailViewUtils.php)
if($result && $adb->num_rows($result)) {
require('user_privileges/user_privileges_'.$current_user->id.'.php');
while($resultrow = $adb->fetch_array($result)) {
$accessCheck = false;
$relatedTabId = getTabid($resultrow['setype']);
if($relatedTabId == 0) {
$accessCheck = true;
} else {
if($profileTabsPermission[$relatedTabId] == 0) {
if($profileActionPermission[$relatedTabId][3] == 0) {
$accessCheck = true;
}
}
}
if($accessCheck) {
$relatedModules[$relatedTabId] = $resultrow['setype'];
}
}
}
return $relatedModules;
}
protected function isUserOrGroup($id) {
global $adb;
$result = $adb->pquery("SELECT 1 FROM vtiger_users WHERE id=?", array($id));
if($result && $adb->num_rows($result)) {
return 'U';
} else {
return 'T';
}
}
protected function smsAssignedTo() {
global $adb;
// Determine the number based on Assign To
$assignedtoid = $this->column_fields['assigned_user_id'];
$type = $this->isUserOrGroup($assignedtoid);
if($type == 'U'){
$userIds = array($assignedtoid);
}else {
require_once('include/utils/GetGroupUsers.php');
$getGroupObj=new GetGroupUsers();
$getGroupObj->getAllUsersInGroup($assignedtoid);
$userIds = $getGroupObj->group_users;
//Clearing static cache for sub groups
GetGroupUsers::$groupIdsList = array();
}
$tonumbers = array();
if(count($userIds) > 0) {
$phoneSqlQuery = "select phone_mobile, id from vtiger_users WHERE status='Active' AND id in(". generateQuestionMarks($userIds) .")";
$phoneSqlResult = $adb->pquery($phoneSqlQuery, array($userIds));
while($phoneSqlResultRow = $adb->fetch_array($phoneSqlResult)) {
$number = $phoneSqlResultRow['phone_mobile'];
if(!empty($number)) {
$tonumbers[] = $number;
}
}
}
if(!empty($tonumbers)) {
$responses = self::fireSendSMS($this->column_fields['message'], $tonumbers);
$this->processFireSendSMSResponse($responses);
}
}
private function processFireSendSMSResponse($responses) {
if(empty($responses)) return;
global $adb;
foreach($responses as $response) {
$responseID = '';
$responseStatus = '';
$responseStatusMessage = '';
$needlookup = 1;
if($response['error']) {
// SalesPlatform.ru begin
$responseStatus = SMSNotifier_ISMSProvider_Model::MSG_STATUS_FAILED;
//$responseStatus = ISMSProvider::MSG_STATUS_FAILED;
$needlookup = 0;
} else {
$responseID = $response['id'];
$responseStatus = $response['status'];
}
if(isset($response['statusmessage'])) {
$responseStatusMessage = $response['statusmessage'];
}
$adb->pquery("INSERT INTO vtiger_smsnotifier_status(smsnotifierid,tonumber,status,statusmessage,smsmessageid,needlookup) VALUES(?,?,?,?,?,?)",
array($this->id,$response['to'],$responseStatus,$responseStatusMessage,$responseID,$needlookup)
);
}
}
static function smsquery($record) {
global $adb;
$results = array();
$result = $adb->pquery("SELECT * FROM vtiger_smsnotifier_status WHERE smsnotifierid = ?", array($record));
if ($result && $adb->num_rows($result)) {
$provider = SMSNotifierManager::getActiveProviderInstance();
// SalesPlatform.ru begin
if ($provider->getName() == 'SigmaSMS') {
return $result;
}
// SalesPlatform.ru end
while ($resultrow = $adb->fetch_array($result)) {
if ($resultrow['needlookup'] == 1) {
$messageid = $resultrow['smsmessageid'];
$response = $provider->query($messageid);
if($response['error']) {
// SalesPlatform.ru begin
$responseStatus = SMSNotifier_ISMSProvider_Model::MSG_STATUS_FAILED;
//$responseStatus = ISMSProvider::MSG_STATUS_FAILED;
// SalesPlatform.ru end
$needlookup = $response['needlookup'];
} else {
$responseStatus = $response['status'];
$needlookup = $response['needlookup'];
}
$responseStatusMessage = '';
if (isset($response['statusmessage'])) {
$responseStatusMessage = $response['statusmessage'];
}
$adb->pquery("UPDATE vtiger_smsnotifier_status SET status=?, statusmessage=?, needlookup=? WHERE smsmessageid = ?", array($responseStatus, $responseStatusMessage, $needlookup, $messageid));
$resultrow['status'] = $responseStatus;
$resultrow['statusmessage'] = $responseStatusMessage;
$resultrow['needlookup'] = $needlookup;
}
$results[] = $resultrow;
}
}
return $results;
}
static function fireSendSMS($message, $tonumbers) {
global $log;
$provider = SMSNotifierManager::getActiveProviderInstance();
if($provider) {
return $provider->send($message, $tonumbers);
}
}
static function getSMSStatusInfo($record) {
global $adb;
// SalesPlatform.ru begin Update message status
SMSNotifier::smsquery($record);
// SalesPlatform.ru end
$results = array();
$qresult = $adb->pquery("SELECT * FROM vtiger_smsnotifier_status WHERE smsnotifierid=?", array($record));
if($qresult && $adb->num_rows($qresult)) {
while($resultrow = $adb->fetch_array($qresult)) {
$results[] = $resultrow;
}
}
return $results;
}
// SalesPlatform.ru begin: Add last SMS date
private static function updateLastSMSDate($moduleName, $crmids) {
$db = PearDatabase::getInstance();
$rel_focus = CRMEntity::getInstance($moduleName);
if(!is_array($crmids)) $crmids = Array($crmids);
$db->pquery('UPDATE ' . $rel_focus->table_name . ' SET splastsms=Now() WHERE ' . $rel_focus->table_index . ' IN (' . generateQuestionMarks($crmids) . ')',
array($crmids));
}
// SalesPlatform.ru end
}
class SMSNotifierManager {
/** Server configuration management */
static function listAvailableProviders() {
return SMSProvider::listAll();
}
static function getActiveProviderInstance() {
global $adb;
$result = $adb->pquery("SELECT * FROM vtiger_smsnotifier_servers WHERE isactive = 1 LIMIT 1", array());
if($result && $adb->num_rows($result)) {
$resultrow = $adb->fetch_array($result);
$provider = SMSProvider::getInstance($resultrow['providertype']);
$parameters = array();
if(!empty($resultrow['parameters'])) $parameters = Zend_Json::decode(decode_html($resultrow['parameters']));
foreach($parameters as $k=>$v) {
$provider->setParameter($k, $v);
}
$password = Vtiger_Functions::fromProtectedText($resultrow['password']);
$provider->setAuthParameters($resultrow['username'], $password);
return $provider;
}
return false;
}
static function listConfiguredServer($id) {
global $adb;
$result = $adb->pquery("SELECT * FROM vtiger_smsnotifier_servers WHERE id=?", array($id));
if($result) {
return $adb->fetch_row($result);
}
return false;
}
static function listConfiguredServers() {
global $adb;
$result = $adb->pquery("SELECT * FROM vtiger_smsnotifier_servers", array());
$servers = array();
if($result) {
while($resultrow = $adb->fetch_row($result)) {
$servers[] = $resultrow;
}
}
return $servers;
}
static function updateConfiguredServer($id, $frmvalues) {
global $adb;
$providertype = vtlib_purify($frmvalues['smsserver_provider']);
$username = vtlib_purify($frmvalues['smsserver_username']);
$password = vtlib_purify($frmvalues['smsserver_password']);
$isactive = vtlib_purify($frmvalues['smsserver_isactive']);
$provider = SMSProvider::getInstance($providertype);
$parameters = '';
if($provider) {
$providerParameters = $provider->getRequiredParams();
$inputServerParams = array();
foreach($providerParameters as $k=>$v) {
$lookupkey = "smsserverparam_{$providertype}_{$v}";
if(isset($frmvalues[$lookupkey])) {
$inputServerParams[$v] = vtlib_purify($frmvalues[$lookupkey]);
}
}
$parameters = Zend_Json::encode($inputServerParams);
}
if(empty($id)) {
$adb->pquery("INSERT INTO vtiger_smsnotifier_servers (providertype,username,password,isactive,parameters) VALUES(?,?,?,?,?)",
array($providertype, $username, $password, $isactive, $parameters));
} else {
$adb->pquery("UPDATE vtiger_smsnotifier_servers SET username=?, password=?, isactive=?, providertype=?, parameters=? WHERE id=?",
array($username, $password, $isactive, $providertype, $parameters, $id));
}
}
static function deleteConfiguredServer($id) {
global $adb;
$adb->pquery("DELETE FROM vtiger_smsnotifier_servers WHERE id=?", array($id));
}
}
?>