config = $config; $this->entityManager = $entityManager; $this->metadata = $metadata; $this->acl = $acl; $this->dataManager = $dataManager; $this->injectableFactory = $injectableFactory; $this->settingsService = $settingsService; $this->user = $user; $this->preferences = $preferences; $this->fieldUtil = $fieldUtil; $this->log = $log; } /** * @return array */ public function getUserData(): array { $preferencesData = $this->preferences->getValueMap(); $this->filterPreferencesData($preferencesData); $user = $this->user; if (!$user->has('teamsIds')) { $user->loadLinkMultipleField('teams'); } if ($user->isPortal()) { $user->loadAccountField(); $user->loadLinkMultipleField('accounts'); } $settings = $this->settingsService->getConfigData(); if ($user->get('dashboardTemplateId')) { $dashboardTemplate = $this->entityManager ->getEntity('DashboardTemplate', $user->get('dashboardTemplateId')); if ($dashboardTemplate) { $settings->forcedDashletsOptions = $dashboardTemplate->get('dashletsOptions') ?? (object) []; $settings->forcedDashboardLayout = $dashboardTemplate->get('layout') ?? []; } } $language = Language::detectLanguage($this->config, $this->preferences); $auth2FARequired = false; if ( $user->isRegular() && $this->config->get('auth2FA') && $this->config->get('auth2FAForced') && !$user->get('auth2FA') ) { $auth2FARequired = true; } $appParams = [ 'maxUploadSize' => $this->getMaxUploadSize() / 1024.0 / 1024.0, 'isRestrictedMode' => $this->config->get('restrictedMode'), 'passwordChangeForNonAdminDisabled' => $this->config->get('authenticationMethod', 'Espo') !== 'Espo', 'timeZoneList' => $this->metadata->get(['entityDefs', 'Settings', 'fields', 'timeZone', 'options'], []), 'auth2FARequired' => $auth2FARequired, ]; foreach (($this->metadata->get(['app', 'appParams']) ?? []) as $paramKey => $item) { /** @var ?class-string */ $className = $item['className'] ?? null; if (!$className) { continue; } try { /** @var AppParam */ $obj = $this->injectableFactory->create($className); $itemParams = $obj->get(); } catch (Throwable $e) { $this->log->error("AppParam {$paramKey}: " . $e->getMessage()); continue; } $appParams[$paramKey] = $itemParams; } return [ 'user' => $this->getUserDataForFrontend(), 'acl' => $this->getAclDataForFrontend(), 'preferences' => $preferencesData, 'token' => $this->user->get('token'), 'settings' => $settings, 'language' => $language, 'appParams' => $appParams, ]; } private function getUserDataForFrontend(): stdClass { $user = $this->user; $emailAddressData = $this->getEmailAddressData(); $data = $user->getValueMap(); $data->emailAddressList = $emailAddressData->emailAddressList; $data->userEmailAddressList = $emailAddressData->userEmailAddressList; unset($data->authTokenId); unset($data->password); $forbiddenAttributeList = $this->acl->getScopeForbiddenAttributeList('User'); $isPortal = $user->isPortal(); foreach ($forbiddenAttributeList as $attribute) { if ($attribute === 'type') { continue; } if ($isPortal) { if (in_array($attribute, ['contactId', 'contactName', 'accountId', 'accountsIds'])) { continue; } } else { if (in_array($attribute, ['teamsIds', 'defaultTeamId', 'defaultTeamName'])) { continue; } } unset($data->$attribute); } return $data; } private function getAclDataForFrontend(): stdClass { $data = $this->acl->getMapData(); if (!$this->user->isAdmin()) { $data = unserialize(serialize($data)); /** @var string[] */ $scopeList = array_keys($this->metadata->get(['scopes'], [])); foreach ($scopeList as $scope) { if (!$this->acl->check($scope)) { unset($data->table->$scope); unset($data->fieldTable->$scope); unset($data->fieldTableQuickAccess->$scope); } } } return $data; } private function getEmailAddressData(): stdClass { $user = $this->user; $emailAddressList = []; $userEmailAddressList = []; $emailAddressCollection = $this->entityManager ->getRDBRepository('User') ->getRelation($user, 'emailAddresses') ->find(); foreach ($emailAddressCollection as $emailAddress) { if ($emailAddress->get('invalid')) { continue; } $userEmailAddressList[] = $emailAddress->get('name'); if ($user->get('emailAddress') === $emailAddress->get('name')) { continue; } $emailAddressList[] = $emailAddress->get('name'); } if ($user->get('emailAddress')) { array_unshift($emailAddressList, $user->get('emailAddress')); } $entityManager = $this->entityManager; /** @var string[] */ $teamIdList = $user->getLinkMultipleIdList('teams'); $groupEmailAccountPermission = $this->acl->get('groupEmailAccountPermission'); if ($groupEmailAccountPermission && $groupEmailAccountPermission !== 'no') { if ($groupEmailAccountPermission === 'team') { if (count($teamIdList)) { $inboundEmailList = $entityManager ->getRDBRepository('InboundEmail') ->where([ 'status' => 'Active', 'useSmtp' => true, 'smtpIsShared' => true, 'teamsMiddle.teamId' => $teamIdList, ]) ->join('teams') ->distinct() ->find(); foreach ($inboundEmailList as $inboundEmail) { if (!$inboundEmail->get('emailAddress')) { continue; } $emailAddressList[] = $inboundEmail->get('emailAddress'); } } } else if ($groupEmailAccountPermission === 'all') { $inboundEmailList = $entityManager ->getRDBRepository('InboundEmail') ->where([ 'status' => 'Active', 'useSmtp' => true, 'smtpIsShared' => true, ]) ->find(); foreach ($inboundEmailList as $inboundEmail) { if (!$inboundEmail->get('emailAddress')) { continue; } $emailAddressList[] = $inboundEmail->get('emailAddress'); } } } return (object) [ 'emailAddressList' => $emailAddressList, 'userEmailAddressList' => $userEmailAddressList, ]; } /** * @return int */ private function getMaxUploadSize() { $maxSize = 0; $postMaxSize = $this->convertPHPSizeToBytes(ini_get('post_max_size')); if ($postMaxSize > 0) { $maxSize = $postMaxSize; } return $maxSize; } /** * @param string|false $size * @return int */ private function convertPHPSizeToBytes($size) { if (is_numeric($size)) { return (int) $size; } if ($size === false) { return 0; } $suffix = substr($size, -1); $value = (int) substr($size, 0, -1); switch (strtoupper($suffix)) { case 'P': $value *= 1024; case 'T': $value *= 1024; case 'G': $value *= 1024; case 'M': $value *= 1024; case 'K': $value *= 1024; break; } return $value; } public function jobClearCache(): void { $this->dataManager->clearCache(); } public function jobRebuild(): void { $this->dataManager->rebuild(); } /** * @todo Remove in 7.2. */ public function jobPopulatePhoneNumberNumeric(): void { $numberList = $this->entityManager ->getRDBRepository('PhoneNumber') ->find(); foreach ($numberList as $number) { $this->entityManager->saveEntity($number); } } /** * @todo Remove in 7.2. Move to another place. CLI command. */ public function jobPopulateArrayValues(): void { /** @var string[] */ $scopeList = array_keys($this->metadata->get(['scopes'])); $query = $this->entityManager->getQueryBuilder() ->delete() ->from('ArrayValue') ->build(); $this->entityManager ->getQueryExecutor() ->execute($query); foreach ($scopeList as $scope) { if (!$this->metadata->get(['scopes', $scope, 'entity'])) { continue; } if ($this->metadata->get(['scopes', $scope, 'disabled'])) { continue; } $attributeList = []; $entityDefs = $this->entityManager ->getDefs() ->getEntity($scope); foreach ($entityDefs->getAttributeList() as $attributeDefs) { $attribute = $attributeDefs->getName(); $type = $attributeDefs->getType(); if ($type !== Entity::JSON_ARRAY) { continue; } if (!$attributeDefs->getParam('storeArrayValues')) { continue; } if (!$attributeDefs->getParam('notStorable')) { continue; } $attributeList[] = $attribute; } $select = ['id']; $orGroup = []; foreach ($attributeList as $attribute) { $select[] = $attribute; $orGroup[$attribute . '!='] = null; } $repository = $this->entityManager->getRepository($scope); if (!$repository instanceof RDBRepository) { continue; } if (!count($attributeList)) { continue; } $query = $this->entityManager ->getQueryBuilder() ->select() ->from($scope) ->select($select) ->where([ 'OR' => $orGroup, ]) ->build(); $sth = $this->entityManager ->getQueryExecutor() ->execute($query); while ($dataRow = $sth->fetch()) { $entity = $this->entityManager->getEntityFactory()->create($scope); if (!$entity instanceof CoreEntity) { continue; } $entity->set($dataRow); $entity->setAsFetched(); foreach ($attributeList as $attribute) { $this->getArrayValueRepository()->storeEntityAttribute($entity, $attribute, true); } } } } /** * @todo Remove in 7.2. Move to another place. CLI command. */ public function jobPopulateOptedOutPhoneNumbers(): void { $entityTypeList = ['Contact', 'Lead']; foreach ($entityTypeList as $entityType) { $entityList = $this->entityManager ->getRDBRepository($entityType) ->where([ 'doNotCall' => true, 'phoneNumber!=' => null, ]) ->select(['id', 'phoneNumber']) ->find(); foreach ($entityList as $entity) { $phoneNumber = $entity->get('phoneNumber'); if (!$phoneNumber) { continue; } $phoneNumberEntity = $this->getPhoneNumberRepository()->getByNumber($phoneNumber); if (!$phoneNumberEntity) { continue; } $phoneNumberEntity->set('optOut', true); $this->entityManager->saveEntity($phoneNumberEntity); } } } private function filterPreferencesData(stdClass $data): void { $passwordFieldList = $this->fieldUtil->getFieldByTypeList('Preferences', 'password'); foreach ($passwordFieldList as $field) { unset($data->$field); } } private function getPhoneNumberRepository(): PhoneNumberRepository { /** @var PhoneNumberRepository */ return $this->entityManager->getRepository(PhoneNumber::ENTITY_TYPE); } private function getArrayValueRepository(): ArrayValueRepository { /** @var ArrayValueRepository */ return $this->entityManager->getRepository(ArrayValue::ENTITY_TYPE); } }