modules/Settings/AutomaticAssignment/models/Record.php
<?php
/**
* Automatic Assignment Record Model Class.
*
* @copyright YetiForce S.A.
* @license YetiForce Public License 6.5 (licenses/LicenseEN.txt or yetiforce.com)
* @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com>
*/
class Settings_AutomaticAssignment_Record_Model extends Settings_Vtiger_Record_Model
{
/** @var array Record changes */
protected $changes = [];
/**
* Function to get the Id.
*
* @return int Role Id
*/
public function getId()
{
return $this->get('id');
}
/**
* Function to set the id of the record.
*
* @param int $value - id value
*/
public function setId($value)
{
return $this->set('id', (int) $value);
}
/**
* Function to get the Role Name.
*
* @return string
*/
public function getName()
{
return $this->get('subject');
}
/**
* Function to get Module instance.
*
* @return Settings_AutomaticAssignment_Module_Model
*/
public function getModule()
{
return $this->module;
}
/**
* Set module Instance.
*
* @param Settings_AutomaticAssignment_Module_Model $moduleModel
*
* @return Settings_AutomaticAssignment_Module_Model
*/
public function setModule($moduleModel)
{
return $this->module = $moduleModel;
}
/**
* Function to get table name.
*
* @return string
*/
public function getTable()
{
return $this->getModule()->baseTable;
}
/**
* Function to get table primary key.
*
* @return string
*/
public function getTableIndex()
{
return $this->getModule()->baseIndex;
}
/**
* Function to get the Edit View Url.
*
* @return string
*/
public function getEditViewUrl()
{
return $this->getModule()->getEditViewUrl() . '&record=' . $this->getId();
}
/**
* Function removes record.
*
* @return bool
*/
public function delete()
{
$db = App\Db::getInstance('admin');
$recordId = $this->getId();
if ($recordId) {
$result = $db->createCommand()->delete($this->getTable(), ['id' => $recordId])->execute();
}
$this->updateHandler();
return !empty($result);
}
/**
* Function to save.
*/
public function save()
{
$db = App\Db::getInstance('admin');
$transaction = $db->beginTransaction();
try {
$this->saveToDb();
$this->updateHandler();
$transaction->commit();
} catch (\Throwable $ex) {
$transaction->rollBack();
\App\Log::error($ex->__toString());
throw $ex;
}
}
/**
* Save data to the database.
*/
public function saveToDb()
{
$db = \App\Db::getInstance('admin');
$tablesData = $this->getId() ? array_intersect_key($this->getData(), $this->changes) : array_intersect_key($this->getData(), array_flip($this->getModule()->getEditableFields()));
if ($tablesData) {
$baseTable = $this->getModule()->baseTable;
$baseTableIndex = $this->getModule()->baseIndex;
foreach ($this->getValuesToSave($tablesData) as $tableName => $tableData) {
if (!$this->getId() && $baseTable === $tableName) {
$db->createCommand()->insert($tableName, $tableData)->execute();
$this->setId((int) $db->getLastInsertID("{$baseTable}_id_seq"));
} elseif ($baseTable === $tableName) {
$db->createCommand()->update($tableName, $tableData, [$baseTableIndex => $this->getId()])->execute();
} else {
$db->createCommand()->delete($tableName, ['id' => $this->getId()])->execute();
if ($tableData) {
$names = $tableData['names'];
$names[] = 'id';
foreach ($tableData['values'] as &$values) {
$values[] = $this->getId();
}
$db->createCommand()->batchInsert($tableName, $names, $tableData['values'])->execute();
}
}
}
}
}
/**
* Function formats data for saving.
*
* @param array $data
*
* @return array
*/
private function getValuesToSave(array $data): array
{
if (!$this->getId()) {
$forSave[$this->getModule()->baseTable] = [];
}
foreach ($data as $fieldName => $value) {
$fieldModel = $this->getFieldInstanceByName($fieldName);
switch ($fieldName) {
case 'members':
$members = $fieldModel->getEditViewDisplayValue($value);
$tables = [
\App\PrivilegeUtil::MEMBER_TYPE_USERS => 's_#__auto_assign_users',
\App\PrivilegeUtil::MEMBER_TYPE_GROUPS => 's_#__auto_assign_groups',
\App\PrivilegeUtil::MEMBER_TYPE_ROLES => 's_#__auto_assign_roles',
\App\PrivilegeUtil::MEMBER_TYPE_ROLE_AND_SUBORDINATES => 's_#__auto_assign_roles'
];
foreach ($tables as $table) {
$forSave[$table] = [];
}
foreach ($members as $member) {
[$type, $id] = explode(':', $member);
$forSave[$tables[$type]]['names'] = ['member', 'type'];
$forSave[$tables[$type]]['values'][] = [$id, $type];
}
break;
default:
$forSave[$fieldModel->getTableName()][$fieldModel->getColumnName()] = $value;
break;
}
}
return $forSave;
}
/** {@inheritdoc} */
public function set($key, $value)
{
if ($this->getId() && !\in_array($key, ['id']) && (\array_key_exists($key, $this->value) && $this->value[$key] != $value)) {
$this->changes[$key] = $this->get($key);
}
return parent::set($key, $value);
}
/** {@inheritdoc} */
public function getRecordLinks(): array
{
$links = [];
$recordLinks = [
[
'linktype' => 'LISTVIEWRECORD',
'linklabel' => 'LBL_EDIT_RECORD',
'linkurl' => $this->getEditViewUrl(),
'linkicon' => 'yfi yfi-full-editing-view',
'linkclass' => 'btn btn-primary btn-sm'
],
[
'linktype' => 'LISTVIEWRECORD',
'linklabel' => 'LBL_DELETE_RECORD',
'linkurl' => 'javascript:Settings_AutomaticAssignment_List_Js.deleteById(' . $this->getId() . ')',
'linkicon' => 'fas fa-trash-alt',
'linkclass' => 'btn text-white btn-danger btn-sm'
],
];
foreach ($recordLinks as $recordLink) {
$links[] = Vtiger_Link_Model::getInstanceFromValues($recordLink);
}
return $links;
}
/**
* Function to get the instance, given id.
*
* @param int $id
*
* @return \self
*/
public static function getInstanceById(int $id)
{
$db = App\Db::getInstance('admin');
$instance = self::getCleanInstance();
$baseTable = $instance->getTable();
$baseIndex = $instance->getTableIndex();
$data = (new App\Db\Query())
->from($baseTable)
->where([$baseIndex => $id])
->one($db);
if ($data) {
$queryAll = null;
$customTables = $instance->getModule()->customFieldTable;
foreach ($customTables as $tableName => $index) {
$query = (new App\Db\Query())
->select(['member' => new \yii\db\Expression('CONCAT(type,\':\', member)')])
->from($tableName)
->where(["{$tableName}.{$index}" => $id]);
if ($queryAll) {
$queryAll->union($query, true);
} else {
$queryAll = $query;
}
}
$members = $queryAll->column($db);
$data['members'] = $instance->getFieldInstanceByName('members')->getUITypeModel()->getDBValue($members);
$instance->setData($data);
}
return $instance;
}
/**
* Function to get the clean instance.
*
* @return \self
*/
public static function getCleanInstance()
{
$cacheName = __CLASS__;
$key = 'Clean';
if (\App\Cache::staticHas($cacheName, $key)) {
return clone \App\Cache::staticGet($cacheName, $key);
}
$moduleInstance = Settings_Vtiger_Module_Model::getInstance('Settings:AutomaticAssignment');
$instance = new self();
$instance->module = $moduleInstance;
\App\Cache::staticSave($cacheName, $key, clone $instance);
return $instance;
}
/**
* Function to get the Display Value, for the current field type with given DB Insert Value.
*
* @param string $name
*
* @return string
*/
public function getDisplayValue(string $name)
{
switch ($name) {
case 'tabid':
$moduleName = \App\Module::getModuleName($this->get($name));
return \App\Language::translate($moduleName, $moduleName);
case 'state':
$label = empty($this->get($name)) ? 'PLL_INACTIVE' : 'PLL_ACTIVE';
return \App\Language::translate($label, $this->getModule()->getName(true));
case 'roleid':
return empty($this->get($name)) ? 'LBL_SYSTEM' : \App\Language::translate(\App\PrivilegeUtil::getRoleName($this->get($name)));
default:
break;
}
$fieldInstance = $this->getFieldInstanceByName($name);
return $fieldInstance->getDisplayValue($this->get($name));
}
/**
* Function checks if record is active.
*
* @return bool
*/
public function isActive()
{
return (bool) $this->get('active');
}
/**
* Default owner.
*
* @return int
*/
public function getDefaultOwner()
{
$owner = $this->get('assign');
if ('Users' === \App\Fields\Owner::getType($owner)) {
return \App\User::isExists($owner) ? $owner : 0;
}
return Settings_Groups_Record_Model::getInstance($owner) ? $owner : 0;
}
/**
* Function defines whether given tab in edit view should be refreshed after saving.
*
* @param string $name
*
* @return bool
*/
public function isRefreshTab($name)
{
if (\in_array($name, ['conditions', 'assign', 'value', 'roleid'])) {
return false;
}
return true;
}
/**
* Function returns field instances for given name.
*
* @param string $name
*
* @return Vtiger_Field_Model
*/
public function getFieldInstanceByName($name)
{
$fieldModel = $this->getModule()->getFieldInstanceByName($name);
if ($this->has($name)) {
$fieldModel->set('fieldvalue', $this->get($name) ?? '');
}
return $fieldModel;
}
/**
* Sets data from request.
*
* @param App\Request $request
*/
public function setDataFromRequest(App\Request $request)
{
foreach ($this->getModule()->getEditableFields() as $fieldName) {
if ($request->has($fieldName)) {
switch ($fieldName) {
case 'conditions':
case 'record_limit_conditions':
$value = \App\Json::encode(\App\Condition::getConditionsFromRequest($request->getArray($fieldName, \App\Purifier::TEXT)));
break;
case 'default_assign':
$fieldModel = $this->getFieldInstanceByName($fieldName);
$value = $request->getByType($fieldName, $fieldModel->get('purifyType'));
$fieldModel->getUITypeModel()->validate($value, true);
break;
default:
$fieldModel = $this->getFieldInstanceByName($fieldName);
$value = $request->getByType($fieldName, $fieldModel->get('purifyType'));
$fieldUITypeModel = $fieldModel->getUITypeModel();
$fieldUITypeModel->validate($value, true);
$value = $fieldModel->getDBValue($value);
break;
}
$this->set($fieldName, $value);
}
}
}
public function validate()
{
$response = [];
$isDuplicate = (new App\Db\Query())
->from($this->getModule()->baseTable)
->where(['subject' => $this->get('subject'), 'tabid' => $this->get('tabid')])
->andWhere(['not', [$this->getModule()->baseIndex => $this->getId()]])
->exists();
if ($isDuplicate) {
$response[] = [
'result' => false,
'hoverField' => 'subject',
'message' => App\Language::translate('LBL_DUPLICATE', $this->getModule()->getName(true))
];
}
return $response;
}
/**
* Get pervious value by field.
*
* @param string $fieldName
*
* @return mixed
*/
public function getPreviousValue(string $fieldName = '')
{
return $fieldName ? ($this->changes[$fieldName] ?? null) : $this->changes;
}
/**
* Update activate/remove handler.
*
* @return void
*/
public function updateHandler()
{
$db = \App\Db::getInstance('admin');
$handlerClass = 'Vtiger_AutoAssign_Handler';
$tableName = $this->getModule()->baseTable;
$modules = (new \App\Db\Query())->select(['vtiger_tab.name'])
->from($tableName)->innerJoin('vtiger_tab', "{$tableName}.tabid=vtiger_tab.tabid")
->where(['and', ["{$tableName}.state" => 1], ["{$tableName}.handler" => 1]])->distinct()->column($db);
if (!$modules) {
\App\EventHandler::deleteHandler($handlerClass);
} else {
$type = 'EntityBeforeSave';
$handlers = (new \App\Db\Query())->from('vtiger_eventhandlers')
->where(['handler_class' => $handlerClass, 'event_name' => $type])
->indexBy('event_name')->all();
if (isset($handlers[$type])) {
$data = ['include_modules' => implode(',', $modules), 'is_active' => 1];
\App\EventHandler::update($data, $handlers[$type]['eventhandler_id']);
} else {
\App\EventHandler::registerHandler($type, $handlerClass, implode(',', $modules), '', 1, true, 0, \App\EventHandler::SYSTEM);
}
}
}
}