Completed
Pull Request — master (#4)
by
unknown
09:35
created

Controller::create()   A

Complexity

Conditions 6
Paths 16

Size

Total Lines 26
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 9.7518

Importance

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