• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tempestphp / tempest-framework / 14717032918

28 Apr 2025 08:17PM UTC coverage: 80.253% (-0.02%) from 80.275%
14717032918

Pull #1181

github

web-flow
Merge fd5c097b7 into afcfb4d76
Pull Request #1181: feat(database): add `count()` helper to `IsDatabaseQuery` trait

0 of 4 new or added lines in 1 file covered. (0.0%)

6 existing lines in 1 file now uncovered.

11859 of 14777 relevant lines covered (80.25%)

106.77 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.77
/src/Tempest/Database/src/IsDatabaseModel.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Tempest\Database;
6

7
use Tempest\Database\Builder\QueryBuilders\CountQueryBuilder;
8
use Tempest\Database\Builder\QueryBuilders\SelectQueryBuilder;
9
use Tempest\Database\Exceptions\MissingRelation;
10
use Tempest\Database\Exceptions\MissingValue;
11
use Tempest\Reflection\ClassReflector;
12
use Tempest\Reflection\PropertyReflector;
13
use Tempest\Validation\SkipValidation;
14

15
use function Tempest\make;
16

17
trait IsDatabaseModel
18
{
19
    #[SkipValidation]
20
    public Id $id;
21

22
    public static function new(mixed ...$params): self
77✔
23
    {
24
        return make(self::class)->from($params);
77✔
25
    }
26

27
    public static function resolve(string $input): static
1✔
28
    {
29
        return self::get(new Id($input));
1✔
30
    }
31

32
    /**
33
     * @return \Tempest\Database\Builder\QueryBuilders\SelectQueryBuilder<self>
34
     */
35
    public static function select(): SelectQueryBuilder
58✔
36
    {
37
        return query(self::class)->select();
58✔
38
    }
39

40
    /** @return self[] */
41
    public static function all(array $relations = []): array
23✔
42
    {
43
        return self::select()
23✔
44
            ->with(...$relations)
23✔
45
            ->all();
23✔
46
    }
47

48
    public static function get(Id $id, array $relations = []): ?self
20✔
49
    {
50
        return self::select()
20✔
51
            ->with(...$relations)
20✔
52
            ->get($id);
20✔
53
    }
54

55
    public static function find(mixed ...$conditions): SelectQueryBuilder
1✔
56
    {
57
        $query = self::select();
1✔
58

59
        array_walk($conditions, fn ($value, $column) => $query->whereField($column, $value));
1✔
60

61
        return $query;
1✔
62
    }
63

NEW
UNCOV
64
    public static function count(): CountQueryBuilder
×
65
    {
NEW
UNCOV
66
        return query(self::class)->count();
×
67
    }
68

NEW
UNCOV
69
    public static function countAll(): int
×
70
    {
NEW
UNCOV
71
        return query(self::class)->count()->execute();
×
72
    }
73

74
    public static function create(mixed ...$params): self
66✔
75
    {
76
        model(self::class)->validate(...$params);
66✔
77

78
        $model = self::new(...$params);
65✔
79

80
        $model->id = query(self::class)
65✔
81
            ->insert($model)
65✔
82
            ->build()
65✔
83
            ->execute();
65✔
84

85
        return $model;
65✔
86
    }
87

88
    public static function findOrNew(array $find, array $update): self
1✔
89
    {
90
        $existing = self::select()->bind(...$find);
1✔
91

92
        foreach ($find as $key => $value) {
1✔
93
            $existing = $existing->where("{$key} = :{$key}");
1✔
94
        }
95

96
        $model = $existing->first() ?? self::new(...$find);
1✔
97

98
        foreach ($update as $key => $value) {
1✔
99
            $model->{$key} = $value;
1✔
100
        }
101

102
        return $model;
1✔
103
    }
104

105
    public static function updateOrCreate(array $find, array $update): self
1✔
106
    {
107
        $model = self::findOrNew($find, $update);
1✔
108

109
        if (! isset($model->id)) {
1✔
UNCOV
110
            return self::create(...$update);
×
111
        }
112

113
        return $model->save();
1✔
114
    }
115

116
    public function __get(string $name): mixed
3✔
117
    {
118
        $property = PropertyReflector::fromParts($this, $name);
3✔
119

120
        if ($property->hasAttribute(Lazy::class)) {
3✔
121
            $this->load($name);
1✔
122

123
            return $property->getValue($this);
1✔
124
        }
125

126
        $type = $property->getType();
2✔
127

128
        if ($type->isIterable()) {
2✔
UNCOV
129
            throw new MissingRelation($this, $name);
×
130
        }
131

132
        if ($type->isBuiltIn()) {
2✔
133
            throw new MissingValue($this, $name);
1✔
134
        }
135

136
        throw new MissingRelation($this, $name);
1✔
137
    }
138

139
    public function load(string ...$relations): self
9✔
140
    {
141
        $new = self::get($this->id, $relations);
9✔
142

143
        foreach (new ClassReflector($new)->getPublicProperties() as $property) {
9✔
144
            $property->setValue($this, $property->getValue($new));
9✔
145
        }
146

147
        return $this;
9✔
148
    }
149

150
    public function save(): self
45✔
151
    {
152
        $model = model($this);
45✔
153

154
        $model->validate(...model($this)->getPropertyValues());
45✔
155

156
        if (! isset($this->id)) {
44✔
157
            $query = query($this::class)->insert($this);
37✔
158

159
            $this->id = $query->execute();
37✔
160
        } else {
161
            query($this)->update(
9✔
162
                ...model($this)->getPropertyValues(),
9✔
163
            )->execute();
9✔
164
        }
165

166
        return $this;
44✔
167
    }
168

169
    public function update(mixed ...$params): self
3✔
170
    {
171
        model(self::class)->validate(...$params);
3✔
172

173
        foreach ($params as $key => $value) {
2✔
174
            $this->{$key} = $value;
2✔
175
        }
176

177
        query($this)
2✔
178
            ->update(...$params)
2✔
179
            ->build()
2✔
180
            ->execute();
2✔
181

182
        return $this;
2✔
183
    }
184

185
    public function delete(): void
2✔
186
    {
187
        query($this)
2✔
188
            ->delete()
2✔
189
            ->build()
2✔
190
            ->execute();
2✔
191
    }
192
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc