Files
icehrm/core/src/Classes/BaseService.php
2021-06-27 17:42:39 +02:00

2017 lines
68 KiB
PHP

<?php
/**
* BaseService class serves as the core logic for managing the application and for handling most
* of the tasks related to retriving and saving data. This can be referred within any module using
* BaseService::getInstance()
*
@class BaseService
*/
namespace Classes;
use Classes\Crypt\AesCtr;
use Classes\Email\EmailSender;
use Classes\Exception\IceHttpException;
use Company\Common\Model\CompanyStructure;
use Employees\Common\Model\Employee;
use Employees\Common\Model\EmployeeApproval;
use FieldNames\Common\Model\CustomField;
use FieldNames\Common\Model\FieldNameMapping;
use Metadata\Common\Model\CalculationHook;
use Model\BaseModel;
use Model\DataEntryBackup;
use Model\Setting;
use Model\SystemData;
use Modules\Common\Model\Module;
use Permissions\Common\Model\Permission;
use Users\Common\Model\User;
use Users\Common\Model\UserRole;
use Utils\LogManager;
use Utils\SessionUtils;
class BaseService
{
public $nonDeletables = array();
public $errros = array();
public $userTables = array();
/* @var User $currentUser */
public $currentUser = null;
public $db = null;
public $auditManager = null;
/* @var NotificationManager $notificationManager */
public $notificationManager = null;
/* @var SettingsManager $settingsManager*/
public $settingsManager = null;
public $fileFields = null;
public $moduleManagers = null;
/* @var EmailSender $emailSender */
public $emailSender = null;
public $user = null;
public $historyManagers = array();
public $calculationHooks = array();
public $customFieldManager = null;
public $migrationManager = null;
public $modelClassMap = [];
public $customFieldsClassMap = [];
public $currentProfileId = false;
protected $cacheService = null;
protected $pro = null;
private static $me = null;
private function __construct()
{
}
/**
* Get the only instance created for BaseService
* @method getInstance
* @return {BaseService} BaseService object
*/
public static function getInstance()
{
if (empty(self::$me)) {
self::$me = new BaseService();
}
return self::$me;
}
/**
* Get an array of objects from database
* @method get
* @param $table {String} model class name of the table to retive data
* (e.g for Users table model class name is User)
* @param $mappingStr {String} a JSON string to specify fields of the $table should be mapped
* to other tables (e.g {"profile":["Profile","id","first_name+last_name"]} : this is how the
* profile field in Users table is mapped to Profile table. In this case users profile field
* will get filled by Profile first name and last name. The original value in User->profile
* field will get moved to User->profile_id)
* @param $filterStr {String} a JSON string to specify the ordering of the items
* (e.g {"job_title":"2","department":"2"} - this will select only items having
* job_title = 2 and department = 2)
* @param $orderBy {String} a string to specify the ordering (e.g in_time desc)
* @param string $limit {String} a string to specify the limit (e.g limit 2)
* @return {Array} an array of objects of type $table
*/
public function get($table, $mappingStr = null, $filterStr = null, $orderBy = null, $limit = null)
{
if (!empty($mappingStr)) {
$map = json_decode($mappingStr);
}
$nsTable = $this->getFullQualifiedModelClassName($table);
$obj = new $nsTable();
$this->checkSecureAccess("get", $obj, $table, $_REQUEST);
$query = "";
$queryData = array();
if (!empty($filterStr)) {
$filter = json_decode($filterStr, true);
if (!empty($filter)) {
if (method_exists($obj, 'getCustomFilterQuery')) {
$response = $obj->getCustomFilterQuery($filter);
$query = $response[0];
$queryData = $response[1];
} else {
$defaultFilterResp = $this->buildDefaultFilterQuery($filter);
$query = $defaultFilterResp[0];
$queryData = $defaultFilterResp[1];
}
}
}
if (empty($orderBy)) {
$orderBy = "";
} else {
$orderBy = " ORDER BY ".$orderBy;
}
if (in_array($table, $this->userTables)) {
$cemp = $this->getCurrentProfileId();
if (!empty($cemp)) {
$signInMappingField = SIGN_IN_ELEMENT_MAPPING_FIELD_NAME;
$list = $obj->Find($signInMappingField." = ?".$query.$orderBy, array_merge(array($cemp), $queryData));
} else {
$list = array();
}
} else {
LogManager::getInstance()->debug("Query: "."1=1".$query.$orderBy);
LogManager::getInstance()->debug("Query Data: ".print_r($queryData, true));
$list = $obj->Find("1=1".$query.$orderBy, $queryData);
}
$newList = array();
foreach ($list as $listObj) {
$newList[] = $this->cleanUpAdoDB($listObj);
}
if (!empty($mappingStr) && count($map)>0) {
$list = $this->populateMapping($newList, $map);
}
return $list;
}
public function getModelClassMap()
{
return $this->modelClassMap;
}
public function addModelClass($modelClass, $fullQualifiedName)
{
$this->modelClassMap[$modelClass] = $fullQualifiedName;
}
public function getCustomFieldClassMap()
{
$map = [];
foreach ($this->customFieldsClassMap as $key => $val) {
$map[] = [$key, $val];
}
return $map;
}
public function addCustomFieldClass($customFieldsClass, $objectName)
{
$this->customFieldsClassMap[$customFieldsClass] = $objectName;
}
public function getModelClassName($name)
{
return $this->getFullQualifiedModelClassName($name);
}
/**
* @param boolean $currentProfileId
*/
public function setCurrentProfileId($currentProfileId)
{
$this->currentProfileId = $currentProfileId;
}
public function buildDefaultFilterQuery($filter)
{
$query = "";
$queryData = array();
foreach ($filter as $k => $v) {
if (empty($v)) {
continue;
}
if (is_array($v)) {
if (empty($v)) {
continue;
}
$length = count($v);
for ($i = 0; $i<$length; $i++) {
if ($i == 0) {
$query.=" and (";
}
$query.=$k." = ?";
if ($i < $length -1) {
$query.=" or ";
} else {
$query.=")";
}
$queryData[] = $v[$i];
}
} else {
if (!empty($v) && $v != 'NULL') {
$query.=" and ".$k."=?";
if ($v == '__myid__') {
$v = $this->getCurrentProfileId();
}
$queryData[] = $v;
}
}
}
return array($query, $queryData);
}
public function getSortingData($req)
{
$data = array();
$data['sorting'] = $req['sorting'];
$columns = json_decode($req['cl'], true);
$data['column'] = $columns[$req['iSortCol_0']];
$data['order'] = $req['sSortDir_0'];
return $data;
}
public function getDataCount()
{
//Get Total row count
$totalRows = 0;
if (!isset($_REQUEST['objects'])) {
$countFilterQuery = "";
$countFilterQueryData = array();
if (!empty($_REQUEST['ft'])) {
$filter = json_decode($_REQUEST['ft']);
if (!empty($filter)) {
\Utils\LogManager::getInstance()->debug("Filter:" . print_r($filter, true));
if (method_exists($obj, 'getCustomFilterQuery')) {
$response = $obj->getCustomFilterQuery($filter);
$countFilterQuery = $response[0];
$countFilterQueryData = $response[1];
} else {
$defaultFilterResp = BaseService::getInstance()->buildDefaultFilterQuery($filter);
$countFilterQuery = $defaultFilterResp[0];
$countFilterQueryData = $defaultFilterResp[1];
}
}
}
if (in_array($table, BaseService::getInstance()->userTables)
&& !$skipProfileRestriction && !$isSubOrdinates) {
$cemp = BaseService::getInstance()->getCurrentProfileId();
$sql = "Select count(id) as count from "
. $obj->_table . " where " . SIGN_IN_ELEMENT_MAPPING_FIELD_NAME . " = ? " . $countFilterQuery;
array_unshift($countFilterQueryData, $cemp);
$rowCount = $obj->DB()->Execute($sql, $countFilterQueryData);
} else {
if ($isSubOrdinates) {
$cemp = BaseService::getInstance()->getCurrentProfileId();
$profileClass = BaseService::getInstance()->getFullQualifiedModelClassName(
ucfirst(SIGN_IN_ELEMENT_MAPPING_FIELD_NAME)
);
$subordinate = new $profileClass();
$subordinates = $subordinate->Find("supervisor = ?", array($cemp));
$cempObj = new \Employees\Common\Model\Employee();
$cempObj->Load("id = ?", array($cemp));
if ($obj->getUserOnlyMeAccessField() == 'id'
&& \Classes\SettingsManager::getInstance()->getSetting(
'System: Company Structure Managers Enabled'
) == 1
&& \Company\Common\Model\CompanyStructure::isHeadOfCompanyStructure($cempObj->department, $cemp)
) {
if (empty($subordinates)) {
$subordinates = array();
}
$childCompaniesIds = array();
if (\Classes\SettingsManager::getInstance()->getSetting(
'System: Child Company Structure Managers Enabled'
) == '1'
) {
$childCompaniesResp = \Company\Common\Model\CompanyStructure::getAllChildCompanyStructures(
$cempObj->department
);
$childCompanies = $childCompaniesResp->getObject();
foreach ($childCompanies as $cc) {
$childCompaniesIds[] = $cc->id;
}
} else {
$childCompaniesIds[] = $cempObj->department;
}
if (!empty($childCompaniesIds)) {
$childStructureSubordinates = $subordinate->Find(
"department in (" . implode(',', $childCompaniesIds) . ") and id != ?",
array($cemp)
);
$subordinates = array_merge($subordinates, $childStructureSubordinates);
}
}
$subordinatesIds = "";
foreach ($subordinates as $sub) {
if ($subordinatesIds != "") {
$subordinatesIds .= ",";
}
$subordinatesIds .= $sub->id;
}
if ($obj->allowIndirectMapping()) {
$indeirectEmployees = $subordinate->Find(
"indirect_supervisors IS NOT NULL and indirect_supervisors <> '' and status = 'Active'",
array()
);
foreach ($indeirectEmployees as $ie) {
$indirectSupervisors = json_decode($ie->indirect_supervisors, true);
if (in_array($cemp, $indirectSupervisors)) {
if ($subordinatesIds != "") {
$subordinatesIds .= ",";
}
$subordinatesIds .= $ie->id;
}
}
}
$sql = "Select count(id) as count from " . $obj->_table .
" where " . $obj->getUserOnlyMeAccessField() . " in (" . $subordinatesIds . ") "
. $countFilterQuery;
$rowCount = $obj->DB()->Execute($sql, $countFilterQueryData);
} else {
$sql = "Select count(id) as count from " . $obj->_table;
if (!empty($countFilterQuery)) {
$sql .= " where 1=1 " . $countFilterQuery;
}
$rowCount = $obj->DB()->Execute($sql, $countFilterQueryData);
}
}
}
if (isset($rowCount) && !empty($rowCount)) {
foreach ($rowCount as $cnt) {
$totalRows = $cnt['count'];
}
}
return $totalRows;
}
/**
* An extention of get method for the use of data tables with ability to search
* @method getData
* @param $table {String} model class name of the table to retive data
* (e.g for Users table model class name is User)
* @param $mappingStr {String} a JSON string to specify fields of the $table should
* be mapped to other tables (e.g {"profile":["Profile","id","first_name+last_name"]}
* : this is how the profile field in Users table is mapped to Profile table.
* In this case users profile field will get filled by Profile first name and last name.
* The original value in User->profile field will get moved to User->profile_id)
* @param $filterStr {String} a JSON string to specify the ordering of the items
* (e.g {"job_title":"2","department":"2"} - this will select only items having
* job_title = 2 and department = 2)
* @param $orderBy {String} a string to specify the ordering (e.g in_time desc)
* @param string $limit {String} a string to specify the limit (e.g limit 2)
* @param string $searchColumns {String} a JSON string to specify names of searchable
* fields (e.g ["id","employee_id","first_name","last_name","mobile_phone","department","gender","supervisor"])
* @param string $searchTerm {String} a string to specify term to search
* @param string $isSubOrdinates {Boolean} a Boolean to specify if we only need to retive
* subordinates. Any item is a subordinate item if the item has "profile" field defined
* and the value of "profile" field is equal to id of one of the subordinates of currenly
* logged in profile id. (Any Profile is a subordinate of curently logged in Profile if the
* supervisor field of a Profile is set to the id of currently logged in Profile)
* @param string $skipProfileRestriction {Boolean} default if false - TODO - I'll explain this later
* @return {Array} an array of objects of type $table
*/
public function getData(
$table,
$mappingStr = null,
$filterStr = null,
$orderBy = null,
$limit = null,
$searchColumns = null,
$searchTerm = null,
$isSubOrdinates = false,
$skipProfileRestriction = false,
$sortData = array()
) {
if (!empty($mappingStr)) {
$map = json_decode($mappingStr);
}
$nsTable = $this->getFullQualifiedModelClassName($table);
$obj = new $nsTable();
$this->checkSecureAccess("get", $obj, $table, $_REQUEST);
$query = "";
$queryData = array();
if (!empty($filterStr)) {
$filter = json_decode($filterStr);
if (!empty($filter)) {
LogManager::getInstance()->debug("Building filter query");
if (method_exists($obj, 'getCustomFilterQuery')) {
LogManager::getInstance()->debug("Method: getCustomFilterQuery exists");
$response = $obj->getCustomFilterQuery($filter);
$query = $response[0];
$queryData = $response[1];
} else {
LogManager::getInstance()->debug("Method: getCustomFilterQuery not found");
$defaultFilterResp = $this->buildDefaultFilterQuery($filter);
$query = $defaultFilterResp[0];
$queryData = $defaultFilterResp[1];
}
}
LogManager::getInstance()->debug("Filter Query:".$query);
LogManager::getInstance()->debug("Filter Query Data:".json_encode($queryData));
}
if (!empty($searchTerm) && !empty($searchColumns)) {
$searchColumnList = json_decode($searchColumns);
$searchColumnList = array_diff($searchColumnList, $obj->getVirtualFields());
if (!empty($searchColumnList)) {
$tempQuery = " and (";
foreach ($searchColumnList as $col) {
if ($tempQuery != " and (") {
$tempQuery.=" or ";
}
$tempQuery.=$col." like ?";
$queryData[] = "%".$searchTerm."%";
}
$query.= $tempQuery.")";
}
}
if (!empty($sortData) && $sortData['sorting']."" == "1" && isset($sortData['column'])) {
$orderBy = " ORDER BY ".$sortData['column']." ".$sortData['order'];
} else {
if (empty($orderBy)) {
$orderBy = "";
} else {
$orderBy = " ORDER BY ".$orderBy;
}
}
if (empty($limit)) {
$limit = "";
}
if (in_array($table, $this->userTables) && !$skipProfileRestriction) {
$cemp = $this->getCurrentProfileId();
if (!empty($cemp)) {
if (!$isSubOrdinates) {
array_unshift($queryData, $cemp);
//$signInMappingField = SIGN_IN_ELEMENT_MAPPING_FIELD_NAME;
$signInMappingField = $obj->getUserOnlyMeAccessField();
LogManager::getInstance()->debug(
"Data Load Query (x1):"."1=1".$signInMappingField." = ?".$query.$orderBy.$limit
);
LogManager::getInstance()->debug("Data Load Query Data (x1):".json_encode($queryData));
$list = $obj->Find($signInMappingField." = ?".$query.$orderBy.$limit, $queryData);
} else {
$profileClass = $this->getFullQualifiedModelClassName(ucfirst(SIGN_IN_ELEMENT_MAPPING_FIELD_NAME));
$subordinate = new $profileClass();
$subordinates = $subordinate->Find("supervisor = ?", array($cemp));
$cempObj = new Employee();
$cempObj->Load("id = ?", array($cemp));
if ($obj->getUserOnlyMeAccessField() == 'id' &&
SettingsManager::getInstance()->getSetting('System: Company Structure Managers Enabled') == 1 &&
CompanyStructure::isHeadOfCompanyStructure($cempObj->department, $cemp)) {
if (empty($subordinates)) {
$subordinates = array();
}
$childCompaniesIds = array();
if (SettingsManager::getInstance()->getSetting(
'System: Child Company Structure Managers Enabled'
) == '1'
) {
$childCompaniesResp = CompanyStructure::getAllChildCompanyStructures($cempObj->department);
$childCompanies = $childCompaniesResp->getObject();
foreach ($childCompanies as $cc) {
$childCompaniesIds[] = $cc->id;
}
} else {
$childCompaniesIds[] = $cempObj->department;
}
if (!empty($childCompaniesIds)) {
$childStructureSubordinates = $subordinate->Find(
"department in (" . implode(',', $childCompaniesIds) . ") and id != ?",
array($cemp)
);
$subordinates = array_merge($subordinates, $childStructureSubordinates);
}
}
$subordinatesIds = "";
foreach ($subordinates as $sub) {
if ($subordinatesIds != "") {
$subordinatesIds.=",";
}
$subordinatesIds.=$sub->id;
}
if ($obj->allowIndirectMapping()) {
$indeirectEmployees = $subordinate->Find(
"indirect_supervisors IS NOT NULL and indirect_supervisors <> '' and status = 'Active'",
array()
);
foreach ($indeirectEmployees as $ie) {
$indirectSupervisors = json_decode($ie->indirect_supervisors, true);
if (in_array($cemp, $indirectSupervisors)) {
if ($subordinatesIds != "") {
$subordinatesIds.=",";
}
$subordinatesIds.=$ie->id;
}
}
}
$signInMappingField = $obj->getUserOnlyMeAccessField();
LogManager::getInstance()->debug(
"Data Load Query (x2):"."1=1".$signInMappingField." in (".$subordinatesIds.") "
.$query.$orderBy.$limit
);
LogManager::getInstance()->debug("Data Load Query Data (x2):".json_encode($queryData));
if (!empty($subordinatesIds)) {
$list = $obj->Find(
$signInMappingField . " in (" . $subordinatesIds . ") " . $query . $orderBy . $limit,
$queryData
);
} else {
$list = array();
}
}
} else {
$list = array();
}
} elseif ($isSubOrdinates) {
$cemp = $this->getCurrentProfileId();
if (!empty($cemp)) {
$profileClass = $this->getFullQualifiedModelClassName(ucfirst(SIGN_IN_ELEMENT_MAPPING_FIELD_NAME));
$subordinate = new $profileClass();
$subordinates = $subordinate->Find("supervisor = ?", array($cemp));
$cempObj = new Employee();
$cempObj->Load("id = ?", array($cemp));
if ($obj->getUserOnlyMeAccessField() == 'id' &&
SettingsManager::getInstance()->getSetting('System: Company Structure Managers Enabled') == 1 &&
CompanyStructure::isHeadOfCompanyStructure($cempObj->department, $cemp)) {
if (empty($subordinates)) {
$subordinates = array();
}
$childCompaniesIds = array();
if (SettingsManager::getInstance()->getSetting(
'System: Child Company Structure Managers Enabled'
) == '1'
) {
$childCompaniesResp = CompanyStructure::getAllChildCompanyStructures($cempObj->department);
$childCompanies = $childCompaniesResp->getObject();
foreach ($childCompanies as $cc) {
$childCompaniesIds[] = $cc->id;
}
} else {
$childCompaniesIds[] = $cempObj->department;
}
if (!empty($childCompaniesIds)) {
$childStructureSubordinates = $subordinate->Find(
"department in (" . implode(',', $childCompaniesIds) . ") and id != ?",
array($cemp)
);
$subordinates = array_merge($subordinates, $childStructureSubordinates);
}
}
$subordinatesIds = "";
foreach ($subordinates as $sub) {
if ($subordinatesIds != "") {
$subordinatesIds.=",";
}
$subordinatesIds.=$sub->id;
}
if ($obj->allowIndirectMapping()) {
$indeirectEmployees = $subordinate->Find(
"indirect_supervisors IS NOT NULL and indirect_supervisors <> '' and status = 'Active'",
array()
);
foreach ($indeirectEmployees as $ie) {
$indirectSupervisors = json_decode($ie->indirect_supervisors, true);
if (in_array($cemp, $indirectSupervisors)) {
if ($subordinatesIds != "") {
$subordinatesIds.=",";
}
$subordinatesIds.=$ie->id;
}
}
}
$signInMappingField = $obj->getUserOnlyMeAccessField();
LogManager::getInstance()->debug(
"Data Load Query (a1):".$signInMappingField." in (".$subordinatesIds.") ".$query.$orderBy.$limit
);
$list = $obj->Find(
$signInMappingField." in (".$subordinatesIds.") ".$query.$orderBy.$limit,
$queryData
);
} else {
$list = $obj->Find("1=1".$query.$orderBy.$limit, $queryData);
}
} else {
$list = $obj->Find("1=1".$query.$orderBy.$limit, $queryData);
}
if (!$list) {
LogManager::getInstance()->debug("Get Data Error:".$obj->ErrorMsg());
}
LogManager::getInstance()->debug("Data Load Query:"."1=1".$query.$orderBy.$limit);
LogManager::getInstance()->debug("Data Load Query Data:".json_encode($queryData));
$processedList = array();
foreach ($list as $obj) {
$processedObj = $this->cleanUpAdoDB($obj->postProcessGetData($obj));
if (null !== $processedObj) {
$processedList[] = $processedObj;
}
}
$list = $processedList;
if (!empty($mappingStr) && count($map)>0) {
$list = $this->populateMapping($list, $map);
}
return $list;
}
/**
* Propulate field mappings for a given set of objects
* @method populateMapping
* @param $list {Array} array of model objects
* @param $map {Array} an associative array of Mappings (e.g {"profile":["Profile","id","first_name+last_name"]})
* @return {Array} array of populated objects
*/
public function populateMapping($list, $map)
{
$listNew = array();
if (empty($list)) {
return $listNew;
}
foreach ($list as $item) {
$item = $this->populateMappingItem($item, $map);
$listNew[] = $item;
}
return $listNew;
}
public function populateMappingItem($item, $map)
{
foreach ($map as $k => $v) {
$fTable = $this->getFullQualifiedModelClassName($v[0]);
$tObj = new $fTable();
$tObj = $tObj->Find($v[1]."= ?", array($item->$k));
if (is_array($tObj)) {
$tObj = $tObj[0];
} else {
continue;
}
if ($tObj->{$v[1]} == $item->$k) {
$v[2] = str_replace("+", " ", $v[2]);
$values = explode(" ", $v[2]);
if (count($values) == 1) {
$idField = $k."_id";
$item->$idField = $item->$k;
$item->$k = $tObj->{$v[2]};
} else {
$objVal = "";
foreach ($values as $val2) {
if ($objVal != "") {
$objVal .= " ";
}
$objVal .= $tObj->$val2;
}
$idField = $k."_id";
$item->$idField = $item->$k;
$item->$k = $objVal;
}
}
}
return $item;
}
/**
* Retive one element from db
* @method getElement
* @param $table {String} model class name of the table to get data (e.g for Users table model class name is User)
* @param $table {Integer} id of the item to get from $table
* @param $mappingStr {String} a JSON string to specify fields of the $table should be mapped to other
* tables (e.g {"profile":["Profile","id","first_name+last_name"]} : this is how the profile field in
* Users table is mapped to Profile table. In this case users profile field will get filled by Profile
* first name and last name. The original value in User->profile field will get moved to User->profile_id)
* @param $skipSecurityCheck {Boolean} if true won't check whether the user has access to that object
* @return {Object} an object of type $table
*/
public function getElement($table, $id, $mappingStr = null, $skipSecurityCheck = false)
{
$nsTable = $this->getFullQualifiedModelClassName($table);
$obj = new $nsTable();
if (in_array($table, $this->userTables)) {
$cemp = $this->getCurrentProfileId();
if (!empty($cemp)) {
$obj->Load("id = ?", array($id));
} else {
}
} else {
$obj->Load("id = ?", array($id));
}
if (!$skipSecurityCheck) {
$this->checkSecureAccess("element", $obj, $table, $_POST);
}
if ($obj->id == $id) {
if (!empty($mappingStr)) {
$map = json_decode($mappingStr);
$obj = $this->enrichObjectMappings($map, $obj);
}
//Add custom fields
$obj = $this->enrichObjectCustomFields($table, $obj);
$obj = $obj->postProcessGetElement($obj);
return $this->cleanUpAdoDB($obj);
}
return null;
}
/**
* @param $nameField
* @param $targetObject
* @return string
*/
private function getCombinedValue($nameField, $targetObject)
{
$values = explode("+", $nameField);
if (count($values) == 1) {
return $targetObject->{$nameField};
}
$objVal = '';
foreach ($values as $value) {
if ($objVal != "") {
$objVal .= " ";
}
if (substr($value, 0, 1) !== ':') {
$objVal .= $targetObject->{$value};
} else {
$objVal .= substr($value, 1);
}
}
return $objVal;
}
/**
* Add an element to a given table
* @method addElement
* @param $table {String} model class name of the table to add data (e.g for Users table model class name is User)
* @param $obj {Array} an associative array with field names and values for the new object.
* If the object id is not empty an existing object will be updated
* @param null $postObject
* @return IceResponse {Object} newly added or updated element of type $table newly added or updated
* element of type $table
*/
public function addElement($table, $obj, $postObject = null)
{
$customFields = array();
$isAdd = true;
$nsTable = $this->getFullQualifiedModelClassName($table);
$ele = new $nsTable();
if ($ele->validateCSRF()
&& (empty($obj->csrf) || $obj->csrf !== SessionUtils::getSessionObject('csrf-'.$table))) {
return new IceResponse(
IceResponse::ERROR,
"CSRF Error"
);
}
if (class_exists("\\Classes\\ProVersion")) {
$pro = new ProVersion();
$subscriptionTables = $pro->getSubscriptionTables();
if (in_array($table, $subscriptionTables)) {
$resp = $pro->subscriptionCheck($obj);
if ($resp->getStatus() != IceResponse::SUCCESS) {
return $resp;
}
}
}
if (!empty($obj['id'])) {
$isAdd = false;
$ele->Load('id = ?', array($obj['id']));
}
$objectKeys = $ele->getObjectKeys();
foreach ($obj as $k => $v) {
if ($k == 'id' || $k == 't' || $k == 'a') {
continue;
}
if ($v == "NULL") {
$v = null;
}
if (isset($objectKeys[$k])) {
$ele->$k = $v;
}
}
if (empty($obj['id'])) {
if (in_array($table, $this->userTables)) {
$cemp = $this->getCurrentProfileId();
if (!empty($cemp)) {
$signInMappingField = SIGN_IN_ELEMENT_MAPPING_FIELD_NAME;
$ele->$signInMappingField = $cemp;
} else {
return new IceResponse(IceResponse::ERROR, "Profile id is not set");
}
}
}
if ($postObject === null) {
$this->checkSecureAccess("save", $ele, $table, $_POST);
} else {
$this->checkSecureAccess("save", $ele, $table, $postObject);
}
$resp = $ele->validateSave($ele);
if ($resp->getStatus() != IceResponse::SUCCESS) {
return $resp;
}
if ($isAdd) {
if (empty($ele->created)) {
$ele->created = date("Y-m-d H:i:s");
}
}
if (empty($ele->updated)) {
$ele->updated = date("Y-m-d H:i:s");
}
if ($isAdd) {
$ele = $ele->executePreSaveActions($ele)->getData();
} else {
$ele = $ele->executePreUpdateActions($ele)->getData();
}
$ok = $ele->Save();
if (!$ok) {
$error = $ele->ErrorMsg();
LogManager::getInstance()->info($error);
if ($isAdd) {
$this->audit(
IceConstants::AUDIT_ERROR,
"Error occurred while adding an object to ".$table." \ Error: ".$error
);
} else {
$this->audit(
IceConstants::AUDIT_ERROR,
"Error occurred while editing an object in ".$table." [id:".$ele->id."] \ Error: ".$error
);
}
return new IceResponse(IceResponse::ERROR, $this->findError($error));
}
$customFields = $ele->getCustomFields($obj);
foreach ($obj as $k => $v) {
if (isset($customFields[$k])) {
$this->customFieldManager->addCustomField($table, $ele->id, $k, $v);
}
}
if ($isAdd) {
$ele->executePostSaveActions($ele);
$this->audit(IceConstants::AUDIT_ADD, "Added an object to ".$table." [id:".$ele->id."]");
} else {
$ele->executePostUpdateActions($ele);
$this->audit(IceConstants::AUDIT_EDIT, "Edited an object in ".$table." [id:".$ele->id."]");
}
return new IceResponse(IceResponse::SUCCESS, $ele);
}
/**
* Delete an element if not the $table and $id is defined as a non deletable
* @method deleteElement
* @param $table {String} model class name of the table to delete data
* (e.g for Users table model class name is User)
* @param $id {Integer} id of the item to delete
* @return NULL
*/
public function deleteElement($table, $id)
{
$fileFields = $this->fileFields;
$nsTable = $this->getFullQualifiedModelClassName($table);
/** @var BaseModel $ele */
$ele = new $nsTable();
$ele->Load('id = ?', array($id));
if (empty($ele->id) || $ele->id !== $id) {
return new IceResponse(
IceResponse::ERROR,
"Item not found"
);
}
$preDeleteResponse = $ele->executePreDeleteActions($ele);
if ($preDeleteResponse->getStatus() !== IceResponse::SUCCESS) {
return $preDeleteResponse;
}
$this->checkSecureAccess("delete", $ele, $table, $_POST);
if (isset($this->nonDeletables[$table])) {
$nonDeletableTable = $this->nonDeletables[$table];
if (!empty($nonDeletableTable)) {
foreach ($nonDeletableTable as $field => $value) {
if ($ele->$field == $value) {
return new IceResponse(
IceResponse::ERROR,
"This item can not be deleted"
);
}
}
}
}
//Delete approval requests
if (class_exists("\\Employees\\Common\\ModelEmployeeApproval")) {
$approvalRequest = new EmployeeApproval();
$approvalRequests = $approvalRequest->Find("type = ? and element = ?", array($table, $id));
foreach ($approvalRequests as $approvalRequest) {
$approvalRequest->Delete();
}
}
$ok = $ele->Delete();
if (!$ok) {
$error = $ele->ErrorMsg();
LogManager::getInstance()->info($error);
return new IceResponse(
IceResponse::ERROR,
$this->findError($error)
);
} else {
//Backup
if ($table == ucfirst(SIGN_IN_ELEMENT_MAPPING_FIELD_NAME)) {
$newObj = $this->cleanUpAdoDB($ele);
$dataEntryBackup = new DataEntryBackup();
$dataEntryBackup->tableType = $table;
$dataEntryBackup->data = json_encode($newObj);
$dataEntryBackup->Save();
}
$ele->executePostDeleteActions($ele);
$this->audit(IceConstants::AUDIT_DELETE, "Deleted an object in ".$table." [id:".$ele->id."]");
}
if (isset($fileFields[$table])) {
foreach ($fileFields[$table] as $k => $v) {
if (!empty($ele->$k)) {
FileService::getInstance()->deleteFileByField($ele->$k, $v);
}
}
}
$cfs = $this->customFieldManager->getCustomFields($table, $id);
/** @var CustomField $cf */
foreach ($cfs as $cf) {
$cf->Delete();
}
return new IceResponse(
IceResponse::SUCCESS,
null
);
}
/**
* Get associative array of by retriving data from $table using $key field ans key and
* $value field as value. Mainly used for getting data for populating option lists of select
* boxes when adding and editing items
* @method getFieldValues
* @param $table {String} model class name of the table to get data (e.g for Users table model class name is User)
* @param $key {String} key field name
* @param $value {String} value field name (multiple fileds cam be concatinated using +) - e.g first_name+last_name
* @param $method {String} if not empty, use this menthod to get only a selected set of objects
* from db instead of retriving all objects. This method should be defined in class $table
* and should return an array of objects of type $table
* @return {Array} associative array
*/
public function getFieldValues($table, $key, $value, $method, $methodParams = null)
{
$values = explode("+", $value);
$ret = array();
$nsTable = $this->getFullQualifiedModelClassName($table);
$ele = new $nsTable();
$this->checkSecureAccess("get", $ele, $table, $_POST);
if (!empty($method)) {
if (method_exists($ele, $method) && in_array($method, $ele->fieldValueMethods())) {
if (!empty($methodParams)) {
$list = $ele->$method(json_decode($methodParams));
} else {
$list = $ele->$method(array());
}
} else {
LogManager::getInstance()->error("Could not find method:".$method." in Class:".$table);
$list = $ele->Find('1 = 1', array());
}
} else {
$list = $ele->Find('1 = 1', array());
}
foreach ($list as $obj) {
$obj = $this->cleanUpAdoDB($obj);
if (count($values) == 1) {
$ret[$obj->$key] = $obj->$value;
} else {
$objVal = "";
foreach ($values as $v) {
if ($objVal != "") {
$objVal .= " ";
}
$objVal .= $obj->$v;
}
$ret[$obj->$key] = $objVal;
}
}
return $ret;
}
public function setNonDeletables($table, $field, $value)
{
if (!isset($this->nonDeletables[$table])) {
$this->nonDeletables[$table] = array();
}
$this->nonDeletables[$table][$field] = $value;
}
public function setSqlErrors($errros)
{
$this->errros = $errros;
}
public function setUserTables($userTables)
{
$this->userTables = $userTables;
}
/**
* Set the current logged in user
* @method setCurrentUser
* @param $currentUser {User} the current logged in user
*/
public function setCurrentUser($currentUser)
{
$this->currentUser = $currentUser;
}
public function findError($error)
{
foreach ($this->errros as $k => $v) {
if (strstr($error, $k)) {
return $v;
} else {
$keyParts = explode("|", $k);
if (count($keyParts) >= 2) {
if (strstr($error, $keyParts[0]) && strstr($error, $keyParts[1])) {
return $v;
}
}
}
}
return $error;
}
/**
* Get the currently logged in user from session
* @method getCurrentUser
* @return {User} currently logged in user from session
*/
public function getCurrentUser()
{
if (!empty($this->currentUser)) {
return $this->currentUser;
}
$user = SessionUtils::getSessionObject('user');
return $user;
}
/**
* Get the Profile id attached to currently logged in user. if the user is switched,
* this will return the id of switched Profile instead of currently logged in users Prifile id
* @method getCurrentProfileId
* @return {Integer}
*/
public function getCurrentProfileId()
{
if ($this->currentProfileId) {
return $this->currentProfileId;
}
$adminEmpId = SessionUtils::getSessionObject('admin_current_profile');
$user = SessionUtils::getSessionObject('user');
if (empty($adminEmpId) && !empty($user)) {
$signInMappingField = SIGN_IN_ELEMENT_MAPPING_FIELD_NAME;
return $user->$signInMappingField;
}
return $adminEmpId;
}
/**
* Get the Profile id attached to currently logged in user
* @method getCurrentProfileId
* @return {Integer}
*/
public function getCurrentUserProfileId()
{
$user = SessionUtils::getSessionObject('user');
$signInMappingField = SIGN_IN_ELEMENT_MAPPING_FIELD_NAME;
return $user->$signInMappingField;
}
/**
* Check if the current user has switched into another user
* @method isEmployeeSwitched
* @return {Boolean}
*/
public function isEmployeeSwitched()
{
$adminEmpId = SessionUtils::getSessionObject('admin_current_profile');
return !empty($adminEmpId);
}
/**
* Get User by profile id
* @method getUserFromProfileId
* @param $profileId {Integer} profile id
* @return {User} user object
*/
public function getUserFromProfileId($profileId)
{
$user = new User();
$signInMappingField = SIGN_IN_ELEMENT_MAPPING_FIELD_NAME;
$user->load($signInMappingField." = ?", array($profileId));
if ($user->$signInMappingField == $profileId) {
return $user;
}
return null;
}
public function setCurrentAdminProfile($profileId)
{
if ($profileId == "-1") {
SessionUtils::saveSessionObject('admin_current_profile', null);
return;
}
if ($this->currentUser->user_level == 'Admin') {
SessionUtils::saveSessionObject('admin_current_profile', $profileId);
} elseif ($this->currentUser->user_level == 'Manager'
&& $this->canManageEmployee($profileId)
) {
SessionUtils::saveSessionObject('admin_current_profile', $profileId);
} else {
SessionUtils::saveSessionObject('admin_current_profile', null);
}
}
public function cleanUpAdoDB($obj)
{
unset($obj->table);
unset($obj->_table);
unset($obj->_dbat);
unset($obj->_tableat);
unset($obj->_where);
unset($obj->_saved);
unset($obj->_lasterr);
unset($obj->_original);
unset($obj->foreignName);
return $obj;
}
public function cleanUpIgnoreKeys($obj)
{
unset($obj->keysToIgnore);
return $obj;
}
public function cleanUpApprovalModelParameters($obj)
{
unset($obj->notificationModuleName);
unset($obj->notificationUnitName);
unset($obj->notificationUnitPrefix);
unset($obj->notificationUnitAdminUrl);
unset($obj->preApproveSettingName);
return $obj;
}
public function cleanUpAll($obj)
{
$obj = $this->cleanUpAdoDB($obj);
$obj = $this->cleanUpIgnoreKeys($obj);
return $obj;
}
public function cleanUpUser($obj)
{
$obj = $this->cleanUpAll($obj);
unset($obj->password);
unset($obj->login_hash);
unset($obj->googleUserData);
unset($obj->wrong_password_count);
unset($obj->last_wrong_attempt_at);
return $obj;
}
public function setDB($db)
{
$this->db = $db;
}
public function getDB()
{
return $this->db;
}
/**
* Use user level security functions defined in model classes to check whether a given action
* type is allowed to be executed by the current user on a given object
* @method checkSecureAccess
* @param $type {String} Action type
* @param $object {Object} object to test access
* @param $table
* @param $request
* @return bool {Boolen} true or exit true or exit
*/
public function checkSecureAccess($type, $object, $table, $request)
{
$userOnlyMeAccessRequestField = $object->getUserOnlyMeAccessRequestField();
$userOnlyMeAccessField = $object->getUserOnlyMeAccessField();
$accessMatrix = $object->getRoleBasedAccess($this->currentUser->user_level, $this->currentUser->user_roles);
if (in_array($type, $accessMatrix)) {
//The user has required permission, so return true
return true;
} elseif (!empty($this->currentUser->$userOnlyMeAccessField)) {
//Now we need to check whther the user has access to his own records
if ($this->isEmployeeSwitched()) {
$accessMatrix = $object->getUserOnlyMeSwitchedAccess();
} else {
$accessMatrix = $object->getUserOnlyMeAccess();
}
//This will check whether user can access his own records using a value in request
if (isset($request[$userOnlyMeAccessField])
&& isset($this->currentUser->$userOnlyMeAccessField)) {
if (in_array($type, $accessMatrix) && $request[$userOnlyMeAccessField]
=== $this->currentUser->$userOnlyMeAccessRequestField) {
return true;
}
}
// This will check if can query his own records
// Employees should be able to update their own records
if (!empty($table) && in_array($type, $accessMatrix)) {
if (!empty($this->currentUser->$userOnlyMeAccessRequestField)
&& in_array($table, $this->userTables)) {
return true;
}
}
}
$action = PermissionManager::ACCESS_LIST_DESCRIPTION[$type];
$message = "You are not allowed to $action object type ".$object->table.'.';
$exception = new IceHttpException(
$message,
403
);
LogManager::getInstance()->notifyException($exception);
throw $exception;
}
public function getInstanceId()
{
$settings = new Setting();
$settings->Load("name = ?", array("Instance : ID"));
if ($settings->name != "Instance : ID" || empty($settings->value)) {
$settings->value = md5(time());
$settings->name = "Instance : ID";
$settings->category = "Instance";
$settings->Save();
}
return $settings->value;
}
public function setInstanceKey($key)
{
$settings = new Setting();
$settings->Load("name = ?", array("Instance: Key"));
if ($settings->name != "Instance: Key") {
$settings->name = "Instance: Key";
$settings->category = "Instance";
}
$settings->value = $key;
$settings->Save();
}
public function getInstanceKey()
{
$settings = new Setting();
$settings->Load("name = ?", array("Instance: Key"));
if ($settings->name != "Instance: Key") {
return null;
}
return $settings->value;
}
public function validateInstance()
{
$instanceId = $this->getInstanceId();
if (empty($instanceId)) {
return true;
}
$key = $this->getInstanceKey();
if (empty($key)) {
return false;
}
if (strlen($key) > 7) {
return true;
}
// $data = AesCtr::decrypt($key, $instanceId, 256);
// $arr = explode("|", $data);
// if ($arr[0] == KEY_PREFIX && $arr[1] == $instanceId) {
// return true;
// }
return false;
}
public function loadModulePermissions($group, $name, $userLevel)
{
$module = new Module();
$module->Load("update_path = ?", array($group.">".$name));
$arr = array();
$arr['user'] = json_decode($module->user_levels, true);
$arr['user_roles'] = !empty($module->user_roles)?json_decode($module->user_roles, true):array();
$permission = new Permission();
$modulePerms = $permission->Find("module_id = ? and user_level = ?", array($module->id,$userLevel));
$perms = array();
foreach ($modulePerms as $p) {
$perms[$p->permission] = $p->value;
}
$arr['perm'] = $perms;
return $arr;
}
public function isModuleAllowedForUser($moduleManagerObj)
{
$moduleObject = $moduleManagerObj->getModuleObject();
//Check if the module is disabled
if ($moduleObject['status'] == 'Disabled') {
return false;
}
//Check if user has permissions to this module
//Check Module Permissions
$modulePermissions = BaseService::getInstance()->loadModulePermissions(
$moduleManagerObj->getModuleType(),
$moduleObject['name'],
BaseService::getInstance()->getCurrentUser()->user_level
);
if (!in_array(BaseService::getInstance()->getCurrentUser()->user_level, $modulePermissions['user'])) {
if (!empty(BaseService::getInstance()->getCurrentUser()->user_roles)) {
$userRoles = json_decode(BaseService::getInstance()->getCurrentUser()->user_roles, true);
} else {
$userRoles = array();
}
$commonRoles = array_intersect($modulePermissions['user_roles'], $userRoles);
if (empty($commonRoles)) {
return false;
}
}
return true;
}
public function isModuleAllowedForGivenUser($moduleManagerObj, $user)
{
$moduleObject = $moduleManagerObj->getModuleObject();
//Check if the module is disabled
if ($moduleObject['status'] == 'Disabled') {
return false;
}
//Check if user has permissions to this module
//Check Module Permissions
$modulePermissions = BaseService::getInstance()->loadModulePermissions(
$moduleManagerObj->getModuleType(),
$moduleObject['name'],
$user->user_level
);
if (!in_array($user->user_level, $modulePermissions['user'])) {
if (!empty($user->user_roles)) {
$userRoles = json_decode($user->user_roles, true);
} else {
$userRoles = array();
}
$commonRoles = array_intersect($modulePermissions['user_roles'], $userRoles);
if (empty($commonRoles)) {
return false;
}
}
return true;
}
public function getGAKey()
{
return SettingsManager::getInstance()->getSetting('Analytics: Google Key');
}
public function setMigrationManager($migrationManager)
{
$this->migrationManager = $migrationManager;
}
public function getMigrationManager()
{
return $this->migrationManager;
}
/**
* Set the audit manager
* @method setAuditManager
* @param $auditManager {AuditManager}
*/
public function setAuditManager($auditManager)
{
$this->auditManager = $auditManager;
}
/**
* Set the NotificationManager
* @method setNotificationManager
* @param $notificationManager {NotificationManager}
*/
public function setNotificationManager($notificationManager)
{
$this->notificationManager = $notificationManager;
}
/**
* Set the SettingsManager
* @method setSettingsManager
* @param $settingsManager {SettingsManager}
*/
public function setSettingsManager($settingsManager)
{
$this->settingsManager = $settingsManager;
}
public function setFileFields($fileFields)
{
$this->fileFields = $fileFields;
}
public function audit($type, $data)
{
if (!empty($this->auditManager)) {
$this->auditManager->addAudit($type, $data);
}
}
public function fixJSON($json)
{
$noJSONRequests = SettingsManager::getInstance()->getSetting("System: Do not pass JSON in request");
if ($noJSONRequests."" == "1") {
$json = base64_decode($json);
}
return $json;
}
public function addModuleManager($moduleManager)
{
if (empty($this->moduleManagers)) {
$this->moduleManagers = array();
}
$moduleObject = $moduleManager->getModuleObject();
$this->moduleManagers[$moduleManager->getModuleType()."_".$moduleObject['name']] = $moduleManager;
}
public function getModuleManagers()
{
return array_values($this->moduleManagers);
}
public function getModuleManagerNames()
{
$keys = array_keys($this->moduleManagers);
$arr = array();
foreach ($keys as $key) {
$arr[$key] = 1;
}
return $arr;
}
public function getModuleManager($type, $name)
{
return isset($this->moduleManagers[$type."_".$name]) ? $this->moduleManagers[$type."_".$name] : null;
}
public function setEmailSender($emailSender)
{
$this->emailSender = $emailSender;
}
public function getEmailSender()
{
return $this->emailSender;
}
public function getFieldNameMappings($type)
{
$fieldNameMap = new FieldNameMapping();
$data = $fieldNameMap->Find("type = ?", array($type));
return $data;
}
public function getCustomFields($type)
{
$customField = new CustomField();
$data = $customField->Find("type = ? and display = ?", array($type,'Form'));
return $data;
}
public function getAllAdmins()
{
$user = new User();
$admins = $user->Find('user_level = ?', array('Admin'));
return $admins;
}
public function getCurrentEmployeeTimeZone()
{
$cemp = $this->getCurrentProfileId();
if (empty($cemp)) {
return null;
}
$emp = new Employee();
$emp->Load("id = ?", array($cemp));
if (empty($emp->id) || empty($emp->department)) {
return null;
}
$dept = new CompanyStructure();
$dept->Load("id = ?", array($emp->department));
return $dept->timezone;
}
public function setupHistoryManager($type, $historyManager)
{
$this->historyManagers[$type] = $historyManager;
}
public function addHistoryItem($historyManagerType, $type, $refId, $field, $oldVal, $newVal)
{
if (isset($this->historyManagers[$historyManagerType])) {
return $this->historyManagers[$historyManagerType]->addHistory($type, $refId, $field, $oldVal, $newVal);
}
return false;
}
public function getItemFromCache($class, $id)
{
$class = $this->getFullQualifiedModelClassName($class);
$data = MemcacheService::getInstance()->get($class."-".$id);
if ($data !== false) {
return unserialize($data);
}
$obj = new $class();
$obj->Load("id = ?", array($id));
if ($obj->id != $id) {
return null;
}
MemcacheService::getInstance()->set($class."-".$id, serialize($obj), 10 * 60);
return $obj;
}
public function addCalculationHook($code, $name, $class, $method)
{
$calcualtionHook = new CalculationHook();
$calcualtionHook->code = $code;
$calcualtionHook->name = $name;
$calcualtionHook->class = $class;
$calcualtionHook->method = $method;
$this->calculationHooks[$code] = $calcualtionHook;
}
public function getCalculationHooks()
{
return array_values($this->calculationHooks);
}
public function getCalculationHook($code)
{
return $this->calculationHooks[$code];
}
public function executeCalculationHook($parameters, $code, $additionalData = null)
{
$ch = BaseService::getInstance()->getCalculationHook($code);
if (empty($ch->code)) {
return null;
}
if (!empty($additionalData)) {
$parameters[] = $additionalData;
}
$class = $ch->class;
return call_user_func_array(array(new $class(), $ch->method), $parameters);
}
public function initializePro()
{
$this->pro = null;
if (class_exists('\\Classes\\ProVersion')) {
$pro = new ProVersion();
if (method_exists($pro, 'isModuleEnabled')) {
$this->pro = $pro;
}
}
}
public function isModuleEnabled($type, $name)
{
if ($this->pro === null) {
return true;
}
return $this->pro->isModuleEnabled($type, $name);
}
public function cleanNonUTFChar($obj)
{
$regex = <<<'END'
/
(
(?: [\x00-\x7F] # single-byte sequences 0xxxxxxx
| [\xC0-\xDF][\x80-\xBF] # double-byte sequences 110xxxxx 10xxxxxx
| [\xE0-\xEF][\x80-\xBF]{2} # triple-byte sequences 1110xxxx 10xxxxxx * 2
| [\xF0-\xF7][\x80-\xBF]{3} # quadruple-byte sequence 11110xxx 10xxxxxx * 3
){1,100} # ...one or more times
)
| . # anything else
/x
END;
if (is_string($obj)) {
return preg_replace($regex, '$1', $obj);
} else {
foreach ($obj as $key => $val) {
$obj->$key = preg_replace($regex, '$1', $val);
}
return $obj;
}
}
public function setCustomFieldManager($customFieldManager)
{
$this->customFieldManager = $customFieldManager;
}
public function getCustomFieldManager()
{
return $this->customFieldManager;
}
public function getFullQualifiedModelClassName($class)
{
if (isset($this->modelClassMap[$class])) {
return $this->modelClassMap[$class];
}
return '\\Model\\'.$class;
}
/**
* @param $profileId
* @return bool
*/
protected function canManageEmployee($profileId)
{
$signInMappingField = SIGN_IN_ELEMENT_MAPPING_FIELD_NAME;
$signInMappingFieldTable = $this->getFullQualifiedModelClassName(ucfirst($signInMappingField));
$subordinate = new $signInMappingFieldTable();
$subordinates = $subordinate->Find("supervisor = ?", array($this->currentUser->$signInMappingField));
$subFound = false;
foreach ($subordinates as $sub) {
if ($sub->id == $profileId) {
$subFound = true;
break;
}
}
$departmentHeadFound = false;
$subordinate = new $signInMappingFieldTable();
$subordinate->Load('id = ?', array($profileId));
if (SettingsManager::getInstance()->getSetting('System: Company Structure Managers Enabled') == 1
&& CompanyStructure::isHeadOfCompanyStructure(
$subordinate->department,
$this->currentUser->$signInMappingField
)
) {
$departmentHeadFound = true;
} elseif (SettingsManager::getInstance()->getSetting(
'System: Child Company Structure Managers Enabled'
) == '1'
) {
$companyStructure = new CompanyStructure();
$companyStructure->Load('id = ?', array($subordinate->department));
do {
if (CompanyStructure::isHeadOfCompanyStructure(
$companyStructure->id,
$this->currentUser->$signInMappingField
)
) {
$departmentHeadFound = true;
break;
}
$parentCompanyStructure = $companyStructure->parent;
if (!empty($parentCompanyStructure)) {
$companyStructure = new CompanyStructure();
$companyStructure->Load('id = ?', array($parentCompanyStructure));
}
} while (!empty($companyStructure->id)
&& !empty($parentCompanyStructure)
);
}
return $subFound || $departmentHeadFound;
}
/**
* @param $value
* @param int $options
* @param int $depth
* @return string
* @throws \Exception
*/
public function safeJsonEncode($value, $options = 0, $depth = 512)
{
$encoded = json_encode($value, $options, $depth);
switch (json_last_error()) {
case JSON_ERROR_NONE:
return $encoded;
case JSON_ERROR_DEPTH:
throw new \Exception('Maximum stack depth exceeded');
case JSON_ERROR_STATE_MISMATCH:
throw new \Exception('Underflow or the modes mismatch');
case JSON_ERROR_CTRL_CHAR:
throw new \Exception('Unexpected control character found');
case JSON_ERROR_SYNTAX:
throw new \Exception('Syntax error, malformed JSON');
case JSON_ERROR_UTF8:
$clean = $this->utf8ize($value);
return $this->safeJsonEncode($clean, $options, $depth);
default:
throw new \Exception('Unknown Json parsing error');
}
}
protected function utf8ize($mixed)
{
if (is_array($mixed)) {
foreach ($mixed as $key => $value) {
$mixed[$key] = $this->utf8ize($value);
}
} elseif (is_object($mixed)) {
foreach ($mixed as $key => $value) {
$mixed->$key = $this->utf8ize($value);
}
} elseif (is_string($mixed)) {
return utf8_encode($mixed);
}
return $mixed;
}
public function generateCsrf($formId)
{
$csrfToken = sha1(rand(4500, 100000) . time(). CLIENT_BASE_URL. $this->currentUser->id);
SessionUtils::saveSessionObject('csrf-'.$formId, $csrfToken);
return $csrfToken;
}
/**
* @param $map
* @param $obj
* @return mixed
*/
public function enrichObjectMappings($map, $obj)
{
if (!empty($map)) {
foreach ($map as $k => $v) {
if (in_array($v[0], array('User', 'Setting'))) {
continue;
}
$fTable = $this->getFullQualifiedModelClassName($v[0]);
$tObj = new $fTable();
$name = $k . "_Name";
$obj->$name = '';
if (isset($v[3]) && $v[3] === true) {
if (!empty($obj->{$k}) && !empty(json_decode($obj->{$k}, true))) {
foreach (json_decode($obj->{$k}, true) as $partialId) {
if ($obj->$name != '') {
$obj->$name .= ', ';
}
$tObjArr = $tObj->Find($v[1] . "= ?", [$partialId]);
if (!is_array($tObjArr) || empty($tObjArr[0])) {
continue;
}
$obj->$name .= $this->getCombinedValue($v[2], $tObjArr[0]);
}
}
} else {
$tObjArr = $tObj->Find($v[1] . "= ?", [$obj->$k]);
if (!is_array($tObjArr) || empty($tObjArr[0])) {
continue;
}
$obj->$name = $this->getCombinedValue($v[2], $tObjArr[0]);
}
}
}
return $obj;
}
/**
* @param $table
* @param $obj
* @return mixed
*/
public function enrichObjectCustomFields($table, $obj)
{
/** @var CustomFieldManager $customFields */
$customFields = $this->customFieldManager->getCustomFields($table, $obj->id);
foreach ($customFields as $cf) {
$obj->{$cf->name} = $cf->value;
}
return $obj;
}
/**
* @return RedisCacheService
*/
public function getCacheService()
{
return $this->cacheService;
}
/**
* @param CacheService $redisCacheService
*/
public function setCacheService($redisCacheService)
{
$this->cacheService = $redisCacheService;
}
public function queryCacheEnabled()
{
return defined('QUERY_CACHE') && QUERY_CACHE === true;
}
public function getCurrentDBUser()
{
$user = BaseService::getInstance()->getCurrentUser();
if (empty($user)) {
return new IceResponse(IceResponse::ERROR);
}
$dbUser = new User();
$dbUser->Load("id = ?", array($user->id));
return $dbUser;
}
public function getAccessToken()
{
$dbUser = $this->getCurrentDBUser();
return RestApiManager::getInstance()->getAccessTokenForUser($dbUser);
}
public function isSubordinateEmployee($supervisorId, $subordinateId)
{
$employee = new Employee();
$employee->Load('id = ? and supervisor = ?', [$subordinateId, $supervisorId]);
return ($supervisorId == $employee->supervisor && $subordinateId == $employee->id);
}
public function setSystemData($name, $value)
{
$sysData = new SystemData();
$sysData->Load('name = ?', [$name]);
if (!empty($sysData->id)) {
$sysData->value = $value;
} else {
$sysData->name = $name;
$sysData->value = $value;
}
return $sysData->Save();
}
public function getSystemData($name)
{
$sysData = new SystemData();
$sysData->Load('name = ?', [$name]);
if (!empty($sysData->id) && $sysData->name === $name) {
return $sysData->value;
}
return null;
}
}