orm refactoring

This commit is contained in:
Yuri Kuznetsov
2020-07-11 23:34:19 +03:00
parent 1f52ab9a3f
commit 460f3fcfd6
8 changed files with 1355 additions and 1376 deletions
File diff suppressed because it is too large Load Diff
-152
View File
@@ -1,152 +0,0 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy 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\ORM\DB;
use Espo\ORM\IEntity;
use Espo\ORM\Classes\EntityFactory;
interface IMapper
{
/**
* Selects entity by id.
*/
function selectById(IEntity $entity, $id, ?array $params = null) : ?IEntity;
/**
* Selects list of entitys according to given parameters.
*
* @return array Array of entities or collection.
*/
function select(IEntity $entity, ?array $params = null);
/**
* Invokes aggregate function and returns a value.
*
* @return mixed Result of the aggregation
*/
function aggregate(IEntity $entity, ?array $params, string $aggregation, string $aggregationBy);
/**
* Returns count of records according to given parameters.
*
* @return int Count of record
*/
function count(IEntity $entity, ?array $params = null);
/**
* Returns max value of the attribute in the select according to given parameters.
*
* @param IEntity $entity
* @param array $params Parameters
* @param string $attribute Needed attribute.
* @return mixed Max value
*/
function max(IEntity $entity, ?array $params, string $attribute);
/**
* Returns min value of the attribute in the select according to given parameters.
*
* @return mixed Min value
*/
function min(IEntity $entity, ?array $params, string $attribute);
/**
* Returns sum value of the attribute in the select according to given parameters.
*
* @return mixed Sum value
*/
function sum(IEntity $entity, ?array $params, string $attribute);
/**
* Selects related entity or list of entitys.
*
* @return array List of entitys or total count if $totalCount was passed as true
*/
function selectRelated(IEntity $entity, $relName, $params, $totalCount);
/**
* Returns count of related records according to given parameters.
*
* @return int Count of records
*/
function countRelated(IEntity $entity, $relName, $params);
/**
* Links entity with another one.
*
* @return bool True if success
*/
function addRelation(IEntity $entity, string $relationName, ?string $id = null, ?IEntity $relEntity = null, ?array $data = null);
/**
* Removes relation of entity with certain record.
*
* @return bool True if success
*/
function removeRelation(IEntity $entity, string $relationName, ?string $id = null, bool $all = false, IEntity $relEntity = null);
/**
* Removes all relations of entity of specified relation name.
*
* @return bool True if success
*/
function removeAllRelations(IEntity $entity, string $relationName);
/**
* Insert entity into db.
*
* @return bool True if success
*/
function insert(IEntity $entity);
/**
* Updates entity in db.
*
* @return bool True if success
*/
function update(IEntity $entity);
/**
* Deletes entity.
* (Marks as deleted)
*
* @return bool True if success
*/
function delete(IEntity $entity);
/**
* Sets class name of a model collection that will be returned by operations such as select.
*
*/
function setCollectionClass(string $collectionClass);
function deleteFromDb(string $entityType, $id, $onlyDeleted = false);
}
File diff suppressed because it is too large Load Diff
+2 -10
View File
@@ -28,18 +28,10 @@
************************************************************************/
namespace Espo\ORM\DB;
use Espo\ORM\Entity;
use Espo\ORM\Classes\EntityCollection;
use PDO;
/**
* Abstraction for MySQL DB.
* Mapping of Entity to DB.
* Should be used internally only.
*/
class MysqlMapper extends Mapper
class MysqlMapper extends BaseMapper
{
protected function toDb($attribute)
protected function toDb(string $attribute)
{
return $this->query->toDb($attribute);
}
+7 -9
View File
@@ -32,7 +32,7 @@ namespace Espo\ORM;
use Espo\Core\Exceptions\Error;
use Espo\ORM\DB\{
IMapper,
Mapper,
Query\Base as Query,
};
@@ -119,7 +119,7 @@ class EntityManager
break;
}
if (!class_exists($className)) {
if (!$className || !class_exists($className)) {
throw new Error("Mapper {$name} does not exist.");
}
@@ -129,20 +129,18 @@ class EntityManager
/**
* Get Mapper.
*/
public function getMapper(?string $name = null) : IMapper
public function getMapper(?string $name = null) : Mapper
{
$name = $name ?? $this->defaultMapperName;
if ($name{0} == '\\') {
$className = $name;
} else {
$className = $this->getMapperClassName($name);
}
$className = $this->getMapperClassName($name);
if (empty($this->mappers[$className])) {
$this->mappers[$className] = new $className(
$this->getPDO(), $this->entityFactory, $this->getQuery(), $this->metadata);
$this->getPDO(), $this->entityFactory, $this->getQuery(), $this->metadata
);
}
return $this->mappers[$className];
}
@@ -29,13 +29,16 @@
namespace Espo\ORM\Repositories;
use Espo\ORM\Entity;
use Espo\ORM\{
Entity,
ICollection as Collection,
};
interface Findable
{
public function count(array $params) : int;
public function find(array $params) : \Traversable;
public function find(array $params) : Collection;
public function findOne(array $params) : ?Entity;
}
+21 -42
View File
@@ -29,20 +29,17 @@
namespace Espo\ORM\Repositories;
use Espo\ORM\EntityManager;
use Espo\ORM\EntityFactory;
use Espo\ORM\EntityCollection;
use Espo\ORM\Entity;
use Espo\ORM\IEntity;
use Espo\ORM\Repository;
use Espo\ORM\DB\IMapper as Mapper;
use Espo\ORM\{
EntityManager,
EntityFactory,
ICollection as Collection,
Entity,
Repository,
DB\Mapper,
};
class RDB extends Repository implements Findable, Relatable, Removable
{
/**
* @var Object Mapper.
*/
protected $mapper;
/**
@@ -85,6 +82,9 @@ class RDB extends Repository implements Findable, Relatable, Removable
{
}
/**
* Reset select parameters.
*/
public function reset()
{
$this->whereClause = [];
@@ -92,6 +92,9 @@ class RDB extends Repository implements Findable, Relatable, Removable
$this->listParams = [];
}
/**
* Get a new entity.
*/
public function getNew() : ?Entity
{
$entity = $this->entityFactory->create($this->entityType);
@@ -190,7 +193,7 @@ class RDB extends Repository implements Findable, Relatable, Removable
return $this->getMapper()->deleteFromDb($this->entityType, $id, $onlyDeleted);
}
public function find(array $params = []) : \Traversable
public function find(array $params = []) : Collection
{
$params = $this->getSelectParams($params);
@@ -198,16 +201,7 @@ class RDB extends Repository implements Findable, Relatable, Removable
$this->handleSelectParams($params);
}
$selectResult = $this->getMapper()->select($this->seed, $params);
if (!empty($params['returnSthCollection'])) {
$collection = $selectResult;
} else {
$dataList = $selectResult;
$collection = new EntityCollection($dataList, $this->entityType, $this->entityFactory);
}
$collection->setAsFetched();
$collection = $this->getMapper()->select($this->seed, $params);
$this->reset();
@@ -225,11 +219,9 @@ class RDB extends Repository implements Findable, Relatable, Removable
public function findByQuery(string $sql, ?string $collectionType = null)
{
$dataArr = $this->getMapper()->selectByQuery($this->seed, $sql);
if (!$collectionType) {
$collection = new EntityCollection($dataArr, $this->entityType, $this->entityFactory);
} else if ($collectionType === \Espo\ORM\EntityManager::STH_COLLECTION) {
$collection = $this->getMapper()->selectByQuery($this->seed, $sql);
} else if ($collectionType === EntityManager::STH_COLLECTION) {
$collection = $this->getEntityManager()->createSthCollection($this->entityType);
$collection->setQuery($sql);
}
@@ -242,7 +234,7 @@ class RDB extends Repository implements Findable, Relatable, Removable
public function findRelated(Entity $entity, string $relationName, array $params = [])
{
if (!$entity->id) {
return [];
return null;
}
if ($entity->getRelationType($relationName) === Entity::BELONGS_TO_PARENT) {
@@ -257,19 +249,7 @@ class RDB extends Repository implements Findable, Relatable, Removable
$result = $this->getMapper()->selectRelated($entity, $relationName, $params);
if (is_array($result)) {
$collection = new EntityCollection($result, $entityType, $this->entityFactory);
$collection->setAsFetched();
return $collection;
} else if ($result instanceof EntityCollection) {
$collection = $result;
return $collection;
} else if ($result instanceof Entity) {
$entity = $result;
return $entity;
} else {
return $result;
}
return $result;
}
public function countRelated(Entity $entity, string $relationName, array $params = []) : int
@@ -373,7 +353,6 @@ class RDB extends Repository implements Findable, Relatable, Removable
return $result;
}
public function unrelate(Entity $entity, string $relationName, $foreign, array $options = [])
{
if (!$entity->id) {
@@ -587,7 +566,7 @@ class RDB extends Repository implements Findable, Relatable, Removable
return $this;
}
public function order($field = 'id', $direction = "ASC")
public function order($field = 'id', $direction = 'ASC')
{
$this->listParams['orderBy'] = $field;
$this->listParams['order'] = $direction;
+4 -6
View File
@@ -61,17 +61,17 @@ class DBMapperTest extends \PHPUnit\Framework\TestCase
return "'" . $args[0] . "'";
}));
$metadata = $this->getMockBuilder('\\Espo\\ORM\\Metadata')->disableOriginalConstructor()->getMock();
$metadata = $this->getMockBuilder('Espo\\ORM\\Metadata')->disableOriginalConstructor()->getMock();
$metadata
->method('get')
->will($this->returnValue(false));
$entityManager = $this->getMockBuilder('\\Espo\\ORM\\EntityManager')->disableOriginalConstructor()->getMock();
$entityManager = $this->getMockBuilder('Espo\\ORM\\EntityManager')->disableOriginalConstructor()->getMock();
$entityManager
->method('getMetadata')
->will($this->returnValue($metadata));
$this->entityFactory = $this->getMockBuilder('\\Espo\\ORM\\EntityFactory')->disableOriginalConstructor()->getMock();
$this->entityFactory = $this->getMockBuilder('Espo\\ORM\\EntityFactory')->disableOriginalConstructor()->getMock();
$this->entityFactory
->expects($this->any())
->method('create')
@@ -81,12 +81,11 @@ class DBMapperTest extends \PHPUnit\Framework\TestCase
return new $className([], $entityManager);
}));
$this->metadata = $this->getMockBuilder('\\Espo\\ORM\\Metadata')->disableOriginalConstructor()->getMock();
$this->metadata = $this->getMockBuilder('Espo\\ORM\\Metadata')->disableOriginalConstructor()->getMock();
$this->query = new Query($this->pdo, $this->entityFactory, $this->metadata);
$this->db = new MysqlMapper($this->pdo, $this->entityFactory, $this->query, $this->metadata);
$this->db->setReturnCollection(true);
$this->post = new \Espo\Entities\Post([], $entityManager);
$this->comment = new \Espo\Entities\Comment([], $entityManager);
@@ -95,7 +94,6 @@ class DBMapperTest extends \PHPUnit\Framework\TestCase
$this->contact = new \Espo\Entities\Contact([], $entityManager);
$this->account = new \Espo\Entities\Account([], $entityManager);
}
protected function tearDown() : void