- 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.
1609 lines
49 KiB
PHP
1609 lines
49 KiB
PHP
<?php
|
|
/**
|
|
This File was developed by Stefan Warnat <vtiger@stefanwarnat.de>
|
|
|
|
It belongs to the Workflow Designer and must not be distributed without complete extension
|
|
**/
|
|
namespace Workflow;
|
|
|
|
use \Workflow\VTInventoryEntity;
|
|
use \CRMEntity;
|
|
|
|
/**
|
|
* VTEntity
|
|
* @version 1.0
|
|
*
|
|
* 1.0 add Dummy Functions to allow "global" not bind Workflows
|
|
*/
|
|
require_once('include/utils/utils.php');
|
|
|
|
/**
|
|
* Class VTEntity
|
|
* Core Components. Represent a CRM Record
|
|
*
|
|
* @package Workflow
|
|
*/
|
|
class VTEntity
|
|
{
|
|
/**
|
|
* ID of current Record
|
|
* @var int
|
|
* @internal
|
|
*/
|
|
protected $_id = 0;
|
|
|
|
/**
|
|
* If known, WSID of current Record
|
|
* @var int|string
|
|
* @internal
|
|
*/
|
|
protected $_wsid = 0;
|
|
|
|
/**
|
|
* The Field-Value Storage of Recorddata
|
|
* @var array|bool
|
|
* @internal
|
|
*/
|
|
protected $_data = false;
|
|
/**
|
|
* ModuleName of Record
|
|
* @var string
|
|
* @internal
|
|
*/
|
|
protected $_moduleName = "";
|
|
|
|
/**
|
|
* Record was changed?
|
|
* @internal
|
|
* @var bool
|
|
*/
|
|
protected $_changed = false;
|
|
|
|
/**
|
|
* Already created references
|
|
* @internal
|
|
* @var VTEntity[]
|
|
*/
|
|
protected $_references = array();
|
|
|
|
/**
|
|
* Environment Variables
|
|
* @internal
|
|
* @var array
|
|
*/
|
|
protected $_environment = array();
|
|
|
|
/**
|
|
* Record was deleted?
|
|
* @internal
|
|
* @var bool
|
|
*/
|
|
protected $_deleted = null;
|
|
|
|
/**
|
|
* @var bool
|
|
* @internal
|
|
*/
|
|
protected $_isNew = false;
|
|
|
|
/**
|
|
* @var bool
|
|
* @internal
|
|
*/
|
|
protected $_isDummy = false;
|
|
|
|
/**
|
|
* @internal
|
|
*/
|
|
protected static $_cache = array();
|
|
/**
|
|
* @var \Users
|
|
* @internal
|
|
*/
|
|
protected static $_user = false;
|
|
/**
|
|
* @internal
|
|
*/
|
|
protected $_oldRequest = false;
|
|
/**
|
|
* @internal
|
|
*/
|
|
protected $_saveRequest = array();
|
|
|
|
/**
|
|
* @internal
|
|
*/
|
|
protected $_internalObj = false;
|
|
|
|
/**
|
|
* @internal
|
|
*/
|
|
protected $_isInventory = false;
|
|
|
|
/**
|
|
* @internal
|
|
*/
|
|
protected $_oldCurrentModule = null;
|
|
|
|
/**
|
|
* @internal
|
|
*/
|
|
public static $RecordStored = array();
|
|
|
|
/**
|
|
* @var bool
|
|
* @internal
|
|
*/
|
|
protected $LineUpdaterMode = false;
|
|
|
|
/**
|
|
* @var bool
|
|
* @internal
|
|
*/
|
|
protected static $TransferPrepared = false;
|
|
|
|
private static $TraceFields = false;
|
|
|
|
protected static $CurrencyFields = array(
|
|
'dummy' => array()
|
|
);
|
|
|
|
/**
|
|
* Get VTEntity Object for specific ID and ModuleName
|
|
* If Module contains Inventory, you get \Workflow\VTInventoryEntity
|
|
* @static
|
|
* @param int $id - CRMID of Record to get
|
|
* @param string $module_name - ModuleName of the Record
|
|
* @param \Users $user - [Optional] Used for Object Access
|
|
* @return VTEntity
|
|
* @example
|
|
* <br/>
|
|
* $record = \Workflow\VTEntity::getForId(815);<br/>
|
|
* $record = \Workflow\VTEntity::getForId(815, 'Accounts');
|
|
*/
|
|
public static function getForId($id, $module_name = false, $user = false) {
|
|
if(empty($id)) {
|
|
return self::getDummy();
|
|
}
|
|
if($module_name === 'ModuleName') {
|
|
$module_name = null;
|
|
}
|
|
|
|
if(strpos($id, "x") !== false) {
|
|
$idParts = explode("x", $id);
|
|
$id = $idParts[1];
|
|
|
|
if(empty($module_name)) {
|
|
global $adb;
|
|
$sql = "SELECT name FROM vtiger_ws_entity WHERE id = ".intval($idParts[0]);
|
|
$result = $adb->query($sql);
|
|
$module_name = $adb->query_result($result, 0, "name");
|
|
}
|
|
}
|
|
if(strpos($id, "@") !== false) {
|
|
$id = explode("@", $id);
|
|
$id = $id[0];
|
|
}
|
|
|
|
if($module_name == false) {
|
|
global $adb;
|
|
$sql = "SELECT setype FROM vtiger_crmentity WHERE crmid = ".intval($id);
|
|
$result = $adb->query($sql);
|
|
$module_name = $adb->query_result($result, 0, "setype");
|
|
}
|
|
if(empty($module_name)) {
|
|
return false;
|
|
}
|
|
if($module_name == "Calendar" || $module_name == "Events") { $module_name = vtws_getCalendarEntityType($id); }
|
|
|
|
if($user === false) {
|
|
$userID = VTEntity::$_user->id;
|
|
} else {
|
|
$userID = $user->id;
|
|
}
|
|
|
|
if(isset(VTEntity::$_cache[$userID][$id])) {
|
|
return VTEntity::$_cache[$userID][$id];
|
|
}
|
|
global $current_user;
|
|
|
|
\Workflow2::log($id, 0, 0, "Get Record");
|
|
|
|
$recordModel = \Vtiger_Module_Model::getInstance($module_name);
|
|
|
|
if($recordModel instanceof \Inventory_Module_Model) {
|
|
VTEntity::$_cache[$userID][$id] = new VTInventoryEntity($module_name, $id);
|
|
} else {
|
|
VTEntity::$_cache[$userID][$id] = new VTEntity($module_name, $id);
|
|
}
|
|
|
|
return VTEntity::$_cache[$userID][$id];
|
|
}
|
|
|
|
/**
|
|
* Clear the cache for single ID if you manipulate database
|
|
* @param $id
|
|
*/
|
|
public static function ClearCache($id) {
|
|
if(!empty(VTEntity::$_user)) {
|
|
unset(VTEntity::$_cache[VTEntity::$_user->id][$id]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set the user, which should be used to access records
|
|
*
|
|
* @param \Users $user
|
|
*/
|
|
public static function setUser($user) {
|
|
// Only change if realy change take place
|
|
if(!empty(VTEntity::$_user) && !empty($user) && $user->id == VTEntity::$_user->id)
|
|
return;
|
|
|
|
VTEntity::$_user = $user;
|
|
|
|
// New User means, new Permissions -> Clear cache
|
|
#VTEntity::$_cache = array();
|
|
}
|
|
|
|
/**
|
|
* Return the current User Object
|
|
* If not set, the $defaultuser will be returned
|
|
* @static
|
|
* @param \Users $defaultUser
|
|
* @return \Users
|
|
*/
|
|
public static function getUser($defaultUser = false) {
|
|
if(self::$_user === false) {
|
|
if($defaultUser === false) {
|
|
self::setUser(VtUtils::getAdminUser());
|
|
} else {
|
|
self::setUser($defaultUser);
|
|
}
|
|
}
|
|
|
|
return VTEntity::$_user;
|
|
}
|
|
|
|
/**
|
|
* Use getById($crmid) instead
|
|
*
|
|
* @internal
|
|
* @param string $module_name
|
|
* @param int $id RecordID
|
|
*/
|
|
protected function __construct($module_name, $id) {
|
|
if($module_name == "Activity") {
|
|
$module_name = "Calendar";
|
|
}
|
|
|
|
if($module_name == "dummy") {
|
|
$this->_isDummy = true;
|
|
|
|
$this->_id = $id;
|
|
$this->_moduleName = $module_name;
|
|
$this->_data = array();
|
|
} else {
|
|
$this->_id = $id;
|
|
|
|
if(!empty($id)) {
|
|
$wsid = vtws_getWebserviceEntityId($module_name, $id);
|
|
$this->_wsid = $wsid;
|
|
} else {
|
|
$this->_data = array("assigned_user_id" => self::$_user->id);
|
|
}
|
|
|
|
$this->_moduleName = $module_name;
|
|
}
|
|
|
|
if(!isset(self::$CurrencyFields[$this->getModuleName()])) {
|
|
self::$CurrencyFields[$this->getModuleName()] = VtUtils::getFieldsWithTypes($this->getModuleName(), array(71, 72));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Function to check if Entity has Inventory
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function isInventory() {
|
|
return $this->_isInventory;
|
|
}
|
|
|
|
/**
|
|
* Function to clear the Environment of a VTEntity Object (All or single Key)
|
|
*
|
|
* @param null $key Key to clear. If not set all keys will be cleared
|
|
*/
|
|
public function clearEnvironment($key = null) {
|
|
if($key === null) {
|
|
$this->_environment = array();
|
|
} else {
|
|
if(isset($this->_environment[$key])) {
|
|
unset($this->_environment[$key]);
|
|
}
|
|
}
|
|
}
|
|
|
|
public function getOwner() {
|
|
$owners = $this->getOwners();
|
|
|
|
$objOwner = new \Users();
|
|
$objOwner->retrieveCurrentUserInfoFromFile($owners[0]);
|
|
return $objOwner;
|
|
}
|
|
/**
|
|
* Get Owner Users of a record
|
|
*
|
|
* @return VTEntityMap
|
|
*/
|
|
public function getOwners() {
|
|
$ownerId = $this->get('assigned_user_id');
|
|
$adb = \PearDatabase::getInstance();
|
|
|
|
$sql = 'SELECT id FROM vtiger_users WHERE id = ?';
|
|
$result = $adb->pquery($sql, array($ownerId));
|
|
|
|
if($adb->num_rows($result) > 0) {
|
|
return new VTEntityMap(array(VTEntity::getForId($adb->query_result($result, 0, 'id'), 'Users')));
|
|
} else {
|
|
require_once('include/utils/GetGroupUsers.php');
|
|
$groupUsersObj = new \GetGroupUsers();
|
|
$groupUsersObj->getAllUsersInGroup($ownerId);
|
|
|
|
$groupUsers = $groupUsersObj->group_users;
|
|
|
|
$result = array();
|
|
foreach($groupUsers as $userId) {
|
|
$result[] = self::getForId($userId, 'Users');
|
|
}
|
|
return new VTEntityMap($result);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get Environmental Key from Entity
|
|
* @param string|bool $key Set the Env-Key you want to get or get all keys
|
|
* @return mixed|bool
|
|
*/
|
|
public function getEnvironment($key = false) {
|
|
if($key === false) {
|
|
return $this->_environment;
|
|
} else {
|
|
return isset($this->_environment[$key])?$this->_environment[$key]:false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load prefilled Environment
|
|
*
|
|
* @param $env
|
|
*/
|
|
public function loadEnvironment($env) {
|
|
if(is_array($env)) {
|
|
$this->_environment = $env;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set a Environment Variable
|
|
*
|
|
* @param $key
|
|
* @param $value
|
|
* @param bool $task
|
|
*/
|
|
public function setEnvironment($key, $value, $task = false) {
|
|
if($task !== false) {
|
|
$env = $task->get("env");
|
|
|
|
if($env !== -1 && !empty($env[$key])) {
|
|
$this->_environment[$env[$key]] = $value;
|
|
}
|
|
} else {
|
|
$this->_environment[$key] = $value;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Function to add a File to temporarily Filestore of this record
|
|
* File will be moved into a tmp folder
|
|
*
|
|
* @param $filepath Current Filepath of file, to be added
|
|
* @param null $filestoreid ID of File, which could be used to access file
|
|
* @param null $filename [optional] Filename. If not set, get the filename from filepath
|
|
* @param bool $execID [optional] ExecID of Execution, which should be used to add file
|
|
*
|
|
* @throws \Exception If tmp Folder is not writable
|
|
*/
|
|
public function addTempFile($filepath, $filestoreid = null, $filename = null, $execID = false) {
|
|
$files = $this->_environment['_tmpfiles'];
|
|
|
|
if(empty($files)) {
|
|
$files = array();
|
|
}
|
|
if($filename === null) {
|
|
$filename = basename($filepath);
|
|
}
|
|
|
|
if($filestoreid === null) {
|
|
$filestoreid = md5(microtime(false).rand(10000,99999));
|
|
}
|
|
$tmpid = md5(microtime(false).rand(10000,99999));
|
|
|
|
global $root_directory;
|
|
$path = realpath($root_directory . '/modules/Workflow2/tmp');
|
|
|
|
if(empty($path) || !is_writeable($path)) {
|
|
throw new \Exception($root_directory.'/modules/Workflow2/tmp/ directory not existing or not writable. Please check!');
|
|
}
|
|
|
|
if($this->isDummy() === false) {
|
|
$recordId = $this->getId();
|
|
} else {
|
|
$recordId = 'dummy';
|
|
}
|
|
|
|
if(!file_exists($path . DIRECTORY_SEPARATOR . $recordId)) {
|
|
@mkdir($path . DIRECTORY_SEPARATOR . $recordId . DIRECTORY_SEPARATOR, 0777, true);
|
|
}
|
|
|
|
if(file_exists($path . '/' . $recordId . DIRECTORY_SEPARATOR . $tmpid)) {
|
|
|
|
$tmpid = md5(microtime(false) . rand(10000,99999));
|
|
|
|
}
|
|
|
|
rename($filepath, $path . DIRECTORY_SEPARATOR . $recordId . DIRECTORY_SEPARATOR . $tmpid);
|
|
|
|
if(file_exists($path . DIRECTORY_SEPARATOR . $recordId . DIRECTORY_SEPARATOR . $tmpid)) {
|
|
|
|
$files[$filestoreid] = array('path' => $path . DIRECTORY_SEPARATOR . $recordId . DIRECTORY_SEPARATOR . $tmpid, 'name' => $filename, 'execid' => ($execID !== false ? $execID : \Workflow2::$currentBlockObj->getExecId()));
|
|
|
|
} else {
|
|
|
|
throw new \Exception('Workflow could not store file! ' . rtrim($root_directory, '/').'/modules/Workflow2/tmp/ must be writeable and existing!');
|
|
|
|
}
|
|
|
|
$this->_environment['_tmpfiles'] = $files;
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* return one tmpfile or all tmpfiles of the current environment
|
|
*
|
|
* @param string $tmpid [optional] FileStoreID to be returned. If not set, all Files will be returned
|
|
*
|
|
* @return array('path' => '/asd', 'name' => 'asd')
|
|
* path is complete filepath to file
|
|
*
|
|
*/
|
|
public function getTempFiles($tmpid = null) {
|
|
$files = $this->_environment['_tmpfiles'];
|
|
|
|
if(empty($files)) {
|
|
$files = array();
|
|
}
|
|
|
|
if($tmpid === null) {
|
|
|
|
return $files;
|
|
|
|
} else {
|
|
if(!isset($files[$tmpid])) {
|
|
return null;
|
|
}
|
|
|
|
return $files[$tmpid];
|
|
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param $execId
|
|
* @internal Function is used only internal
|
|
*/
|
|
public function unlinkTempFiles($execId) {
|
|
$files = $this->_environment['_tmpfiles'];
|
|
|
|
if(!empty($files)) {
|
|
foreach($files as $file) {
|
|
|
|
if($file['execid'] == $execId) {
|
|
@unlink($file['path']);
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if function is not related to a record
|
|
* @return bool
|
|
*/
|
|
public function isDummy() {
|
|
return $this->_isDummy;
|
|
}
|
|
|
|
/**
|
|
* @internal
|
|
*/
|
|
public function setIsNew($value) {
|
|
$this->_isNew = $value;
|
|
}
|
|
|
|
/**
|
|
* Check if Record was created or only modified
|
|
* @return bool
|
|
*/
|
|
public function isNew() {
|
|
return $this->_isNew;
|
|
}
|
|
|
|
/**
|
|
* Delete Record and move to trash
|
|
*/
|
|
public function delete() {
|
|
if($this->_isDummy) {
|
|
return;
|
|
}
|
|
|
|
$this->_deleted = true;
|
|
|
|
$this->prepareTransfer();
|
|
|
|
try {
|
|
|
|
$recordModel = \Vtiger_Record_Model::getInstanceById($this->_id, $this->getModuleName());
|
|
$recordModel->delete();
|
|
|
|
} catch(\Exception $exp) {
|
|
if($exp->getCode() == "DATABASE_QUERY_ERROR") {
|
|
global $adb;
|
|
$handleResult = $this->_handleDatabaseError($adb->database->_errorMsg);
|
|
$this->_data = array();
|
|
} else {
|
|
|
|
#error_log("ERROR RETRIEVE ".$this->getWsId()." ".$exp->getMessage());
|
|
\Workflow2::error_handler($exp->getCode(), $exp->getMessage(), $exp->getFile(), $exp->getLine());
|
|
}
|
|
}
|
|
|
|
$this->_data = array();
|
|
|
|
$this->afterTransfer();
|
|
}
|
|
|
|
/**
|
|
* Check if Record is still available
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function isAvailable() {
|
|
if(empty($this->_id)) {
|
|
return true;
|
|
}
|
|
|
|
if($this->_deleted === null) {
|
|
$adb = \PearDatabase::getInstance();
|
|
$sql = 'SELECT deleted FROM vtiger_crmentity WHERE crmid = ?';
|
|
$result = $adb->pquery($sql, array($this->_id));
|
|
|
|
$this->_deleted = $adb->query_result($result, 0, 'deleted') == '1';
|
|
}
|
|
|
|
return !$this->_deleted;
|
|
}
|
|
|
|
/**
|
|
* Get DetailURL for Record
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getDetailUrl() {
|
|
return "index.php?module=".$this->getModuleName()."&view=Detail&record=".$this->getId();
|
|
}
|
|
|
|
public function initData($data) {
|
|
$this->_data = $data;
|
|
}
|
|
|
|
/**
|
|
* Get all Fields of Record with values
|
|
*
|
|
* @return array|bool
|
|
* @throws \Exception
|
|
*
|
|
*/
|
|
public function getData() {
|
|
global $current_user, $adb;
|
|
|
|
if($this->_isDummy) {
|
|
if($this->_data === false) {
|
|
return array();
|
|
}
|
|
return $this->_data;
|
|
}
|
|
|
|
require_once 'include/Webservices/Retrieve.php';
|
|
|
|
if($this->_data === false) {
|
|
#$crmObj = CRMEntity::getInstance($this->_moduleName);
|
|
#$this->_data = $crmObj;
|
|
|
|
#$this->_data->id = $this->_id;
|
|
#$this->_data->mode = "edit";
|
|
#$data = $this->_data;
|
|
|
|
#$this->_data->retrieve_entity_info($this->_id, $this->_moduleName);
|
|
|
|
$this->prepareTransfer();
|
|
|
|
try {
|
|
$focus = CRMEntity::getInstance($this->getModuleName());
|
|
$focus->id = $this->_id;
|
|
$focus->mode = 'edit';
|
|
$focus->retrieve_entity_info($this->_id, $this->getModuleName());
|
|
// var_dump($focus->column_fields);
|
|
$this->_data = $focus->column_fields;
|
|
|
|
global $default_charset;
|
|
foreach($this->_data as $key => $value) {
|
|
$this->_data[$key] = decode_html($value);
|
|
}
|
|
|
|
if(($this->_moduleName == 'Products' || $this->_moduleName == 'Services') && !empty($this->_id)) {
|
|
$listPriceResult = $adb->pquery('SELECT * FROM vtiger_productcurrencyrel WHERE productid = ?', array($this->_id));
|
|
|
|
while($listPrice = $adb->fetchByAssoc($listPriceResult)) {
|
|
$this->_data["curname" . $listPrice['currencyid']] = floatval($listPrice['actual_price']);
|
|
}
|
|
}
|
|
|
|
/*
|
|
global $default_charset;
|
|
foreach($this->_data as $key => $value) {
|
|
$this->_data[$key] = html_entity_decode($value, ENT_QUOTES, $default_charset);
|
|
}
|
|
*/
|
|
|
|
/* both values are irrelevant use ->id and ->getModuleName() */
|
|
//unset($this->_data['record_id']);
|
|
//unset($this->_data['record_module']);
|
|
|
|
} catch(\Exception $exp) {
|
|
if($exp->getCode() == "DATABASE_QUERY_ERROR") {
|
|
global $adb;
|
|
$handleResult = $this->_handleDatabaseError($adb->database->_errorMsg);
|
|
$this->_data = array();
|
|
} elseif($exp->getCode() == "ACCESS_DENIED" && $exp->getMessage() == "Permission to perform the operation is denied") {
|
|
$sql = "SELECT setype FROM vtiger_crmentity WHERE crmid = ".$this->_id;
|
|
$checkTMP = $adb->query($sql);
|
|
if($adb->num_rows($checkTMP) == 0) {
|
|
#Workflow2::error_handler(E_NONBREAK_ERROR, "Record ".$this->_id." don't exist in the database. Maybe you try to load data from a group?", $exp->getFile(), $exp->getLine());
|
|
$this->_data = array();
|
|
return array();
|
|
}
|
|
if($adb->query_result($checkTMP, 0, "setype") != $this->getModuleName()) {
|
|
\Workflow2::error_handler(E_NONBREAK_ERROR, "You want to get a field from ".$this->getModuleName()." Module, but the ID is from module ".$adb->query_result($checkTMP, 0, "setype").".", $exp->getFile(), $exp->getLine());
|
|
$this->_data = array();
|
|
return array();
|
|
}
|
|
$entity = VTEntity::getForId($this->_id);
|
|
#if(empty($entit))
|
|
#var_dump($this->getModuleName());
|
|
#var_dump($this->_id);
|
|
} else {
|
|
|
|
#error_log("ERROR RETRIEVE ".$this->getWsId()." ".$exp->getMessage());
|
|
\Workflow2::error_handler($exp->getCode(), $exp->getMessage()." for UserID ".$useUser->id, $exp->getFile(), $exp->getLine());
|
|
}
|
|
}
|
|
|
|
$this->afterTransfer();
|
|
|
|
if($this->_moduleName == "Emails") {
|
|
require_once("include/Zend/Json.php");
|
|
//\Zend_Json::$useBuiltinEncoderDecoder = false;
|
|
$sql = "SELECT * FROM vtiger_emaildetails WHERE emailid = ".$this->getId();
|
|
$result = $adb->query($sql);
|
|
|
|
$to_email = $adb->query_result($result, 0, "to_email");
|
|
|
|
#if(VtUtils::is_utf8($to_email)) $to_email = utf8_encode($to_email);
|
|
if(is_array($to_email) || is_object($to_email)) {
|
|
throw new \Exception('Wrong input $to_email='.serialize($to_email));
|
|
}
|
|
|
|
//$this->_data["saved_to"] = implode(",", \Workflow\VtUtils::json_decode(html_entity_decode($to_email)));
|
|
$this->_data["from_email"] = $adb->query_result($result, 0, "from_email");
|
|
}
|
|
|
|
if($this->_moduleName == 'Products' || $this->_moduleName == 'Services') {
|
|
$recordModel = \Vtiger_Record_Model::getInstanceById($this->getId(), $this->getModuleName());
|
|
$taxes = $recordModel->getTaxClassDetails();
|
|
foreach($taxes as $tax) {
|
|
if($tax['check_value'] == '1') {
|
|
$this->_data[$tax['check_name']] = 'on';
|
|
$this->_data[$tax['taxname']] = $tax['percentage'];
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fix for vtiger bug
|
|
if($this->_moduleName == "SalesOrder" && $this->_data["enable_recurring"] == "0") {
|
|
$this->_data["invoicestatus"] = "AutoCreated";
|
|
}
|
|
|
|
}
|
|
|
|
#return $this->_data->column_fields;
|
|
return $this->_data;
|
|
}
|
|
|
|
/**
|
|
* Get ModuleName of Record
|
|
* @return string
|
|
*/
|
|
public function getModuleName() {
|
|
return $this->_moduleName;
|
|
}
|
|
|
|
/**
|
|
* Get WebserviceID of Record
|
|
* @return string
|
|
*/
|
|
public function getWsId() {
|
|
if($this->_isDummy) {
|
|
return "0x0";
|
|
}
|
|
|
|
return vtws_getWebserviceEntityId($this->_moduleName, $this->_id);
|
|
}
|
|
|
|
/**
|
|
* Clear complete Data and load on next access from database
|
|
*/
|
|
public function clearData() {
|
|
$this->_data = false;
|
|
}
|
|
|
|
/**
|
|
* Set a value of this record
|
|
*
|
|
* @param $key
|
|
* @param $value
|
|
* @throws \Exception
|
|
* @example <br/>
|
|
* $record->set('bill_city', 'Leipzig');
|
|
*/
|
|
public function set($key, $value) {
|
|
$data = $this->getData();
|
|
|
|
if(!isset($this->_data[$key]) || $this->_data[$key] != $value) {
|
|
$this->_data[$key] = $value;
|
|
$this->_changed = true;
|
|
}
|
|
|
|
if(defined('WFD-TRACEFIELDS')) {
|
|
if(self::$TraceFields === false) {
|
|
$tmp = explode(',', constant('WFD-TRACEFIELDS'));
|
|
foreach($tmp as $field) {
|
|
self::$TraceFields[$field] = true;
|
|
}
|
|
}
|
|
|
|
if(isset(self::$TraceFields[$key])) {
|
|
// @TODO: Trace Variable einfügen
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Get Single Field
|
|
* @param $key
|
|
* @return bool|int|string
|
|
* @throws \Exception
|
|
*/
|
|
public function get($key) {
|
|
|
|
if($key == "crmid")
|
|
return $this->_id;
|
|
if($key == "id")
|
|
return $this->_id;
|
|
if($key == "ModuleName")
|
|
return $this->getModuleName();
|
|
if($key == 'lastComment')
|
|
return \Workflow\VtUtils::getLastComment($this->_id);
|
|
if($key == 'last5Comments')
|
|
return \Workflow\VtUtils::getComments($this->_id, 5);
|
|
if($key == 'comments')
|
|
return \Workflow\VtUtils::getComments($this->_id);
|
|
if($key == 'current_user_id') {
|
|
$currentUser = \Users_Record_Model::getCurrentUserModel();
|
|
return $currentUser->getId();
|
|
}
|
|
|
|
if($key == 'smownerid')
|
|
$key = 'assigned_user_id';
|
|
|
|
$data = $this->getData();
|
|
|
|
if(!isset($data[$key]))
|
|
return false;
|
|
|
|
if(\Workflow2::$formatCurrencies === true && !$this->isDummy()) {
|
|
if(isset(self::$CurrencyFields[$this->getModuleName()][$key])) {
|
|
return \CurrencyField::convertToUserFormat($data[$key]);
|
|
}
|
|
}
|
|
|
|
return $data[$key];
|
|
}
|
|
|
|
/**
|
|
* Get ID
|
|
* @return int
|
|
*/
|
|
public function getId() {
|
|
return $this->_id;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get another Record, which is stored in a reference field
|
|
* Load Record ID from fieldvalue
|
|
* @param $module
|
|
* @param $field
|
|
* @return VTEntity
|
|
* @example <br/>
|
|
* $record = contact->getReference('Accounts', 'accountname');
|
|
*/
|
|
public function getReference($module, $field) {
|
|
if($field == "smownerid") {
|
|
$field = "assigned_user_id";
|
|
}
|
|
|
|
if(!empty($this->_references[$field]))
|
|
return $this->_references[$field];
|
|
|
|
$id = $this->get($field);
|
|
|
|
if(empty($id)) {
|
|
return self::getDummy();
|
|
}
|
|
|
|
if($module == 'ModuleName' && ($field == 'modifiedby' || $field == 'created_user_id')) {
|
|
$module = 'Users';
|
|
}
|
|
|
|
if($module === false) {
|
|
$module = $this->getModuleName();
|
|
}
|
|
|
|
$this->_references[$field] = self::getForId($id, $module);
|
|
|
|
return $this->_references[$field];
|
|
}
|
|
|
|
|
|
/**
|
|
* @internal
|
|
*/
|
|
protected function prepareTransfer() {
|
|
global $current_user, $oldCurrentUser, $currentModule;
|
|
if(self::$TransferPrepared === true) return;
|
|
self::$TransferPrepared = true;
|
|
|
|
if(empty(VTEntity::$_user)) {
|
|
VTEntity::$_user = $current_user;
|
|
}
|
|
|
|
$this->_oldRequest = $_REQUEST;
|
|
$this->_oldCurrentModule = $currentModule;
|
|
unset($_REQUEST);
|
|
$_REQUEST = $this->_saveRequest;
|
|
|
|
$useUser = \Users::getActiveAdminUser();
|
|
|
|
if(!empty($current_user)) {
|
|
$oldCurrentUser = clone $current_user;
|
|
} else {
|
|
$current_user = \Users::getActiveAdminUser();
|
|
$oldCurrentUser = clone $current_user;
|
|
}
|
|
|
|
if($current_user->is_admin != 'on') {
|
|
$current_user = $useUser;
|
|
}
|
|
|
|
$currentModule = $this->getModuleName();
|
|
|
|
\Workflow2::log($this->_id, 0, 0, 'Prepare Transfer to Record');
|
|
|
|
# Quotes absichern
|
|
$_REQUEST['ajxaction'] = 'DETAILVIEW';
|
|
#$_REQUEST['action'] = 'MassEditSave';
|
|
$_REQUEST['search'] = true;
|
|
$_REQUEST['submode'] = true;
|
|
unset($_REQUEST['tableblocks']);
|
|
/*
|
|
VTEntity::$_user->currency_decimal_separator = ".";
|
|
VTEntity::$_user->currency_grouping_separator = "";
|
|
VTEntity::$_user->column_fields["currency_decimal_separator"] = ".";
|
|
VTEntity::$_user->column_fields["currency_grouping_separator"] = "";
|
|
|
|
$current_user->currency_decimal_separator = ".";
|
|
$current_user->currency_grouping_separator = "";
|
|
|
|
$current_user->column_fields["currency_decimal_separator"] = ".";
|
|
$current_user->column_fields["currency_grouping_separator"] = "";
|
|
*/
|
|
if($this->getModuleName() == "Contacts") {
|
|
$_FILES = array("index" => array("name" => "", "size" => 0));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @internal
|
|
*/
|
|
protected function afterTransfer() {
|
|
if(self::$TransferPrepared === false) return;
|
|
|
|
global $current_user, $oldCurrentUser, $currentModule;
|
|
|
|
$_REQUEST = $this->_oldRequest;
|
|
$current_user = $oldCurrentUser;
|
|
$currentModule = $this->_oldCurrentModule;
|
|
|
|
self::$TransferPrepared = false;
|
|
}
|
|
|
|
/**
|
|
* @internal
|
|
*/
|
|
protected function createRecord() {
|
|
global $current_user;
|
|
global $adb;
|
|
|
|
if($this->_isDummy) {
|
|
return;
|
|
}
|
|
|
|
require_once("include/Webservices/Create.php");
|
|
$this->prepareTransfer();
|
|
|
|
// WICHTIG!
|
|
if($this->_moduleName == "Events") {
|
|
$_REQUEST["set_reminder"] = "No";
|
|
} else {
|
|
$_REQUEST["set_reminder"] = "Yes";
|
|
}
|
|
|
|
try {
|
|
$newEntity = CRMEntity::getInstance($this->getModuleName());
|
|
$newEntity->mode = '';
|
|
$metaHandler = self::getMetaHandler($this->getModuleName());
|
|
|
|
// $ownerFields = $metaHandler->getOwnerFields();
|
|
$moduleFields = $metaHandler->getModuleFields();
|
|
|
|
$_REQUEST = $this->fillRequest();
|
|
|
|
foreach($this->_data as $key => $newValue) {
|
|
$fieldInstance = $moduleFields[$key];
|
|
if(empty($fieldInstance)) {
|
|
$newEntity->column_fields[$key] = $newValue;
|
|
//throw new \Exception('Field '.$key.' not found in module '.$this->getModuleName().'.');
|
|
} else {
|
|
$fieldDataType = $fieldInstance->getFieldDataType();
|
|
|
|
if('currency' == $fieldDataType) {
|
|
$newValue = \CurrencyField::convertToUserFormat($newValue);
|
|
}
|
|
|
|
if('reference' == $fieldDataType || 'owner' == $fieldDataType) {
|
|
$newValue = $this->getCrmId($newValue, $fieldInstance);
|
|
|
|
}
|
|
|
|
$newEntity->column_fields[$key] = $newValue;
|
|
}
|
|
}
|
|
|
|
$newEntity = $this->modifyValuesBeforeSave($newEntity);
|
|
|
|
if(!empty($this->_data['cf_team']) && is_string($this->_data['cf_team'])) {
|
|
$_REQUEST['cf_team'] = explode(' |##| ', $this->_data['cf_team']);
|
|
} else {
|
|
unset($_REQUEST['cf_team']);
|
|
}
|
|
|
|
$newEntity->save($this->getModuleName());
|
|
|
|
} catch(\Exception $exp) {
|
|
// var_dump($exp);
|
|
if($exp->getCode() == "DATABASE_QUERY_ERROR") {
|
|
$handleResult = $this->_handleDatabaseError($adb->database->_errorMsg);
|
|
return;
|
|
}
|
|
|
|
if($exp->getCode() == "MANDATORY_FIELDS_MISSING") {
|
|
$handleResult = $this->_handleMandatoryError($exp);
|
|
if($handleResult !== false) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
\Workflow2::error_handler($exp->getCode(), $exp->getMessage(), $exp->getFile(), $exp->getLine());
|
|
}
|
|
|
|
$this->afterTransfer();
|
|
|
|
$this->_id = $this->getCrmId($newEntity->id);
|
|
|
|
if(!empty($this->_data['smcreatorid'])) {
|
|
$sql = 'UPDATE vtiger_crmentity SET smcreatorid = ? WHERE crmid = ?';
|
|
$adb->pquery($sql, array($this->_data['smcreatorid'], $this->_id));
|
|
} else {
|
|
$sql = 'UPDATE vtiger_crmentity SET smcreatorid = ? WHERE crmid = ?';
|
|
$adb->pquery($sql, array($current_user->id, $this->_id));
|
|
}
|
|
|
|
$wsid = vtws_getWebserviceEntityId($this->getModuleName(), $this->_id);
|
|
$this->_wsid = $wsid;
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Helper to get CRMID of Parameter. Could also used to get ID to Record Handle, if FieldInstance is set
|
|
*
|
|
* Return false if no ID could resolved
|
|
*
|
|
* @param $idString
|
|
* @param \WebserviceField $fieldInstance
|
|
* @return int|bool
|
|
*/
|
|
public function getCrmId($idString, $fieldInstance = null) {
|
|
if(is_numeric($idString)) {
|
|
return $idString;
|
|
}
|
|
|
|
if($fieldInstance !== null && !empty($idString)) {
|
|
$modules = \VtUtils::getModuleForReference($fieldInstance->getTabId(), $fieldInstance->getFieldName(), $fieldInstance->getUIType());
|
|
if($modules[0] === 'Users') {
|
|
global $adb;
|
|
|
|
$sql = 'SELECT id FROM vtiger_users WHERE user_name = ? AND `status` = "Active"';
|
|
|
|
$result = $adb->pquery($sql, array($idString));
|
|
if($adb->num_rows($result) > 0) {
|
|
return $adb->query_result($result, 0, 'id');
|
|
}
|
|
}
|
|
}
|
|
|
|
if(strpos($idString, "x") !== false) {
|
|
$idParts = explode("x", $idString);
|
|
return $idParts[1];
|
|
}
|
|
|
|
if(strpos($idString, "@") !== false) {
|
|
$id = explode("@", $idString);
|
|
return $id[0];
|
|
}
|
|
|
|
if($fieldInstance !== null && !empty($idString)) {
|
|
global $adb;
|
|
$sql = 'SELECT * FROM vtiger_crmentity WHERE setype IN ("'.implode('","', $modules).'") AND label = ? AND deleted = 0';
|
|
|
|
$result = $adb->pquery($sql, array($idString));
|
|
if($adb->num_rows($result) > 0) {
|
|
return $adb->query_result($result, 0, 'crmid');
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/** EntityData Functions BEGIN */
|
|
|
|
/**
|
|
* Permanently add a new Key and a related Value to database
|
|
* EntityData could be used to permanently store values
|
|
*
|
|
* @param string $key Key to be added
|
|
* @param mixed $value Value to be added
|
|
* @param mixed $assigned_to User, which create the Key
|
|
* @param string $mode Simple|Multi Could one Key exist mulitple time
|
|
*
|
|
* Function set the EntityData into the Record and replace if $mode = simple and key already exist
|
|
*/
|
|
public function addEntityData($key, $value, $assigned_to = false, $mode = "simple") {
|
|
global $adb;
|
|
|
|
if($mode == "simple") {
|
|
$this->removeEntityData($key);
|
|
|
|
$sql = "INSERT INTO vtiger_wf_entityddata SET crmid = ?, `key` = ?, `value` = ?, assigned_to = ?, `mode` = ?";
|
|
$adb->pquery($sql, array($this->_id, $key, @serialize($value), $assigned_to, $mode));
|
|
} else {
|
|
$sql = "INSERT INTO vtiger_wf_entityddata SET crmid = ?, `key` = ?, `value` = ?, assigned_to = ?, `mode` = ?";
|
|
$adb->pquery($sql, array($this->_id, $key, @serialize($value), $assigned_to, $mode));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get EntityData Value to a key
|
|
*
|
|
* @param $key key to be loaded
|
|
* @return mixed
|
|
* @throws \Exception
|
|
*/
|
|
public function getEntityData($key) {
|
|
global $adb;
|
|
|
|
$sql = "SELECT * FROM vtiger_wf_entityddata WHERE crmid = ? AND `key` = ?";
|
|
$result = $adb->pquery($sql, array($this->_id, $key));
|
|
|
|
if($adb->num_rows($result) == 0) {
|
|
return -1;
|
|
}
|
|
|
|
$return = array();
|
|
while($row = $adb->fetchByAssoc($result)) {
|
|
if(is_array($row["value"]) || is_object($row["value"])) {
|
|
throw new \Exception('Wrong input VTEntity::'.__LINE__.'='.serialize($row["value"]));
|
|
}
|
|
|
|
if($row["mode"] == "simple") {
|
|
$return = @unserialize(html_entity_decode($row["value"], ENT_QUOTES));
|
|
break;
|
|
} else {
|
|
$return[] = @unserialize(html_entity_decode($row["value"], ENT_QUOTES));
|
|
}
|
|
}
|
|
|
|
return $return;
|
|
}
|
|
|
|
/**
|
|
* Remove a EntityData by Key and ID (used internally)
|
|
*
|
|
* @param $key Key to remove
|
|
* @param bool $dataID
|
|
*
|
|
*/
|
|
public function removeEntityData($key, $dataID = false) {
|
|
global $adb;
|
|
|
|
$sql = "DELETE FROM vtiger_wf_entityddata WHERE `crmid` = ? AND `key` = ?".($dataID!==false?" AND dataid = ?":"");
|
|
$values = array($this->_id, $key);
|
|
if($dataID !== false) {
|
|
$values[] = $dataID;
|
|
}
|
|
|
|
$adb->pquery($sql, $values);
|
|
}
|
|
|
|
/**
|
|
* Check if EntityData exists by Key
|
|
* @param $key Key to be checked
|
|
* @return bool
|
|
*/
|
|
public function existEntityData($key) {
|
|
global $adb;
|
|
|
|
$sql = "SELECT crmid FROM vtiger_wf_entityddata WHERE crmid = ? AND `key` = ?";
|
|
$result = $adb->pquery($sql, array($this->_id, $key));
|
|
|
|
if($adb->num_rows($result) > 0) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
/** EntityData Functions END */
|
|
|
|
/**
|
|
* @param $exp
|
|
* @return bool
|
|
* @internal
|
|
* @throws \Exception
|
|
*/
|
|
protected function _handleMandatoryError($exp) {
|
|
$fieldname = trim(substr($exp->getMessage(), 0, strpos($exp->getMessage(), " ")));
|
|
$sql = "SELECT defaultvalue FROM vtiger_field WHERE tabid = '".getTabid($this->getModuleName())."' AND columnname = ?";
|
|
global $adb;
|
|
$defaultRST = $adb->pquery($sql, array($fieldname));
|
|
$defaultValue = $adb->query_result($defaultRST, 0, "defaultvalue");
|
|
if(!empty($defaultValue)) {
|
|
$this->set($fieldname, $defaultValue);
|
|
$this->save();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @param $errorMsg
|
|
* @internal
|
|
*/
|
|
public function _handleDatabaseError($errorMsg) {
|
|
\Workflow2::error_handler("Database Query error", $errorMsg, "", "");
|
|
}
|
|
|
|
protected function fillRequest() {
|
|
|
|
if($this->_moduleName == 'Products' || $this->_moduleName == 'Services') {
|
|
$currency_details = getAllCurrencies('all');
|
|
foreach($currency_details as $currency) {
|
|
if(!empty($this->_data["curname".$currency['curid']])) {
|
|
$this->_data['cur_' . $currency['curid'] . '_check'] = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $this->_data;
|
|
}
|
|
|
|
/**
|
|
* Save all modifications permanent in database
|
|
* @return void
|
|
*/
|
|
public function save() {
|
|
if($this->_data == false) {
|
|
return;
|
|
}
|
|
if($this->_isDummy) {
|
|
return;
|
|
}
|
|
|
|
if(empty($this->_id)) {
|
|
$result = $this->createRecord();
|
|
|
|
return $result;
|
|
}
|
|
if(!$this->isAvailable()) {
|
|
return;
|
|
}
|
|
|
|
if($this->_changed == false)
|
|
return;
|
|
|
|
|
|
//var_dump('save');
|
|
//var_dump(debug_backtrace(false, 4));
|
|
// I must prevent $ajaxSave to come true in vtws_update. This will remove all date fields !
|
|
|
|
self::$RecordStored[$this->_id] = true;
|
|
|
|
global $default_charset;
|
|
|
|
\Workflow2::log($this->_id, 0, 0, "Save Record");
|
|
|
|
$this->prepareTransfer();
|
|
$oldFiles = $_FILES;
|
|
|
|
try {
|
|
require_once('data/CRMEntity.php');
|
|
$metaHandler = self::getMetaHandler($this->getModuleName());
|
|
|
|
$_REQUEST = $this->fillRequest();
|
|
|
|
$focus = CRMEntity::getInstance($this->getModuleName());
|
|
$focus->id = $this->_id;
|
|
$focus->mode = 'edit';
|
|
$focus->retrieve_entity_info($this->_id, $this->getModuleName());
|
|
|
|
$focus->clearSingletonSaveFields();
|
|
$focus->column_fields = \DataTransform::sanitizeDateFieldsForInsert( $focus->column_fields, $metaHandler);
|
|
$focus->column_fields = \DataTransform::sanitizeCurrencyFieldsForInsert( $focus->column_fields, $metaHandler);
|
|
$moduleFields = $metaHandler->getModuleFields();
|
|
|
|
$changed = $this->_data->getChanged();
|
|
|
|
foreach($changed as $key) {
|
|
if(substr($key, -4) == '_raw' && isset($focus->column_fields[substr($key, 0, -4)])) continue;
|
|
if(preg_match('/tax[0-9]+_check/', $key)) continue;
|
|
|
|
if($this->getModuleName() == 'Products' || $this->getModuleName() == 'Services') {
|
|
if (substr($key, 0, 7) == 'curname') continue;
|
|
if (substr($key, 0, 4) == 'cur_' && substr($key, -6) == '_check') continue;
|
|
}
|
|
|
|
//var_dump(substr($key, 0, 7));
|
|
if(!in_array($key, array('record_id', 'record_module', 'label', 'file', 'action', 'ajxaction', 'loop'))) {
|
|
//var_dump($key, $this->_data[$key], $value);
|
|
$newValue = $this->_data[$key];
|
|
$fieldInstance = $moduleFields[$key];
|
|
|
|
if(empty($fieldInstance) && !in_array(array('file', 'action', 'ajxaction', 'loop'), $key)) {
|
|
if(in_array($key, array('file', 'action', 'ajxaction', 'loop'))) {
|
|
continue;
|
|
}
|
|
|
|
throw new \Exception('Field '.$key.' not found in module '.$this->getModuleName().'.');
|
|
}
|
|
$fieldDataType = $fieldInstance->getFieldDataType();
|
|
|
|
if('currency' == $fieldDataType) {
|
|
$newValue = \CurrencyField::convertToUserFormat($newValue);
|
|
if($focus->column_fields[$key] == $newValue) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if('reference' == $fieldDataType || 'owner' == $fieldDataType) {
|
|
$newValue = $this->getCrmId($newValue, $fieldInstance);
|
|
if($focus->column_fields[$key] == $newValue) {
|
|
continue;
|
|
}
|
|
}
|
|
//var_dump('set');
|
|
$focus->column_fields[$key] = $newValue;
|
|
}
|
|
if(!empty($moduleFields[$key]) && $moduleFields[$key]->getFieldDataType() == 'date') {
|
|
if (preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) [0-9]{2}:[0-9]{2}:[0-9]{2}$/", $value)) {
|
|
$parts = explode(' ', $value);
|
|
$focus->column_fields[$key] = $value = $parts[0];
|
|
}
|
|
}
|
|
if(!empty($moduleFields[$key]) && $moduleFields[$key]->getFieldDataType() == 'time') {
|
|
if (preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/", $value)) {
|
|
$focus->column_fields[$key] = $value = date('H:i:s');
|
|
}
|
|
if (preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) [0-9]{2}:[0-9]{2}:[0-9]{2}$/", $value)) {
|
|
$parts = explode(' ', $value);
|
|
$focus->column_fields[$key] = $value = $parts[1];
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach ($focus->column_fields as $fieldName => $fieldValue) {
|
|
if(is_array($fieldValue)) {
|
|
throw new \Exception('Wrong input VTEntity::'.__LINE__.'='.serialize($fieldValue));
|
|
}
|
|
|
|
$focus->column_fields[$fieldName] = html_entity_decode($fieldValue, ENT_QUOTES, $default_charset);
|
|
}
|
|
|
|
$focus = $this->modifyValuesBeforeSave($focus);
|
|
|
|
if(!empty($focus->colum_fields['cf_team']) && is_string($focus->colum_fields['cf_team'])) {
|
|
$_REQUEST['cf_team'] = explode(' |##| ', $focus->colum_fields['cf_team']);
|
|
} else {
|
|
unset($_REQUEST['cf_team']);
|
|
}
|
|
|
|
$_REQUEST['file'] = '';
|
|
$_REQUEST['ajxaction'] = '';
|
|
|
|
// Added as Mass Edit triggers workflow and date and currency fields are set to user format
|
|
// When saving the information in database saveentity API should convert to database format
|
|
// and save it. But it converts in database format only if that date & currency fields are
|
|
// changed(massedit) other wise they wont be converted thereby changing the values in user
|
|
// format, CRMEntity.php line 474 has the login to check wheather to convert to database format
|
|
$actionName = $_REQUEST['action'];
|
|
$_REQUEST['action'] = '';
|
|
//var_dump($focus->column_fields);
|
|
// For workflows update field tasks is deleted all the lineitems.
|
|
$focus->isLineItemUpdate = $this->LineUpdaterMode;
|
|
|
|
$this->_changed = false;
|
|
|
|
$adb = \PearDatabase::getInstance();
|
|
$minModTrackerIndex = 0;
|
|
$sql = 'SELECT MAX(id) as max FROM vtiger_modtracker_basic WHERE crmid = '.$this->_id;
|
|
$result = $adb->query($sql);
|
|
if($adb->num_rows($result) > 0) $minModTrackerIndex = $adb->query_result($result, 0, 'max');
|
|
if(empty($minModTrackerIndex)) $minModTrackerIndex = 0;
|
|
// $tmpEnvironment = $this->_environment;
|
|
|
|
$focus->save($this->getModuleName());
|
|
// $this->_environment = $tmpEnvironment;
|
|
|
|
global $oldCurrentUser;
|
|
$sql = 'UPDATE vtiger_crmentity SET modifiedby = ? WHERE crmid = '.$this->_id;
|
|
\PearDatabase::getInstance()->pquery($sql, array($oldCurrentUser->id));
|
|
|
|
$sql = 'UPDATE vtiger_modtracker_basic SET whodid = ? WHERE crmid = '.$this->_id.' AND id > '.$minModTrackerIndex;
|
|
\PearDatabase::getInstance()->pquery($sql, array($oldCurrentUser->id));
|
|
|
|
} catch(\Exception $exp) {
|
|
ExecutionLogger::getCurrentInstance()->log('Error: '.$exp->getMessage());
|
|
|
|
if($exp->getCode() == "MANDATORY_FIELDS_MISSING") {
|
|
$handleResult = $this->_handleMandatoryError($exp);
|
|
if($handleResult !== false) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
throw $exp;
|
|
//\Workflow2::error_handler($exp->getCode(), $exp->getMessage(), $exp->getFile(), $exp->getLine());
|
|
}
|
|
$this->afterTransfer();
|
|
|
|
$this->_changed = false;
|
|
$_FILES = $oldFiles;
|
|
|
|
unset(VTEntity::$_cache[VTEntity::$_user->id][$this->_id]);
|
|
|
|
if(!$this instanceof VTInventoryEntity) {
|
|
$this->_data = false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param $focus
|
|
* @return mixed
|
|
* @internal
|
|
*/
|
|
public function modifyValuesBeforeSave($focus) {
|
|
return $focus;
|
|
}
|
|
|
|
/**
|
|
* @param $module
|
|
* @return mixed
|
|
* @internal
|
|
*/
|
|
public static function GetMetaHandler($module) {
|
|
if(isset(self::$_cache['metaHandler_'.$module])) {
|
|
return self::$_cache['metaHandler_'.$module];
|
|
}
|
|
|
|
global $current_user;
|
|
|
|
$moduleHandler = vtws_getModuleHandlerFromName($module, $current_user);
|
|
self::$_cache['metaHandler_'.$module] = $moduleHandler->getMeta();
|
|
|
|
return self::$_cache['metaHandler_'.$module];
|
|
}
|
|
|
|
/**
|
|
* Get Record_Model of this record.
|
|
*
|
|
* Modifications not saved to database won't be available
|
|
*
|
|
* @return \Vtiger_Record_Model
|
|
*/
|
|
public function getModel() {
|
|
if($this->_isDummy) {
|
|
return false;
|
|
}
|
|
|
|
$this->save();
|
|
|
|
return \Vtiger_Record_Model::getInstanceById($this->_id, $this->_moduleName);
|
|
}
|
|
|
|
/**
|
|
* Get CRMEntity of record
|
|
*
|
|
* Modifications not saved to database won't be available
|
|
*
|
|
* @return \CRMEntity
|
|
*/
|
|
public function getInternalObject() {
|
|
if($this->_isDummy) {
|
|
return false;
|
|
}
|
|
|
|
if($this->_internalObj !== false) {
|
|
return $this->_internalObj;
|
|
} else {
|
|
$obj = CRMEntity::getInstance($this->_moduleName);
|
|
$obj->id = $this->_id;
|
|
$obj->retrieve_entity_info($this->_id,$this->_moduleName);
|
|
$this->_internalObj = $obj;
|
|
}
|
|
|
|
return $this->_internalObj;
|
|
}
|
|
|
|
/**
|
|
* Create new Record
|
|
*
|
|
* @param $module ModuleName of new Recor
|
|
* @return VTEntity|\Workflow\VTInventoryEntity
|
|
*/
|
|
public static function create($module) {
|
|
$moduleObj = \Vtiger_Module_Model::getInstance($module);
|
|
if($moduleObj instanceof \Inventory_Module_Model) {
|
|
return new VTInventoryEntity($module, 0);
|
|
} else {
|
|
return new VTEntity($module, 0);
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* @throws \Exception
|
|
* @internal
|
|
*/
|
|
public function redirectToCreationForm() {
|
|
$data = $this->getData();
|
|
if($this->isInventory()) {
|
|
$data = array_merge($data, $this->getProductFields());
|
|
}
|
|
?>
|
|
<form method="POST" id="submitCreationForm" name="submitCreationForm" action="index.php?module=<?php echo $this->getModuleName(); ?>&view=Edit">
|
|
<?php foreach($data as $field => $value) {
|
|
echo '<input type="hidden" name="'.$field.'" value="'.htmlentities($value).'" />';
|
|
}
|
|
?>
|
|
</form>
|
|
<script type="text/javascript">document.forms["submitCreationForm"].submit();</script>
|
|
<?php
|
|
exit();
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public function __toString() {
|
|
return ''.$this->getId();
|
|
}
|
|
|
|
/**
|
|
* @param $values
|
|
* @internal
|
|
*/
|
|
public function importInventory($values) {}
|
|
|
|
/**
|
|
* @return bool
|
|
* @internal
|
|
*/
|
|
public function exportInventory() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Function get a dummy Entity, which don't represent a Record
|
|
*
|
|
* @return VTEntity
|
|
*/
|
|
public static function getDummy() {
|
|
return new VTEntity("dummy", 0);
|
|
}
|
|
|
|
public function getCRMRecordLabel() {
|
|
if($this->_moduleName != 'Users') {
|
|
|
|
if($this->_changed == true) {
|
|
$metainfo = \Vtiger_Functions::getEntityModuleInfo($this->_moduleName);
|
|
$columns = explode(',', $metainfo['fieldname']);
|
|
|
|
$tabid = getTabid($this->_moduleName);
|
|
$labelValues = array();
|
|
|
|
foreach($columns as $col) {
|
|
$fieldName = VtUtils::getFieldName($col, $tabid);
|
|
$labelValues[] = $this->get($fieldName);
|
|
}
|
|
|
|
return implode(' ', $labelValues);
|
|
} else {
|
|
$label = \Vtiger_Functions::getCRMRecordLabel($this->_id);
|
|
|
|
if(empty($label)) {
|
|
$label = \Vtiger_Functions::computeCRMRecordLabels($this->_moduleName, array($this->_id));
|
|
$label = $label[$this->_id];
|
|
}
|
|
|
|
return $label;
|
|
}
|
|
|
|
|
|
} else {
|
|
return \Vtiger_Functions::getUserRecordLabel($this->_id);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
?>
|