mirror of
https://github.com/SuiteCRM/SuiteCRM-Core.git
synced 2025-08-29 08:17:18 +08:00
5a66316965 SuiteCRM 7.12.3 Release 1cfaf51831 Fix #9454 - Avoid duplicate results in basic search 7eb52791f1 Fix #9455 - Popup metadata override removed when filtered a21463bee1 Fix #8155 - Removed Unused PDF Settings 7f3c59f382 Fix #8948 - Make Project Tasks Importable ac4a1e79a7 Fix #9191 - Add utf normalization repair command bcb784eef7 Fix #9434 - Cron notion unit test fails 2e4aa8f594 Fix #8309 - Delete button showing for users with no delete access bf5fe39148 Fix #8525 - Bulk Action label not showing for users without delete access 1a45a93b5c Fix #9398 - Consistently store dropdowns in $app_list_strings rather than $GLOBALS 664b2d5c74 Fix #9406 - Validation displayed static message isn't correct de192fa845 Fix #9271 - Primary Email property is kept after ading an extra Email address 206db24eaa Fix #9378 - Filter by Email1 Field Through the API 6c39d73580 Fix #9312 - Declaring object within StudioClass to remove Strict Warnings be2044b341 Fix #9387 - Correct Variable Names 7e3c96d5b4 Fix #9387 - Clean Cron Historic and Failed Jobs b3e0556482 Fix #9387 - Display Actual Job Result in Subpanel 90b4e0423a Fix issue #9380 where date action in workflow fails to save Add check on if value is array, if is array don't attempt date formatting 864d614945 Fix #9408 - adding fix for deleting emails 7b442f10ca Merge next into suite 8 b522a5acf3 [Legacy] Meeting Module Styling Fixes 4e4d4e7d86 [Legacy] Admin Import Styling Fixes e320acd63c [Legacy] Popup Selector Styling Fixes 60acfc36f5 [Legacy] Backup Modules Styling Fixes 73cc52ce14 [Legacy] Jotpad Dashlet Styling Fixes 0128df2e63 [Legacy] User Name Longtext styling fixes f12c72e8f6 [Legacy] Diagnostic Tool Whitespace Styling Fixes 841b16e033 [Legacy] Dashboard Dashlet Styling Fixes e274de5a58 [Legacy] Scheduler Styling Fixes 0c330bc280 [Legacy] Reports Subpanels Styling Fixes 0730d433b2 [Legacy] Meeting Popup Selector Styling Fixes a22626df09 [Legacy] Bump version to 8.0.0 ebde6fb8cc [Legacy] Apply set-timezone styling ot the the users set-timezone page 55f1e360df [Legacy] Add name mapping for SetTimezone action 44fa660c65 [Legacy] Define summary templates for contacts, leads, prospects f363b741f9 [Legacy] Change Contacts detailviewdefs to use full name 8afde55218 [Legacy] Fix .htaccess build to take the full CRM url into account 8373995c26 [Legacy] Admin diagnostic tool styling fixes 03593b259c [Legacy] Disable upgrade wizard in admin 66c9fe4d8f [Legacy] Remove lucene and AOD_index 21f9844286 [Legacy] Fix event invite mod_strings handling 04bdfd8975 [Legacy] Forgot Password Page Styling Fixes ba459af407 [Legacy] fix redirect from projects subpanel 0f19a141d1 [Legacy] Add Default Link Item Mapper - add relate module injection on backend bean field_defs efc2083eaf [Legacy] Email Body Styling Fixes 648a1d9350 Merge next into suite 8 a0cfd72ab3 [Legacy] Remove deprecated spots module 103fd1076f [Legacy] Fix capitalized url on user profile calendar options 97fca254bd [Legacy] Re-add user module reset password modal 864c35c4ad [Legacy] Remove echo on user save 169a15a6c9 [Legacy] Close user action dropdown on password reset e8c400ab24 [Legacy] Fix user triggered password reset e38f48c6d4 [Legacy] Fix password recovery templates setup on install 927969c9a3 [Legacy] Bump version to 8.0.0-rc.2 b27584577d [Legacy] UserProfile Settings Modal Styling Fixes 2aba88dfe8 [Legacy] Meetings Styling Fixes 13d743e598 [Legacy] Password & System Settings Action Button Fixes cfb0bcc86d [Legacy] User Setup Modal Styling Fixes d05f3aa4f5 [Legacy] Fix legacy widget acl definitions e469e337f8 [Legacy] Suite 8 extensions to legacy plugins 41e84b1d17 [Legacy] Override server variables when doing kernel bypass 7f5d03f280 Merge commit '75ea167930
' into suite7merge c5f43d6c88 [Legacy] Popup Selector Styling Fixes 0445c1c0ab [Legacy] update install language label eb3fe0472b [Legacy] Dashlet Settings Modal Styling Fixes 6f0918b73d [Legacy] User Profile Mobile Styling Fixes 5af790f7fa [Legacy] Add acls calculation on legacy list data calls 096a59a7cf [Legacy] Get list of visible modules from module name mapper c2d618e631 Fix valid module check aa79de3a31 [Legacy] add widget acl metadata - update acl config for top widget 315b554b7e [Legacy] Subpanels Action Button Styling Fixes c87e66a262 remove photo widgets for contacts and leads 433940a72f [Legacy] Admin Release Styling Fixes c0a1378873 Suite8 ChangeLog ModalPopup Styling Fixes aa484f3f9e [Legacy] Add close menu label 8f81b47c65 [Legacy] Add not module selected label 36a0b05eb2 [Legacy] Add parent type ApiBeanMapper 7e02d1d23c [Legacy] Fix username display for unauthorized users 2ea8f210a1 [Legacy] DetailView Header Title Overlaps fixes 2a25edd6c4 [Legacy] Fix htaccess generation 34500ba791 Fix Date Filed for Targets 211ce6bfbb [Legacy] Remove Button Hover Fixes 223adf26bc [Legacy] Reports footer button removed fixes c567777afe [Legacy] Reports Styling Fixes 6f71ed31c2 [Legacy] Maps Button Position Fixes c5d5936c22 [Legacy] Add Tab Dashlet Sapcing Fixes 018c11c562 [Legacy] Dashlet Setting Modal Label Fix & Button Fixes 9645c68ca6 [Legacy] Activity Stream Post Button Hover color fixes 445ab52dae [Legacy] Bump version to 8.0.0-rc e10b872b21 [Legacy] Remove license from install app strings e5c21ca68c Merge commit 'dd455a1c2d
' into legacy_update_2 3886e3cfa6 Fix ignore system checks valitation 415cdd57b0 [Legacy] Add install labels 70ae186de5 [Legacy] add new install labels 7e05e69580 [Legacy] add install validator class 4c4ed83f3d [Legacy] Add Label for Subpanel Edit Line Action 17d8f4e7e9 [Legacy] Dashboard Mobile Styling Fixes abd914702a [Legacy] History Subpanel Button Styling Fixes 34a0dac449 [Legacy] Workflow Stying Fixes 32c4827895 [Legacy] Convert Lead Styling Fixes f1ca14c009 [Legacy] Roles Styling Fixes 3dbdce8055 [Legacy] Admin Modules label font fixes 36a38a1c44 [Legacy] HomePage Mobile Fixes a5b451ab12 update legacy handlers to apply new logic considering - base actions - action resolvers - fix url navigation issue in classic view 87e6e239ce [Legacy] Module framework - move suite 8 module config to legacy ee973e74f6 [Legacy] Add support for more metadata on listviewdefs ad312c45fd [Legacy] Add Support for all modules with parent css classes a409d81e2b [Legacy] Security Group Styling Fixes 5171ae319f [Legacy] Password Management Mobile Fixes d0eca8193d [Leagcy] Email Settings Fixes 766af5f4e6 [Legacy] Products Modules Buttons fixes 99ec9e30f9 [Legacy] OAUTH2 Clients and tokens fixes 54c962a532 [Legacy] adapt legacy install scripts to work with Suite8 install d6f20e38e6 [Legacy] add labels for S8 Installer 83b00b6a94 [Legacy] Add widget not found label 3ac807db61 Merge commit '114b895b6d
' into merge_develop 1feeb409f8 [Legacy] Email Action DropDown Styling Fixes git-subtree-dir: public/legacy git-subtree-split: 5a663169652b57bb561de74a7e3a8051c9330a83
607 lines
18 KiB
PHP
607 lines
18 KiB
PHP
<?php
|
|
/**
|
|
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
|
|
* Copyright (C) 2021 SalesAgility Ltd.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it under
|
|
* the terms of the GNU Affero General Public License version 3 as published by the
|
|
* Free Software Foundation with the addition of the following permission added
|
|
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
|
|
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
|
|
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see http://www.gnu.org/licenses.
|
|
*
|
|
* In accordance with Section 7(b) of the GNU Affero General Public License
|
|
* version 3, these Appropriate Legal Notices must retain the display of the
|
|
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
|
|
* feasible for technical reasons, the Appropriate Legal Notices must display
|
|
* the words "Supercharged by SuiteCRM".
|
|
*/
|
|
|
|
require_once __DIR__ . '/FieldMappers/AssignedUserMapper.php';
|
|
require_once __DIR__ . '/LinkMappers/LinkMapperInterface.php';
|
|
require_once __DIR__ . '/LinkMappers/EmailAddressLinkMapper.php';
|
|
require_once __DIR__ . '/LinkMappers/DefaultLinkMapper.php';
|
|
require_once __DIR__ . '/TypeMappers/FullNameMapper.php';
|
|
require_once __DIR__ . '/TypeMappers/ParentMapper.php';
|
|
require_once __DIR__ . '/TypeMappers/DateMapper.php';
|
|
require_once __DIR__ . '/TypeMappers/DateTimeMapper.php';
|
|
require_once __DIR__ . '/TypeMappers/DateTimeComboMapper.php';
|
|
require_once __DIR__ . '/TypeMappers/MultiEnumMapper.php';
|
|
require_once __DIR__ . '/TypeMappers/BooleanMapper.php';
|
|
require_once __DIR__ . '/ApiBeanModuleMappers.php';
|
|
require_once __DIR__ . '/ModuleMappers/SavedSearch/SavedSearchMappers.php';
|
|
require_once __DIR__ . '/ModuleMappers/AOP_Case_Updates/CaseUpdatesMappers.php';
|
|
|
|
class ApiBeanMapper
|
|
{
|
|
|
|
/**
|
|
* @var FieldMapperInterface[]
|
|
*/
|
|
protected $fieldMappers = [];
|
|
|
|
/**
|
|
* @var TypeMapperInterface[]
|
|
*/
|
|
protected $typeMappers = [];
|
|
|
|
/**
|
|
* @var LinkMapperInterface[][]
|
|
*/
|
|
protected $linkMappers = [];
|
|
|
|
/**
|
|
* @var ApiBeanModuleMappers[]
|
|
*/
|
|
protected $moduleMappers = [];
|
|
|
|
public function __construct()
|
|
{
|
|
$this->fieldMappers[AssignedUserMapper::getField()] = new AssignedUserMapper();
|
|
$this->typeMappers[FullNameMapper::getType()] = new FullNameMapper();
|
|
$this->typeMappers[ParentMapper::getType()] = new ParentMapper();
|
|
$this->typeMappers[DateMapper::getType()] = new DateMapper();
|
|
$this->typeMappers[DateTimeMapper::getType()] = new DateTimeMapper();
|
|
$this->typeMappers[MultiEnumMapper::getType()] = new MultiEnumMapper();
|
|
$this->typeMappers[BooleanMapper::getType()] = new BooleanMapper();
|
|
$this->typeMappers['boolean'] = $this->typeMappers[BooleanMapper::getType()];
|
|
$this->moduleMappers[SavedSearchMappers::getModule()] = new SavedSearchMappers();
|
|
$this->typeMappers[DateTimeComboMapper::getType()] = new DateTimeMapper();
|
|
$this->linkMappers[EmailAddressLinkMapper::getRelateModule()] = [];
|
|
$this->linkMappers[EmailAddressLinkMapper::getRelateModule()]['all'] = new EmailAddressLinkMapper();
|
|
$this->moduleMappers[CaseUpdatesMappers::getModule()] = new CaseUpdatesMappers();
|
|
$this->linkMappers[DefaultLinkMapper::getRelateModule()] = [];
|
|
$this->linkMappers[DefaultLinkMapper::getRelateModule()]['all'] = new DefaultLinkMapper();
|
|
}
|
|
|
|
/**
|
|
* @param SugarBean $bean
|
|
* @return array
|
|
*/
|
|
public function toApi(SugarBean $bean): array
|
|
{
|
|
$bean->field_defs = $this->mapLinkedModule($bean);
|
|
|
|
$arr = [];
|
|
|
|
$arr['module_name'] = $bean->module_name ?? '';
|
|
$arr['object_name'] = $bean->object_name ?? '';
|
|
|
|
foreach ($bean->field_defs as $field => $definition) {
|
|
if ($this->isSensitiveField($definition)) {
|
|
continue;
|
|
}
|
|
|
|
if (!$this->checkFieldAccess($bean, $definition)) {
|
|
continue;
|
|
}
|
|
|
|
if ($this->isLinkField($definition)) {
|
|
if (!$this->hasLinkMapper($bean->module_name, $definition)) {
|
|
continue;
|
|
}
|
|
|
|
$this->mapLinkFieldToApi($bean, $arr, $definition);
|
|
|
|
continue;
|
|
}
|
|
|
|
if ($this->isRelateField($definition)) {
|
|
$this->addRelateFieldToArray($bean, $definition, $arr, $field);
|
|
continue;
|
|
}
|
|
|
|
$this->setValue($bean, $field, $arr, $definition);
|
|
}
|
|
|
|
return $arr;
|
|
}
|
|
|
|
/**
|
|
* @param SugarBean $bean
|
|
* @param array $values
|
|
* @return void
|
|
*/
|
|
public function toBean(SugarBean $bean, array $values): void
|
|
{
|
|
require_once __DIR__ . '/../../../include/SugarFields/SugarFieldHandler.php';
|
|
|
|
$bean->field_defs = $this->mapLinkedModule($bean);
|
|
|
|
foreach ($bean->field_defs as $field => $properties) {
|
|
if (!isset($values[$field])) {
|
|
continue;
|
|
}
|
|
|
|
$this->toBeanMap($bean, $values, $properties, $field);
|
|
|
|
if ($this->isLinkField($properties)) {
|
|
if (!$this->hasLinkMapper($bean->module_name, $properties)) {
|
|
continue;
|
|
}
|
|
|
|
$this->mapLinkFieldToBean($bean, $values, $properties);
|
|
}
|
|
|
|
$bean->$field = $values[$field];
|
|
}
|
|
|
|
foreach ($bean->relationship_fields as $field => $link) {
|
|
if (!empty($values[$field])) {
|
|
$bean->$field = $values[$field];
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param SugarBean $bean
|
|
* @param array $values
|
|
* @return void
|
|
*/
|
|
public function toBeanAttributes(SugarBean $bean, array &$values): void
|
|
{
|
|
require_once __DIR__ . '/../../../include/SugarFields/SugarFieldHandler.php';
|
|
|
|
foreach ($bean->field_defs as $field => $properties) {
|
|
if (!isset($values[$field])) {
|
|
continue;
|
|
}
|
|
|
|
$this->toBeanMap($bean, $values, $properties, $field);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param $definition
|
|
* @return bool
|
|
*/
|
|
protected function isRelateField($definition): bool
|
|
{
|
|
return isset($definition['type']) && $definition['type'] === 'relate';
|
|
}
|
|
|
|
/**
|
|
* @param $definition
|
|
* @return bool
|
|
*/
|
|
protected function isLinkField($definition): bool
|
|
{
|
|
return isset($definition['type']) && $definition['type'] === 'link';
|
|
}
|
|
|
|
|
|
/**
|
|
* @param $fieldDefinition
|
|
* @return bool
|
|
*/
|
|
protected function isSensitiveField($fieldDefinition): bool
|
|
{
|
|
return $fieldDefinition['sensitive'] ?? false;
|
|
}
|
|
|
|
/**
|
|
* @param $fieldDefinition
|
|
* @return bool
|
|
*/
|
|
protected function isAdminOnlyField($fieldDefinition): bool
|
|
{
|
|
return $fieldDefinition['admin-only'] ?? false;
|
|
}
|
|
|
|
/**
|
|
* @param $fieldDefinition
|
|
* @return bool
|
|
*/
|
|
protected function isOwnerOnlyField($fieldDefinition): bool
|
|
{
|
|
return $fieldDefinition['owner-only'] ?? false;
|
|
}
|
|
|
|
/**
|
|
* @param $fieldDefinition
|
|
* @return bool
|
|
*/
|
|
protected function checkAdminOnlyField($fieldDefinition): bool
|
|
{
|
|
global $current_user;
|
|
|
|
$isAdminOnlyField = $this->isAdminOnlyField($fieldDefinition);
|
|
|
|
if (!$isAdminOnlyField) {
|
|
return true;
|
|
}
|
|
|
|
return $isAdminOnlyField && $current_user->isAdmin();
|
|
}
|
|
|
|
/**
|
|
* @param $fieldDefinition
|
|
* @param SugarBean $bean
|
|
* @return bool
|
|
*/
|
|
protected function checkOwnerOnlyField($fieldDefinition, SugarBean $bean): bool
|
|
{
|
|
global $current_user;
|
|
|
|
$assignedUserId = $bean->assigned_user_id ?? '';
|
|
$isOwnerOnlyField = $this->isOwnerOnlyField($fieldDefinition);
|
|
|
|
if (!$isOwnerOnlyField) {
|
|
return true;
|
|
}
|
|
|
|
return $isOwnerOnlyField && $current_user->id === $assignedUserId;
|
|
}
|
|
|
|
/**
|
|
* @param SugarBean $bean
|
|
* @param $definition
|
|
* @return bool
|
|
*/
|
|
protected function checkFieldAccess(SugarBean $bean, $definition): bool
|
|
{
|
|
if (!$this->isAdminOnlyField($definition) && !$this->isOwnerOnlyField($definition)) {
|
|
return true;
|
|
}
|
|
|
|
return !$this->checkAdminOnlyField($definition) && !$this->checkOwnerOnlyField($definition, $bean);
|
|
}
|
|
|
|
/**
|
|
* @param SugarBean $bean
|
|
* @param $definition
|
|
* @param array $arr
|
|
* @param $field
|
|
*/
|
|
protected function addRelateFieldToArray(SugarBean $bean, $definition, array &$arr, $field): void
|
|
{
|
|
$fieldRName = $definition['rname'] ?? 'name';
|
|
$idName = $definition['id_name'] ?? '';
|
|
$source = $definition['source'] ?? '';
|
|
$idDefinition = $definition[$idName] ?? [];
|
|
$groupingField = $field;
|
|
|
|
if ($source !== 'non-db') {
|
|
$this->setValue($bean, $field, $arr, $definition);
|
|
|
|
return;
|
|
}
|
|
|
|
if ($idName === $field) {
|
|
$this->setValue($bean, $field, $arr, $definition);
|
|
|
|
return;
|
|
}
|
|
|
|
$arr[$groupingField] = $arr[$groupingField] ?? [];
|
|
$this->setValue($bean, $field, $arr[$groupingField], $definition, $fieldRName);
|
|
|
|
if (isset($bean->$idName)) {
|
|
$idFieldRName = $idDefinition['rname'] ?? 'id';
|
|
$this->setValue($bean, $idName, $arr[$groupingField], $definition, $idFieldRName);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param SugarBean $bean
|
|
* @param $field
|
|
* @param array $arr
|
|
* @param array $definition
|
|
* @param string $alternativeName
|
|
*/
|
|
protected function setValue(
|
|
SugarBean $bean,
|
|
$field,
|
|
array &$arr,
|
|
array $definition,
|
|
string $alternativeName = ''
|
|
): void
|
|
{
|
|
$name = $field;
|
|
|
|
if (!empty($alternativeName)) {
|
|
$name = $alternativeName;
|
|
}
|
|
|
|
$fieldMapper = $this->getFieldMapper($bean->module_name, $field);
|
|
if (null !== $fieldMapper) {
|
|
$fieldMapper->toApi($bean, $arr, $name);
|
|
|
|
return;
|
|
}
|
|
|
|
$type = $definition['type'] ?? '';
|
|
$typeMapper = $this->getTypeMappers($bean->module_name, $type);
|
|
if (null !== $typeMapper) {
|
|
$typeMapper->toApi($bean, $arr, $field, $name);
|
|
|
|
return;
|
|
}
|
|
|
|
$arr[$name] = html_entity_decode($bean->$field ?? '', ENT_QUOTES);
|
|
}
|
|
|
|
/**
|
|
* @param SugarBean $bean
|
|
* @param array $container
|
|
* @param array $definition
|
|
*/
|
|
protected function mapLinkFieldToApi(SugarBean $bean, array &$container, array $definition): void
|
|
{
|
|
$module = $bean->module_name ?? '';
|
|
$relateModule = $definition['module'] ?? '';
|
|
$name = $definition['name'] ?? '';
|
|
|
|
$linkMapper = $this->getLinkMapper($module, $relateModule, $name);
|
|
if ($linkMapper === null) {
|
|
return;
|
|
}
|
|
|
|
$linkMapper->toApi($bean, $container, $name);
|
|
}
|
|
|
|
/**
|
|
* @param SugarBean $bean
|
|
* @param array $container
|
|
* @param array $definition
|
|
*/
|
|
protected function mapLinkFieldToBean(SugarBean $bean, array &$container, array $definition): void
|
|
{
|
|
$module = $bean->module_name ?? '';
|
|
$relateModule = $definition['module'] ?? '';
|
|
$name = $definition['name'] ?? '';
|
|
|
|
$linkMapper = $this->getLinkMapper($module, $relateModule, $name);
|
|
|
|
if ($linkMapper === null) {
|
|
return;
|
|
}
|
|
|
|
$linkMapper->toBean($bean, $container, $name);
|
|
}
|
|
|
|
/**
|
|
* @param string $module
|
|
* @param string $field
|
|
* @return FieldMapperInterface
|
|
*/
|
|
protected function getFieldMapper(string $module, string $field): ?FieldMapperInterface
|
|
{
|
|
$moduleMappers = $this->moduleMappers[$module] ?? null;
|
|
|
|
if ($moduleMappers !== null && $moduleMappers->hasFieldMapper($field)) {
|
|
return $moduleMappers->getFieldMappers()[$field];
|
|
}
|
|
|
|
return $this->fieldMappers[$field] ?? null;
|
|
}
|
|
|
|
/**
|
|
* @param string $module
|
|
* @param string $relateModule
|
|
* @param string $field
|
|
* @return LinkMapperInterface
|
|
*/
|
|
protected function getLinkMapper(string $module, string $relateModule, string $field): ?LinkMapperInterface
|
|
{
|
|
if ($module === '' || $relateModule === '' || $field === '') {
|
|
return null;
|
|
}
|
|
|
|
$moduleMappers = $this->moduleMappers[$module] ?? null;
|
|
|
|
if ($moduleMappers !== null && $moduleMappers->hasLinkMapper($relateModule, $field)) {
|
|
return $moduleMappers->getLinkMapper($relateModule, $field);
|
|
}
|
|
|
|
$moduleLinkMappers = $this->linkMappers[$relateModule] ?? $this->linkMappers['default'] ?? [];
|
|
|
|
return $moduleLinkMappers[$field] ?? $moduleLinkMappers['all'] ?? null;
|
|
}
|
|
|
|
/**
|
|
* @param $definition
|
|
* @return bool
|
|
*/
|
|
protected function hasLinkMapper($module, $definition): bool
|
|
{
|
|
$relateModule = $definition['module'] ?? '';
|
|
$name = $definition['name'] ?? '';
|
|
|
|
if ($relateModule === '' || $name === '') {
|
|
return false;
|
|
}
|
|
|
|
return $this->getLinkMapper($module, $relateModule, $name) !== null;
|
|
}
|
|
|
|
/**
|
|
* @param string $module
|
|
* @param string $type
|
|
* @return TypeMapperInterface
|
|
*/
|
|
protected function getTypeMappers(string $module, string $type): ?TypeMapperInterface
|
|
{
|
|
$moduleMappers = $this->moduleMappers[$module] ?? null;
|
|
|
|
if ($moduleMappers !== null && $moduleMappers->hasTypeMapper($type)) {
|
|
return $moduleMappers->getTypeMappers()[$type];
|
|
}
|
|
|
|
return $this->typeMappers[$type] ?? null;
|
|
}
|
|
|
|
/**
|
|
* @param SugarBean $bean
|
|
* @param array $values
|
|
* @param $properties
|
|
* @param $field
|
|
*/
|
|
protected function toBeanMap(SugarBean $bean, array &$values, $properties, $field): void
|
|
{
|
|
$type = $properties['type'] ?? '';
|
|
|
|
if ($type === 'relate' && isset($bean->field_defs[$field])) {
|
|
$idName = $bean->field_defs[$field]['id_name'] ?? '';
|
|
|
|
if ($idName !== $field) {
|
|
|
|
$idValue = $values[$field]['id'] ?? '';
|
|
if (empty($values[$idName]) && !empty($idValue)) {
|
|
$values[$idName] = $idValue;
|
|
}
|
|
|
|
$rName = $bean->field_defs[$field]['rname'] ?? '';
|
|
$value = $values[$field][$rName] ?? '';
|
|
$values[$field] = $value;
|
|
}
|
|
}
|
|
|
|
if (!empty($properties['isMultiSelect']) || $type === 'multienum') {
|
|
$multiSelectValue = $values[$field];
|
|
if (!is_array($values[$field])) {
|
|
$multiSelectValue = [];
|
|
}
|
|
$values[$field] = encodeMultienumValue($multiSelectValue);
|
|
}
|
|
|
|
$fieldMapper = $this->getFieldMapper($bean->module_name, $field);
|
|
if (null !== $fieldMapper) {
|
|
$fieldMapper->toBean($bean, $values, $field);
|
|
}
|
|
|
|
$typeMapper = $this->getTypeMappers($bean->module_name, $type);
|
|
if (null !== $typeMapper) {
|
|
$typeMapper->toBean($bean, $values, $field, $field);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param SugarBean $bean
|
|
* @return array
|
|
*/
|
|
public function mapLinkedModule(SugarBean $bean): array
|
|
{
|
|
$beanModule = $bean->module_name;
|
|
if (empty($beanModule)) {
|
|
return [];
|
|
}
|
|
|
|
$field_defs = $bean->field_defs;
|
|
if (empty($field_defs)) {
|
|
return [];
|
|
}
|
|
|
|
$beanObject = BeanFactory::newBean($beanModule);
|
|
if ($beanObject === null) {
|
|
return [];
|
|
}
|
|
|
|
$beanObject->load_relationships();
|
|
if (empty($beanObject)) {
|
|
return [];
|
|
}
|
|
|
|
foreach ($field_defs as $fieldName => $fieldDefinition) {
|
|
|
|
//skip, if module property already exists in fieldDefinition
|
|
$module = $fieldDefinition['module'] ?? '';
|
|
if (!empty($module)) {
|
|
continue;
|
|
}
|
|
|
|
$type = $fieldDefinition['type'] ?? '';
|
|
if ($type !== 'link') {
|
|
continue;
|
|
}
|
|
|
|
$relationship = $fieldDefinition['relationship'] ?? '';
|
|
if (empty($relationship)) {
|
|
continue;
|
|
}
|
|
|
|
$name = $fieldDefinition['name'] ?? '';
|
|
if (empty($name)) {
|
|
continue;
|
|
}
|
|
|
|
if (!property_exists($beanObject, $name)) {
|
|
continue;
|
|
}
|
|
|
|
if (!property_exists($beanObject->$name, 'relationship')) {
|
|
continue;
|
|
}
|
|
|
|
if (!property_exists($beanObject->$name->relationship, 'def')) {
|
|
continue;
|
|
}
|
|
|
|
$relationshipMetadata = $beanObject->$name->relationship->def;
|
|
if (empty($relationshipMetadata)) {
|
|
continue;
|
|
}
|
|
|
|
$this->injectRelatedModule($fieldDefinition, $relationshipMetadata, $beanModule);
|
|
|
|
$field_defs[$fieldName] = $fieldDefinition;
|
|
}
|
|
|
|
return $field_defs;
|
|
}
|
|
|
|
/**
|
|
* @param array $fieldDefinition
|
|
* @param array $relationshipMetadata
|
|
* @param string $beanModule
|
|
* @return void
|
|
* @desc this function retrieves the related module for the link type field.
|
|
* this information is required to link the relationship between the two modules
|
|
*/
|
|
public function injectRelatedModule(array &$fieldDefinition, array $relationshipMetadata, string $beanModule): void
|
|
{
|
|
if (empty($relationshipMetadata)) {
|
|
return;
|
|
}
|
|
|
|
$lhsModule = $relationshipMetadata['lhs_module'] ?? '';
|
|
$rhsModule = $relationshipMetadata['rhs_module'] ?? '';
|
|
|
|
if ($lhsModule === $beanModule) {
|
|
$fieldDefinition['module'] = $rhsModule;
|
|
}
|
|
|
|
if ($rhsModule === $beanModule) {
|
|
$fieldDefinition['module'] = $lhsModule;
|
|
}
|
|
}
|
|
|
|
}
|