refactoring
This commit is contained in:
@@ -56,7 +56,7 @@ class Entity extends BaseEntity
|
||||
$this->hasRelation($field);
|
||||
}
|
||||
|
||||
public function loadParentNameField(string $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}'.");
|
||||
@@ -81,12 +81,16 @@ class Entity extends BaseEntity
|
||||
|
||||
if ($foreignEntity) {
|
||||
$this->set($field . 'Name', $foreignEntity->get('name'));
|
||||
} else {
|
||||
$this->set($field . 'Name', null);
|
||||
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
||||
$this->set($field . 'Name', null);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->set($field . 'Name', null);
|
||||
}
|
||||
|
||||
protected function getRelationOrderParams(string $link) : ?array
|
||||
@@ -141,7 +145,7 @@ class Entity extends BaseEntity
|
||||
];
|
||||
}
|
||||
|
||||
public function loadLinkMultipleField(string $field, $columns = null)
|
||||
public function loadLinkMultipleField(string $field, $columns = null) : void
|
||||
{
|
||||
if (!$this->hasRelation($field) || !$this->hasAttribute($field . 'Ids')) {
|
||||
return;
|
||||
@@ -158,7 +162,7 @@ class Entity extends BaseEntity
|
||||
}
|
||||
|
||||
if (!empty($columns)) {
|
||||
foreach ($columns as $key => $item) {
|
||||
foreach ($columns as $item) {
|
||||
$select[] = $item;
|
||||
}
|
||||
}
|
||||
@@ -186,7 +190,9 @@ class Entity extends BaseEntity
|
||||
|
||||
foreach ($collection as $e) {
|
||||
$id = $e->id;
|
||||
|
||||
$ids[] = $id;
|
||||
|
||||
$names->$id = $e->get('name');
|
||||
|
||||
if ($hasType) {
|
||||
@@ -221,7 +227,7 @@ class Entity extends BaseEntity
|
||||
}
|
||||
}
|
||||
|
||||
public function loadLinkField(string $field)
|
||||
public function loadLinkField(string $field) : void
|
||||
{
|
||||
if (!$this->hasRelation($field) || !$this->hasAttribute($field . 'Id')) {
|
||||
throw new LogicException("There's no link field '{$field}'.");
|
||||
@@ -254,9 +260,13 @@ class Entity extends BaseEntity
|
||||
}
|
||||
|
||||
$this->set($idAttribute, $entityId);
|
||||
|
||||
$this->set($field . 'Name', $entityName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ?mixed
|
||||
*/
|
||||
public function getLinkMultipleName(string $field, string $id)
|
||||
{
|
||||
$namesAttribute = $field . 'Names';
|
||||
@@ -267,18 +277,14 @@ class Entity extends BaseEntity
|
||||
|
||||
$names = $this->get($namesAttribute);
|
||||
|
||||
if ($names instanceof StdClass) {
|
||||
if (isset($names->$id)) {
|
||||
if (isset($names->$id)) {
|
||||
return $names->$id;
|
||||
}
|
||||
}
|
||||
if ($names instanceof StdClass && isset($names->$id) && isset($names->$id)) {
|
||||
return $names->$id;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function setLinkMultipleName(string $field, string $id, ?string $value)
|
||||
public function setLinkMultipleName(string $field, string $id, ?string $value) : void
|
||||
{
|
||||
$namesAttribute = $field . 'Names';
|
||||
|
||||
@@ -293,9 +299,13 @@ class Entity extends BaseEntity
|
||||
}
|
||||
|
||||
$object->$id = $value;
|
||||
|
||||
$this->set($namesAttribute, $object);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ?mixed
|
||||
*/
|
||||
public function getLinkMultipleColumn(string $field, string $column, string $id)
|
||||
{
|
||||
$columnsAttribute = $field . 'Columns';
|
||||
@@ -306,18 +316,14 @@ class Entity extends BaseEntity
|
||||
|
||||
$columns = $this->get($columnsAttribute);
|
||||
|
||||
if ($columns instanceof StdClass) {
|
||||
if (isset($columns->$id)) {
|
||||
if (isset($columns->$id->$column)) {
|
||||
return $columns->$id->$column;
|
||||
}
|
||||
}
|
||||
if ($columns instanceof StdClass && isset($columns->$id) && isset($columns->$id->$column)) {
|
||||
return $columns->$id->$column;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function setLinkMultipleColumn(string $field, string $column, string $id, $value)
|
||||
public function setLinkMultipleColumn(string $field, string $column, string $id, $value) : void
|
||||
{
|
||||
$columnsAttribute = $field . 'Columns';
|
||||
|
||||
@@ -344,14 +350,14 @@ class Entity extends BaseEntity
|
||||
$this->set($columnsAttribute, $object);
|
||||
}
|
||||
|
||||
public function setLinkMultipleIdList(string $field, array $idList)
|
||||
public function setLinkMultipleIdList(string $field, array $idList) : void
|
||||
{
|
||||
$idsAttribute = $field . 'Ids';
|
||||
|
||||
$this->set($idsAttribute, $idList);
|
||||
}
|
||||
|
||||
public function addLinkMultipleId(string $field, string $id)
|
||||
public function addLinkMultipleId(string $field, string $id) : void
|
||||
{
|
||||
$idsAttribute = $field . 'Ids';
|
||||
|
||||
@@ -379,7 +385,7 @@ class Entity extends BaseEntity
|
||||
}
|
||||
}
|
||||
|
||||
public function removeLinkMultipleId(string $field, string $id)
|
||||
public function removeLinkMultipleId(string $field, string $id) : void
|
||||
{
|
||||
if ($this->hasLinkMultipleId($field, $id)) {
|
||||
$list = $this->getLinkMultipleIdList($field);
|
||||
@@ -421,7 +427,9 @@ class Entity extends BaseEntity
|
||||
{
|
||||
$idsAttribute = $field . 'Ids';
|
||||
|
||||
if (!$this->hasAttribute($idsAttribute)) return false;
|
||||
if (!$this->hasAttribute($idsAttribute)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->has($idsAttribute)) {
|
||||
if (!$this->isNew()) {
|
||||
|
||||
@@ -122,6 +122,10 @@ class Integration extends \Espo\Core\ORM\Entity
|
||||
return parent::isAttributeChanged($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @todo Make protected.
|
||||
*/
|
||||
public function populateFromArray(array $array, bool $onlyAccessible = true, bool $reset = false) : void
|
||||
{
|
||||
if ($reset) {
|
||||
@@ -141,29 +145,43 @@ class Integration extends \Espo\Core\ORM\Entity
|
||||
if (!is_null($value)) {
|
||||
switch ($defs['type']) {
|
||||
case self::VARCHAR:
|
||||
|
||||
break;
|
||||
|
||||
case self::BOOL:
|
||||
$value = ($value === 'true' || $value === '1' || $value === true);
|
||||
|
||||
break;
|
||||
|
||||
case self::INT:
|
||||
$value = intval($value);
|
||||
|
||||
break;
|
||||
|
||||
case self::FLOAT:
|
||||
$value = floatval($value);
|
||||
|
||||
break;
|
||||
|
||||
case self::JSON_ARRAY:
|
||||
$value = is_string($value) ? json_decode($value) : $value;
|
||||
|
||||
if (!is_array($value)) {
|
||||
$value = null;
|
||||
}
|
||||
break;
|
||||
|
||||
case self::JSON_OBJECT:
|
||||
$value = is_string($value) ? json_decode($value) : $value;
|
||||
if (!($value instanceof \StdClass) && !is_array($value)) {
|
||||
|
||||
if (!($value instanceof StdClass) && !is_array($value)) {
|
||||
$value = null;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,21 +29,24 @@
|
||||
|
||||
namespace Espo\ORM;
|
||||
|
||||
use StdClass;
|
||||
|
||||
use const E_USER_DEPRECATED;
|
||||
|
||||
use StdClass;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class BaseEntity implements Entity
|
||||
{
|
||||
public $id = null;
|
||||
|
||||
protected $entityType;
|
||||
|
||||
private $isNew = false;
|
||||
|
||||
private $isSaved = false;
|
||||
|
||||
protected $entityType;
|
||||
protected $isFetched = false;
|
||||
|
||||
protected $isBeingSaved = false;
|
||||
|
||||
/**
|
||||
* @todo Make protected. Rename to `attributes`.
|
||||
@@ -54,21 +57,20 @@ class BaseEntity implements Entity
|
||||
protected $relations = [];
|
||||
|
||||
/**
|
||||
* @var array Field-Value pairs.
|
||||
* A field-value map.
|
||||
*/
|
||||
protected $valuesContainer = [];
|
||||
|
||||
/**
|
||||
* @var array Field-Value pairs of initial values (fetched from DB).
|
||||
* A field-value map of values fetched from DB (before changed).
|
||||
*/
|
||||
protected $fetchedValuesContainer = [];
|
||||
|
||||
/**
|
||||
* @var ?EntityManager
|
||||
*/
|
||||
protected $entityManager;
|
||||
|
||||
protected $isFetched = false;
|
||||
|
||||
protected $isBeingSaved = false;
|
||||
|
||||
public function __construct(string $entityType, array $defs = [], ?EntityManager $entityManager = null)
|
||||
{
|
||||
$this->entityType = $entityType ?? null;
|
||||
@@ -79,6 +81,11 @@ class BaseEntity implements Entity
|
||||
$this->relations = $defs['relations'] ?? $this->relations;
|
||||
}
|
||||
|
||||
public function getId() : ?string
|
||||
{
|
||||
return $this->get('id');
|
||||
}
|
||||
|
||||
public function clear(string $name) : void
|
||||
{
|
||||
unset($this->valuesContainer[$name]);
|
||||
@@ -125,16 +132,22 @@ class BaseEntity implements Entity
|
||||
$this->id = $value;
|
||||
}
|
||||
|
||||
if ($this->hasAttribute($name)) {
|
||||
$method = '_set' . ucfirst($name);
|
||||
|
||||
if (method_exists($this, $method)) {
|
||||
$this->$method($value);
|
||||
} else {
|
||||
$this->valuesContainer[$name] = $value;
|
||||
}
|
||||
if (!$this->hasAttribute($name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$method = '_set' . ucfirst($name);
|
||||
|
||||
if (method_exists($this, $method)) {
|
||||
$this->$method($value);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->populateFromArray([
|
||||
$name => $value,
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -148,7 +161,7 @@ class BaseEntity implements Entity
|
||||
*/
|
||||
public function get(string $name, $params = [])
|
||||
{
|
||||
if ($name == 'id') {
|
||||
if ($name === 'id') {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
@@ -172,7 +185,8 @@ class BaseEntity implements Entity
|
||||
// @todo Remove this.
|
||||
if ($this->hasRelation($name) && $this->id && $this->entityManager) {
|
||||
trigger_error(
|
||||
"Accessing related records with Entity::get is deprecated. Use \$repository->getRelation(...)->find()",
|
||||
"Accessing related records with Entity::get is deprecated. " .
|
||||
"Use \$repository->getRelation(...)->find()",
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
|
||||
@@ -203,13 +217,17 @@ class BaseEntity implements Entity
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @todo Make protected.
|
||||
*/
|
||||
public function populateFromArray(array $data, bool $onlyAccessible = true, bool $reset = false) : void
|
||||
{
|
||||
if ($reset) {
|
||||
$this->reset();
|
||||
}
|
||||
|
||||
foreach ($this->getAttributes() as $attribute => $defs) {
|
||||
foreach ($this->getAttributeList() as $attribute) {
|
||||
if (!array_key_exists($attribute, $data)) {
|
||||
continue;
|
||||
}
|
||||
@@ -226,79 +244,122 @@ class BaseEntity implements Entity
|
||||
|
||||
$value = $data[$attribute];
|
||||
|
||||
if (!is_null($value)) {
|
||||
$valueType = $this->getAttributeType($attribute);
|
||||
|
||||
if ($valueType === self::FOREIGN) {
|
||||
$relation = $this->getAttributeParam($attribute, 'relation');
|
||||
$foreign = $this->getAttributeParam($attribute, 'foreign');
|
||||
|
||||
if (is_string($foreign)) {
|
||||
$foreignEntityType = $this->getRelationParam($relation, 'entity');
|
||||
|
||||
if ($foreignEntityType && $this->entityManager) {
|
||||
$valueType = $this->entityManager->getMetadata()->get(
|
||||
$foreignEntityType, ['fields', $foreign, 'type']
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch ($valueType) {
|
||||
case self::VARCHAR:
|
||||
|
||||
break;
|
||||
|
||||
case self::BOOL:
|
||||
$value = ($value === 'true' || $value === '1' || $value === true);
|
||||
|
||||
break;
|
||||
|
||||
case self::INT:
|
||||
$value = intval($value);
|
||||
|
||||
break;
|
||||
|
||||
case self::FLOAT:
|
||||
$value = floatval($value);
|
||||
|
||||
break;
|
||||
|
||||
case self::JSON_ARRAY:
|
||||
$value = is_string($value) ? json_decode($value) : $value;
|
||||
|
||||
if (!is_array($value)) {
|
||||
$value = null;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case self::JSON_OBJECT:
|
||||
$value = is_string($value) ? json_decode($value) : $value;
|
||||
|
||||
if (!($value instanceof StdClass) && !is_array($value)) {
|
||||
$value = null;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$method = '_set' . ucfirst($attribute);
|
||||
|
||||
if (method_exists($this, $method)) {
|
||||
$this->$method($value);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->valuesContainer[$attribute] = $value;
|
||||
$this->populateFromArrayItem($attribute, $value);
|
||||
}
|
||||
}
|
||||
|
||||
protected function populateFromArrayItem(string $attribute, $value) : void
|
||||
{
|
||||
$preparedValue = $this->preparePopulateFromArrayItemValue($attribute, $value);
|
||||
|
||||
$method = '_set' . ucfirst($attribute);
|
||||
|
||||
if (method_exists($this, $method)) {
|
||||
$this->$method($preparedValue);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->valuesContainer[$attribute] = $preparedValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ?mixed
|
||||
*/
|
||||
protected function preparePopulateFromArrayItemValue(string $attribute, $value)
|
||||
{
|
||||
if (is_null($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
$attributeType = $this->getAttributeType($attribute);
|
||||
|
||||
if ($attributeType === self::FOREIGN) {
|
||||
$attributeType = $this->getForeignAttributeType($attribute) ?? $attributeType;
|
||||
}
|
||||
|
||||
switch ($attributeType) {
|
||||
case self::VARCHAR:
|
||||
break;
|
||||
|
||||
case self::BOOL:
|
||||
return ($value === true || $value === 'true' || $value === '1');
|
||||
|
||||
case self::INT:
|
||||
return intval($value);
|
||||
|
||||
case self::FLOAT:
|
||||
return floatval($value);
|
||||
|
||||
case self::JSON_ARRAY:
|
||||
$preparedValue = is_string($value) ? json_decode($value) : $value;
|
||||
|
||||
if (!is_array($preparedValue)) {
|
||||
$value = null;
|
||||
}
|
||||
|
||||
return $preparedValue;
|
||||
|
||||
case self::JSON_OBJECT:
|
||||
$preparedValue = is_string($value) ? json_decode($value) : $value;
|
||||
|
||||
if (!($preparedValue instanceof StdClass) && !is_array($preparedValue)) {
|
||||
$preparedValue = null;
|
||||
}
|
||||
|
||||
return $preparedValue;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
private function getForeignAttributeType(string $attribute) : ?string
|
||||
{
|
||||
if (!$this->entityManager) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$defs = $this->entityManager->getDefs();
|
||||
|
||||
$entityDefs = $defs->getEntity($this->entityType);
|
||||
|
||||
$relation = $entityDefs->getAttribute($attribute)->getParam('relation');
|
||||
$foreign = $entityDefs->getAttribute($attribute)->getParam('foreign');
|
||||
|
||||
if (!$relation) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!$foreign) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!is_string($foreign)) {
|
||||
return self::VARCHAR;
|
||||
}
|
||||
|
||||
if (!$entityDefs->getRelation($relation)->hasForeignEntityType()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$entityType = $entityDefs->getRelation($relation)->getForeignEntityType();
|
||||
|
||||
if (!$defs->hasEntity($entityType)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$foreignEntityDefs = $defs->getEntity($entityType);
|
||||
|
||||
if (!$foreignEntityDefs->hasAttribute($foreign)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $foreignEntityDefs->getAttribute($foreign)->getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is an entity new.
|
||||
*/
|
||||
|
||||
@@ -56,6 +56,11 @@ interface Entity
|
||||
const BELONGS_TO_PARENT = 'belongsToParent';
|
||||
const HAS_CHILDREN = 'hasChildren';
|
||||
|
||||
/**
|
||||
* Get an entity ID.
|
||||
*/
|
||||
public function getId() : ?string;
|
||||
|
||||
/**
|
||||
* Reset all attributes (empty an entity).
|
||||
*/
|
||||
|
||||
@@ -30,11 +30,11 @@
|
||||
namespace tests\unit\Espo\ORM;
|
||||
|
||||
use Espo\ORM\{
|
||||
DB\MysqlMapper,
|
||||
DB\Query\Mysql as Query,
|
||||
EntityFactory,
|
||||
Metadata,
|
||||
MetadataDataProvider,
|
||||
Defs\Defs,
|
||||
Defs\DefsData,
|
||||
BaseEntity,
|
||||
};
|
||||
|
||||
use tests\unit\testData\DB\Job;
|
||||
@@ -57,19 +57,30 @@ class EntityTest extends \PHPUnit\Framework\TestCase
|
||||
->willReturn($ormMetadata);
|
||||
|
||||
$this->metadata = new Metadata($metadataDataProvider);
|
||||
|
||||
$defsData = new DefsData($this->metadata);
|
||||
|
||||
$defs = new Defs($defsData);
|
||||
|
||||
$this->entityManager = $this->createMock(EntityManager::class);
|
||||
|
||||
$this->entityManager
|
||||
->expects($this->any())
|
||||
->method('getDefs')
|
||||
->willReturn($defs);
|
||||
}
|
||||
|
||||
protected function tearDown() : void
|
||||
{
|
||||
}
|
||||
|
||||
protected function createEntity(string $entityType, string $className)
|
||||
protected function createEntity(string $entityType, ?string $className = null)
|
||||
{
|
||||
$em = $this->getMockBuilder(EntityManager::class)->disableOriginalConstructor()->getMock();
|
||||
|
||||
$defs = $this->metadata->get($entityType);
|
||||
|
||||
$entity = new $className($entityType, $defs, $em);
|
||||
$classNameToUse = $className ?? BaseEntity::class;
|
||||
|
||||
$entity = new $classNameToUse($entityType, $defs, $this->entityManager);
|
||||
|
||||
return $entity;
|
||||
}
|
||||
@@ -236,4 +247,43 @@ class EntityTest extends \PHPUnit\Framework\TestCase
|
||||
]);
|
||||
$this->assertTrue($job->isAttributeChanged('object'));
|
||||
}
|
||||
|
||||
public function testSetForeign()
|
||||
{
|
||||
$entity = $this->createEntity('Comment');
|
||||
|
||||
$entity->set([
|
||||
'postName' => 'test',
|
||||
]);
|
||||
|
||||
$this->assertEquals('test', $entity->get('postName'));
|
||||
}
|
||||
|
||||
public function testSetJsonObject()
|
||||
{
|
||||
$entity = $this->createEntity('Test');
|
||||
|
||||
$value = '{"test": "1"}';
|
||||
|
||||
$entity->set([
|
||||
'object' => '{"test": "1"}',
|
||||
]);
|
||||
|
||||
$this->assertEquals(json_decode($value), $entity->get('object'));
|
||||
}
|
||||
|
||||
public function testSetWrongType()
|
||||
{
|
||||
$entity = $this->createEntity('Test');
|
||||
|
||||
$entity->set([
|
||||
'int' => '1',
|
||||
]);
|
||||
|
||||
$this->assertEquals(1, $entity->get('int'));
|
||||
|
||||
$entity->set('int', '1');
|
||||
|
||||
$this->assertEquals(1, $entity->get('int'));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user