1 | <?php |
||
2 | |||
3 | namespace Isswp101\Persimmon\Models; |
||
4 | |||
5 | use Elasticsearch\ClientBuilder; |
||
6 | use Isswp101\Persimmon\Concerns\Attributable; |
||
7 | use Isswp101\Persimmon\Concerns\Elasticsearchable; |
||
8 | use Isswp101\Persimmon\Concerns\Eventable; |
||
9 | use Isswp101\Persimmon\Concerns\Existable; |
||
10 | use Isswp101\Persimmon\Concerns\Timestampable; |
||
11 | use Isswp101\Persimmon\Contracts\Arrayable; |
||
12 | use Isswp101\Persimmon\Contracts\ElasticsearchModelContract; |
||
13 | use Isswp101\Persimmon\Contracts\Persistencable; |
||
14 | use Isswp101\Persimmon\Contracts\PersistenceContract; |
||
15 | use Isswp101\Persimmon\DTO\Id; |
||
16 | use Isswp101\Persimmon\DTO\Path; |
||
17 | use Isswp101\Persimmon\Exceptions\ModelNotFoundException; |
||
18 | use Isswp101\Persimmon\Persistence\Persistence; |
||
19 | use Stringable; |
||
20 | |||
21 | /** |
||
22 | * @property int|string|null id |
||
23 | * @property string created_at |
||
24 | * @property string updated_at |
||
25 | */ |
||
26 | abstract class BaseElasticsearchModel implements ElasticsearchModelContract, Persistencable, Arrayable, Stringable |
||
27 | { |
||
28 | use Elasticsearchable, Timestampable, Eventable, Existable, Attributable; |
||
29 | |||
30 | private PersistenceContract $persistence; |
||
31 | |||
32 | protected int $perRequest = 50; |
||
33 | |||
34 | public function __construct(array $attributes = []) |
||
35 | { |
||
36 | $this->fill($attributes); |
||
37 | |||
38 | $this->persistence = $this->createPersistence(); |
||
39 | } |
||
40 | |||
41 | public function createPersistence(): PersistenceContract |
||
42 | { |
||
43 | $client = ClientBuilder::create()->build(); |
||
44 | |||
45 | return new Persistence($client); |
||
46 | } |
||
47 | |||
48 | public function getId(): int|string|null |
||
49 | { |
||
50 | return $this->id; |
||
51 | } |
||
52 | |||
53 | private function persist(Path $path, array $keys): Id |
||
54 | { |
||
55 | if ($this->exists && $keys) { |
||
56 | $keys = $this->timestamps ? array_merge($keys, ['created_at', 'updated_at']) : $keys; |
||
57 | return $this->persistence->update($path, $this->toArray($keys)); |
||
58 | } |
||
59 | return $this->persistence->create($path, $this->toArray($keys)); |
||
60 | } |
||
61 | |||
62 | public function save(array $columns = []): void |
||
63 | { |
||
64 | if (!$this->saving()) { |
||
65 | return; |
||
66 | } |
||
67 | |||
68 | $path = new Path($this->index, $this->type, new Id($this->id)); |
||
69 | |||
70 | $this->touch($this->exists); |
||
71 | |||
72 | $this->id = $this->persist($path, $columns)->value(); |
||
73 | |||
74 | $this->exists = true; |
||
75 | |||
76 | $this->saved(); |
||
77 | } |
||
78 | |||
79 | public function delete(): void |
||
80 | { |
||
81 | if (!$this->deleting()) { |
||
82 | return; |
||
83 | } |
||
84 | |||
85 | $path = new Path($this->index, $this->type, new Id($this->id)); |
||
86 | |||
87 | $this->persistence->delete($path); |
||
88 | |||
89 | $this->exists = false; |
||
90 | |||
91 | $this->deleted(); |
||
92 | } |
||
93 | |||
94 | public static function create(array $attributes): static |
||
95 | { |
||
96 | $model = new static($attributes); |
||
97 | |||
98 | $model->save(); |
||
99 | |||
100 | return $model; |
||
101 | } |
||
102 | |||
103 | public static function find(int|string $id, array $columns = []): static|null |
||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||
104 | { |
||
105 | $model = new static(); |
||
106 | |||
107 | $path = new Path($model->getIndex(), $model->getType(), new Id($id)); |
||
108 | |||
109 | $attributes = $model->persistence->find($path, $columns); |
||
110 | |||
111 | if (!$attributes) { |
||
112 | return null; |
||
113 | } |
||
114 | |||
115 | $model->fill($attributes); |
||
116 | |||
117 | $model->id = $id; |
||
118 | |||
119 | $model->exists = true; |
||
120 | |||
121 | return $model; |
||
122 | } |
||
123 | |||
124 | public static function findOrFail(int|string $id, array $columns = []): static |
||
125 | { |
||
126 | return static::find($id, $columns) ?? throw new ModelNotFoundException(); |
||
127 | } |
||
128 | |||
129 | public static function destroy(int|string $id): void |
||
130 | { |
||
131 | $model = new static(); |
||
132 | |||
133 | $model->id = $id; |
||
134 | |||
135 | $model->delete(); |
||
136 | } |
||
137 | |||
138 | public static function search(array $query = []): array |
||
139 | { |
||
140 | $model = new static(); |
||
141 | |||
142 | if (!$model->searching()) { |
||
143 | return []; |
||
144 | } |
||
145 | |||
146 | $path = new Path($model->index, $model->type, Id::undefined()); |
||
147 | |||
148 | $response = $model->persistence->search($path, $query); |
||
149 | |||
150 | $models = []; |
||
151 | foreach ($response->getItems() as $attributes) { |
||
152 | $models[] = new static($attributes); |
||
153 | } |
||
154 | |||
155 | $model->searched($response); |
||
156 | |||
157 | return $models; |
||
158 | } |
||
159 | |||
160 | public static function first(array $query): static|null |
||
161 | { |
||
162 | $query['size'] = 1; |
||
163 | |||
164 | $items = static::search($query); |
||
165 | |||
166 | return $items[0] ?? null; |
||
167 | } |
||
168 | |||
169 | public static function firstOrFail(array $query): static |
||
170 | { |
||
171 | return static::first($query) ?? throw new ModelNotFoundException(); |
||
172 | } |
||
173 | |||
174 | public static function all(array $query = []): array |
||
175 | { |
||
176 | $items = []; |
||
177 | |||
178 | $model = new static(); |
||
179 | |||
180 | $query['from'] = 0; |
||
181 | $query['size'] = $model->perRequest; |
||
182 | $itemsPerRequest = static::search($query); |
||
183 | $items = array_merge($items, $itemsPerRequest); |
||
184 | |||
185 | while (count($itemsPerRequest) == $model->perRequest) { |
||
186 | $query['from'] += $model->perRequest; |
||
187 | $itemsPerRequest = static::search($query); |
||
188 | $items = array_merge($items, $itemsPerRequest); |
||
189 | } |
||
190 | |||
191 | return $items; |
||
192 | } |
||
193 | } |
||
194 |