Files
crm.clientright.ru/include/Webservices/GetUpdates.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

317 lines
11 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.
*************************************************************************************/
require_once 'include/Webservices/Utils.php';
require_once 'include/Webservices/ModuleTypes.php';
require_once 'include/utils/CommonUtils.php';
require_once('include/utils/GetUserGroups.php');
require_once 'include/Webservices/DescribeObject.php';
function vtws_sync($mtime,$elementType,$syncType,$user){
global $adb, $recordString,$modifiedTimeString;
$numRecordsLimit = 100;
$ignoreModules = array("Users");
$typed = true;
$dformat = "Y-m-d H:i:s";
$datetime = date($dformat, $mtime);
$setypeArray = array();
$setypeData = array();
$setypeHandler = array();
$setypeNoAccessArray = array();
$output = array();
$output["updated"] = array();
$output["deleted"] = array();
$applicationSync = false;
if(is_object($syncType) && ($syncType instanceof Users)){
$user = $syncType;
} else if($syncType == 'application'){
$applicationSync = true;
} else if($syncType == 'userandgroup'){
$userAndGroupSync = true;
}
if($applicationSync && !is_admin($user)){
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,"Only admin users can perform application sync");
}
$ownerIds = array($user->id);
// To get groupids in which this user exist
if ($userAndGroupSync) {
$userGroups = new GetUserGroups();
$userGroups->getAllUserGroups($user->id);
$ownerIds = array_merge($ownerIds, $userGroups->user_groups);
}
// End
if(!isset($elementType) || $elementType=='' || $elementType==null){
$typed=false;
}
$adb->startTransaction();
$accessableModules = array();
$entityModules = array();
$modulesDetails = vtws_listtypes(null,$user);
$moduleTypes = $modulesDetails['types'];
$modulesInformation = $modulesDetails["information"];
foreach($modulesInformation as $moduleName=>$entityInformation){
if($entityInformation["isEntity"])
$entityModules[] = $moduleName;
}
if(!$typed){
$accessableModules = $entityModules;
}
else{
if(!in_array($elementType,$entityModules))
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,"Permission to perform the operation is denied");
$accessableModules[] = $elementType;
}
$accessableModules = array_diff($accessableModules,$ignoreModules);
if(count($accessableModules)<=0)
{
$output['lastModifiedTime'] = $mtime;
$output['more'] = false;
return $output;
}
if($typed){
$handler = vtws_getModuleHandlerFromName($elementType, $user);
$moduleMeta = $handler->getMeta();
$entityDefaultBaseTables = $moduleMeta->getEntityDefaultTableList();
//since there will be only one base table for all entities
$baseCRMTable = $entityDefaultBaseTables[0];
if($elementType=="Calendar" || $elementType=="Events" ){
$baseCRMTable = getSyncQueryBaseTable($elementType);
}
}
else
$baseCRMTable = " vtiger_crmentity ";
//modifiedtime - next token
$q = "SELECT modifiedtime FROM $baseCRMTable WHERE modifiedtime>? and setype IN(".generateQuestionMarks($accessableModules).") ";
$params = array($datetime);
foreach($accessableModules as $entityModule){
if($entityModule == "Events")
$entityModule = "Calendar";
$params[] = $entityModule;
}
if(!$applicationSync){
$q .= ' and smownerid IN('.generateQuestionMarks($ownerIds).')';
$params = array_merge($params,$ownerIds);
}
$q .=" order by modifiedtime limit $numRecordsLimit";
$result = $adb->pquery($q,$params);
$modTime = array();
for($i=0;$i<$adb->num_rows($result);$i++){
$modTime[] = $adb->query_result($result,$i,'modifiedtime');
}
if(!empty($modTime)){
$maxModifiedTime = max($modTime);
}
if(!$maxModifiedTime){
$maxModifiedTime = $datetime;
}
foreach($accessableModules as $elementType){
$handler = vtws_getModuleHandlerFromName($elementType, $user);
$moduleMeta = $handler->getMeta();
$deletedQueryCondition = $moduleMeta->getEntityDeletedQuery();
preg_match_all("/(?:\s+\w+[ \t\n\r]+)?([^=]+)\s*=([^\s]+|'[^']+')/",$deletedQueryCondition,$deletedFieldDetails);
$fieldNameDetails = $deletedFieldDetails[1];
$deleteFieldValues = $deletedFieldDetails[2];
$deleteColumnNames = array();
foreach($fieldNameDetails as $tableName_fieldName){
$fieldComp = explode(".",$tableName_fieldName);
$deleteColumnNames[$tableName_fieldName] = $fieldComp[1];
}
$params = array($moduleMeta->getTabName(),$datetime,$maxModifiedTime);
$queryGenerator = new QueryGenerator($elementType, $user);
$fields = array();
$moduleFields = $moduleMeta->getModuleFields();
$moduleFieldNames = getSelectClauseFields($elementType,$moduleMeta,$user);
$moduleFieldNames[]='id';
$queryGenerator->setFields($moduleFieldNames);
$selectClause = "SELECT ".$queryGenerator->getSelectClauseColumnSQL();
// adding the fieldnames that are present in the delete condition to the select clause
// since not all fields present in delete condition will be present in the fieldnames of the module
foreach($deleteColumnNames as $table_fieldName=>$columnName){
if(!in_array($columnName,$moduleFieldNames)){
$selectClause .=", ".$table_fieldName;
}
}
if($elementType=="Emails")
$fromClause = vtws_getEmailFromClause();
else
$fromClause = $queryGenerator->getFromClause();
$fromClause .= " INNER JOIN (select modifiedtime, crmid,deleted,setype FROM $baseCRMTable WHERE setype=? and modifiedtime >? and modifiedtime<=?";
if(!$applicationSync){
$fromClause.= 'and smownerid IN('.generateQuestionMarks($ownerIds).')';
$params = array_merge($params,$ownerIds);
}
$fromClause.= ' ) vtiger_ws_sync ON (vtiger_crmentity.crmid = vtiger_ws_sync.crmid)';
if ($elementType == 'Events') {
// If we have more than one contact attached to Vtiger Event then we are getting duplicates
$moduleFocus = CRMEntity::getInstance('Activity');
$fromClause .= " GROUP BY $moduleFocus->table_name.$moduleFocus->table_index";
}
$q = $selectClause." ".$fromClause;
$result = $adb->pquery($q, $params);
$recordDetails = array();
$deleteRecordDetails = array();
while($arre = $adb->fetchByAssoc($result)){
$key = $arre[$moduleMeta->getIdColumn()];
if(vtws_isRecordDeleted($arre,$deleteColumnNames,$deleteFieldValues)){
if(!$moduleMeta->hasAccess()){
continue;
}
$output["deleted"][] = vtws_getId($moduleMeta->getEntityId(), $key);
}
else{
if(!$moduleMeta->hasAccess() ||!$moduleMeta->hasPermission(EntityMeta::$RETRIEVE,$key)){
continue;
}
try{
$output["updated"][] = DataTransform::sanitizeDataWithColumn($arre,$moduleMeta);
}catch(WebServiceException $e){
//ignore records the user doesn't have access to.
continue;
}catch(Exception $e){
throw new WebServiceException(WebServiceErrorCode::$INTERNALERROR,"Unknown Error while processing request");
}
}
}
}
$q = "SELECT crmid FROM $baseCRMTable WHERE modifiedtime>? and setype IN(".generateQuestionMarks($accessableModules).")";
$params = array($maxModifiedTime);
foreach($accessableModules as $entityModule){
if($entityModule == "Events")
$entityModule = "Calendar";
$params[] = $entityModule;
}
if(!$applicationSync){
$q.='and smownerid IN('.generateQuestionMarks($ownerIds).')';
$params = array_merge($params,$ownerIds);
}
$result = $adb->pquery($q,$params);
if($adb->num_rows($result)>0){
$output['more'] = true;
}
else{
$output['more'] = false;
}
if(!$maxModifiedTime){
$modifiedtime = $mtime;
}else{
$modifiedtime = vtws_getSeconds($maxModifiedTime);
}
if(is_string($modifiedtime)){
$modifiedtime = intval($modifiedtime);
}
$output['lastModifiedTime'] = $modifiedtime;
$error = $adb->hasFailedTransaction();
$adb->completeTransaction();
if($error){
throw new WebServiceException(WebServiceErrorCode::$DATABASEQUERYERROR,
vtws_getWebserviceTranslatedString('LBL_'.
WebServiceErrorCode::$DATABASEQUERYERROR));
}
VTWS_PreserveGlobal::flush();
return $output;
}
function vtws_getSeconds($mtimeString){
//TODO handle timezone and change time to gmt.
return strtotime($mtimeString);
}
function vtws_isRecordDeleted($recordDetails,$deleteColumnDetails,$deletedValues){
$deletedRecord = false;
$i=0;
foreach($deleteColumnDetails as $tableName_fieldName=>$columnName){
if($recordDetails[$columnName]!=$deletedValues[$i++]){
$deletedRecord = true;
break;
}
}
return $deletedRecord;
}
function vtws_getEmailFromClause(){
$q = "FROM vtiger_activity
INNER JOIN vtiger_crmentity ON vtiger_activity.activityid = vtiger_crmentity.crmid
LEFT JOIN vtiger_users ON vtiger_crmentity.smownerid = vtiger_users.id
LEFT JOIN vtiger_groups ON vtiger_crmentity.smownerid = vtiger_groups.groupid
LEFT JOIN vtiger_seattachmentsrel ON vtiger_activity.activityid = vtiger_seattachmentsrel.crmid
LEFT JOIN vtiger_attachments ON vtiger_seattachmentsrel.attachmentsid = vtiger_attachments.attachmentsid
LEFT JOIN vtiger_email_track ON vtiger_activity.activityid = vtiger_email_track.mailid
INNER JOIN vtiger_emaildetails ON vtiger_activity.activityid = vtiger_emaildetails.emailid
LEFT JOIN vtiger_users vtiger_users2 ON vtiger_emaildetails.idlists = vtiger_users2.id
LEFT JOIN vtiger_groups vtiger_groups2 ON vtiger_emaildetails.idlists = vtiger_groups2.groupid";
return $q;
}
function getSyncQueryBaseTable($elementType){
if($elementType!="Calendar" && $elementType!="Events"){
return "vtiger_crmentity";
}
else{
$activityCondition = getCalendarTypeCondition($elementType);
$query = "vtiger_crmentity INNER JOIN vtiger_activity ON (vtiger_crmentity.crmid = vtiger_activity.activityid and $activityCondition)";
return $query;
}
}
function getCalendarTypeCondition($elementType){
if($elementType == "Events")
$activityCondition = "vtiger_activity.activitytype !='Task' and vtiger_activity.activitytype !='Emails'";
else
$activityCondition = "vtiger_activity.activitytype ='Task'";
return $activityCondition;
}
function getSelectClauseFields($module,$moduleMeta,$user){
$moduleFieldNames = $moduleMeta->getModuleFields();
$inventoryModules = getInventoryModules();
if(in_array($module, $inventoryModules)){
$fields = vtws_describe('LineItem', $user);
foreach($fields['fields'] as $field){
unset($moduleFieldNames[$field['name']]);
}
foreach ($moduleFieldNames as $field => $fieldObj){
if(substr($field, 0, 5) == 'shtax'){
unset($moduleFieldNames[$field]);
}
}
}
return array_keys($moduleFieldNames);
}
?>