Skip to content

Commit 3789ad1

Browse files
committed
wip
1 parent d7b519e commit 3789ad1

File tree

16 files changed

+192
-85
lines changed

16 files changed

+192
-85
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,15 @@
3737
"symfony/var-exporter": "^7.1",
3838
"symfony/yaml": "^7.3",
3939
"tempest/highlight": "^2.11.4",
40-
"vlucas/phpdotenv": "^5.6.1",
40+
"vlucas/phpdotenv": "^5.6",
4141
"voku/portable-ascii": "^2.0.3"
4242
},
4343
"require-dev": {
4444
"azure-oss/storage-blob-flysystem": "^1.2",
4545
"carthage-software/mago": "0.26.1",
4646
"guzzlehttp/psr7": "^2.6.1",
4747
"league/flysystem-aws-s3-v3": "^3.0",
48+
"league/flysystem-azure-blob-storage": "^3.0",
4849
"league/flysystem-ftp": "^3.0",
4950
"league/flysystem-google-cloud-storage": "^3.0",
5051
"league/flysystem-memory": "^3.0",

packages/database/src/Builder/QueryBuilders/BuildsQuery.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@
44

55
use Tempest\Database\Query;
66

7+
/**
8+
* @template TModelClass
9+
*/
710
interface BuildsQuery
811
{
912
public function build(mixed ...$bindings): Query;
13+
14+
/** @return self<TModelClass> */
15+
public function bind(mixed ...$bindings): self;
1016
}

packages/database/src/Builder/QueryBuilders/CountQueryBuilder.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,18 @@
1010
use Tempest\Database\OnDatabase;
1111
use Tempest\Database\Query;
1212
use Tempest\Database\QueryStatements\CountStatement;
13+
use Tempest\Database\QueryStatements\HasWhereStatements;
1314
use Tempest\Database\QueryStatements\WhereStatement;
1415
use Tempest\Support\Conditions\HasConditions;
1516

1617
/**
1718
* @template TModelClass of object
19+
* @implements \Tempest\Database\Builder\QueryBuilders\BuildsQuery<TModelClass>
20+
* @uses \Tempest\Database\Builder\QueryBuilders\IsQueryBuilderWithWhere<TModelClass>
1821
*/
1922
final class CountQueryBuilder implements BuildsQuery
2023
{
21-
use HasConditions, OnDatabase;
24+
use HasConditions, OnDatabase, IsQueryBuilderWithWhere;
2225

2326
private ?ModelDefinition $modelDefinition;
2427

@@ -107,4 +110,9 @@ private function resolveTable(string|object $model): TableDefinition
107110

108111
return $this->modelDefinition->getTableDefinition();
109112
}
113+
114+
private function getStatementForWhere(): HasWhereStatements
115+
{
116+
return $this->count;
117+
}
110118
}

packages/database/src/Builder/QueryBuilders/DeleteQueryBuilder.php

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,28 @@
77
use Tempest\Database\OnDatabase;
88
use Tempest\Database\Query;
99
use Tempest\Database\QueryStatements\DeleteStatement;
10+
use Tempest\Database\QueryStatements\HasWhereStatements;
1011
use Tempest\Database\QueryStatements\WhereStatement;
1112
use Tempest\Support\Conditions\HasConditions;
1213

1314
use function Tempest\Database\model;
1415

1516
/**
1617
* @template TModelClass of object
18+
* @implements \Tempest\Database\Builder\QueryBuilders\BuildsQuery<TModelClass>
19+
* @uses \Tempest\Database\Builder\QueryBuilders\IsQueryBuilderWithWhere<TModelClass>
1720
*/
1821
final class DeleteQueryBuilder implements BuildsQuery
1922
{
20-
use HasConditions, OnDatabase;
23+
use HasConditions, OnDatabase, IsQueryBuilderWithWhere;
2124

2225
private DeleteStatement $delete;
2326

2427
private array $bindings = [];
2528

2629
public function __construct(
27-
private string|object $model,
30+
/** @var class-string<TModelClass>|string $model */
31+
private readonly string|object $model,
2832
) {
2933
$table = ModelDefinition::tryFrom($this->model)?->getTableDefinition() ?? new TableDefinition($this->model);
3034
$this->delete = new DeleteStatement($table);
@@ -39,22 +43,15 @@ public function execute(): void
3943
$this->build()->execute();
4044
}
4145

46+
/** @return self<TModelClass> */
4247
public function allowAll(): self
4348
{
4449
$this->delete->allowAll = true;
4550

4651
return $this;
4752
}
4853

49-
public function where(string $where, mixed ...$bindings): self
50-
{
51-
$this->delete->where[] = new WhereStatement($where);
52-
53-
$this->bind(...$bindings);
54-
55-
return $this;
56-
}
57-
54+
/** @return self<TModelClass> */
5855
public function bind(mixed ...$bindings): self
5956
{
6057
$this->bindings = [...$this->bindings, ...$bindings];
@@ -71,4 +68,9 @@ public function build(mixed ...$bindings): Query
7168
{
7269
return new Query($this->delete, [...$this->bindings, ...$bindings])->onDatabase($this->onDatabase);
7370
}
71+
72+
private function getStatementForWhere(): HasWhereStatements
73+
{
74+
return $this->delete;
75+
}
7476
}

packages/database/src/Builder/QueryBuilders/InsertQueryBuilder.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ final class InsertQueryBuilder implements BuildsQuery
2626

2727
private array $after = [];
2828

29+
private array $bindings = [];
30+
2931
public function __construct(
3032
private readonly string|object $model,
3133
private readonly array $rows,
@@ -74,7 +76,14 @@ public function build(mixed ...$bindings): Query
7476
$this->insert->addEntry($data);
7577
}
7678

77-
return new Query($this->insert, $bindings)->onDatabase($this->onDatabase);
79+
return new Query($this->insert, [...$this->bindings, ...$bindings])->onDatabase($this->onDatabase);
80+
}
81+
82+
public function bind(mixed ...$bindings): self
83+
{
84+
$this->bindings = [...$this->bindings, ...$bindings];
85+
86+
return $this;
7887
}
7988

8089
public function then(Closure ...$callbacks): self
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
namespace Tempest\Database\Builder\QueryBuilders;
4+
5+
use Tempest\Database\Builder\FieldDefinition;
6+
use Tempest\Database\QueryStatements\HasWhereStatements;
7+
use Tempest\Database\QueryStatements\WhereStatement;
8+
use function Tempest\Support\str;
9+
10+
/**
11+
* @template TModelClass
12+
* @phpstan-require-implements \Tempest\Database\Builder\QueryBuilders\BuildsQuery
13+
*/
14+
trait IsQueryBuilderWithWhere
15+
{
16+
private abstract function getStatementForWhere(): HasWhereStatements;
17+
18+
/** @return self<TModelClass> */
19+
public function where(string $where, mixed ...$bindings): self
20+
{
21+
if ($this->getStatementForWhere()->where->isNotEmpty() && ! str($where)->trim()->startsWith(['AND', 'OR'])) {
22+
return $this->andWhere($where, ...$bindings);
23+
}
24+
25+
$this->getStatementForWhere()->where[] = new WhereStatement($where);
26+
27+
$this->bind(...$bindings);
28+
29+
return $this;
30+
}
31+
32+
/** @return self<TModelClass> */
33+
public function andWhere(string $where, mixed ...$bindings): self
34+
{
35+
return $this->where("AND {$where}", ...$bindings);
36+
}
37+
38+
/** @return self<TModelClass> */
39+
public function orWhere(string $where, mixed ...$bindings): self
40+
{
41+
return $this->where("OR {$where}", ...$bindings);
42+
}
43+
44+
/** @return self<TModelClass> */
45+
public function whereField(string $field, mixed $value): self
46+
{
47+
$field = new FieldDefinition(
48+
$this->model->getTableDefinition(),
49+
$field,
50+
);
51+
52+
return $this->where("{$field} = :{$field->name}", ...[$field->name => $value]);
53+
}
54+
}

packages/database/src/Builder/QueryBuilders/SelectQueryBuilder.php

Lines changed: 11 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,31 @@
55
namespace Tempest\Database\Builder\QueryBuilders;
66

77
use Closure;
8-
use Tempest\Database\Builder\FieldDefinition;
98
use Tempest\Database\Builder\ModelInspector;
109
use Tempest\Database\Id;
1110
use Tempest\Database\Mappers\SelectModelMapper;
1211
use Tempest\Database\OnDatabase;
1312
use Tempest\Database\Query;
1413
use Tempest\Database\QueryStatements\FieldStatement;
14+
use Tempest\Database\QueryStatements\HasWhereStatements;
1515
use Tempest\Database\QueryStatements\JoinStatement;
1616
use Tempest\Database\QueryStatements\OrderByStatement;
1717
use Tempest\Database\QueryStatements\RawStatement;
1818
use Tempest\Database\QueryStatements\SelectStatement;
19-
use Tempest\Database\QueryStatements\WhereStatement;
2019
use Tempest\Support\Arr\ImmutableArray;
2120
use Tempest\Support\Conditions\HasConditions;
2221

2322
use function Tempest\Database\model;
2423
use function Tempest\map;
25-
use function Tempest\Support\str;
2624

2725
/**
2826
* @template TModelClass of object
27+
* @implements \Tempest\Database\Builder\QueryBuilders\BuildsQuery<TModelClass>
28+
* @uses \Tempest\Database\Builder\QueryBuilders\IsQueryBuilderWithWhere<TModelClass>
2929
*/
3030
final class SelectQueryBuilder implements BuildsQuery
3131
{
32-
use HasConditions, OnDatabase;
32+
use HasConditions, OnDatabase, IsQueryBuilderWithWhere;
3333

3434
/** @var class-string<TModelClass> $modelClass */
3535
private readonly string $modelClass;
@@ -57,9 +57,7 @@ public function __construct(string|object $model, ?ImmutableArray $fields = null
5757
);
5858
}
5959

60-
/**
61-
* @return TModelClass|null
62-
*/
60+
/** @return TModelClass|null */
6361
public function first(mixed ...$bindings): mixed
6462
{
6563
$query = $this->build(...$bindings);
@@ -79,9 +77,7 @@ public function first(mixed ...$bindings): mixed
7977
return $result[array_key_first($result)];
8078
}
8179

82-
/**
83-
* @return TModelClass|null
84-
*/
80+
/** @return TModelClass|null */
8581
public function get(Id $id): mixed
8682
{
8783
return $this->whereField('id', $id)->first();
@@ -120,44 +116,6 @@ public function chunk(Closure $closure, int $amountPerChunk = 200): void
120116
} while ($data !== []);
121117
}
122118

123-
/** @return self<TModelClass> */
124-
public function where(string $where, mixed ...$bindings): self
125-
{
126-
if (
127-
$this->select->where->isNotEmpty()
128-
&& ! str($where)->trim()->startsWith(['AND', 'OR'])
129-
) {
130-
return $this->andWhere($where, ...$bindings);
131-
}
132-
133-
$this->select->where[] = new WhereStatement($where);
134-
135-
$this->bind(...$bindings);
136-
137-
return $this;
138-
}
139-
140-
public function andWhere(string $where, mixed ...$bindings): self
141-
{
142-
return $this->where("AND {$where}", ...$bindings);
143-
}
144-
145-
public function orWhere(string $where, mixed ...$bindings): self
146-
{
147-
return $this->where("OR {$where}", ...$bindings);
148-
}
149-
150-
/** @return self<TModelClass> */
151-
public function whereField(string $field, mixed $value): self
152-
{
153-
$field = new FieldDefinition(
154-
$this->model->getTableDefinition(),
155-
$field,
156-
);
157-
158-
return $this->where("{$field} = :{$field->name}", ...[$field->name => $value]);
159-
}
160-
161119
/** @return self<TModelClass> */
162120
public function orderBy(string $statement): self
163121
{
@@ -264,4 +222,9 @@ private function getIncludedRelations(): array
264222

265223
return $relations;
266224
}
225+
226+
private function getStatementForWhere(): HasWhereStatements
227+
{
228+
return $this->select;
229+
}
267230
}

0 commit comments

Comments
 (0)