relation save processing refactoring

This commit is contained in:
Yuri Kuznetsov
2021-04-20 18:02:15 +03:00
parent d2fdd37084
commit 556ea8754c
5 changed files with 813 additions and 276 deletions
@@ -0,0 +1,199 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\FieldProcessing\Relation;
use Espo\Core\{
ORM\Entity,
ORM\EntityManager,
};
class LinkMultipleSaveProcessor
{
private $entityManager;
public function __construct(EntityManager $entityManager)
{
$this->entityManager = $entityManager;
}
public function process(Entity $entity, string $name, array $options): void
{
$entityType = $entity->getEntityType();
$repository = $this->entityManager->getRDBRepository($entityType);
$idListAttribute = $name . 'Ids';
$columnsAttribute = $name . 'Columns';
$defs = $this->entityManager->getDefs()->getEntity($entityType);
$skipCreate = $options['skipLinkMultipleCreate'] ?? false;
$skipRemove = $options['skipLinkMultipleRemove'] ?? false;
$skipUpdate = $options['skipLinkMultipleUpdate'] ?? false;
if ($entity->isNew()) {
$skipRemove = true;
$skipUpdate = true;
}
if ($entity->has($idListAttribute)) {
$specifiedIdList = $entity->get($idListAttribute);
}
else if ($entity->has($columnsAttribute)) {
$skipRemove = true;
$specifiedIdList = array_keys(
get_object_vars(
$entity->get($columnsAttribute) ?? (object) []
)
);
}
else {
return;
}
if (!is_array($specifiedIdList)) {
return;
}
$toRemoveIdList = [];
$existingIdList = [];
$toUpdateIdList = [];
$toCreateIdList = [];
$existingColumnsData = (object) [];
$columns = null;
if ($defs->hasField($name)) {
$columns = $defs->getField($name)->getParam('columns');
}
$columnData = !empty($columns) ?
$entity->get($columnsAttribute) :
null;
if (!$skipRemove || !$skipUpdate) {
$foreignEntityList = $repository->getRelation($entity, $name)->find();
foreach ($foreignEntityList as $foreignEntity) {
$existingIdList[] = $foreignEntity->id;
if (empty($columns)) {
continue;
}
$data = (object) [];
foreach ($columns as $columnName => $columnField) {
$foreignId = $foreignEntity->id;
$data->$columnName = $foreignEntity->get($columnField);
}
$existingColumnsData->$foreignId = $data;
if (!$entity->isNew()) {
$entity->setFetched($columnsAttribute, $existingColumnsData);
}
}
}
if (!$entity->isNew()) {
if ($entity->has($idListAttribute) && !$entity->hasFetched($idListAttribute)) {
$entity->setFetched($idListAttribute, $existingIdList);
}
if ($entity->has($columnsAttribute) && !empty($columns)) {
$entity->setFetched($columnsAttribute, $existingColumnsData);
}
}
foreach ($existingIdList as $id) {
if (!in_array($id, $specifiedIdList)) {
if (!$skipRemove) {
$toRemoveIdList[] = $id;
}
continue;
}
if ($skipUpdate || empty($columns)) {
continue;
}
foreach ($columns as $columnName => $columnField) {
if (!isset($columnData->$id) || !is_object($columnData->$id)) {
continue;
}
if (
property_exists($columnData->$id, $columnName)
&&
(
!property_exists($existingColumnsData->$id, $columnName)
||
$columnData->$id->$columnName !== $existingColumnsData->$id->$columnName
)
) {
$toUpdateIdList[] = $id;
}
}
}
if (!$skipCreate) {
foreach ($specifiedIdList as $id) {
if (!in_array($id, $existingIdList)) {
$toCreateIdList[] = $id;
}
}
}
foreach ($toCreateIdList as $id) {
$data = null;
if (!empty($columns) && isset($columnData->$id)) {
$data = (array) $columnData->$id;
}
$repository->getRelation($entity, $name)->relateById($id, $data);
}
foreach ($toRemoveIdList as $id) {
$repository->getRelation($entity, $name)->unrelateById($id);
}
foreach ($toUpdateIdList as $id) {
$data = (array) $columnData->$id;
$repository->getRelation($entity, $name)->updateColumnsById($id, (array) $data);
}
}
}
@@ -0,0 +1,403 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\FieldProcessing\Relation;
use Espo\Core\{
ORM\Entity,
ORM\EntityManager,
};
class SaveProcessor
{
private $entityManager;
private $linkMultipleSaveProcessor;
private $manyRelationListMapCache = [];
private $hasOneRelationListMapCache = [];
private $belongsToHasOneRelationListMapCache = [];
public function __construct(
EntityManager $entityManager,
LinkMultipleSaveProcessor $linkMultipleSaveProcessor
) {
$this->entityManager = $entityManager;
$this->linkMultipleSaveProcessor = $linkMultipleSaveProcessor;
}
public function process(Entity $entity, array $options): void
{
$this->processMany($entity, $options);
$this->processHasOne($entity, $options);
$this->processBelongsToHasOne($entity, $options);
return;
foreach ($entity->getRelationList() as $name) {
$type = $entity->getRelationType($name);
$foreignEntityType = $entity->getRelationParam($name, 'entity');
$foreignKey = $entity->getRelationParam($name, 'foreignKey');
/*if (in_array($type, $manyRelationTypeList)) {
$idListAttribute = $name . 'Ids';
$columnsAttribute = $name . 'Columns';
if ($entity->has($idListAttribute) || $entity->has($columnsAttribute)) {
$this->processLinkMultipleFieldSave($entity, $name, $options);
}
continue;
}*/
if ($type === $entity::HAS_ONE) {
/*if (!$foreignEntityType || !$foreignKey) {
continue;
}*/
/*$noSave = $this->metadata
->get(['entityDefs', $entity->getEntityType(), 'fields', $name, 'noSave']);
if ($noSave) {
continue;
}*/
$idAttribute = $name . 'Id';
if (!$entity->has($idAttribute)) {
continue;
}
continue;
}
if ($type === $entity::BELONGS_TO) {
if (!$entity->get($name . 'Id')) {
continue;
}
if (!$entity->isAttributeChanged($name . 'Id')) {
continue;
}
$foreignLink = $entity->getRelationParam($name, 'foreign');
if (
$this->metadata->get(
['entityDefs', $foreignEntityType, 'links', $foreignLink, 'type']
) === $entity::HAS_ONE
) {
$anotherEntity = $this
->select(['id'])
->where([
$name . 'Id' => $entity->get($name . 'Id'),
'id!=' => $entity->id,
])
->findOne();
if ($anotherEntity) {
$anotherEntity->set($name . 'Id', null);
$this->entityManager->saveEntity($anotherEntity, [
'skipAll' => true,
]);
}
}
continue;
}
}
}
private function processMany(Entity $entity, array $options): void
{
$entityType = $entity->getEntityType();
foreach ($this->getManyRelationList($entityType) as $name) {
$this->processManyItem($entity, $name, $options);
}
}
private function processManyItem(Entity $entity, string $name, array $options): void
{
$idListAttribute = $name . 'Ids';
$columnsAttribute = $name . 'Columns';
if (!$entity->has($idListAttribute) && !$entity->has($columnsAttribute)) {
return;
}
$this->linkMultipleSaveProcessor->process($entity, $name, $options);
}
private function processHasOne(Entity $entity, array $options): void
{
$entityType = $entity->getEntityType();
foreach ($this->getHasOneRelationList($entityType) as $name) {
$this->processHasOneItem($entity, $name);
}
}
private function processHasOneItem(Entity $entity, string $name): void
{
$entityType = $entity->getEntityType();
$idAttribute = $name . 'Id';
if (!$entity->has($idAttribute)) {
return;
}
$id = $entity->get($idAttribute);
$defs = $this->entityManager->getDefs()->getEntity($entityType);
$relationDefs = $defs->getRelation($name);
$foreignKey = $relationDefs->getForeignKey();
$foreignEntityType = $relationDefs->getForeignEntityType();
$previousForeignEntity = $this->entityManager
->getRDBRepository($foreignEntityType)
->select(['id'])
->where([
$foreignKey => $entity->getId(),
])
->findOne();
if ($previousForeignEntity) {
if (!$entity->isNew()) {
$entity->setFetched($idAttribute, $previousForeignEntity->getId());
}
if (!$id) {
$previousForeignEntity->set($foreignKey, null);
$this->entityManager->saveEntity($previousForeignEntity, [
'skipAll' => true,
]);
}
}
else if (!$entity->isNew()) {
$entity->setFetched($idAttribute, null);
}
if ($id) {
$this->entityManager
->getRDBRepository($entityType)
->getRelation($entity, $name)
->relateById($id);
}
}
private function processBelongsToHasOne(Entity $entity, array $options): void
{
$entityType = $entity->getEntityType();
foreach ($this->getBelongsToHasOneRelationList($entityType) as $name) {
$this->processBelongsToHasOneItem($entity, $name);
}
}
private function processBelongsToHasOneItem(Entity $entity, string $name): void
{
$entityType = $entity->getEntityType();
$idAttribute = $name . 'Id';
if (!$entity->get($idAttribute)) {
return;
}
if (!$entity->isAttributeChanged($idAttribute)) {
return;
}
$anotherEntity = $this->entityManager
->getRDBRepository($entityType)
->select(['id'])
->where([
$idAttribute => $entity->get($idAttribute),
'id!=' => $entity->getId(),
])
->findOne();
if (!$anotherEntity) {
return;
}
$anotherEntity->set($idAttribute, null);
$this->entityManager->saveEntity($anotherEntity, [
'skipAll' => true,
]);
}
private function getManyRelationList(string $entityType): array
{
if (array_key_exists($entityType, $this->manyRelationListMapCache)) {
return $this->manyRelationListMapCache[$entityType];
}
$typeList = [
Entity::HAS_MANY,
Entity::MANY_MANY,
Entity::HAS_CHILDREN,
];
$defs = $this->entityManager->getDefs()->getEntity($entityType);
$list = [];
foreach ($defs->getRelationNameList() as $name) {
$type = $defs->getRelation($name)->getType();
if (!in_array($type, $typeList)) {
continue;
}
if (!$defs->hasAttribute($name . 'Ids')) {
continue;
}
if ($defs->hasField($name) && $defs->getField($name)->getParam('noSave')) {
continue;
}
$list[] = $name;
}
$this->manyRelationListMapCache[$entityType] = $list;
return $list;
}
private function getHasOneRelationList(string $entityType): array
{
if (array_key_exists($entityType, $this->hasOneRelationListMapCache)) {
return $this->hasOneRelationListMapCache[$entityType];
}
$ormDefs = $this->entityManager->getDefs();
$defs = $ormDefs->getEntity($entityType);
$list = [];
foreach ($defs->getRelationNameList() as $name) {
$relationDefs = $defs->getRelation($name);
$type = $relationDefs->getType();
if ($type !== Entity::HAS_ONE) {
continue;
}
if (!$relationDefs->hasForeignEntityType()) {
continue;
}
if (!$relationDefs->hasForeignKey()) {
continue;
}
if (!$defs->hasAttribute($name . 'Id')) {
continue;
}
if ($defs->hasField($name) && $defs->getField($name)->getParam('noSave')) {
continue;
}
$list[] = $name;
}
$this->hasOneRelationListMapCache[$entityType] = $list;
return $list;
}
private function getBelongsToHasOneRelationList(string $entityType): array
{
if (array_key_exists($entityType, $this->belongsToHasOneRelationListMapCache)) {
return $this->belongsToHasOneRelationListMapCache[$entityType];
}
$ormDefs = $this->entityManager->getDefs();
$defs = $ormDefs->getEntity($entityType);
$list = [];
foreach ($defs->getRelationNameList() as $name) {
$relationDefs = $defs->getRelation($name);
$type = $relationDefs->getType();
if ($type !== Entity::BELONGS_TO) {
continue;
}
if (!$relationDefs->hasForeignRelationName()) {
continue;
}
if (!$relationDefs->hasForeignEntityType()) {
continue;
}
if (!$defs->hasAttribute($name . 'Id')) {
continue;
}
$foreignEntityType = $relationDefs->getForeignEntityType();
$foreignRelationName = $relationDefs->getForeignRelationName();
$foreignType = $ormDefs
->getEntity($foreignEntityType)
->getRelation($foreignRelationName)
->getType();
if ($foreignType !== Entity::HAS_ONE) {
continue;
}
$list[] = $name;
}
$this->belongsToHasOneRelationListMapCache[$entityType] = $list;
return $list;
}
}
@@ -34,6 +34,7 @@ use Espo\Core\ORM\Entity;
use Espo\Core\{
FieldProcessing\EmailAddress\SaveProcessor as EmailAddressSaveProcessor,
FieldProcessing\PhoneNumber\SaveProcessor as PhoneNumberSaveProcessor,
FieldProcessing\Relation\SaveProcessor as RelationSaveProcessor,
};
/**
@@ -45,17 +46,22 @@ class SaveProcessor
private $phoneNumberSaveProcessor;
private $relationSaveProcessor;
public function __construct(
EmailAddressSaveProcessor $emailAddressSaveProcessor,
PhoneNumberSaveProcessor $phoneNumberSaveProcessor
PhoneNumberSaveProcessor $phoneNumberSaveProcessor,
RelationSaveProcessor $relationSaveProcessor
) {
$this->emailAddressSaveProcessor = $emailAddressSaveProcessor;
$this->phoneNumberSaveProcessor = $phoneNumberSaveProcessor;
$this->relationSaveProcessor = $relationSaveProcessor;
}
public function process(Entity $entity, array $options): void
{
$this->emailAddressSaveProcessor->process($entity, $options);
$this->phoneNumberSaveProcessor->process($entity, $options);
$this->relationSaveProcessor->process($entity, $options);
}
}
+12 -275
View File
@@ -139,7 +139,11 @@ class Database extends RDBRepository
];
$this->hookManager->process(
$this->entityType, 'afterMassRelate', $entity, $options, $hookData
$this->entityType,
'afterMassRelate',
$entity,
$options,
$hookData
);
}
}
@@ -151,11 +155,14 @@ class Database extends RDBRepository
if (!$this->hooksDisabled && empty($options['skipHooks'])) {
if (is_string($foreign)) {
$foreignId = $foreign;
$foreignEntityType = $entity->getRelationParam($relationName, 'entity');
if ($foreignEntityType) {
$foreign = $this->getEntityManager()->getEntity($foreignEntityType);
$foreign->id = $foreignId;
$foreign->set('id', $foreignId);
$foreign->setAsFetched();
}
}
@@ -213,7 +220,6 @@ class Database extends RDBRepository
parent::afterSave($entity, $options);
if (!$this->processFieldsAfterSaveDisabled) {
$this->processSpecifiedRelationsSave($entity, $options);
$this->processFileFieldsSave($entity);
$this->processArrayFieldsSave($entity);
$this->processWysiwygFieldsSave($entity);
@@ -227,6 +233,7 @@ class Database extends RDBRepository
public function save(Entity $entity, array $options = []): void
{
$nowString = date('Y-m-d H:i:s', time());
$restoreData = [];
if (
@@ -262,7 +269,8 @@ class Database extends RDBRepository
}
}
}
} else {
}
else {
if (empty($options['silent']) && empty($options['skipModifiedBy'])) {
if ($entity->hasAttribute('modifiedAt')) {
$entity->set('modifiedAt', $nowString);
@@ -427,275 +435,4 @@ class Database extends RDBRepository
}
}
}
public function processLinkMultipleFieldSave(Entity $entity, string $link, array $options = [])
{
$name = $link;
$idListAttribute = $link . 'Ids';
$columnsAttribute = $link . 'Columns';
if ($this->getMetadata()->get("entityDefs." . $entity->getEntityType() . ".fields.{$name}.noSave")) {
return;
}
$skipCreate = false;
$skipRemove = false;
$skipUpdate = false;
if (!empty($options['skipLinkMultipleCreate'])) {
$skipCreate = true;
}
if (!empty($options['skipLinkMultipleRemove'])) {
$skipRemove = true;
}
if (!empty($options['skipLinkMultipleUpdate'])) {
$skipUpdate = true;
}
if ($entity->isNew()) {
$skipRemove = true;
$skipUpdate = true;
}
if ($entity->has($idListAttribute)) {
$specifiedIdList = $entity->get($idListAttribute);
}
else if ($entity->has($columnsAttribute)) {
$skipRemove = true;
$specifiedIdList = [];
foreach ($entity->get($columnsAttribute) as $id => $d) {
$specifiedIdList[] = $id;
}
} else {
return;
}
if (!is_array($specifiedIdList)) {
return;
}
$toRemoveIdList = [];
$existingIdList = [];
$toUpdateIdList = [];
$toCreateIdList = [];
$existingColumnsData = (object) [];
$columns = $this->getMetadata()->get(['entityDefs', $entity->getEntityType(), 'fields', $name, 'columns']);
if (!empty($columns)) {
$columnData = $entity->get($columnsAttribute);
}
if (!$skipRemove || !$skipUpdate) {
$foreignEntityList = $this->getRelation($entity, $name)->find();
if ($foreignEntityList) {
foreach ($foreignEntityList as $foreignEntity) {
$existingIdList[] = $foreignEntity->id;
if (!empty($columns)) {
$data = (object) [];
foreach ($columns as $columnName => $columnField) {
$foreignId = $foreignEntity->id;
$data->$columnName = $foreignEntity->get($columnField);
}
$existingColumnsData->$foreignId = $data;
if (!$entity->isNew()) {
$entity->setFetched($columnsAttribute, $existingColumnsData);
}
}
}
}
}
if (!$entity->isNew()) {
if ($entity->has($idListAttribute) && !$entity->hasFetched($idListAttribute)) {
$entity->setFetched($idListAttribute, $existingIdList);
}
if ($entity->has($columnsAttribute) && !empty($columns)) {
$entity->setFetched($columnsAttribute, $existingColumnsData);
}
}
foreach ($existingIdList as $id) {
if (!in_array($id, $specifiedIdList)) {
if (!$skipRemove) {
$toRemoveIdList[] = $id;
}
}
else {
if (!$skipUpdate && !empty($columns)) {
foreach ($columns as $columnName => $columnField) {
if (isset($columnData->$id) && is_object($columnData->$id)) {
if (
property_exists($columnData->$id, $columnName)
&&
(
!property_exists($existingColumnsData->$id, $columnName)
||
$columnData->$id->$columnName !== $existingColumnsData->$id->$columnName
)
) {
$toUpdateIdList[] = $id;
}
}
}
}
}
}
if (!$skipCreate) {
foreach ($specifiedIdList as $id) {
if (!in_array($id, $existingIdList)) {
$toCreateIdList[] = $id;
}
}
}
foreach ($toCreateIdList as $id) {
$data = null;
if (!empty($columns) && isset($columnData->$id)) {
$data = (array) $columnData->$id;
}
$this->getRelation($entity, $name)->relateById($id, $data);
}
foreach ($toRemoveIdList as $id) {
$this->getRelation($entity, $name)->unrelateById($id);
}
foreach ($toUpdateIdList as $id) {
$data = (array) $columnData->$id;
$this->getRelation($entity, $name)->updateColumnsById($id, (array) $data);
}
}
protected function processSpecifiedRelationsSave(Entity $entity, array $options = [])
{
$relationTypeList = [
$entity::HAS_MANY,
$entity::MANY_MANY,
$entity::HAS_CHILDREN,
];
foreach ($entity->getRelationList() as $name) {
$type = $entity->getRelationType($name);
$foreignEntityType = $entity->getRelationParam($name, 'entity');
$foreignKey = $entity->getRelationParam($name, 'foreignKey');
if (in_array($type, $relationTypeList)) {
$idListAttribute = $name . 'Ids';
$columnsAttribute = $name . 'Columns';
if ($entity->has($idListAttribute) || $entity->has($columnsAttribute)) {
$this->processLinkMultipleFieldSave($entity, $name, $options);
}
continue;
}
if ($type === $entity::HAS_ONE) {
if (!$foreignEntityType || !$foreignKey) {
continue;
}
$noSave = $this->getMetadata()->get(
['entityDefs', $entity->getEntityType(), 'fields', $name, 'noSave']
);
if ($noSave) {
continue;
}
$idAttribute = $name . 'Id';
if (!$entity->has($idAttribute)) {
continue;
}
$where = [];
$where[$foreignKey] = $entity->id;
$previousForeignEntity = $this->getEntityManager()
->getRepository($foreignEntityType)
->select(['id'])
->where($where)
->findOne();
if ($previousForeignEntity) {
if (!$entity->isNew()) {
$entity->setFetched($idAttribute, $previousForeignEntity->id);
}
if (!$entity->get($idAttribute)) {
$previousForeignEntity->set($foreignKey, null);
$this->getEntityManager()->saveEntity($previousForeignEntity, ['skipAll' => true]);
}
} else {
if (!$entity->isNew()) {
$entity->setFetched($idAttribute, null);
}
}
if ($entity->get($idAttribute)) {
$relateResult = $this->relate($entity, $name, $entity->get($idAttribute));
if (!$relateResult) {
$entity->set($idAttribute, null);
}
}
continue;
}
if ($type === $entity::BELONGS_TO) {
if (!$entity->get($name . 'Id')) {
continue;
}
if (!$entity->isAttributeChanged($name . 'Id')) {
continue;
}
$foreignLink = $entity->getRelationParam($name, 'foreign');
if (
$this->getMetadata()->get(
['entityDefs', $foreignEntityType, 'links', $foreignLink, 'type']
) === $entity::HAS_ONE
) {
$anotherEntity = $this
->select(['id'])
->where([
$name . 'Id' => $entity->get($name . 'Id'),
'id!=' => $entity->id,
])
->findOne();
if ($anotherEntity) {
$anotherEntity->set($name . 'Id', null);
$this->getEntityManager()->saveEntity($anotherEntity, ['skipAll' => true]);
}
}
continue;
}
}
}
}
@@ -0,0 +1,192 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace tests\integration\Espo\Core\FieldProcessing;
use Espo\Core\ORM\EntityManager;
class RelationTest extends \tests\integration\Core\BaseTestCase
{
public function testLinkMultiple1(): void
{
/* @var $entityManager EntityManager */
$entityManager = $this->getContainer()->get('entityManager');
$contact1 = $entityManager->createEntity('Contact', []);
$contact2 = $entityManager->createEntity('Contact', []);
$contact3 = $entityManager->createEntity('Contact', []);
$opportunity = $entityManager->createEntity('Opportunity', [
'contactsIds' => [
$contact1->getId(),
$contact2->getId(),
],
'contactsColumns' => (object) [
$contact1->getId() => (object) [
'role' => 'Decision Maker',
],
],
]);
$opportunity = $entityManager->getEntity('Opportunity', $opportunity->getId());
$this->assertEquals(
self::sortArray([
$contact1->getId(),
$contact2->getId(),
]),
self::sortArray($opportunity->getLinkMultipleIdList('contacts'))
);
$column1 = $entityManager
->getRDBRepository('Opportunity')
->getRelation($opportunity, 'contacts')
->getColumn($contact1, 'role');
$this->assertEquals('Decision Maker', $column1);
$opportunity->set([
'contactsIds' => [
$contact2->getId(),
$contact3->getId(),
],
'contactsColumns' => (object) [
$contact2->getId() => (object) [
'role' => null,
],
$contact3->getId() => (object) [
'role' => 'Evaluator',
],
],
]);
$entityManager->saveEntity($opportunity);
$opportunity = $entityManager->getEntity('Opportunity', $opportunity->getId());
$this->assertEquals(
self::sortArray([
$contact2->getId(),
$contact3->getId(),
]),
self::sortArray($opportunity->getLinkMultipleIdList('contacts'))
);
$column3 = $entityManager
->getRDBRepository('Opportunity')
->getRelation($opportunity, 'contacts')
->getColumn($contact3, 'role');
$this->assertEquals('Evaluator', $column3);
$opportunity = $entityManager->getEntity('Opportunity', $opportunity->getId());
$opportunity->set([
'contactsColumns' => (object) [
$contact3->getId() => (object) [
'role' => 'Decision Maker',
],
],
]);
$entityManager->saveEntity($opportunity);
$column3 = $entityManager
->getRDBRepository('Opportunity')
->getRelation($opportunity, 'contacts')
->getColumn($contact3, 'role');
$this->assertEquals('Decision Maker', $column3);
}
public function testHasOne(): void
{
/* @var $entityManager EntityManager */
$entityManager = $this->getContainer()->get('entityManager');
$lead1 = $entityManager->createEntity('Lead', []);
$lead2 = $entityManager->createEntity('Lead', []);
$account = $entityManager->createEntity('Account', []);
$lead1->set('createdAccountId', $account->getId());
$entityManager->saveEntity($lead1);
$lead2->set('createdAccountId', $account->getId());
$entityManager->saveEntity($lead2);
$lead1 = $entityManager->getEntity('Lead', $lead1->getId());
$this->assertNull($lead1->get('createdAccountId'));
$lead2 = $entityManager->getEntity('Lead', $lead2->getId());
$this->assertEquals($account->getId(), $lead2->get('createdAccountId'));
}
public function testBelongsToHasOne(): void
{
/* @var $entityManager EntityManager */
$entityManager = $this->getContainer()->get('entityManager');
$lead1 = $entityManager->createEntity('Lead', []);
$lead2 = $entityManager->createEntity('Lead', []);
$account = $entityManager->createEntity('Account', [
'originalLeadId' => $lead1->getId(),
]);
$entityManager->saveEntity($account);
$account = $entityManager->getEntity('Account', $account->getId());
$account->set([
'originalLeadId' => $lead2->getId(),
]);
$entityManager->saveEntity($account);
$lead2 = $entityManager->getEntity('Lead', $lead2->getId());
$this->assertEquals($account->getId(), $lead2->get('createdAccountId'));
$lead1 = $entityManager->getEntity('Lead', $lead1->getId());
$this->assertEquals(null, $lead1->get('createdAccountId'));
}
private static function sortArray(array $array): array
{
sort($array);
return $array;
}
}