Controller::comments()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 7
nc 1
nop 2
dl 0
loc 13
ccs 8
cts 8
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Enomotodev\LaractiveAdmin\Http\Controllers;
4
5
use ReflectionClass;
6
use ReflectionMethod;
7
use ReflectionException;
8
use Illuminate\Support\Str;
9
use Illuminate\Http\Request;
10
use Illuminate\Http\UploadedFile;
11
use Illuminate\Support\HtmlString;
12
use Illuminate\Database\Eloquent\Relations\BelongsTo;
13
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
14
15
abstract class Controller
16
{
17
    /**
18
     * @var string
19
     */
20
    public $model;
21
22
    /**
23
     * @var array
24
     */
25
    protected $files = [];
26
27
    /**
28
     * @var array
29
     */
30
    protected $validate = [];
31
32
    /**
33
     * @var array
34
     */
35
    protected $enum = [];
36
37
    /**
38
     * @var int
39
     */
40
    protected $paginate = 30;
41
42
    /**
43
     * @var array
44
     */
45
    public static $actions = [];
46
47
    /**
48
     * The default layout view.
49
     *
50
     * @var string
51
     */
52
    public static $defaultLayoutView = 'laractive-admin::layout';
53
54
    /**
55
     * The default index view.
56
     *
57
     * @var string
58
     */
59
    public static $defaultIndexView = 'laractive-admin::index';
60
61
    /**
62
     * The default index view.
63
     *
64
     * @var string
65
     */
66
    public static $defaultShowView = 'laractive-admin::show';
67
68
    /**
69
     * The default new view.
70
     *
71
     * @var string
72
     */
73
    public static $defaultNewView = 'laractive-admin::new';
74
75
    /**
76
     * The default edit view.
77
     *
78
     * @var string
79
     */
80
    public static $defaultEditView = 'laractive-admin::edit';
81
82
    /**
83
     * @var \Illuminate\Session\SessionManager
84
     */
85
    protected $session;
86
87
    /**
88
     * @return \Illuminate\Support\HtmlString
89
     *
90
     * @throws \Throwable
91
     */
92 2
    public function index()
93
    {
94 2
        $model = $this->model::newModelInstance();
95 2
        $columns = $this->getColumnsFromTable($model);
96 2
        $collection = $this->getQueryBuilderForIndex()->paginate($this->paginate);
97
98 2
        return new HtmlString(
99 2
            view()->make(static::$defaultIndexView, [
100 2
                'table' => $this->getTable(),
101 2
                'columns' => $columns,
102 2
                'collection' => $collection,
103 2
                'enum' => $this->enum,
104 2
            ])->render()
105
        );
106
    }
107
108
    /**
109
     * @param  int  $id
110
     * @return \Illuminate\Support\HtmlString
111
     *
112
     * @throws \Throwable
113
     */
114 4
    public function show(int $id)
115
    {
116 4
        $model = $this->model::findOrFail($id);
117 4
        $commentColumns = array_filter($this->getColumnsFromTable($model->comments()->getRelated()), function ($type, $name) use ($model) {
118 4
            return ! in_array($name, ['id', 'updated_at', $model->comments()->getForeignKeyName(), $model->comments()->getMorphType()]);
119 4
        }, ARRAY_FILTER_USE_BOTH);
120
121 4
        return new HtmlString(
122 4
            view()->make(static::$defaultShowView, [
123 4
                'table' => $this->getTable(),
124 4
                'model' => $model,
125 4
                'commentColumns' => $commentColumns,
126 4
                'enum' => $this->enum,
127 4
            ])->render()
128
        );
129
    }
130
131
    /**
132
     * @return \Illuminate\Support\HtmlString
133
     *
134
     * @throws \Throwable
135
     */
136 2
    public function new()
137
    {
138 2
        $model = $this->model::newModelInstance();
139 2
        $columns = $this->getColumnsFromTable($model);
140 2
        $relations = $this->getRelations();
141
142 2
        return new HtmlString(
143 2
            view()->make(static::$defaultNewView, [
144 2
                'table' => $this->getTable(),
145 2
                'columns' => $columns,
146 2
                'model' => $model,
147 2
                'relations' => $relations,
148 2
                'files' => $this->files,
149 2
                'enum' => $this->enum,
150 2
            ])->render()
151
        );
152
    }
153
154
    /**
155
     * @param  \Illuminate\Http\Request  $request
156
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
157
     */
158
    public function create(Request $request)
159
    {
160 2
        $inputs = $this->validate ? $request->validate($this->validate) : array_filter($request->post(), function ($item) {
0 ignored issues
show
Bug introduced by
It seems like $request->post() can also be of type null and string; however, parameter $input of array_filter() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

160
        $inputs = $this->validate ? $request->validate($this->validate) : array_filter(/** @scrutinizer ignore-type */ $request->post(), function ($item) {
Loading history...
161
            return $item !== null;
162 2
        });
163 2
        if (isset($inputs['password'])) {
164 2
            $inputs['password'] = \Hash::make($inputs['password']);
165
        }
166 2
        $inputs = $this->getInputsWithFiles($request, $inputs);
167 2
        $model = $this->model::create($inputs);
168 2
        foreach ($this->getRelations() as $key => $relation) {
169
            if ($relation['type'] !== 'BelongsToMany') {
170
                continue;
171
            }
172
173
            if (! empty($inputs[$key])) {
174
                $model->{$relation['relation_name']}()->sync($inputs[$key]);
175
            }
176
        }
177
178 2
        $request->session()->flash('message', 'Create');
179
180 2
        return redirect(route("admin.{$this->getTable()}.show", [$model->id]));
181
    }
182
183
    /**
184
     * @param  int  $id
185
     * @return \Illuminate\Support\HtmlString
186
     *
187
     * @throws \Throwable
188
     */
189 1
    public function edit(int $id)
190
    {
191 1
        $model = $this->model::findOrFail($id);
192 1
        $columns = $this->getColumnsFromTable($model);
193 1
        $relations = $this->getRelations();
194
195 1
        return new HtmlString(
196 1
            view()->make(static::$defaultEditView, [
197 1
                'table' => $this->getTable(),
198 1
                'columns' => $columns,
199 1
                'model' => $model,
200 1
                'relations' => $relations,
201 1
                'files' => $this->files,
202 1
                'enum' => $this->enum,
203 1
            ])->render()
204
        );
205
    }
206
207
    /**
208
     * @param  \Illuminate\Http\Request  $request
209
     * @param  int  $id
210
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
211
     */
212 1
    public function update(Request $request, int $id)
213
    {
214 1
        $model = $this->model::findOrFail($id);
215 1
        $inputs = $this->validate ? $request->validate($this->validate) : array_filter($request->post(), function ($item) {
0 ignored issues
show
Bug introduced by
It seems like $request->post() can also be of type null and string; however, parameter $input of array_filter() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

215
        $inputs = $this->validate ? $request->validate($this->validate) : array_filter(/** @scrutinizer ignore-type */ $request->post(), function ($item) {
Loading history...
216
            return $item !== null;
217 1
        });
218 1
        if (isset($inputs['password'])) {
219 1
            $inputs['password'] = \Hash::make($inputs['password']);
220
        }
221 1
        $inputs = $this->getInputsWithFiles($request, $inputs);
222 1
        $model->update($inputs);
223 1
        foreach ($this->getRelations() as $key => $relation) {
224
            if ($relation['type'] !== 'BelongsToMany') {
225
                continue;
226
            }
227
228
            if (! empty($inputs[$key])) {
229
                $model->{$relation['relation_name']}()->sync($inputs[$key]);
230
            }
231
        }
232
233 1
        $request->session()->flash('message', 'Update');
234
235 1
        return redirect(route("admin.{$this->getTable()}.show", [$model->id]));
236
    }
237
238
    /**
239
     * @param  \Illuminate\Http\Request  $request
240
     * @param  int  $id
241
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
242
     */
243 1
    public function destroy(Request $request, int $id)
244
    {
245 1
        $model = $this->model::findOrFail($id);
246 1
        $model->delete();
247
248 1
        $request->session()->flash('message', 'Delete');
249
250 1
        return redirect(route("admin.{$this->getTable()}.index"));
251
    }
252
253
    /**
254
     * @param  \Illuminate\Http\Request  $request
255
     * @param  int  $id
256
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
257
     */
258 1
    public function comments(Request $request, int $id)
259
    {
260 1
        $model = $this->model::findOrFail($id);
261 1
        $inputs = $request->validate([
262 1
            'body' => 'required',
263
        ]);
264 1
        $model->comments()->create([
265 1
            'body' => $inputs['body'],
266
        ]);
267
268 1
        $request->session()->flash('message', 'Create comment');
269
270 1
        return redirect(route("admin.{$this->getTable()}.show", [$model->id]));
271
    }
272
273
    /**
274
     * @return string
275
     */
276 7
    public function getClassName()
277
    {
278
        try {
279 7
            return (new ReflectionClass($this))->getShortName();
280
        } catch (ReflectionException $e) {
281
            return '';
282
        }
283
    }
284
285
    /**
286
     * @return string
287
     */
288 6
    protected function getTable()
289
    {
290 6
        return (new $this->model)->getTable();
291
    }
292
293
    /**
294
     * @return array
295
     */
296 2
    protected function getRelations()
297
    {
298 2
        $model = (new $this->model)->newInstance();
299
300 2
        $relations = [];
301
302
        try {
303 2
            $methods = (new ReflectionClass($model))->getMethods(ReflectionMethod::IS_PUBLIC);
304 2
            foreach ($methods as $method) {
305
                if (
306 2
                    $method->class != get_class($model) ||
307 2
                    ! empty($method->getParameters()) ||
308 2
                    $method->getName() == __FUNCTION__
309
                ) {
310 2
                    continue;
311
                }
312
313
                try {
314 2
                    $return = $method->invoke($model);
315
316 2
                    if ($return instanceof BelongsTo) {
317
                        $relations[$return->getForeignKey()] = [
318
                            'type' => (new ReflectionClass($return))->getShortName(),
319
                            'model' => (new ReflectionClass($return->getRelated()))->getName(),
320
                        ];
321 2
                    } elseif ($return instanceof BelongsToMany) {
322
                        $relations[$return->getRelatedPivotKeyName()] = [
323
                            'type' => (new ReflectionClass($return))->getShortName(),
324
                            'model' => (new ReflectionClass($return->getRelated()))->getName(),
325 2
                            'relation_name' => $return->getRelationName(),
326
                        ];
327
                    }
328 2
                } catch (ReflectionException $e) {
329
                    // Ignore exception
330
                }
331
            }
332
        } catch (ReflectionException $e) {
333
            // Ignore exception
334
        }
335
336 2
        return $relations;
337
    }
338
339
    /**
340
     * @param  \Illuminate\Database\Eloquent\Model $model
341
     * @return array
342
     *
343
     * @throws \Throwable
344
     */
345 6
    protected function getColumnsFromTable($model)
346
    {
347 6
        $table = $model->getConnection()->getTablePrefix().$model->getTable();
348 6
        $schema = $model->getConnection()->getDoctrineSchemaManager();
349 6
        $databasePlatform = $schema->getDatabasePlatform();
350 6
        $databasePlatform->registerDoctrineTypeMapping('enum', 'string');
351
352 6
        $database = null;
353 6
        if (strpos($table, '.')) {
354
            list($database, $table) = explode('.', $table);
355
        }
356
357 6
        $listTableColumns = $schema->listTableColumns($table, $database);
358
359 6
        $columns = [];
360 6
        if ($listTableColumns) {
361 6
            foreach ($listTableColumns as $column) {
362 6
                $name = $column->getName();
363 6
                $columns[$name] = $this->convertColumnTypeName($column->getType()->getName());
364
            }
365
        }
366
367 6
        return $columns;
368
    }
369
370
    /**
371
     * @param  \Illuminate\Http\Request $request
372
     * @param  array $inputs
373
     * @return array
374
     */
375 2
    protected function getInputsWithFiles($request, $inputs)
376
    {
377 2
        if (! empty($this->files)) {
378
            $files = array_filter($inputs, function ($item, $key) {
379
                return in_array($key, $this->files) && $item instanceof UploadedFile;
380
            }, ARRAY_FILTER_USE_BOTH);
381
382
            foreach ($files as $key => $file) {
383
                $fileName = Str::random(32).'.'.$request->{$key}->extension();
384
                $request->{$key}->storePubliclyAs("public/{$this->getTable()}", $fileName);
385
386
                $inputs[$key] = $fileName;
387
            }
388
        }
389
390 2
        return $inputs;
391
    }
392
393
    /**
394
     * @return \Illuminate\Database\Query\Builder
395
     */
396 2
    protected function getQueryBuilderForIndex()
397
    {
398 2
        return $this->model::orderBy('id', 'desc');
399
    }
400
401
    /**
402
     * @param  string $typeName
403
     * @return string
404
     */
405 6
    private function convertColumnTypeName($typeName)
406
    {
407
        $mapping = [
408 6
            'string' => 'string',
409
            'text' => 'text',
410
            'date' => 'date',
411
            'time' => 'time',
412
            'datetimetz' => 'datetime',
413
            'datetime' => 'datetime',
414
            'integer' => 'integer',
415
            'bigint' => 'integer',
416
            'smallint' => 'integer',
417
            'boolean' => 'boolean',
418
            'decimal' => 'float',
419
            'float' => 'float',
420
        ];
421 6
        $defaultType = 'mixed';
422
423 6
        return isset($mapping[$typeName]) ? $mapping[$typeName] : $defaultType;
424
    }
425
}
426