orm isRelatedById method
This commit is contained in:
@@ -61,6 +61,7 @@ class IsRelatedType extends \Espo\Core\Formula\Functions\Base implements
|
||||
|
||||
return $this->entityManager
|
||||
->getRDBRepository($this->getEntity()->getEntityType())
|
||||
->isRelated($this->getEntity(), $link, $id);
|
||||
->getRelation($this->getEntity(), $link)
|
||||
->isRelatedById($id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +105,11 @@ class DefaultOwnershipChecker implements
|
||||
$repository = $this->entityManager->getRDBRepository($entity->getEntityType());
|
||||
|
||||
foreach ($accountIdList as $accountId) {
|
||||
if ($repository->isRelated($entity, self::FIELD_ACCOUNTS, $accountId)) {
|
||||
if (
|
||||
$repository
|
||||
->getRelation($entity, self::FIELD_ACCOUNTS)
|
||||
->isRelatedById($accountId)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -146,7 +150,11 @@ class DefaultOwnershipChecker implements
|
||||
) {
|
||||
$repository = $this->entityManager->getRDBRepository($entity->getEntityType());
|
||||
|
||||
if ($repository->isRelated($entity, self::FIELD_CONTACTS, $contactId)) {
|
||||
if (
|
||||
$repository
|
||||
->getRelation($entity, self::FIELD_CONTACTS)
|
||||
->isRelatedById($contactId)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,7 +318,7 @@ class BaseMapper implements RDBMapper
|
||||
case Entity::BELONGS_TO:
|
||||
/** @var Entity $relEntity */
|
||||
|
||||
$params['whereClause'][$foreignKey] = $entity->get($key);
|
||||
$params['whereClause'][] = [$foreignKey =>$entity->get($key)];
|
||||
$params['offset'] = 0;
|
||||
$params['limit'] = 1;
|
||||
$params['from'] = $relEntity->getEntityType();
|
||||
@@ -358,7 +358,7 @@ class BaseMapper implements RDBMapper
|
||||
|
||||
$params['from'] = $relEntity->getEntityType();
|
||||
$params['fromAlias'] ??= lcfirst($relEntity->getEntityType());
|
||||
$params['whereClause'][$foreignKey] = $entity->get($key);
|
||||
$params['whereClause'][] = [$foreignKey => $entity->get($key)];
|
||||
|
||||
if ($relType == Entity::HAS_CHILDREN) {
|
||||
$foreignType = $keySet['foreignType'] ?? null;
|
||||
@@ -367,7 +367,7 @@ class BaseMapper implements RDBMapper
|
||||
throw new RuntimeException("Bad relation key.");
|
||||
}
|
||||
|
||||
$params['whereClause'][$foreignType] = $entity->getEntityType();
|
||||
$params['whereClause'][] = [$foreignType => $entity->getEntityType()];
|
||||
}
|
||||
|
||||
$relConditions = $this->getRelationParam($entity, $relationName, 'conditions');
|
||||
@@ -456,7 +456,7 @@ class BaseMapper implements RDBMapper
|
||||
return null;
|
||||
}
|
||||
|
||||
$params['whereClause'][$foreignKey] = $foreignEntityId;
|
||||
$params['whereClause'][] = [$foreignKey => $foreignEntityId];
|
||||
$params['offset'] = 0;
|
||||
$params['limit'] = 1;
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ class RDBRelation
|
||||
}
|
||||
|
||||
if (!$entity->hasRelation($relationName)) {
|
||||
throw new RuntimeException("Entity does not have a relation '{$relationName}'.");
|
||||
throw new RuntimeException("Entity does not have a relation '$relationName'.");
|
||||
}
|
||||
|
||||
$this->relationName = $relationName;
|
||||
@@ -103,7 +103,7 @@ class RDBRelation
|
||||
private function createSelectBuilder(?Select $query = null): Builder
|
||||
{
|
||||
if ($this->noBuilder) {
|
||||
throw new RuntimeException("Can't use query builder for the '{$this->relationType}' relation type.");
|
||||
throw new RuntimeException("Can't use query builder for the '$this->relationType' relation type.");
|
||||
}
|
||||
|
||||
return new Builder($this->entityManager, $this->entity, $this->relationName, $query);
|
||||
@@ -115,7 +115,7 @@ class RDBRelation
|
||||
public function clone(Select $query): Builder
|
||||
{
|
||||
if ($this->noBuilder) {
|
||||
throw new RuntimeException("Can't use clone for the '{$this->relationType}' relation type.");
|
||||
throw new RuntimeException("Can't use clone for the '$this->relationType' relation type.");
|
||||
}
|
||||
|
||||
if ($query->getFrom() !== $this->foreignEntityType) {
|
||||
@@ -134,6 +134,7 @@ class RDBRelation
|
||||
{
|
||||
$mapper = $this->entityManager->getMapper();
|
||||
|
||||
/** @noinspection PhpConditionAlreadyCheckedInspection */
|
||||
if (!$mapper instanceof RDBMapper) {
|
||||
throw new LogicException();
|
||||
}
|
||||
@@ -251,7 +252,7 @@ class RDBRelation
|
||||
* * `where(string $key, string $value)`
|
||||
*
|
||||
* @param WhereItem|array<string|int, mixed>|string $clause A key or where clause.
|
||||
* @param mixed[]|scalar|null $value A value. Should be omitted if the first argument is not string.
|
||||
* @param array<int, mixed>|scalar|null $value A value. Should be omitted if the first argument is not string.
|
||||
*/
|
||||
public function where($clause = [], $value = null): Builder
|
||||
{
|
||||
@@ -267,7 +268,7 @@ class RDBRelation
|
||||
* * `having(string $key, string $value)`
|
||||
*
|
||||
* @param WhereItem|array<string|int, mixed>|string $clause A key or where clause.
|
||||
* @param mixed[]|string|null $value A value. Should be omitted if the first argument is not string.
|
||||
* @param array<int, mixed>|string|null $value A value. Should be omitted if the first argument is not string.
|
||||
*/
|
||||
public function having($clause = [], $value = null): Builder
|
||||
{
|
||||
@@ -396,6 +397,22 @@ class RDBRelation
|
||||
->findOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether related with another entity. An entity is specified by an ID.
|
||||
* Does not work with 'belongsToParent' relations.
|
||||
*/
|
||||
public function isRelatedById(string $id): bool
|
||||
{
|
||||
if ($this->isBelongsToParentType()) {
|
||||
throw new LogicException("Can't use isRelatedById for 'belongsToParent'.");
|
||||
}
|
||||
|
||||
return (bool) $this->createSelectBuilder()
|
||||
->select(['id'])
|
||||
->where(['id' => $id])
|
||||
->findOne();
|
||||
}
|
||||
|
||||
private function isRelatedBelongsToParent(Entity $entity): bool
|
||||
{
|
||||
$fromEntity = $this->entity;
|
||||
|
||||
@@ -106,15 +106,16 @@ class RDBRelationSelectBuilder
|
||||
return $this->createSelectBuilder()->clone($newQuery);
|
||||
}
|
||||
|
||||
protected function createSelectBuilder(): SelectBuilder
|
||||
private function createSelectBuilder(): SelectBuilder
|
||||
{
|
||||
return new SelectBuilder();
|
||||
}
|
||||
|
||||
protected function getMapper(): RDBMapper
|
||||
private function getMapper(): RDBMapper
|
||||
{
|
||||
$mapper = $this->entityManager->getMapper();
|
||||
|
||||
/** @noinspection PhpConditionAlreadyCheckedInspection */
|
||||
if (!$mapper instanceof RDBMapper) {
|
||||
throw new LogicException();
|
||||
}
|
||||
@@ -155,7 +156,7 @@ class RDBRelationSelectBuilder
|
||||
* @param array<string|int, mixed> $where
|
||||
* @return array<string|int, mixed>
|
||||
*/
|
||||
protected function applyMiddleAliasToWhere(array $where): array
|
||||
private function applyMiddleAliasToWhere(array $where): array
|
||||
{
|
||||
$transformedWhere = [];
|
||||
|
||||
@@ -293,7 +294,7 @@ class RDBRelationSelectBuilder
|
||||
* * `where(string $key, string $value)`
|
||||
*
|
||||
* @param WhereItem|array<int|string, mixed>|string $clause A key or where clause.
|
||||
* @param mixed[]|scalar|null $value A value. Should be omitted if the first argument is not string.
|
||||
* @param array<int, mixed>|scalar|null $value A value. Should be omitted if the first argument is not string.
|
||||
*/
|
||||
public function where($clause = [], $value = null): self
|
||||
{
|
||||
@@ -322,8 +323,8 @@ class RDBRelationSelectBuilder
|
||||
* * `having(array $clause)`
|
||||
* * `having(string $key, string $value)`
|
||||
*
|
||||
* @param WhereItem|array<mixed, mixed>|string $clause A key or where clause.
|
||||
* @param mixed[]|string|null $value A value. Should be omitted if the first argument is not string.
|
||||
* @param WhereItem|array<int|string, mixed>|string $clause A key or where clause.
|
||||
* @param array<int, mixed>|string|null $value A value. Should be omitted if the first argument is not string.
|
||||
*/
|
||||
public function having($clause = [], $value = null): self
|
||||
{
|
||||
@@ -411,7 +412,7 @@ class RDBRelationSelectBuilder
|
||||
return $this->group($groupBy);
|
||||
}
|
||||
|
||||
protected function getMiddleTableAlias(): ?string
|
||||
private function getMiddleTableAlias(): ?string
|
||||
{
|
||||
if (!$this->isManyMany()) {
|
||||
return null;
|
||||
@@ -430,7 +431,7 @@ class RDBRelationSelectBuilder
|
||||
return $this->middleTableAlias;
|
||||
}
|
||||
|
||||
protected function applyRelationAliasToWhereClauseKey(string $item): string
|
||||
private function applyRelationAliasToWhereClauseKey(string $item): string
|
||||
{
|
||||
if (!$this->isManyMany()) {
|
||||
return $item;
|
||||
@@ -445,7 +446,7 @@ class RDBRelationSelectBuilder
|
||||
* @param array<int|string, mixed> $where
|
||||
* @return array<int|string, mixed>
|
||||
*/
|
||||
protected function applyRelationAliasToWhereClause(array $where): array
|
||||
private function applyRelationAliasToWhereClause(array $where): array
|
||||
{
|
||||
if (!$this->isManyMany()) {
|
||||
return $where;
|
||||
@@ -457,10 +458,6 @@ class RDBRelationSelectBuilder
|
||||
$transformedKey = $key;
|
||||
$transformedValue = $value;
|
||||
|
||||
if (is_int($key)) {
|
||||
$transformedKey = $key;
|
||||
}
|
||||
|
||||
if (is_string($key)) {
|
||||
$transformedKey = $this->applyRelationAliasToWhereClauseKey($key);
|
||||
}
|
||||
@@ -475,7 +472,7 @@ class RDBRelationSelectBuilder
|
||||
return $transformedWhere;
|
||||
}
|
||||
|
||||
protected function isManyMany(): bool
|
||||
private function isManyMany(): bool
|
||||
{
|
||||
return $this->relationType === Entity::MANY_MANY;
|
||||
}
|
||||
@@ -484,7 +481,7 @@ class RDBRelationSelectBuilder
|
||||
* @param Collection<Entity> $collection
|
||||
* @return Collection<Entity>
|
||||
*/
|
||||
protected function handleReturnCollection(Collection $collection): Collection
|
||||
private function handleReturnCollection(Collection $collection): Collection
|
||||
{
|
||||
if (!$collection instanceof SthCollection) {
|
||||
return $collection;
|
||||
@@ -499,6 +496,7 @@ class RDBRelationSelectBuilder
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @noinspection PhpSameParameterValueInspection
|
||||
*/
|
||||
private function getRelationParam(string $param)
|
||||
{
|
||||
|
||||
@@ -790,8 +790,8 @@ class Processor
|
||||
|
||||
foreach ($eaList as $ea) {
|
||||
if (
|
||||
$emailRepository->isRelated($emailSubject, 'toEmailAddresses', $ea) ||
|
||||
$emailRepository->isRelated($emailSubject, 'ccEmailAddresses', $ea)
|
||||
$emailRepository->getRelation($emailSubject, 'toEmailAddresses')->isRelated($ea) ||
|
||||
$emailRepository->getRelation($emailSubject, 'ccEmailAddresses')->isRelated($ea)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,9 @@ use Espo\Core\Field\DateTime;
|
||||
use Espo\Core\Field\DateTimeOptional;
|
||||
use Espo\Core\Formula\Manager;
|
||||
use Espo\Entities\User;
|
||||
use Espo\Modules\Crm\Entities\Account;
|
||||
use Espo\Modules\Crm\Entities\Meeting;
|
||||
use Espo\Modules\Crm\Entities\Opportunity;
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
class FormulaTest extends \tests\integration\Core\BaseTestCase
|
||||
@@ -871,4 +873,26 @@ class FormulaTest extends \tests\integration\Core\BaseTestCase
|
||||
);
|
||||
$this->assertFalse($fm->run($script));
|
||||
}
|
||||
|
||||
public function testIsRelated(): void
|
||||
{
|
||||
$em = $this->getEntityManager();
|
||||
$fm = $this->getContainer()->getByClass(Manager::class);
|
||||
|
||||
$account = $em->createEntity(Account::ENTITY_TYPE, []);
|
||||
$opp = $em->createEntity(Opportunity::ENTITY_TYPE, []);
|
||||
|
||||
$em
|
||||
->getRDBRepositoryByClass(Account::class)
|
||||
->getRelation($account, 'opportunities')
|
||||
->relate($opp);
|
||||
|
||||
$script = sprintf(
|
||||
"entity\\isRelated('opportunities', '%s')",
|
||||
$opp->getId()
|
||||
);
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$this->assertTrue($fm->run($script, $account));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
namespace tests\integration\Espo\ORM;
|
||||
|
||||
use Espo\Modules\Crm\Entities\Account;
|
||||
use Espo\Modules\Crm\Entities\Contact;
|
||||
use Espo\Modules\Crm\Entities\Opportunity;
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
class RepositoryTest extends \tests\integration\Core\BaseTestCase
|
||||
@@ -70,4 +72,54 @@ class RepositoryTest extends \tests\integration\Core\BaseTestCase
|
||||
|
||||
$this->assertEquals($user2->getId(), $account->get('modifiedById'));
|
||||
}
|
||||
|
||||
public function testIsRelated(): void
|
||||
{
|
||||
$em = $this->getEntityManager();
|
||||
|
||||
$acc1 = $em->createEntity(Account::ENTITY_TYPE, []);
|
||||
$acc2 = $em->createEntity(Account::ENTITY_TYPE, []);
|
||||
|
||||
$opp1 = $em->createEntity(Opportunity::ENTITY_TYPE, []);
|
||||
|
||||
$contact1 = $em->createEntity(Contact::ENTITY_TYPE, []);
|
||||
$contact2 = $em->createEntity(Contact::ENTITY_TYPE, []);
|
||||
|
||||
$oppRepo = $em->getRDBRepositoryByClass(Opportunity::class);
|
||||
|
||||
$oppRepo->getRelation($opp1, 'account')->relate($acc1);
|
||||
$oppRepo->getRelation($opp1, 'contacts')->relate($contact1);
|
||||
|
||||
$this->assertTrue(
|
||||
$oppRepo->getRelation($opp1, 'account')->isRelatedById($acc1->getId())
|
||||
);
|
||||
|
||||
$this->assertTrue(
|
||||
$oppRepo->getRelation($opp1, 'account')->isRelated($acc1)
|
||||
);
|
||||
|
||||
$this->assertFalse(
|
||||
$oppRepo->getRelation($opp1, 'account')->isRelatedById($acc2->getId())
|
||||
);
|
||||
|
||||
$this->assertFalse(
|
||||
$oppRepo->getRelation($opp1, 'account')->isRelated($acc2)
|
||||
);
|
||||
|
||||
$this->assertTrue(
|
||||
$oppRepo->getRelation($opp1, 'contacts')->isRelatedById($contact1->getId())
|
||||
);
|
||||
|
||||
$this->assertTrue(
|
||||
$oppRepo->getRelation($opp1, 'contacts')->isRelated($contact1)
|
||||
);
|
||||
|
||||
$this->assertFalse(
|
||||
$oppRepo->getRelation($opp1, 'contacts')->isRelatedById($contact2->getId())
|
||||
);
|
||||
|
||||
$this->assertFalse(
|
||||
$oppRepo->getRelation($opp1, 'contacts')->isRelated($contact2)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,46 +297,6 @@ class FormulaTest extends \PHPUnit\Framework\TestCase
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
function testHasValue()
|
||||
{
|
||||
$item = new Argument(self::stringToNode('
|
||||
{
|
||||
"type": "entity\\\\isRelated",
|
||||
"value": [
|
||||
{
|
||||
"type": "value",
|
||||
"value": "teams"
|
||||
},
|
||||
{
|
||||
"type": "value",
|
||||
"value": "1"
|
||||
}
|
||||
]
|
||||
}
|
||||
'));
|
||||
|
||||
$this->entity
|
||||
->expects($this->any())
|
||||
->method('getEntityType')
|
||||
->will($this->returnValue('Test'));
|
||||
|
||||
$this->repository
|
||||
->expects($this->any())
|
||||
->method('isRelated')
|
||||
->will($this->returnValueMap([
|
||||
[$this->entity, 'teams', '1', true]
|
||||
]));
|
||||
|
||||
$this->entityManager
|
||||
->expects($this->any())
|
||||
->method('getRDBRepository')
|
||||
->will($this->returnValue($this->repository));
|
||||
|
||||
$result = $this->createProcessor()->process($item);
|
||||
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
function testAddLinkMultipleId()
|
||||
{
|
||||
$item = new Argument(self::stringToNode('
|
||||
|
||||
@@ -525,8 +525,8 @@ class MapperTest extends \PHPUnit\Framework\TestCase
|
||||
$query = SelectBuilder::create()
|
||||
->from('Note', 'note')
|
||||
->where([
|
||||
'parentId' => '1',
|
||||
'parentType' => 'Post'
|
||||
['parentId' => '1'],
|
||||
['parentType' => 'Post'],
|
||||
])
|
||||
->build();
|
||||
|
||||
@@ -560,7 +560,7 @@ class MapperTest extends \PHPUnit\Framework\TestCase
|
||||
"post.created_by_id AS `createdById`, post.deleted AS `deleted` ".
|
||||
"FROM `post` AS `post` ".
|
||||
"LEFT JOIN `user` AS `createdBy` ON post.created_by_id = createdBy.id " .
|
||||
"WHERE post.id = '1' AND post.deleted = 0 ".
|
||||
"WHERE (post.id = '1') AND post.deleted = 0 ".
|
||||
"LIMIT 0, 1";
|
||||
$return = [
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user