BaseRepository::sortByAttribute()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 2
c 1
b 0
f 0
dl 0
loc 5
ccs 0
cts 3
cp 0
rs 10
cc 2
nc 2
nop 2
crap 6
1
<?php
2
3
namespace TarfinLabs\Parasut\Repositories;
4
5
use Illuminate\Database\Eloquent\Collection;
6
use TarfinLabs\Parasut\API\ClientGateway;
7
use TarfinLabs\Parasut\Enums\HttpMethods;
8
use TarfinLabs\Parasut\Models\BaseModel;
9
use TarfinLabs\Parasut\Repositories\Meta\BaseMeta;
10
11
abstract class BaseRepository
12
{
13
    protected ClientGateway $clientGateway;
14
15
    protected string $endpoint;
16
    protected string $model;
17
18
    protected ?BaseMeta $meta;
19
    protected ?Links $links;
20
21
    protected array $sorts = [];
22
    protected array $filters = [];
23
    protected array $includes = [];
24
    protected int $page;
25
    protected int $pageSize;
26
27 10
    public function __construct()
28
    {
29 10
        $this->clientGateway = app(ClientGateway::class);
30 10
    }
31
32
    // region CRUD
33
34 2
    public function all(): ?Collection
35
    {
36 2
        $rawData = $this->clientGateway->send(
37 2
            HttpMethods::GET,
38 2
            [$this->endpoint],
39 2
            $this->filters,
40 2
            $this->sorts,
41 2
            $this->includes,
42 2
            null,
43 2
            $this->page ?? null,
44 2
            $this->pageSize ?? null
45
        );
46
47 2
        $this->meta = ! empty($rawData['meta'])
48 2
            ? $this->createMeta($rawData['meta'])
49
            : null;
50
51 2
        $this->links = ! empty($rawData['links'])
52 2
            ? new Links($rawData['links'])
53
            : null;
54
55 2
        $this->removeFirstSushiModel();
56
57 2
        if (! empty($rawData['data'])) {
58 2
            $this->model::insert($this->multipleRawDataToAttributes($rawData['data']));
59
        }
60
61 2
        return $this->model::all();
62
    }
63
64 2
    public function find(int $id): ?BaseModel
65
    {
66 2
        $rawData = $this->clientGateway->send(
67 2
            HttpMethods::GET,
68 2
            [$this->endpoint, $id],
69 2
            null,
70 2
            null,
71 2
            $this->includes,
72 2
            null,
73 2
            null,
74 2
            null
75
        );
76
77 2
        $attributes = $this->rawDataToAttributes($rawData['data']);
78
79 2
        $this->removeFirstSushiModel();
80 2
        $this->model::insert($attributes);
81
82 2
        return $this->model::find($attributes['id']);
83
    }
84
85 6
    public function create(BaseModel $model): BaseModel
86
    {
87 6
        $rawData = $this->clientGateway->send(
88 6
            HttpMethods::POST,
89 6
            [$this->endpoint],
90 6
            null,
91 6
            null,
92 6
            $this->includes,
93 6
            $this->generateCreationBodyForModel($model),
94 6
            null,
95 6
            null
96
        );
97
98 6
        $attributes = $this->rawDataToAttributes($rawData['data']);
99
100 6
        $this->model::insert($attributes);
101
102 6
        return $this->model::find($attributes['id']);
103
    }
104
105 2
    public function update(BaseModel $model): ?BaseModel
106
    {
107 2
        $rawData = $this->clientGateway->send(
108 2
            HttpMethods::PUT,
109 2
            [$this->endpoint, $model->id],
110 2
            null,
111 2
            null,
112 2
            $this->includes,
113 2
            $this->generateCreationBodyForModel($model),
114 2
            null,
115 2
            null
116
        );
117
118 2
        $attributes = $this->rawDataToAttributes($rawData['data']);
119
120 2
        $model->update($attributes);
121
122 2
        return $model;
123
    }
124
125 2
    public function delete(BaseModel $model): bool
126
    {
127 2
        $this->clientGateway->send(
128 2
            HttpMethods::DELETE,
129 2
            [$this->endpoint, $model->id],
130 2
            null,
131 2
            null,
132 2
            null,
133 2
            $this->generateCreationBodyForModel($model),
134 2
            null,
135 2
            null
136
        );
137
138 2
        return $model->delete();
139
    }
140
141
    // endregion
142
143
    // region Supports
144
145 6
    protected function generateCreationBodyForModel(BaseModel $model): array
146
    {
147 6
        $attributes = [];
148
149 6
        foreach ($model->getAttributes() as $name => $value) {
150 6
            if (! empty($value)) {
151 6
                $attributes[$name] = $value;
152
            }
153
        }
154
155
        return [
156
            'data' => [
157 6
                'type'       => $this->endpoint,
158 6
                'attributes' => $attributes,
159
                'relationships' => [],
160
            ],
161
        ];
162
    }
163
164 10
    protected function rawDataToAttributes(array $rawData): array
165
    {
166 10
        $mappings = [];
167 10
        $mappings['id'] = $rawData['id'];
168
169 10
        foreach ((new $this->model)->getFillable() as $field) {
170 10
            $mappings[$field] = $rawData['attributes'][$field];
171
        }
172
173 10
        return $mappings;
174
    }
175
176 2
    protected function multipleRawDataToAttributes(array $rawData): array
177
    {
178
        return array_map(function ($item) {
179 2
            return $this->rawDataToAttributes($item);
180 2
        }, $rawData);
181
    }
182
183
    // endregion
184
185
    // region Helpers
186
187 4
    protected function removeFirstSushiModel(): void
188
    {
189
        // TODO: Find a way to remove initilize model with sushi without a draft record creation
190 4
        $this->model::first()->delete();
191 4
    }
192
193
    public function sortByAttribute(string $attribute, bool $descending = false): self
194
    {
195
        $this->sorts[] = ($descending ? '-' : '').$attribute;
196
197
        return $this;
198
    }
199
200
    public function paginate(int $perPage, int $pageNumber): self
201
    {
202
        $this->pageSize = $perPage;
203
        $this->page = $pageNumber;
204
205
        return $this;
206
    }
207
208
    abstract protected static function createMeta(array $meta): BaseMeta;
209
210
    // endregion
211
}
212