Skip to content

Commit 67ba89b

Browse files
authored
Merge pull request #17 from WyriHaximus/support-functions-in-where-clauses
Support functions in where clauses
2 parents 358c1a7 + cfd2470 commit 67ba89b

File tree

5 files changed

+111
-17
lines changed

5 files changed

+111
-17
lines changed

infection.json.dist

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,44 @@
2020
"WyriHaximus\\React\\SimpleORM\\Repository::page"
2121
]
2222
},
23+
"DecrementInteger": {
24+
"ignore": [
25+
"WyriHaximus\\React\\SimpleORM\\Repository::translateFieldName"
26+
]
27+
},
2328
"IncrementInteger": {
2429
"ignore": [
2530
"WyriHaximus\\React\\SimpleORM\\Repository::count",
26-
"WyriHaximus\\React\\SimpleORM\\Repository::buildTree"
31+
"WyriHaximus\\React\\SimpleORM\\Repository::buildTree",
32+
"WyriHaximus\\React\\SimpleORM\\Repository::translateFieldName"
2733
]
2834
},
2935
"OneZeroInteger": {
3036
"ignore": [
31-
"WyriHaximus\\React\\SimpleORM\\Repository::count"
37+
"WyriHaximus\\React\\SimpleORM\\Repository::count",
38+
"WyriHaximus\\React\\SimpleORM\\Repository::translateFieldName"
3239
]
3340
},
3441
"Foreach_": {
3542
"ignore": [
3643
"WyriHaximus\\React\\SimpleORM\\Repository::buildTree"
3744
]
45+
},
46+
"CastString": {
47+
"ignore": [
48+
"WyriHaximus\\React\\SimpleORM\\Repository::buildTree"
49+
]
50+
},
51+
"Plus": {
52+
"ignore": [
53+
"WyriHaximus\\React\\SimpleORM\\Repository::translateFieldName"
54+
]
55+
},
56+
"NotIdentical": {
57+
"ignore": [
58+
"WyriHaximus\\React\\SimpleORM\\Repository::buildTree",
59+
"WyriHaximus\\React\\SimpleORM\\Repository::buildJoins"
60+
]
3861
}
3962
}
4063
}

src/Repository.php

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace WyriHaximus\React\SimpleORM;
44

55
use Plasma\SQL\QueryBuilder;
6+
use Plasma\SQL\QueryExpressions\Fragment;
67
use Ramsey\Uuid\Uuid;
78
use React\Promise\Promise;
89
use React\Promise\PromiseInterface;
@@ -73,16 +74,23 @@ public function fetch(array $where = [], array $order = []): Observable
7374

7475
public function create(array $fields): PromiseInterface
7576
{
76-
$fields['id'] = Uuid::getFactory()->uuid4()->toString();
77+
$id = Uuid::getFactory()->uuid4()->toString();
78+
$fields['id'] = $id;
7779
$fields['created'] = new \DateTimeImmutable();
7880
$fields['modified'] = new \DateTimeImmutable();
7981

8082
$fields = $this->prepareFields($fields);
8183

8284
return $this->client->query(
8385
QueryBuilder::create()->insert($fields)->into($this->entity->getTable())->returning()
84-
)->toPromise()->then(function (array $row): EntityInterface {
85-
return $this->hydrator->hydrate($this->entity, $row);
86+
)->toPromise()->then(function (array $row) use ($id): PromiseInterface {
87+
return $this->fetch([
88+
[
89+
'id',
90+
'=',
91+
$id,
92+
],
93+
])->take(1)->toPromise();
8694
});
8795
}
8896

@@ -95,9 +103,9 @@ public function update(EntityInterface $entity): PromiseInterface
95103

96104
return $this->client->query(
97105
QueryBuilder::create()->
98-
update($fields)->
99-
into($this->entity->getTable())->
100-
where('id', '=', $entity->getId())
106+
update($fields)->
107+
into($this->entity->getTable())->
108+
where('id', '=', $entity->getId())
101109
)->toPromise()->then(function () use ($entity) {
102110
return $this->fetch([
103111
['id', '=', $entity->getId()],
@@ -112,7 +120,7 @@ private function buildSelectQuery(array $where = [], array $order = []): QueryBu
112120
$query = $query->select($this->fields);
113121

114122
foreach ($where as $constraint) {
115-
$constraint[0] = $this->translateFieldName($constraint[0]);
123+
$constraint[0] = $this->translateFieldName((string)$constraint[0]);
116124
$query = $query->where(...$constraint);
117125
}
118126

@@ -262,20 +270,30 @@ private function buildTree(array $row, InspectedEntityInterface $entity, string
262270
$where = [];
263271

264272
foreach ($join->getClause() as $clause) {
273+
$onLeftSide = $clause->getForeignKey();
274+
if ($clause->getForeignFunction() !== null) {
275+
/** @psalm-suppress PossiblyNullOperand */
276+
$onLeftSide = new Fragment($clause->getForeignFunction() . '(' . $onLeftSide . ')');
277+
}
278+
if ($clause->getForeignCast() !== null) {
279+
/** @psalm-suppress PossiblyNullOperand */
280+
$onLeftSide = new Fragment('CAST(' . (string)$onLeftSide . ' AS ' . $clause->getForeignCast() . ')');
281+
}
282+
265283
$where[] = [
266-
$clause->getForeignKey(),
284+
$onLeftSide,
267285
'=',
268286
$row[$this->tableAliases[$tableKey]][$clause->getLocalKey()],
269287
];
270288
}
271289

272290
$this->client
273-
->getRepository($join->getEntity()
274-
->getClass())
275-
->fetch($where)
276-
->take(1)
277-
->toPromise()
278-
->then($resolve, $reject);
291+
->getRepository($join->getEntity()
292+
->getClass())
293+
->fetch($where)
294+
->take(1)
295+
->toPromise()
296+
->then($resolve, $reject);
279297
});
280298

281299
continue;
@@ -304,7 +322,12 @@ function () use ($row, $join, $tableKey) {
304322

305323
private function translateFieldName(string $name): string
306324
{
307-
return 't0.' . $name;
325+
$pos = \strpos($name, '(');
326+
if ($pos === false) {
327+
return 't0.' . $name;
328+
}
329+
330+
return \substr($name, 0, $pos + 1) . 't0.' . \substr($name, $pos + 1);
308331
}
309332

310333
private function prepareFields(array $fields): array

tests/FunctionalTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,4 +351,26 @@ public function increaseViews(): void
351351
self::assertGreaterThan($originalBlogPost->getModified(), $updatedBlogPost->getModified());
352352
self::assertSame($timestamp, (int)$updatedBlogPost->getModified()->format('U'));
353353
}
354+
355+
/**
356+
* @test
357+
*/
358+
public function userSelf(): void
359+
{
360+
$repository = $this->client->getRepository(UserStub::class);
361+
362+
/** @var string|null $userId */
363+
$userId = null;
364+
365+
/** @var UserStub|null $self */
366+
$self = $this->await($repository->fetch()->take(1)->toPromise()->then(function (UserStub $user) use (&$userId) {
367+
$userId = $user->getId();
368+
369+
return $user->getZelf();
370+
}), $this->loop);
371+
372+
self::assertNotNull($userId);
373+
self::assertNotNull($self);
374+
self::assertSame($userId, $self->getId());
375+
}
354376
}

tests/HydratorTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public function testHydrate(): void
2727
[
2828
'id' => $id,
2929
'name' => $title,
30+
'zelf' => resolve(true),
3031
]
3132
);
3233

@@ -54,10 +55,12 @@ public function testHydrateWithJoins(): void
5455
'author' => [
5556
'id' => $authorId,
5657
'name' => $authorName,
58+
'zelf' => resolve(true),
5759
],
5860
'publisher' => [
5961
'id' => $publisherId,
6062
'name' => $publisherName,
63+
'zelf' => resolve(true),
6164
],
6265
'comments' => observableFromArray([]),
6366
]

tests/Stub/UserStub.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,26 @@
22

33
namespace WyriHaximus\React\Tests\SimpleORM\Stub;
44

5+
use React\Promise\PromiseInterface;
6+
use WyriHaximus\React\SimpleORM\Annotation\Clause;
7+
use WyriHaximus\React\SimpleORM\Annotation\InnerJoin;
58
use WyriHaximus\React\SimpleORM\Annotation\Table;
69
use WyriHaximus\React\SimpleORM\EntityInterface;
710

811
/**
912
* @Table("users")
13+
* @InnerJoin(
14+
entity=UserStub::class,
15+
clause={
16+
@Clause(
17+
local_key="name",
18+
foreign_key="name",
19+
foreign_function="INITCAP",
20+
)
21+
},
22+
property="zelf",
23+
lazy=true
24+
* )
1025
*/
1126
class UserStub implements EntityInterface
1227
{
@@ -16,6 +31,9 @@ class UserStub implements EntityInterface
1631
/** @var string */
1732
protected $name;
1833

34+
/** @var PromiseInterface */
35+
protected $zelf;
36+
1937
public function getId(): string
2038
{
2139
return $this->id;
@@ -25,4 +43,9 @@ public function getName(): string
2543
{
2644
return $this->name;
2745
}
46+
47+
public function getZelf(): PromiseInterface
48+
{
49+
return $this->zelf;
50+
}
2851
}

0 commit comments

Comments
 (0)