Files
crm.clientright.ru/modules/Google/helpers/Utils.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

372 lines
16 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.
* *********************************************************************************** */
class Google_Utils_Helper {
const settings_table_name = 'vtiger_google_sync_settings';
const fieldmapping_table_name = 'vtiger_google_sync_fieldmapping';
const fieldlocalization_table_name = 'vtiger_google_sync_localization';
/**
* Updates the database with syncronization times
* @param <sting> $sourceModule module to which sync time should be stored
* @param <date> $modifiedTime Max modified time of record that are sync
*/
public static function updateSyncTime($sourceModule, $modifiedTime = false, $user = false) {
$db = PearDatabase::getInstance();
self::intialiseUpdateSchema();
if(!$user)
$user = Users_Record_Model::getCurrentUserModel();
if (!$modifiedTime) {
$modifiedTime = self::getSyncTime($sourceModule, $user);
}
if (!self::getSyncTime($sourceModule, $user)) {
if ($modifiedTime) {
$db->pquery('INSERT INTO vtiger_google_sync (googlemodule,user,synctime,lastsynctime) VALUES (?,?,?,?)', array($sourceModule, $user->id, $modifiedTime, date('Y-m-d H:i:s')));
}
} else {
$db->pquery('UPDATE vtiger_google_sync SET synctime = ?,lastsynctime = ? WHERE user=? AND googlemodule=?', array($modifiedTime, date('Y-m-d H:i:s'), $user->id, $sourceModule));
}
}
/**
* Creates sync table if not exists
*/
private static function intialiseUpdateSchema() {
if (!Vtiger_Utils::CheckTable('vtiger_google_sync')) {
Vtiger_Utils::CreateTable('vtiger_google_sync', '(googlemodule varchar(50),user int(10), synctime datetime,lastsynctime datetime)', true);
}
}
/**
* Gets the max Modified time of last sync records
* @param <sting> $sourceModule modulename to which sync time should return
* @return <date> max Modified time of last sync records OR <boolean> false when date not present
*/
public static function getSyncTime($sourceModule, $user = false) {
$db = PearDatabase::getInstance();
self::intialiseUpdateSchema();
if(!$user)
$user = Users_Record_Model::getCurrentUserModel();
$result = $db->pquery('SELECT synctime FROM vtiger_google_sync WHERE user=? AND googlemodule=?', array($user->id, $sourceModule));
if ($result && $db->num_rows($result) > 0) {
$row = $db->fetch_array($result);
return $row['synctime'];
} else {
return false;
}
}
/**
* Gets the last syncronazation time
* @param <sting> $sourceModule modulename to which sync time should return
* @return <date> last syncronazation time OR <boolean> false when date not present
*/
public static function getLastSyncTime($sourceModule) {
$db = PearDatabase::getInstance();
self::intialiseUpdateSchema();
$user = Users_Record_Model::getCurrentUserModel();
$result = $db->pquery('SELECT lastsynctime FROM vtiger_google_sync WHERE user=? AND googlemodule=?', array($user->id, $sourceModule));
if ($result && $db->num_rows($result) > 0) {
$row = $db->fetch_array($result);
return $row['lastsynctime'];
} else {
return false;
}
}
/**
* Get the callback url for a module
* @global type $site_URL
* @param <object> $request
* @param <array> $options any extra parameter add to url
* @return string callback url
*/
static function getCallbackUrl($request, $options = array()) {
global $site_URL;
$callback = rtrim($site_URL, '/') . "/index.php?module=".$request['module']."&view=List&sourcemodule=".$request['sourcemodule'];
foreach ($options as $key => $value) {
$callback.="&" . $key . "=" . $value;
}
return $callback;
}
/**
* To get users currently in sync with Google
* @global type $adb
* @return type
*/
public static function getSyncUsers(){
global $adb;
$users = array();
$result = $adb->pquery("SELECT DISTINCT userid FROM vtiger_google_oauth2", array());
if($result && $adb->num_rows($result)) {
while($resultrow = $adb->fetch_array($result)) {
$users[] = $resultrow['id'];
}
}
return $users;
}
static function hasSettingsForUser($userId,$source_module) {
$db = PearDatabase::getInstance();
$sql = 'SELECT 1 FROM ' . self::settings_table_name . ' WHERE user = ? AND module = ?';
$result = $db->pquery($sql, array($userId,$source_module));
if($db->num_rows($result) > 0){
return true;
}
return false;
}
static function saveSettings($request) {
$db = PearDatabase::getInstance();
$user = Users_Record_Model::getCurrentUserModel();
$userId = $user->getId();
$source_module = $request->get('sourcemodule');
$google_group = $request->get('google_group');
$sync_direction = $request->get('sync_direction');
if(Google_Utils_Helper::hasSettingsForUser($userId,$source_module)) {
$sql = 'UPDATE ' . self::settings_table_name . ' SET clientgroup = ?, direction = ? WHERE user = ? AND module = ?';
$params = array($google_group,$sync_direction,$userId,$source_module);
$db->pquery($sql, $params);
} else {
$sql = 'INSERT INTO ' . self::settings_table_name . '(user,module,clientgroup,direction) VALUES (?,?,?,?)';
$params = array($userId,$source_module,$google_group,$sync_direction);
$db->pquery($sql, $params);
}
}
static function saveFieldMappings($sourceModule, $fieldMappings) {
$db = PearDatabase::getInstance();
$user = Users_Record_Model::getCurrentUserModel();
$sql = 'SELECT 1 FROM ' . self::fieldmapping_table_name . ' WHERE user = ?';
$res = $db->pquery($sql,array($user->getId()));
$sqlParams = array();
if($db->num_rows($res)) {
$sql = 'DELETE FROM ' . self::fieldmapping_table_name . ' WHERE user = ?';
$db->pquery($sql,array($user->getId()));
}
$sql = 'INSERT INTO ' . self::fieldmapping_table_name . ' (vtiger_field,google_field,google_field_type,google_custom_label,user) VALUES ';
foreach($fieldMappings as $fieldMap) {
$fieldMap['user'] = $user->getId();
$values = '(' . generateQuestionMarks($fieldMap) . '), ';
$params = array();
foreach($fieldMap as $field) {
$params[] = $field;
}
$sqlParams = array_merge($sqlParams,$params);
$sql .= $values;
}
$sql = rtrim($sql,', ');
$db->pquery($sql,$sqlParams);
}
static function getSelectedContactGroupForUser($user = false) {
if(!$user) $user = Users_Record_Model::getCurrentUserModel();
$userId = $user->getId();
if(!Google_Utils_Helper::hasSettingsForUser($userId,'Contacts')) {
return ''; // defaults to all - other contacts groups
} else {
$db = PearDatabase::getInstance();
$sql = 'SELECT clientgroup FROM ' . self::settings_table_name . ' WHERE user = ? AND module = ?';
$result = $db->pquery($sql, array($userId,'Contacts'));
return $db->query_result($result, 0, 'clientgroup');
}
}
static function getSyncDirectionForUser($user = false, $module = 'Contacts') {
if(!$user) $user = Users_Record_Model::getCurrentUserModel();
if(!Google_Utils_Helper::hasSettingsForUser($user->getId(),$module)) {
return '11'; // defaults to bi-directional sync
} else {
$db = PearDatabase::getInstance();
$sql = 'SELECT direction FROM ' . self::settings_table_name . ' WHERE user = ? AND module = ?';
$result = $db->pquery($sql, array($user->getId(),$module));
return $db->query_result($result, 0, 'direction');
}
}
static function getFieldMappingForUser($user = false) {
if(!$user) $user = Users_Record_Model::getCurrentUserModel();
$db = PearDatabase::getInstance();
$fieldmapping = array(
'salutationtype' => array(
'google_field_name' => 'gd:namePrefix',
'google_field_type' => '',
'google_custom_label' => ''
),
'firstname' => array(
'google_field_name' => 'gd:givenName',
'google_field_type' => '',
'google_custom_label' => ''
),
'lastname' => array(
'google_field_name' => 'gd:familyName',
'google_field_type' => '',
'google_custom_label' => ''
),
'title' => array(
'google_field_name' => 'gd:orgTitle',
'google_field_type' => '',
'google_custom_label' => ''
),
'account_id' => array(
'google_field_name' => 'gd:orgName',
'google_field_type' => '',
'google_custom_label' => ''
),
'birthday' => array(
'google_field_name' => 'gContact:birthday',
'google_field_type' => '',
'google_custom_label' => ''
),
'email' => array(
'google_field_name' => 'gd:email',
'google_field_type' => array('home', 'Домашние контакты'),
'google_custom_label' => ''
),
'secondaryemail' => array(
'google_field_name' => 'gd:email',
'google_field_type' => array('work', 'Рабочие контакты'),
'google_custom_label' => ''
),
'mobile' => array(
'google_field_name' => 'gd:phoneNumber',
'google_field_type' => array ('mobile', 'Мобильные устройства'),
'google_custom_label' => ''
),
'phone' => array(
'google_field_name' => 'gd:phoneNumber',
'google_field_type' => array('work', 'Рабочие контакты'),
'google_custom_label' => ''
),
'homephone' => array(
'google_field_name' => 'gd:phoneNumber',
'google_field_type' => array('home', 'Домашние контакты'),
'google_custom_label' => ''
),
'mailingaddress' => array(
'google_field_name' => 'gd:structuredPostalAddress',
'google_field_type' => array('home', 'Домашние контакты'),
'google_custom_label' => ''
),
'otheraddress' => array(
'google_field_name' => 'gd:structuredPostalAddress',
'google_field_type' => array('work', 'Рабочие контакты'),
'google_custom_label' => ''
),
'description' => array(
'google_field_name' => 'content',
'google_field_type' => '',
'google_custom_label' => ''
)
);
$sql = 'SELECT vtiger_field,google_field,google_field_type,google_custom_label, russian_field_type FROM '
. self::fieldmapping_table_name
. ' INNER JOIN ' . self::fieldlocalization_table_name .
' ON (' . self::fieldmapping_table_name . '.google_field = ' . self::fieldlocalization_table_name .'.field_name) WHERE user = ?';
$result = $db->pquery($sql,array($user->getId()));
for($i=0;$i<$db->num_rows($result);$i++) {
$row = $db->fetch_row($result);
$fieldmapping[$row['vtiger_field']] = array(
'google_field_name' => $row['google_field'],
'google_field_type' => array($row['google_field_type'], $row['russian_field_type'] ),
'google_custom_label' => $row['google_custom_label']
);
}
return $fieldmapping;
}
public static function getSelectedCalendarForUser($user = false) {
if(!$user) $user = Users_Record_Model::getCurrentUserModel();
$userId = $user->getId();
if(!Google_Utils_Helper::hasSettingsForUser($userId,'Calendar')) {
return 'primary'; // defaults to primary calendar
} else {
$db = PearDatabase::getInstance();
$sql = 'SELECT clientgroup FROM ' . self::settings_table_name . ' WHERE user = ? AND module = ?';
$result = $db->pquery($sql, array($userId,'Calendar'));
return $db->query_result($result, 0, 'clientgroup');
}
}
public static function errorLog() {
$i = 0;
$debug = debug_backtrace();
array_shift($debug);
foreach ($debug as $value) {
$error.= "\t#".$i++.' File : '.$value['file'].' || Line : '.$value['line'].' || Class : '.$value['class'].' || Function : '.$value['function']."\n";
}
$fp = fopen('logs/googleErrorLog.txt','a+');
fwrite($fp, "Debug traced ON ".date('Y-m-d H:i:s')."\n\n");
fwrite($fp, $error);
fwrite($fp, "\n\n");
fclose($fp);
}
static function toGoogleXml($string) {
$string = str_replace('&', '&amp;amp;', $string);
$string = str_replace('<', '&amp;lt;', $string);
$string = str_replace('>', '&amp;gt;', $string);
return $string;
}
static function saveSyncSettings($request) {
$db = PearDatabase::getInstance();
$user = Users_Record_Model::getCurrentUserModel();
$userId = $user->getId();
$source_module = $request->get('sourcemodule');
$google_group = $request->get('google_group');
$sync_direction = $request->get('sync_direction');
if($request->get('enabled') == 'on' || $request->get('enabled') == 1) {
$enabled = 1;
} else {
$enabled = 0;
}
if(Google_Utils_Helper::hasSettingsForUser($userId,$source_module)) {
$sql = 'UPDATE ' . self::settings_table_name . ' SET clientgroup = ?, direction = ?, enabled = ? WHERE user = ? AND module = ?';
$params = array($google_group,$sync_direction,$enabled,$userId,$source_module);
$db->pquery($sql, $params);
} else {
$sql = 'INSERT INTO ' . self::settings_table_name . ' VALUES (?,?,?,?,?)';
$params = array($userId,$source_module,$google_group,$sync_direction,$enabled);
$db->pquery($sql, $params);
}
}
/**
* Function to check if the sync is enabled for a module and for user given
* @param <string > $module
* @param <Users_Record_Model> $user
* @return <boolean> true/false
*/
static function checkSyncEnabled($module, $user = false) {
if(!$user) $user = Users_Record_Model::getCurrentUserModel();
$userId = $user->getId();
if(!Google_Utils_Helper::hasSettingsForUser($userId,$module)) {
return true; // defaults to enabled
} else {
$db = PearDatabase::getInstance();
$sql = 'SELECT enabled FROM ' . self::settings_table_name . ' WHERE user = ? AND module = ?';
$result = $db->pquery($sql, array($userId,$module));
$enabled = $db->query_result($result, 0, 'enabled');
}
if($enabled == 1) {
return true;
}
return false;
}
}