CRUDServices   A
last analyzed

Complexity

Total Complexity 25

Size/Duplication

Total Lines 186
Duplicated Lines 0 %

Importance

Changes 20
Bugs 2 Features 2
Metric Value
eloc 55
c 20
b 2
f 2
dl 0
loc 186
rs 10
wmc 25

9 Methods

Rating   Name   Duplication   Size   Complexity  
A update() 0 12 4
A getParentRelationship() 0 3 1
A destroy() 0 12 3
A create() 0 12 4
A optimizeAttributes() 0 5 1
A getParent() 0 20 4
A createFromParent() 0 14 4
A getModelClassName() 0 7 2
A getServiceVariable() 0 8 2
1
<?php
2
3
namespace InnoFlash\LaraStart\Services;
4
5
use Illuminate\Database\Eloquent\Model;
6
use Illuminate\Support\Str;
7
use InnoFlash\LaraStart\Traits\APIResponses;
8
use InvalidArgumentException;
9
10
abstract class CRUDServices
11
{
12
    use APIResponses;
13
14
    /**
15
     * This sets the attributes to be removed from the given set for updating or creating.
16
     * @return array
17
     */
18
    abstract public function getUnsetFields(): array;
19
20
    /**
21
     * This gets the relationship of the given model to the parent.
22
     *
23
     * @return mixed
24
     */
25
    public function getParentRelationship()
26
    {
27
        throw new InvalidArgumentException('A relationship for these models is not set!');
28
    }
29
30
    /**
31
     * Deletes the model from the database.
32
     *
33
     * @param string $message
34
     *
35
     * @return
36
     */
37
    public function destroy(string $message = null)
38
    {
39
        try {
40
            $this->getServiceVariable()->delete();
41
42
            if (config('larastart.return_object')) {
43
                return '';
44
            }
45
46
            return $this->successResponse($message ?? $this->getModelClassName(true).' deleted successfully', [], 204);
47
        } catch (\Exception $e) {
48
            abort(500, $e->getMessage());
49
        }
50
    }
51
52
    /**
53
     *  Updates the model with the given filtered attributes.
54
     *
55
     * @param array $attributes
56
     * @param string $message
57
     * @param bool $returnObject
58
     *
59
     * @return \Illuminate\Http\JsonResponse|mixed
60
     */
61
    public function update(array $attributes, string $message = null, bool $returnObject = false)
62
    {
63
        try {
64
            $this->getServiceVariable()->update($this->optimizeAttributes($attributes));
65
66
            if ($returnObject || config('larastart.return_object')) {
67
                return $this->getServiceVariable()->refresh();
68
            }
69
70
            return $this->successResponse($message ?? $this->getModelClassName(true).' updated successfully');
71
        } catch (\Exception $e) {
72
            abort(500, $e->getMessage());
73
        }
74
    }
75
76
    /**
77
     * Creates a new model with the given filtered attributes.
78
     *
79
     * @param array $attributes
80
     * @param string $message
81
     * @param bool $returnObject
82
     *
83
     * @return \Illuminate\Http\JsonResponse
84
     */
85
    public function create(array $attributes, string $message = null, bool $returnObject = false)
86
    {
87
        try {
88
            $model = $this->getModelClassName()::create($this->optimizeAttributes($attributes));
89
90
            if ($returnObject || config('larastart.return_object')) {
91
                return $model;
92
            }
93
94
            return $this->successResponse($message ?? $this->getModelClassName(true).' created successfully', [], 201);
95
        } catch (\Exception $e) {
96
            abort(500, $e->getMessage());
97
        }
98
    }
99
100
    /**
101
     * Creates a new model from the given parent relationship.
102
     *
103
     * @param array $attributes
104
     * @param string $message
105
     * @param bool $returnObject
106
     *
107
     * @return \Illuminate\Http\JsonResponse
108
     */
109
    public function createFromParent(array $attributes, string $message = null, bool $returnObject = false)
110
    {
111
        $class = $this->getModelClassName();
112
        $model = new $class($this->optimizeAttributes($attributes));
113
114
        try {
115
            $this->getParent()->save($model);
116
            if ($returnObject || config('larastart.return_object')) {
117
                return $model;
118
            }
119
120
            return $this->successResponse($message ?? $this->getModelClassName(true).' created successfully', [], 201);
121
        } catch (\Exception $e) {
122
            abort(500, $e->getMessage());
123
        }
124
    }
125
126
    /**
127
     * This removes unwanted fields from the incoming create/update requests.
128
     *
129
     * @param array $attributes
130
     *
131
     * @return array
132
     */
133
    protected function optimizeAttributes(array $attributes)
134
    {
135
        return collect($attributes)
136
            ->except($this->getUnsetFields())
137
            ->toArray();
138
    }
139
140
    /**
141
     * Retrieves the parent to child relationship between this model and its parent.
142
     */
143
    private function getParent()
144
    {
145
        if (\is_object($this->getParentRelationship())) {
146
            return $this->getParentRelationship();
147
        }
148
149
        if (\is_array($this->getParentRelationship())) {
150
            [$class, $relationship, $parentIdRouteKey] = $this->getParentRelationship();
151
152
            $_class = new $class();
153
            $parent = $class::findOrFail(request($_class->getForeignKey()));
154
155
            if ($parentIdRouteKey) {
156
                $parent = $class::findOrFail(request($parentIdRouteKey));
157
            }
158
159
            return $parent->$relationship();
160
        }
161
162
        throw new InvalidArgumentException('You have set an invalid parent for this model');
163
    }
164
165
    /**
166
     * Return the class name of the service main model.
167
     *
168
     * Returns class base name if shortened.
169
     *
170
     * @param bool $shortened
171
     *
172
     * @return string
173
     */
174
    protected function getModelClassName(bool $shortened = false): string
175
    {
176
        if ($shortened) {
177
            return class_basename($this->getServiceVariable());
178
        }
179
180
        return get_class($this->getServiceVariable());
181
    }
182
183
    /**
184
     * Get the service variable.
185
     *
186
     * @return mixed
187
     */
188
    private function getServiceVariable()
189
    {
190
        return collect(get_object_vars($this))
191
            ->reject(fn($var) => ! ($var instanceof Model))
192
            ->filter(function ($var, $key) {
193
                return Str::contains('get'.Str::ucfirst($key), get_class_methods($this))
194
                    && Str::startsWith(Str::lower(class_basename($this)), $key);
195
            })->first();
196
    }
197
}
198