This commit is contained in:
Yuri Kuznetsov
2024-11-15 11:15:57 +02:00
parent a925a9ec14
commit 5821ce7cb2
17 changed files with 117 additions and 49 deletions

View File

@@ -31,6 +31,7 @@ namespace Espo\Core\Field\EmailAddress;
use Espo\Core\ORM\Type\FieldType;
use Espo\Entities\EmailAddress as EmailAddressEntity;
use Espo\ORM\Defs\Params\FieldParam;
use Espo\Repositories\EmailAddress as Repository;
use Espo\ORM\Entity;
@@ -63,7 +64,7 @@ class EmailAddressGroupFactory implements ValueFactory
public function isCreatableFromEntity(Entity $entity, string $field): bool
{
$type = $this->metadata->get(['entityDefs', $entity->getEntityType(), 'fields', $field, 'type']);
$type = $this->metadata->get(['entityDefs', $entity->getEntityType(), 'fields', $field, FieldParam::TYPE]);
if ($type !== FieldType::EMAIL) {
return false;

View File

@@ -31,6 +31,7 @@ namespace Espo\Core\Field\PhoneNumber;
use Espo\Core\ORM\Type\FieldType;
use Espo\Entities\PhoneNumber as PhoneNumberEntity;
use Espo\ORM\Defs\Params\FieldParam;
use Espo\Repositories\PhoneNumber as Repository;
use Espo\ORM\Entity;
@@ -63,7 +64,7 @@ class PhoneNumberGroupFactory implements ValueFactory
public function isCreatableFromEntity(Entity $entity, string $field): bool
{
$type = $this->metadata->get(['entityDefs', $entity->getEntityType(), 'fields', $field, 'type']);
$type = $this->metadata->get(['entityDefs', $entity->getEntityType(), 'fields', $field, FieldParam::TYPE]);
if ($type !== FieldType::PHONE) {
return false;

View File

@@ -38,6 +38,7 @@ use Espo\Core\ORM\Type\FieldType;
use Espo\Core\Utils\Config;
use Espo\Core\Utils\FieldUtil;
use Espo\Entities\User;
use Espo\ORM\Defs\Params\FieldParam;
use Espo\ORM\Entity;
use Espo\ORM\EntityManager;
use RuntimeException;
@@ -85,7 +86,7 @@ class DefaultPopulator implements Populator
}
foreach ($this->fieldUtil->getEntityTypeFieldList($entityType) as $field) {
$type = $this->fieldUtil->getEntityTypeFieldParam($entityType, $field, 'type');
$type = $this->fieldUtil->getEntityTypeFieldParam($entityType, $field, FieldParam::TYPE);
if (
$type === FieldType::CURRENCY &&

View File

@@ -36,6 +36,7 @@ use Espo\Core\Utils\Metadata;
use Espo\Core\Binding\BindingContainerBuilder;
use Espo\Core\Binding\ContextualBinder;
use Espo\ORM\Defs\Params\FieldParam;
use RuntimeException;
class ItemConverterFactory
@@ -84,7 +85,7 @@ class ItemConverterFactory
}
$type = $this->metadata->get([
'entityDefs', $entityType, 'fields', $field, 'type'
'entityDefs', $entityType, 'fields', $field, FieldParam::TYPE
]);
if (!$type) {

View File

@@ -30,6 +30,7 @@
namespace Espo\Core\Select\Order;
use Espo\Core\Utils\Metadata;
use Espo\ORM\Defs\Params\FieldParam;
use Espo\ORM\EntityManager;
class MetadataProvider
@@ -40,7 +41,7 @@ class MetadataProvider
public function getFieldType(string $entityType, string $field): ?string
{
return $this->metadata->get([
'entityDefs', $entityType, 'fields', $field, 'type'
'entityDefs', $entityType, 'fields', $field, FieldParam::TYPE
]) ?? null;
}

View File

@@ -32,6 +32,7 @@ namespace Espo\Core\Select\Text;
use Espo\Core\Utils\Metadata;
use Espo\ORM\Defs;
use Espo\ORM\Defs\Params\FieldParam;
class MetadataProvider
{
@@ -69,7 +70,7 @@ class MetadataProvider
public function isFullTextSearchSupportedForField(string $entityType, string $field): bool
{
$fieldType = $this->metadata->get([
'entityDefs', $entityType, 'fields', $field, 'type'
'entityDefs', $entityType, 'fields', $field, FieldParam::TYPE
]);
return (bool) $this->metadata->get([

View File

@@ -42,6 +42,7 @@ use Espo\ORM\Defs\FieldDefs;
use Espo\ORM\Defs\IndexDefs;
use Espo\ORM\Defs\Params\AttributeParam;
use Espo\ORM\Defs\Params\FieldParam;
use Espo\ORM\Defs\Params\RelationParam;
use Espo\ORM\Defs\RelationDefs;
use Espo\ORM\Entity;
use Espo\Core\Utils\Metadata;
@@ -73,7 +74,7 @@ class Converter
* @var array<string, string>
*/
private array $paramMap = [
'type' => 'type',
FieldParam::TYPE => AttributeParam::TYPE,
FieldParam::DB_TYPE => AttributeParam::DB_TYPE,
FieldParam::MAX_LENGTH => AttributeParam::LEN,
'len' => AttributeParam::LEN, // @todo Revise.
@@ -255,7 +256,7 @@ class Converter
// Remove fields without type.
if (
!isset($attributeParams['type']) &&
!isset($attributeParams[AttributeParam::TYPE]) &&
(
!isset($attributeParams[AttributeParam::NOT_STORABLE]) ||
$attributeParams[AttributeParam::NOT_STORABLE] === false
@@ -266,7 +267,7 @@ class Converter
continue;
}
$attributeType = $attributeParams['type'] ?? null;
$attributeType = $attributeParams[AttributeParam::TYPE] ?? null;
switch ($attributeType) {
case Entity::ID:
@@ -306,7 +307,7 @@ class Converter
$constName = strtoupper(Util::toUnderScore($attributeType));
if (!defined('Espo\\ORM\\Type\\AttributeType::' . $constName)) {
$attributeParams['type'] = $this->defaultAttributeType;
$attributeParams[AttributeParam::TYPE] = $this->defaultAttributeType;
}
break;
@@ -325,7 +326,7 @@ class Converter
{
foreach ($ormMetadata as $entityType => &$entityParams) {
foreach ($entityParams['attributes'] as $attribute => &$attributeParams) {
$attributeType = $attributeParams['type'] ?? null;
$attributeType = $attributeParams[AttributeParam::TYPE] ?? null;
switch ($attributeType) {
case Entity::FOREIGN:
@@ -364,7 +365,7 @@ class Converter
$foreignParams = $data[$foreignEntityType]['attributes'][$foreign] ?? [];
return $foreignParams['type'] ?? null;
return $foreignParams[AttributeParam::TYPE] ?? null;
}
/**
@@ -376,30 +377,28 @@ class Converter
$entityMetadata['fields'] ??= [];
// List of unmerged fields with default field definitions in $output.
$unmergedFields = [
'name',
];
$unmergedFields = [Field::NAME];
$output = [
Attribute::ID => [
'type' => Entity::ID,
AttributeParam::TYPE => Entity::ID,
],
'name' => [
'type' => $entityMetadata['fields']['name']['type'] ?? Entity::VARCHAR,
AttributeParam::TYPE => $entityMetadata['fields'][Field::NAME][FieldParam::TYPE] ?? Entity::VARCHAR,
AttributeParam::NOT_STORABLE => true,
],
Attribute::DELETED => [
'type' => Entity::BOOL,
AttributeParam::TYPE => Entity::BOOL,
'default' => false,
],
];
if ($entityMetadata['noDeletedAttribute'] ?? false) {
unset($output['deleted']);
unset($output[Attribute::DELETED]);
}
foreach ($entityMetadata['fields'] as $attribute => $attributeParams) {
if (empty($attributeParams['type'])) {
if (empty($attributeParams[AttributeParam::TYPE])) {
continue;
}
@@ -450,7 +449,7 @@ class Converter
$entityMetadata = $ormMetadata[$entityType];
foreach ($entityMetadata['attributes'] as $field => $itemParams) {
$type = $itemParams['type'] ?? null;
$type = $itemParams[AttributeParam::TYPE] ?? null;
if (!$type) {
continue;
@@ -509,19 +508,19 @@ class Converter
if ($scopeDefs['stream'] ?? false) {
if (!isset($entityMetadata['fields'][Field::IS_FOLLOWED])) {
$ormMetadata[$entityType]['attributes'][Field::IS_FOLLOWED] = [
'type' => Entity::BOOL,
AttributeParam::TYPE => Entity::BOOL,
AttributeParam::NOT_STORABLE => true,
CoreAttributeParam::NOT_EXPORTABLE => true,
];
$ormMetadata[$entityType]['attributes'][Field::FOLLOWERS . 'Ids'] = [
'type' => Entity::JSON_ARRAY,
AttributeParam::TYPE => Entity::JSON_ARRAY,
AttributeParam::NOT_STORABLE => true,
CoreAttributeParam::NOT_EXPORTABLE => true,
];
$ormMetadata[$entityType]['attributes'][Field::FOLLOWERS . 'Names'] = [
'type' => Entity::JSON_OBJECT,
AttributeParam::TYPE => Entity::JSON_OBJECT,
AttributeParam::NOT_STORABLE => true,
CoreAttributeParam::NOT_EXPORTABLE => true,
];
@@ -532,7 +531,7 @@ class Converter
if ($scopeDefs['stars'] ?? false) {
if (!isset($entityMetadata['fields'][Field::IS_STARRED])) {
$ormMetadata[$entityType]['attributes'][Field::IS_STARRED] = [
'type' => Entity::BOOL,
AttributeParam::TYPE => Entity::BOOL,
AttributeParam::NOT_STORABLE => true,
CoreAttributeParam::NOT_EXPORTABLE => true,
'readOnly' => true,
@@ -543,7 +542,7 @@ class Converter
// @todo Refactor.
if ($this->metadata->get(['entityDefs', $entityType, 'optimisticConcurrencyControl'])) {
$ormMetadata[$entityType]['attributes']['versionNumber'] = [
'type' => Entity::INT,
AttributeParam::TYPE => Entity::INT,
AttributeParam::DB_TYPE => Types::BIGINT,
CoreAttributeParam::NOT_EXPORTABLE => true,
];
@@ -572,7 +571,7 @@ class Converter
$fieldParams = Util::merge($fieldParams, $fieldTypeMetadata['fieldDefs']);
}
if ($fieldParams['type'] == self::FIELD_TYPE_BASE && isset($fieldParams[FieldParam::DB_TYPE])) {
if ($fieldParams[FieldParam::TYPE] == self::FIELD_TYPE_BASE && isset($fieldParams[FieldParam::DB_TYPE])) {
$fieldParams[FieldParam::NOT_STORABLE] = false;
}
@@ -593,7 +592,7 @@ class Converter
$fieldDefs[AttributeParam::NOT_STORABLE] = true;
}
$type = $fieldDefs['type'] ?? null;
$type = $fieldDefs[FieldParam::TYPE] ?? null;
if (
$type &&
@@ -611,7 +610,7 @@ class Converter
*/
private function prepareFieldParamsBeforeConvert(array &$fieldParams): void
{
$type = $fieldParams['type'] ?? null;
$type = $fieldParams[FieldParam::TYPE] ?? null;
if ($type === FieldType::ENUM) {
if (($fieldParams['default'] ?? null) === '') {
@@ -681,8 +680,8 @@ class Converter
}
}
if (isset($attributeParams['type'])) {
$values['fieldType'] = $attributeParams['type'];
if (isset($attributeParams[AttributeParam::TYPE])) {
$values['fieldType'] = $attributeParams[AttributeParam::TYPE];
}
return $values;
@@ -705,11 +704,11 @@ class Converter
foreach ($fieldList as $field) {
$defs = $this->metadata->get(['entityDefs', $entityType, 'fields', $field], []);
if (empty($defs['type'])) {
if (empty($defs[FieldParam::TYPE])) {
continue;
}
$fieldType = $defs['type'];
$fieldType = $defs[FieldParam::TYPE];
if (!empty($defs[FieldParam::NOT_STORABLE])) {
continue;
@@ -779,7 +778,7 @@ class Converter
if (isset($defs['relations'])) {
foreach ($defs['relations'] as &$relationData) {
$type = $relationData['type'] ?? null;
$type = $relationData[RelationParam::TYPE] ?? null;
if ($type !== Entity::MANY_MANY) {
continue;
@@ -892,12 +891,12 @@ class Converter
'skipRebuild' => true,
'attributes' => [
Attribute::ID => [
'type' => Entity::ID,
AttributeParam::TYPE => Entity::ID,
'autoincrement' => true,
AttributeParam::DB_TYPE => Types::BIGINT, // ignored because of `skipRebuild`
],
Attribute::DELETED => [
'type' => Entity::BOOL,
AttributeParam::TYPE => Entity::BOOL,
],
],
];
@@ -914,17 +913,17 @@ class Converter
foreach ($midKeys as $key) {
$itemDefs['attributes'][$key] = [
'type' => Entity::FOREIGN_ID,
AttributeParam::TYPE => Entity::FOREIGN_ID,
];
}
foreach ($relationDefs->getParam('additionalColumns') ?? [] as $columnName => $columnItem) {
$columnItem['type'] ??= Entity::VARCHAR;
$columnItem[AttributeParam::TYPE] ??= Entity::VARCHAR;
$attributeDefs = AttributeDefs::fromRaw($columnItem, $columnName);
$columnDefs = [
'type' => $attributeDefs->getType(),
AttributeParam::TYPE => $attributeDefs->getType(),
];
if ($attributeDefs->getLength()) {

View File

@@ -64,7 +64,7 @@ class AttributeDefs
public function getType(): ?string
{
/** @var ?AttributeType::* $value */
$value = $this->getParam('type');
$value = $this->getParam(AttributeParam::TYPE);
return $value;
}
@@ -76,7 +76,7 @@ class AttributeDefs
*/
public function withType(string $type): self
{
return $this->withParam('type', $type);
return $this->withParam(AttributeParam::TYPE, $type);
}
/**

View File

@@ -29,6 +29,8 @@
namespace Espo\Core\Utils;
use Espo\ORM\Defs\Params\FieldParam;
class FieldUtil
{
/** @var array<string, array<string, string[]>> */
@@ -113,7 +115,7 @@ class FieldUtil
return [];
}
$type = $this->metadata->get(['entityDefs', $entityType, 'fields', $name, 'type']);
$type = $this->metadata->get(['entityDefs', $entityType, 'fields', $name, FieldParam::TYPE]);
if (!$type) {
return [];

View File

@@ -31,6 +31,8 @@ namespace Espo\ORM;
use Espo\ORM\DataLoader\EmptyLoader;
use Espo\ORM\DataLoader\Loader;
use Espo\ORM\Defs\Params\AttributeParam;
use Espo\ORM\Defs\Params\RelationParam;
use Espo\ORM\Name\Attribute;
use Espo\ORM\Relation\EmptyRelations;
use Espo\ORM\Relation\Relations;
@@ -720,7 +722,7 @@ class BaseEntity implements Entity
return null;
}
return $this->attributesDefs[$attribute]['type'] ?? null;
return $this->attributesDefs[$attribute][AttributeParam::TYPE] ?? null;
}
/**
@@ -732,7 +734,7 @@ class BaseEntity implements Entity
return null;
}
return $this->relationsDefs[$relation]['type'] ?? null;
return $this->relationsDefs[$relation][RelationParam::TYPE] ?? null;
}
/**

View File

@@ -68,7 +68,7 @@ class AttributeDefs
*/
public function getType(): string
{
return $this->data['type'];
return $this->data[AttributeParam::TYPE];
}
/**

View File

@@ -69,7 +69,7 @@ class FieldDefs
*/
public function getType(): string
{
$type = $this->data['type'] ?? null;
$type = $this->data[FieldParam::TYPE] ?? null;
if ($type === null) {
throw new RuntimeException("Field '$this->name' has no type.");

View File

@@ -29,8 +29,16 @@
namespace Espo\ORM\Defs\Params;
/**
* An attribute parameter.
*/
class AttributeParam
{
/**
* A type.
*/
public const TYPE = 'type';
/**
* Not stored in database.
*/

View File

@@ -29,8 +29,16 @@
namespace Espo\ORM\Defs\Params;
/**
* A field parameter.
*/
class FieldParam
{
/**
* A type.
*/
public const TYPE = 'type';
/**
* Not stored in database.
*/

View File

@@ -0,0 +1,41 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM Open Source CRM application.
* Copyright (C) 2014-2024 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 <https://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 Affero General Public License version 3.
*
* 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 "EspoCRM" word.
************************************************************************/
namespace Espo\ORM\Defs\Params;
/**
* A relation parameter.
*/
class RelationParam
{
/**
* A type.
*/
public const TYPE = 'type';
}

View File

@@ -29,6 +29,7 @@
namespace Espo\ORM\Defs;
use Espo\ORM\Defs\Params\RelationParam;
use Espo\ORM\Entity;
use RuntimeException;
@@ -70,7 +71,7 @@ class RelationDefs
*/
public function getType(): string
{
$type = $this->data['type'] ?? null;
$type = $this->data[RelationParam::TYPE] ?? null;
if ($type === null) {
throw new RuntimeException("Relation '{$this->name}' has no type.");

View File

@@ -30,6 +30,7 @@
namespace Espo\ORM\Mapper;
use Espo\ORM\Defs\Params\AttributeParam;
use Espo\ORM\Defs\Params\RelationParam;
use Espo\ORM\Entity;
use Espo\ORM\BaseEntity;
use Espo\ORM\Collection;
@@ -678,7 +679,7 @@ class BaseMapper implements RDBMapper
return null;
}
$columnType = $additionalColumns[$column]['type'] ?? Entity::VARCHAR;
$columnType = $additionalColumns[$column][AttributeParam::TYPE] ?? Entity::VARCHAR;
$where = [
$nearKey => $entity->getId(),
@@ -854,7 +855,7 @@ class BaseMapper implements RDBMapper
if (
$foreignRelationName &&
$this->getRelationParam($relEntity, $foreignRelationName, 'type') === Entity::HAS_ONE
$this->getRelationParam($relEntity, $foreignRelationName, RelationParam::TYPE) === Entity::HAS_ONE
) {
$where = [
self::ATTR_ID . '!=' => $entity->getId(),