Skip to content

Commit

Permalink
dev
Browse files Browse the repository at this point in the history
  • Loading branch information
mvkasatkin committed Nov 9, 2017
1 parent 36e3eb7 commit 0b3b40f
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 78 deletions.
64 changes: 63 additions & 1 deletion src/entity/AbstractEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,20 @@

namespace WebComplete\core\entity;

use function WebComplete\core\utils\typecast\cast;

class AbstractEntity
abstract class AbstractEntity
{

protected $id;

private $data = [];

/**
* @return array
*/
abstract public static function fields(): array;

/**
* @return int|string|null
*/
Expand All @@ -23,4 +31,58 @@ public function setId($id)
{
$this->id = $id;
}

/**
* @param array $data
* @param bool $update
*/
public function mapFromArray(array $data, bool $update = false)
{
if (!$update) {
$this->data = [];
}

foreach ($data as $field => $value) {
$this->setField($field, $value);
}
}

/**
* @return array
*/
public function mapToArray(): array
{
$result = [
'id' => $this->getId()
];
$fields = \array_keys(static::fields());
foreach ($fields as $field) {
$result[$field] = $this->getField($field);
}

return $result;
}

/**
* @param $name
* @param $value
*/
protected function setField($name, $value)
{
$fields = static::fields();
if (isset($fields[$name])) {
$this->data[$name] = cast($value, $fields[$name]);
}
}

/**
* @param $name
* @param null $default
*
* @return mixed|null
*/
protected function getField($name, $default = null)
{
return $this->data[$name] ?? $default;
}
}
16 changes: 4 additions & 12 deletions src/entity/AbstractEntityRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use WebComplete\core\condition\Condition;
use WebComplete\core\factory\ObjectFactory;
use WebComplete\core\utils\hydrator\HydratorInterface;

abstract class AbstractEntityRepository implements EntityRepositoryInterface
{
Expand All @@ -14,19 +13,12 @@ abstract class AbstractEntityRepository implements EntityRepositoryInterface
*/
protected $factory;

/**
* @var HydratorInterface
*/
protected $hydrator;

/**
* @param ObjectFactory $factory
* @param HydratorInterface $hydrator
*/
public function __construct(ObjectFactory $factory, HydratorInterface $hydrator)
public function __construct(ObjectFactory $factory)
{
$this->factory = $factory;
$this->hydrator = $hydrator;
}

/**
Expand All @@ -41,14 +33,14 @@ public function create(): AbstractEntity

/**
* @param array $data
* @param array|null $map
*
* @return AbstractEntity
*/
public function createFromData(array $data, array $map = null): AbstractEntity
public function createFromData(array $data): AbstractEntity
{
$result = $this->factory->createFromData($data, $map);
/** @var AbstractEntity $result */
$result = $this->factory->create();
$result->mapFromArray($data);
return $result;
}

Expand Down
26 changes: 5 additions & 21 deletions src/entity/AbstractEntityRepositoryDb.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
use Doctrine\DBAL\Query\QueryBuilder;
use WebComplete\core\condition\ConditionDbParser;
use WebComplete\core\factory\ObjectFactory;
use WebComplete\core\utils\hydrator\HydratorInterface;
use WebComplete\core\condition\Condition;

abstract class AbstractEntityRepositoryDb extends AbstractEntityRepository
Expand All @@ -15,11 +14,6 @@ abstract class AbstractEntityRepositoryDb extends AbstractEntityRepository
const SERIALIZE_STRATEGY_PHP = 2;

protected $table;
/**
* map: fieldName: propertyName
* @var array|null
*/
protected $map;
protected $serializeFields = [];
protected $serializeStrategy = self::SERIALIZE_STRATEGY_JSON;

Expand All @@ -33,17 +27,15 @@ abstract class AbstractEntityRepositoryDb extends AbstractEntityRepository

/**
* @param ObjectFactory $factory
* @param HydratorInterface $hydrator
* @param ConditionDbParser $conditionParser
* @param Connection $db
*/
public function __construct(
ObjectFactory $factory,
HydratorInterface $hydrator,
ConditionDbParser $conditionParser,
Connection $db
) {
parent::__construct($factory, $hydrator);
parent::__construct($factory);
$this->db = $db;
$this->conditionParser = $conditionParser;
}
Expand Down Expand Up @@ -122,7 +114,7 @@ public function count(Condition $condition = null): int
*/
public function save(AbstractEntity $item)
{
$data = $this->hydrator->extract($item, $this->getMapping());
$data = $item->mapToArray();
$this->beforeDataSave($data);
$this->serializeFields($data);
if ($id = $item->getId()) {
Expand Down Expand Up @@ -177,14 +169,6 @@ public function getMap(string $field, string $key = 'id', Condition $condition =
return $result;
}

/**
* @return array|null
*/
public function getMapping()
{
return $this->map;
}

/**
* @param Condition|null $condition
* @return QueryBuilder
Expand All @@ -193,7 +177,7 @@ protected function selectQuery(Condition $condition = null): QueryBuilder
{
$queryBuilder = $this->db->createQueryBuilder();
$queryBuilder->select(['t1.*'])->from($this->table, 't1');
$this->conditionParser->parse($queryBuilder, $condition, $this->getMapping());
$this->conditionParser->parse($queryBuilder, $condition);
return $queryBuilder;
}

Expand All @@ -210,10 +194,10 @@ protected function beforeDataSave(&$data)
*
* @return AbstractEntity
*/
private function rowToEntity($data)
private function rowToEntity($data): AbstractEntity
{
$this->unserializeFields($data);
$entity = $this->factory->createFromData($data, $this->getMapping());
$entity = $this->factory->createFromData($data);
/** @var AbstractEntity $entity */
return $entity;
}
Expand Down
6 changes: 2 additions & 4 deletions src/entity/AbstractEntityService.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,13 @@ public function create(): AbstractEntity

/**
* Proxy method
*
* @param array $data
* @param array|null $map
*
* @return AbstractEntity
*/
public function createFromData(array $data, array $map = null): AbstractEntity
public function createFromData(array $data): AbstractEntity
{
return $this->repository->createFromData($data, $map);
return $this->repository->createFromData($data);
}

/**
Expand Down
3 changes: 1 addition & 2 deletions src/entity/EntityRepositoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,10 @@ public function create(): AbstractEntity;

/**
* @param array $data
* @param array|null $map
*
* @return AbstractEntity
*/
public function createFromData(array $data, array $map = null): AbstractEntity;
public function createFromData(array $data): AbstractEntity;

/**
* @param $id
Expand Down
59 changes: 38 additions & 21 deletions tests/core/entity/AbstractEntityRepositoryDbTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use WebComplete\core\entity\AbstractEntity;
use WebComplete\core\entity\AbstractEntityRepositoryDb;
use WebComplete\core\factory\ObjectFactory;
use WebComplete\core\utils\hydrator\Hydrator;
use WebComplete\core\utils\typecast\Cast;

class AbstractEntityRepositoryDbTest extends CoreTestCase
{
Expand All @@ -17,7 +17,7 @@ public function testTransaction()
$closure = function(){};
$conn = $this->createMock(\Doctrine\DBAL\Connection::class);
$conn->expects($this->once())->method('transactional')->with($closure);
$rep = $this->createRep(null, null, null, $conn);
$rep = $this->createRep(null, null, $conn);
$rep->transaction($closure);
}

Expand All @@ -37,7 +37,7 @@ public function testFindById()
$of = $this->createMock(ObjectFactory::class);
$of->method('createFromData')->willReturn($entity);

$rep = $this->createRep($of, null, null, $conn, ['selectQuery']);
$rep = $this->createRep($of, null, $conn, ['selectQuery']);
$rep->expects($this->once())->method('selectQuery')->willReturn($qb);
$this->assertEquals($entity, $rep->findById(1));
}
Expand All @@ -56,11 +56,10 @@ public function testFindOne()

$entity = Mocker::create(AbstractEntity::class);
$of = $this->createMock(ObjectFactory::class);
$of->method('createFromData')->with(['a' => 1, 'arr' => [1,2,3], 'arr2' => null], ['a' => 'b'])->willReturn($entity);
$of->method('createFromData')->with(['a' => 1, 'arr' => [1,2,3], 'arr2' => null])->willReturn($entity);

$rep = $this->createRep($of, null, null, $conn, ['selectQuery']);
$rep = $this->createRep($of, null, $conn, ['selectQuery']);
$rep->expects($this->once())->method('selectQuery')->willReturn($qb);
Mocker::setProperty($rep, 'map', ['a' => 'b']);
$this->assertEquals($entity, $rep->findOne(new Condition()));
}

Expand All @@ -87,7 +86,7 @@ public function testFindAll()
$of = $this->createMock(ObjectFactory::class);
$of->method('createFromData')->willReturn($o1, $o2);

$rep = $this->createRep($of, null, null, $conn, ['selectQuery']);
$rep = $this->createRep($of, null, $conn, ['selectQuery']);
$rep->expects($this->once())->method('selectQuery')->willReturn($qb);
$this->assertEquals([11 => $o1,12 => $o2], $rep->findAll(new Condition()));
}
Expand All @@ -105,19 +104,19 @@ public function testCount()

$conn = $this->createMock(\Doctrine\DBAL\Connection::class);

$rep = $this->createRep(null, null, null, $conn, ['selectQuery']);
$rep = $this->createRep(null, null, $conn, ['selectQuery']);
$rep->expects($this->once())->method('selectQuery')->willReturn($qb);
$this->assertEquals(3, $rep->count(new Condition()));
}

public function testSaveNew()
{
$o1 = new AbstractEntityRepositoryDbTestEntity();
$o1->a = 1;
$o1->setA(1);
$conn = $this->createMock(\Doctrine\DBAL\Connection::class);
$conn->expects($this->once())->method('insert')->with('tbl', ['a' => 1, 'arr' => null, 'arr2' => null]);
$conn->expects($this->once())->method('lastInsertId')->willReturn(22);
$rep = $this->createRep(null, null, null, $conn);
$rep = $this->createRep(null, null, $conn);
$rep->save($o1);
$this->assertEquals(22, $o1->getId());
}
Expand All @@ -126,11 +125,11 @@ public function testSaveUpdate()
{
$o1 = new AbstractEntityRepositoryDbTestEntity();
$o1->setId(33);
$o1->a = 2;
$o1->arr = [1,2,3];
$o1->setA(2);
$o1->setArr([1,2,3]);
$conn = $this->createMock(\Doctrine\DBAL\Connection::class);
$conn->expects($this->once())->method('update')->with('tbl', ['id' => 33, 'a' => 2, 'arr' => '[1,2,3]', 'arr2' => null], ['t1.id' => 33]);
$rep = $this->createRep(null, null, null, $conn);
$rep = $this->createRep(null, null, $conn);
$rep->save($o1);
$this->assertEquals(33, $o1->getId());
}
Expand All @@ -141,7 +140,7 @@ public function testDelete()
$o1->setId(44);
$conn = $this->createMock(\Doctrine\DBAL\Connection::class);
$conn->expects($this->once())->method('delete')->with('tbl', ['t1.id' => 44]);
$rep = $this->createRep(null, null, null, $conn);
$rep = $this->createRep(null, null, $conn);
$rep->delete($o1->getId());
}

Expand Down Expand Up @@ -206,16 +205,15 @@ public function testGetTable()
*
* @return PHPUnit_Framework_MockObject_MockObject|AbstractEntityRepositoryDb
*/
protected function createRep($of = null, $h = null, $p = null, $c = null, $mockedMethods = [])
protected function createRep($of = null, $p = null, $c = null, $mockedMethods = [])
{
$of = $of ?: $this->createMock(ObjectFactory::class);
$of->expects($this->any())->method('create')->willReturn(new AbstractEntityRepositoryDbTestEntity());

$hydrator = $h ?: new Hydrator();
$parser = $p ?: new ConditionDbParser();
$conn = $c ?: DriverManager::getConnection(['url' => 'sqlite:///:memory:']);

$aer = $this->getMockForAbstractClass(AbstractEntityRepositoryDb::class, [$of, $hydrator, $parser, $conn], '', true, true, true, $mockedMethods);
$aer = $this->getMockForAbstractClass(AbstractEntityRepositoryDb::class, [$of, $parser, $conn], '', true, true, true, $mockedMethods);
$reflection = new ReflectionClass($aer);
$reflection_property = $reflection->getProperty('table');
$reflection_property->setAccessible(true);
Expand All @@ -232,7 +230,26 @@ protected function createRep($of = null, $h = null, $p = null, $c = null, $mock
}

class AbstractEntityRepositoryDbTestEntity extends AbstractEntity {
public $a;
public $arr;
public $arr2;
}

/**
* @return array
*/
public static function fields(): array
{
return [
'a' => Cast::STRING,
'arr' => Cast::ARRAY,
'arr2' => Cast::ARRAY,
];
}

public function setA($value)
{
$this->setField('a', $value);
}

public function setArr($value)
{
$this->setField('arr', $value);
}
}
Loading

0 comments on commit 0b3b40f

Please sign in to comment.