This commit is contained in:
Yuri Kuznetsov
2023-04-21 17:24:54 +03:00
parent 755f3de523
commit 427d2dcf52
23 changed files with 200 additions and 172 deletions
@@ -126,8 +126,8 @@ class AccessChecker implements AccessEntityCREDChecker
{
if ($note->getTargetType() === Note::TARGET_TEAMS) {
$intersect = array_intersect(
$note->getLinkMultipleIdList('teams') ?? [],
$user->getLinkMultipleIdList('teams') ?? []
$note->getLinkMultipleIdList('teams'),
$user->getLinkMultipleIdList('teams')
);
if (count($intersect)) {
@@ -126,7 +126,7 @@ class AccessChecker implements AccessEntityCREDChecker
}
if ($entity->getTargetType() === Note::TARGET_TEAMS) {
$targetTeamIdList = $entity->getLinkMultipleIdList('teams') ?? [];
$targetTeamIdList = $entity->getLinkMultipleIdList('teams');
foreach ($user->getTeamIdList() as $teamId) {
if (in_array($teamId, $targetTeamIdList)) {
@@ -138,7 +138,7 @@ class AccessChecker implements AccessEntityCREDChecker
}
if ($entity->getTargetType() === Note::TARGET_USERS) {
return in_array($user->getId(), $entity->getLinkMultipleIdList('users') ?? []);
return in_array($user->getId(), $entity->getLinkMultipleIdList('users'));
}
return false;
@@ -51,8 +51,8 @@ class OwnershipChecker implements OwnershipOwnChecker, OwnershipTeamChecker
assert($entity instanceof CoreEntity);
$intersect = array_intersect(
$user->getLinkMultipleIdList('teams') ?? [],
$entity->getLinkMultipleIdList('teams') ?? []
$user->getLinkMultipleIdList('teams'),
$entity->getLinkMultipleIdList('teams')
);
if (count($intersect)) {
@@ -131,8 +131,8 @@ class AccessChecker implements AccessEntityCREDChecker
if ($note->getTargetType() === Note::TARGET_PORTALS) {
$intersect = array_intersect(
$note->getLinkMultipleIdList('portals') ?? [],
$user->getLinkMultipleIdList('portals') ?? []
$note->getLinkMultipleIdList('portals'),
$user->getLinkMultipleIdList('portals')
);
if (count($intersect)) {
@@ -118,7 +118,7 @@ class AccessChecker implements AccessEntityCREDChecker
}
if ($entity->getTargetType() === Note::TARGET_PORTALS) {
return in_array($user->getPortalId(), $entity->getLinkMultipleIdList('portals') ?? []);
return in_array($user->getPortalId(), $entity->getLinkMultipleIdList('portals'));
}
return false;
@@ -128,8 +128,7 @@ class ApplyTemplateType extends BaseFunction implements
$emailData = $processor->process($emailTemplate, $params, $data);
/** @var string[] $attachmentsIdList */
$attachmentsIdList = $email->getLinkMultipleIdList('attachments') ?? [];
$attachmentsIdList = $email->getLinkMultipleIdList('attachments');
$attachmentsIdList = array_merge(
$attachmentsIdList,
+157 -109
View File
@@ -30,13 +30,20 @@
namespace Espo\Core\ORM;
use Espo\ORM\BaseEntity;
use Espo\ORM\Query\Part\Order;
use Espo\ORM\Type\RelationType;
use LogicException;
use stdClass;
/**
* An entity.
*/
class Entity extends BaseEntity
{
/**
* Has a link-multiple field.
*/
public function hasLinkMultipleField(string $field): bool
{
return
@@ -44,11 +51,17 @@ class Entity extends BaseEntity
$this->getAttributeParam($field . 'Ids', 'isLinkMultipleIdList');
}
/**
* Has a link field.
*/
public function hasLinkField(string $field): bool
{
return $this->hasAttribute($field . 'Id') && $this->hasRelation($field);
}
/**
* Has a link-parent field.
*/
public function hasLinkParentField(string $field): bool
{
return
@@ -57,10 +70,13 @@ class Entity extends BaseEntity
$this->hasRelation($field);
}
/**
* Load a parent-name field.
*/
public function loadParentNameField(string $field): void
{
if (!$this->hasAttribute($field. 'Id') || !$this->hasAttribute($field . 'Type')) {
throw new LogicException("There's no link-parent field '{$field}'.");
if (!$this->hasLinkParentField($field)) {
throw new LogicException("Called `loadParentNameField` on non-link-parent field `$field`.");
}
$parentId = $this->get($field . 'Id');
@@ -70,40 +86,39 @@ class Entity extends BaseEntity
throw new LogicException("No entity-manager.");
}
if ($parentId && $parentType) {
if (!$this->entityManager->hasRepository($parentType)) {
return;
}
$repository = $this->entityManager->getRDBRepository($parentType);
$select = ['id', 'name'];
$foreignEntity = $repository
->select($select)
->where(['id' => $parentId])
->findOne();
if ($foreignEntity) {
$this->set($field . 'Name', $foreignEntity->get('name'));
return;
}
if (!$parentId || !$parentType) {
$this->set($field . 'Name', null);
return;
}
if (!$this->entityManager->hasRepository($parentType)) {
return;
}
$repository = $this->entityManager->getRDBRepository($parentType);
$select = ['id', 'name'];
$foreignEntity = $repository
->select($select)
->where(['id' => $parentId])
->findOne();
if ($foreignEntity) {
$this->set($field . 'Name', $foreignEntity->get('name'));
return;
}
$this->set($field . 'Name', null);
}
/**
*
* @param string $link
* @return ?array{
* orderBy: string|array<int,array{string,string}>|null,
* order: ?string,
* orderBy: string|array<int, array{string, string}>|null,
* order: ?string,
* }
*/
protected function getRelationOrderParams(string $link): ?array
@@ -161,12 +176,10 @@ class Entity extends BaseEntity
/**
* @param ?array<string, string> $columns
*/
public function loadLinkMultipleField(string $field, $columns = null): void
public function loadLinkMultipleField(string $field, ?array $columns = null): void
{
if (!$this->hasRelation($field) || !$this->hasAttribute($field . 'Ids')) {
return;
// @todo Throw exception on v7.2.
// throw new LogicException("There's no link-multiple field '{$field}'.");
if (!$this->hasLinkMultipleField($field)) {
throw new LogicException("Called `loadLinkMultipleField` on non-link-multiple field `$field`.");
}
if (!$this->entityManager) {
@@ -237,12 +250,14 @@ class Entity extends BaseEntity
$types->$id = $e->get('type');
}
if (!empty($columns)) {
$columnsData->$id = (object) [];
if (empty($columns)) {
continue;
}
foreach ($columns as $column => $f) {
$columnsData->$id->$column = $e->get($f);
}
$columnsData->$id = (object) [];
foreach ($columns as $column => $f) {
$columnsData->$id->$column = $e->get($f);
}
}
@@ -265,14 +280,20 @@ class Entity extends BaseEntity
}
}
/**
* Load a link field.
*/
public function loadLinkField(string $field): void
{
if (!$this->hasRelation($field) || !$this->hasAttribute($field . 'Id')) {
throw new LogicException("There's no link field '{$field}'.");
if (!$this->hasLinkField($field)) {
throw new LogicException("Called `loadLinkField` on non-link field '$field'.");
}
if ($this->getRelationType($field) !== 'hasOne' && $this->getRelationType($field) !== 'belongsTo') {
throw new LogicException("Can't load link '{$field}'.");
if (
$this->getRelationType($field) !== RelationType::HAS_ONE &&
$this->getRelationType($field) !== RelationType::BELONGS_TO
) {
throw new LogicException("Can't load link '$field'.");
}
if (!$this->entityManager) {
@@ -302,42 +323,52 @@ class Entity extends BaseEntity
}
$this->set($idAttribute, $entityId);
$this->set($field . 'Name', $entityName);
}
/**
* @return mixed
* Get a link-multiple name.
*/
public function getLinkMultipleName(string $field, string $id)
public function getLinkMultipleName(string $field, string $id): ?string
{
$namesAttribute = $field . 'Names';
if (!$this->hasAttribute($namesAttribute)) {
throw new LogicException("Called `getLinkMultipleName` on non-link-multiple field `$field.");
}
if (!$this->has($namesAttribute)) {
return;
return null;
}
$names = $this->get($namesAttribute);
$object = $this->get($namesAttribute) ?? (object) [];
if ($names instanceof stdClass && isset($names->$id) && isset($names->$id)) {
return $names->$id;
if (!$object instanceof stdClass) {
throw new LogicException("Non-object value in `$namesAttribute`.");
}
return null;
return $object?->$id ?? null;
}
/**
* Set a link-multiple name.
*/
public function setLinkMultipleName(string $field, string $id, ?string $value): void
{
$namesAttribute = $field . 'Names';
if (!$this->hasAttribute($namesAttribute)) {
throw new LogicException("Called `setLinkMultipleName` on non-link-multiple field `$field.");
}
if (!$this->has($namesAttribute)) {
return;
}
$object = $this->get($namesAttribute);
$object = $this->get($namesAttribute) ?? (object) [];
if (!isset($object) || !($object instanceof stdClass)) {
$object = (object) [];
if (!$object instanceof stdClass) {
throw new LogicException("Non-object value in `$namesAttribute`.");
}
$object->$id = $value;
@@ -346,71 +377,77 @@ class Entity extends BaseEntity
}
/**
* @return mixed
* Get a link-multiple column value.
*/
public function getLinkMultipleColumn(string $field, string $column, string $id)
public function getLinkMultipleColumn(string $field, string $column, string $id): mixed
{
$columnsAttribute = $field . 'Columns';
if (!$this->hasAttribute($columnsAttribute)) {
throw new LogicException("Called `getLinkMultipleColumn` on not supported field `$field.");
}
if (!$this->has($columnsAttribute)) {
return null;
}
$columns = $this->get($columnsAttribute);
$object = $this->get($columnsAttribute) ?? (object) [];
if ($columns instanceof stdClass && isset($columns->$id) && isset($columns->$id->$column)) {
return $columns->$id->$column;
if (!$object instanceof stdClass) {
throw new LogicException("Non-object value in `$columnsAttribute`.");
}
return null;
return $object?->$id?->$column ?? null;
}
/**
* @param mixed $value
* Set a link-multiple column value.
*/
public function setLinkMultipleColumn(string $field, string $column, string $id, $value): void
public function setLinkMultipleColumn(string $field, string $column, string $id, mixed $value): void
{
$columnsAttribute = $field . 'Columns';
if (!$this->hasAttribute($columnsAttribute)) {
return;
throw new LogicException("Called `setLinkMultipleColumn` on non-link-multiple field `$field.");
}
$object = $this->get($columnsAttribute);
$object = $this->get($columnsAttribute) ?? (object) [];
if (!isset($object) || !($object instanceof stdClass)) {
$object = (object) [];
}
if (!isset($object->$id)) {
$object->$id = (object) [];
}
if (!isset($object->$id->$column)) {
$object->$id->$column = (object) [];
if (!$object instanceof stdClass) {
throw new LogicException("Non-object value in `$columnsAttribute`.");
}
$object->$id ??= (object) [];
$object->$id->$column = $value;
$this->set($columnsAttribute, $object);
}
/**
* Set link-multiple IDs.
*
* @param string[] $idList
*/
public function setLinkMultipleIdList(string $field, array $idList): void
{
$idsAttribute = $field . 'Ids';
if (!$this->hasAttribute($idsAttribute)) {
throw new LogicException("Called `setLinkMultipleIdList` on non-link-multiple field `$field.");
}
$this->set($idsAttribute, $idList);
}
/**
* Add an ID to a link-multiple field.
*/
public function addLinkMultipleId(string $field, string $id): void
{
$idsAttribute = $field . 'Ids';
if (!$this->hasAttribute($idsAttribute)) {
return;
throw new LogicException("Called `addLinkMultipleId` on non-link-multiple field `$field.");
}
if (!$this->has($idsAttribute)) {
@@ -427,40 +464,56 @@ class Entity extends BaseEntity
$idList = $this->get($idsAttribute);
if (!in_array($id, $idList)) {
$idList[] = $id;
$this->set($idsAttribute, $idList);
if ($idList === null) {
throw new LogicException("Null value set in `$idsAttribute`.");
}
}
public function removeLinkMultipleId(string $field, string $id): void
{
if ($this->hasLinkMultipleId($field, $id)) {
/** @var string[] $list */
$list = $this->getLinkMultipleIdList($field);
$index = array_search($id, $list);
if ($index !== false) {
unset($list[$index]);
$list = array_values($list);
}
$this->setLinkMultipleIdList($field, $list);
if (!is_array($idList)) {
throw new LogicException("Non-array value set in `$idsAttribute`.");
}
if (in_array($id, $idList)) {
return;
}
$idList[] = $id;
$this->set($idsAttribute, $idList);
}
/**
* @return ?string[]
* @todo Throw exception if the link does not exist.
* Remove an ID from link-multiple field.
*/
public function getLinkMultipleIdList(string $field): ?array
public function removeLinkMultipleId(string $field, string $id): void
{
if (!$this->hasLinkMultipleId($field, $id)) {
return;
}
$list = $this->getLinkMultipleIdList($field);
$index = array_search($id, $list);
if ($index !== false) {
unset($list[$index]);
$list = array_values($list);
}
$this->setLinkMultipleIdList($field, $list);
}
/**
* Get link-multiple field IDs.
*
* @return string[]
*/
public function getLinkMultipleIdList(string $field): array
{
$idsAttribute = $field . 'Ids';
if (!$this->hasAttribute($idsAttribute)) {
return null;
throw new LogicException("Called `getLinkMultipleIdList` for non-link-multiple field `$field.");
}
if (!$this->has($idsAttribute)) {
@@ -469,21 +522,19 @@ class Entity extends BaseEntity
}
}
$valueList = $this->get($idsAttribute);
if (empty($valueList)) {
return [];
}
return $valueList;
/** @var string[] */
return $this->get($idsAttribute) ?? [];
}
/**
* Has an ID in a link-multiple field.
*/
public function hasLinkMultipleId(string $field, string $id): bool
{
$idsAttribute = $field . 'Ids';
if (!$this->hasAttribute($idsAttribute)) {
return false;
throw new LogicException("Called `hasLinkMultipleId` for non-link-multiple field `$field.");
}
if (!$this->has($idsAttribute)) {
@@ -496,12 +547,9 @@ class Entity extends BaseEntity
return false;
}
$idList = $this->get($idsAttribute);
/** @var string[] $idList */
$idList = $this->get($idsAttribute) ?? [];
if (in_array($id, $idList)) {
return true;
}
return false;
return in_array($id, $idList);
}
}
@@ -47,7 +47,7 @@ class PortalOnlyAccount implements Filter
{
$orGroup = [];
$accountIdList = $this->user->getLinkMultipleIdList('accounts') ?? [];
$accountIdList = $this->user->getLinkMultipleIdList('accounts');
$contactId = $this->user->get('contactId');
if (count($accountIdList)) {
@@ -31,20 +31,19 @@ namespace Espo\Modules\Crm\Classes\AclPortal\Account;
use Espo\Entities\User;
use Espo\Modules\Crm\Entities\Account;
use Espo\ORM\Entity;
use Espo\Core\{
Portal\Acl\OwnershipAccountChecker,
};
use Espo\Core\Portal\Acl\OwnershipAccountChecker;
/**
* @implements OwnershipAccountChecker<\Espo\Modules\Crm\Entities\Account>
* @implements OwnershipAccountChecker<Account>
*/
class OwnershipChecker implements OwnershipAccountChecker
{
public function checkAccount(User $user, Entity $entity): bool
{
$accountIdList = $user->getLinkMultipleIdList('accounts') ?? [];
$accountIdList = $user->getLinkMultipleIdList('accounts');
if (in_array($entity->getId(), $accountIdList)) {
return true;
@@ -62,7 +62,7 @@ class AccessChecker implements AccessEntityCREDChecker
assert($entity instanceof CoreEntity);
$portalIdList = $entity->getLinkMultipleIdList('portals') ?? [];
$portalIdList = $entity->getLinkMultipleIdList('portals');
$portalId = $user->get('portalId');
@@ -61,13 +61,13 @@ class PhoneNumberMapLoader implements Loader
assert($entity instanceof CoreEntity);
$contactIdList = $entity->getLinkMultipleIdList('contacts') ?? [];
$contactIdList = $entity->getLinkMultipleIdList('contacts');
if (count($contactIdList)) {
$this->populate($map, 'Contact', $contactIdList);
}
$leadIdList = $entity->getLinkMultipleIdList('leads') ?? [];
$leadIdList = $entity->getLinkMultipleIdList('leads');
if (count($leadIdList)) {
$this->populate($map, 'Lead', $leadIdList);
@@ -36,16 +36,12 @@ use Espo\Entities\User;
class PortalOnlyAccount implements Filter
{
private $user;
public function __construct(User $user)
{
$this->user = $user;
}
public function __construct(private User $user)
{}
public function apply(SelectBuilder $queryBuilder): void
{
$accountIdList = $this->user->getLinkMultipleIdList(User::LINK_ACCOUNTS) ?? [];
$accountIdList = $this->user->getLinkMultipleIdList(User::LINK_ACCOUNTS);
if (!count($accountIdList)) {
$queryBuilder->where([
@@ -36,18 +36,14 @@ use Espo\Entities\User;
class OnlyTeam implements Filter
{
private $user;
public function __construct(User $user)
{
$this->user = $user;
}
public function __construct(private User $user)
{}
public function apply(SelectBuilder $queryBuilder): void
{
$queryBuilder->leftJoin('campaign', 'campaignAccess');
$teamIdList = $this->user->getLinkMultipleIdList('teams') ?? [];
$teamIdList = $this->user->getLinkMultipleIdList('teams');
if (count($teamIdList) === 0) {
$queryBuilder->where([
@@ -36,18 +36,14 @@ use Espo\Entities\User;
class OnlyTeam implements Filter
{
private $user;
public function __construct(User $user)
{
$this->user = $user;
}
public function __construct(private User $user)
{}
public function apply(SelectBuilder $queryBuilder): void
{
$queryBuilder->leftJoin('campaign', 'campaignAccess');
$teamIdList = $this->user->getLinkMultipleIdList('teams') ?? [];
$teamIdList = $this->user->getLinkMultipleIdList('teams');
if (count($teamIdList) === 0) {
$queryBuilder->where([
@@ -36,18 +36,14 @@ use Espo\Entities\User;
class OnlyTeam implements Filter
{
private $user;
public function __construct(User $user)
{
$this->user = $user;
}
public function __construct(private User $user)
{}
public function apply(SelectBuilder $queryBuilder): void
{
$queryBuilder->leftJoin('campaign', 'campaignAccess');
$teamIdList = $this->user->getLinkMultipleIdList('teams') ?? [];
$teamIdList = $this->user->getLinkMultipleIdList('teams');
if (count($teamIdList) === 0) {
$queryBuilder->where([
@@ -56,11 +56,13 @@ class Users implements BeforeSave
{
if (!$this->config->get('eventAssignedUserIsAttendeeDisabled')) {
if ($entity->hasLinkMultipleField('assignedUsers')) {
$assignedUserIdList = $entity->getLinkMultipleIdList('assignedUsers') ?? [];
$assignedUserIdList = $entity->getLinkMultipleIdList('assignedUsers');
foreach ($assignedUserIdList as $assignedUserId) {
$entity->addLinkMultipleId('users', $assignedUserId);
$entity->setLinkMultipleName('users', $assignedUserId,
$entity->setLinkMultipleName(
'users',
$assignedUserId,
$entity->getLinkMultipleName('assignedUsers', $assignedUserId)
);
}
@@ -579,7 +579,7 @@ class Service
}
if ($this->acl->getPermissionLevel('userPermission') === Table::LEVEL_TEAM) {
$userTeamIdList = $this->user->getLinkMultipleIdList('teams') ?? [];
$userTeamIdList = $this->user->getLinkMultipleIdList('teams');
foreach ($teamIdList as $teamId) {
if (!in_array($teamId, $userTeamIdList)) {
@@ -127,7 +127,7 @@ class MailMergeService
$campaign->loadLinkMultipleField('targetLists');
$campaign->loadLinkMultipleField('excludingTargetLists');
if (count($campaign->getLinkMultipleIdList('targetLists') ?? []) === 0) {
if (count($campaign->getLinkMultipleIdList('targetLists')) === 0) {
throw new Error("Could not mail merge campaign w/o any specified target list.");
}
@@ -458,10 +458,7 @@ class SendingProcessor
}
if ($campaign) {
$email->setLinkMultipleIdList(
'teams',
$campaign->getLinkMultipleIdList('teams') ?? []
);
$email->setLinkMultipleIdList('teams', $campaign->getLinkMultipleIdList('teams'));
}
$senderParams = $senderParams->withFromAddress(
+1 -1
View File
@@ -432,7 +432,7 @@ class Email extends Database implements
public function applyUsersFilters(EmailEntity $entity): void
{
$userIdList = $entity->getLinkMultipleIdList('users') ?? [];
$userIdList = $entity->getLinkMultipleIdList('users');
foreach ($userIdList as $userId) {
if (
+1 -1
View File
@@ -341,7 +341,7 @@ class AppService
}
if ($groupEmailAccountPermission === Acl\Table::LEVEL_TEAM) {
$teamIdList = $user->getLinkMultipleIdList('teams') ?? [];
$teamIdList = $user->getLinkMultipleIdList('teams');
if (!count($teamIdList)) {
return [];
@@ -88,8 +88,8 @@ class HookProcessor
private function processMultiple(CoreEntity $entity): void
{
$userIdList = $entity->getLinkMultipleIdList('assignedUsers') ?? [];
$fetchedAssignedUserIdList = $entity->getFetched('assignedUsersIds') ?? [];
$userIdList = $entity->getLinkMultipleIdList('assignedUsers');
$fetchedAssignedUserIdList = $entity->getFetched('assignedUsersIds');
foreach ($userIdList as $userId) {
if (
+2 -3
View File
@@ -29,7 +29,6 @@
namespace Espo\Tools\Stream;
use Espo\Core\ApplicationUser;
use Espo\Core\Exceptions\Error;
use Espo\Core\Record\ServiceContainer as RecordServiceContainer;
@@ -1305,7 +1304,7 @@ class Service
if ($usersAttributeIsChanged || $forceProcessNoteNotifications) {
if ($fieldDefs->getType() === 'linkMultiple') {
$userIdList = $entity->getLinkMultipleIdList($ownerUserField) ?? [];
$userIdList = $entity->getLinkMultipleIdList($ownerUserField);
}
else {
$userId = $entity->get($ownerUserIdAttribute);
@@ -1321,7 +1320,7 @@ class Service
}
if ($teamsAttributeIsChanged || $forceProcessNoteNotifications) {
$teamIdList = $entity->getLinkMultipleIdList('teams') ?? [];
$teamIdList = $entity->getLinkMultipleIdList('teams');
}
}