Skip to content

Commit a3c9d99

Browse files
committed
Added trait Initialize
1 parent 22ec13a commit a3c9d99

File tree

4 files changed

+308
-1
lines changed

4 files changed

+308
-1
lines changed

src/LeanMapper/DefaultEntityFactory.php

+7-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,13 @@ class DefaultEntityFactory implements IEntityFactory
2323

2424
public function createEntity(string $entityClass, $arg = null): Entity
2525
{
26-
$entity = new $entityClass($arg);
26+
if (method_exists($entityClass, 'initialize')) {
27+
$entity = call_user_func([$entityClass, 'initialize'], $arg);
28+
29+
} else {
30+
$entity = new $entityClass($arg);
31+
}
32+
2733
assert($entity instanceof Entity);
2834
return $entity;
2935
}

src/LeanMapper/Initialize.php

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
3+
/**
4+
* This file is part of the Lean Mapper library (http://www.leanmapper.com)
5+
*
6+
* Copyright (c) 2013 Vojtěch Kohout (aka Tharos)
7+
*
8+
* For the full copyright and license information, please view the file
9+
* license.md that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace LeanMapper;
15+
16+
trait Initialize
17+
{
18+
/**
19+
* Creates & initializes entity instance from given argument
20+
*
21+
* @param Row|iterable<string, mixed>|null $arg
22+
*/
23+
public static function initialize($arg): Entity
24+
{
25+
$reflection = static::getReflection();
26+
$entity = $reflection->newInstanceWithoutConstructor();
27+
28+
if ($arg instanceof Row) {
29+
if ($arg->isDetached()) {
30+
throw new Exception\InvalidArgumentException(
31+
'It is not allowed to create entity ' . get_called_class() . ' from detached instance of ' . Row::class . '.'
32+
);
33+
}
34+
35+
$entity->row = $arg;
36+
$entity->mapper = $arg->getMapper();
37+
38+
} else {
39+
$entity->row = Result::createDetachedInstance()->getRow();
40+
41+
foreach ($entity->getCurrentReflection()->getEntityProperties() as $property) {
42+
if ($property->hasDefaultValue()) {
43+
$propertyName = $property->getName();
44+
$entity->set($propertyName, $property->getDefaultValue());
45+
}
46+
}
47+
48+
$entity->initDefaults();
49+
50+
if ($arg !== null) {
51+
if (!is_iterable($arg)) {
52+
$type = Helpers::getType($arg);
53+
throw new Exception\InvalidArgumentException(
54+
"Argument \$arg in " . get_called_class(
55+
) . "::__construct must contain either null, array, instance of " . Row::class . " or instance of " . \Traversable::class . ", $type given."
56+
);
57+
}
58+
59+
$entity->assign($arg);
60+
}
61+
}
62+
63+
return $entity;
64+
}
65+
}
+134
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use LeanMapper\Entity;
6+
use LeanMapper\Initialize;
7+
use LeanMapper\Result;
8+
use LeanMapper\Row;
9+
use Tester\Assert;
10+
11+
require_once __DIR__ . '/../bootstrap.php';
12+
13+
$connection = Tests::createConnection();
14+
$mapper = Tests::createMapper();
15+
$entityFactory = Tests::createEntityFactory();
16+
17+
//////////
18+
19+
/**
20+
* @property int $id
21+
* @property string $name
22+
* @property string $pubdate
23+
*/
24+
class Book extends Entity
25+
{
26+
use Initialize;
27+
28+
29+
public function __construct(
30+
string $name,
31+
string $pubdate
32+
)
33+
{
34+
parent::__construct();
35+
36+
$this->name = $name;
37+
$this->pubdate = $pubdate;
38+
}
39+
}
40+
41+
//////////
42+
43+
$book = Book::initialize([]);
44+
45+
Assert::type(Book::class, $book);
46+
47+
//////////
48+
49+
$data = [
50+
'id' => 1,
51+
'name' => 'PHP guide',
52+
'pubdate' => '2013-06-13',
53+
];
54+
55+
$book = Book::initialize($data);
56+
57+
Assert::type(Book::class, $book);
58+
Assert::equal($data, $book->getData());
59+
60+
//////////
61+
62+
$dibiRow = new \Dibi\Row($data);
63+
$row = new Row(Result::createInstance($dibiRow, 'book', $connection, $mapper), 1);
64+
$book = Book::initialize($row);
65+
66+
Assert::type(Book::class, $book);
67+
Assert::equal($data, $book->getData());
68+
69+
//////////
70+
71+
$dibiRow = new \Dibi\Row($data);
72+
$row = Result::createInstance($dibiRow, 'book', $connection, $mapper)->getRow(1);
73+
$book = Book::initialize($row);
74+
75+
Assert::type(Book::class, $book);
76+
Assert::equal($data, $book->getData());
77+
78+
//////////
79+
80+
$book = Book::initialize(new ArrayObject($data));
81+
82+
Assert::type(Book::class, $book);
83+
Assert::equal($data, $book->getData());
84+
85+
//////////
86+
87+
Assert::exception(
88+
function () {
89+
Book::initialize(false);
90+
},
91+
LeanMapper\Exception\InvalidArgumentException::class,
92+
'Argument $arg in Book::__construct must contain either null, array, instance of LeanMapper\Row or instance of Traversable, boolean given.'
93+
);
94+
95+
Assert::exception(
96+
function () {
97+
Book::initialize('hello');
98+
},
99+
LeanMapper\Exception\InvalidArgumentException::class,
100+
'Argument $arg in Book::__construct must contain either null, array, instance of LeanMapper\Row or instance of Traversable, string given.'
101+
);
102+
103+
//////////
104+
105+
$dibiRow = new \Dibi\Row($data);
106+
$row = new Row(Result::createInstance($dibiRow, 'book', $connection, $mapper), 1);
107+
$row->detach();
108+
109+
Assert::exception(
110+
function () use ($row) {
111+
Book::initialize($row);
112+
},
113+
LeanMapper\Exception\InvalidArgumentException::class,
114+
'It is not allowed to create entity Book from detached instance of LeanMapper\Row.'
115+
);
116+
117+
//////////
118+
119+
$data = [
120+
'id' => 1,
121+
'name' => 'PHP guide',
122+
'pubdate' => '2013-06-13',
123+
];
124+
125+
$book = new Book(
126+
$data['name'],
127+
$data['pubdate']
128+
);
129+
130+
Assert::type(Book::class, $book);
131+
Assert::equal([
132+
'name' => $data['name'],
133+
'pubdate' => $data['pubdate'],
134+
], $book->getRowData());
+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use LeanMapper\Entity;
6+
use LeanMapper\Initialize;
7+
use Tester\Assert;
8+
9+
require_once __DIR__ . '/../bootstrap.php';
10+
11+
//////////
12+
13+
/**
14+
* @property int $id
15+
* @property string $name
16+
* @property string|null $web
17+
* @property Book[] $books m:belongsToMany
18+
*/
19+
class Author extends Entity
20+
{
21+
use Initialize;
22+
23+
24+
public function __construct(
25+
string $name,
26+
?string $web
27+
)
28+
{
29+
parent::__construct();
30+
31+
$this->name = $name;
32+
$this->web = $web;
33+
}
34+
}
35+
36+
/**
37+
* @property int $id
38+
* @property string $name
39+
* @property string $pubdate
40+
* @property NULL|Author $author m:hasOne
41+
*/
42+
class Book extends Entity
43+
{
44+
use Initialize;
45+
46+
47+
public function __construct(
48+
string $name,
49+
string $pubdate,
50+
?Author $author
51+
)
52+
{
53+
parent::__construct();
54+
55+
$this->name = $name;
56+
$this->pubdate = $pubdate;
57+
$this->author = $author;
58+
}
59+
}
60+
61+
class BookRepository extends \LeanMapper\Repository
62+
{
63+
64+
public function find($id)
65+
{
66+
$row = $this->connection->select('*')->from($this->getTable())->where('id = %i', $id)->fetch();
67+
if ($row === false) {
68+
throw new \Exception('Entity was not found.');
69+
}
70+
return $this->createEntity($row);
71+
}
72+
73+
}
74+
75+
//////////
76+
77+
$connection = Tests::createConnection();
78+
$mapper = Tests::createMapper();
79+
$entityFactory = Tests::createEntityFactory();
80+
81+
$bookRepository = new BookRepository($connection, $mapper, $entityFactory);
82+
83+
$book = $bookRepository->find(1);
84+
85+
Assert::type(Author::class, $book->author);
86+
87+
$author = $book->author;
88+
89+
$book->author = null;
90+
91+
Assert::equal(null, $book->author);
92+
93+
Assert::equal(
94+
[
95+
'author_id' => null,
96+
],
97+
$book->getModifiedRowData()
98+
);
99+
100+
$book->author = $author;
101+
102+
Assert::type(Author::class, $book->author);

0 commit comments

Comments
 (0)