Completed
Push — master ( f173b1...4fb3c4 )
by Takafumi
05:21
created

Controller::update()   D

Complexity

Conditions 9
Paths 32

Size

Total Lines 35
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 20.5013

Importance

Changes 0
Metric Value
cc 9
eloc 21
nc 32
nop 2
dl 0
loc 35
ccs 11
cts 23
cp 0.4783
crap 20.5013
rs 4.909
c 0
b 0
f 0
1
<?php
2
3
namespace Enomotodev\LaractiveAdmin\Http\Controllers;
4
5
use ReflectionClass;
6
use ReflectionException;
7
use ReflectionMethod;
8
use Illuminate\Database\Eloquent\Relations\BelongsTo;
9
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
10
use Illuminate\Http\Request;
11
use Illuminate\Http\UploadedFile;
12
use Illuminate\Support\HtmlString;
13
use Illuminate\Support\Str;
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
     * The default layout view.
34
     *
35
     * @var string
36
     */
37
    public static $defaultLayoutView = 'laractive-admin::layout';
38
39
    /**
40
     * The default index view.
41
     *
42
     * @var string
43
     */
44
    public static $defaultIndexView = 'laractive-admin::index';
45
46
    /**
47
     * The default index view.
48
     *
49
     * @var string
50
     */
51
    public static $defaultShowView = 'laractive-admin::show';
52
53
    /**
54
     * The default new view.
55
     *
56
     * @var string
57
     */
58
    public static $defaultNewView = 'laractive-admin::new';
59
60
    /**
61
     * The default edit view.
62
     *
63
     * @var string
64
     */
65
    public static $defaultEditView = 'laractive-admin::edit';
66
67
    /**
68
     * @var \Illuminate\Session\SessionManager
69
     */
70
    protected $session;
71
72
    /**
73
     * @return \Illuminate\Support\HtmlString
74
     *
75
     * @throws \Throwable
76
     */
77 2
    public function index()
78
    {
79 2
        $model = $this->model::newModelInstance();
80 2
        $columns = $this->getColumnsFromTable($model);
81 2
        $collection = $this->model::paginate();
82
83 2
        return new HtmlString(
84 2
            view()->make(static::$defaultIndexView, [
85 2
                'class' => $this->getClassName(),
86 2
                'table' => $this->getTable(),
87 2
                'layoutView' => static::$defaultLayoutView,
88 2
                'columns' => $columns,
89 2
                'collection' => $collection,
90 2
            ])->render()
91
        );
92
    }
93
94
    /**
95
     * @param  int  $id
96
     * @return \Illuminate\Support\HtmlString
97
     *
98
     * @throws \Throwable
99
     */
100 4
    public function show(int $id)
101
    {
102 4
        $model = $this->model::findOrFail($id);
103 4
        $commentColumns = array_filter($this->getColumnsFromTable($model->comments()->getRelated()), function ($type, $name) use ($model) {
104 4
            return !in_array($name, ['id', 'updated_at', $model->comments()->getForeignKeyName(), $model->comments()->getMorphType()]);
105 4
        }, ARRAY_FILTER_USE_BOTH);
106
107 4
        return new HtmlString(
108 4
            view()->make(static::$defaultShowView, [
109 4
                'class' => $this->getClassName(),
110 4
                'table' => $this->getTable(),
111 4
                'layoutView' => static::$defaultLayoutView,
112 4
                'model' => $model,
113 4
                'commentColumns' => $commentColumns,
114 4
            ])->render()
115
        );
116
    }
117
118
    /**
119
     * @return \Illuminate\Support\HtmlString
120
     *
121
     * @throws \Throwable
122
     */
123 2
    public function new()
124
    {
125 2
        $model = $this->model::newModelInstance();
126 2
        $columns = $this->getColumnsFromTable($model);
127 2
        $relations = $this->getRelations();
128
129 2
        return new HtmlString(
130 2
            view()->make(static::$defaultNewView, [
131 2
                'class' => $this->getClassName(),
132 2
                'table' => $this->getTable(),
133 2
                'layoutView' => static::$defaultLayoutView,
134 2
                'columns' => $columns,
135 2
                'model' => $model,
136 2
                'relations' => $relations,
137 2
                'files' => $this->files,
138 2
            ])->render()
139
        );
140
    }
141
142
    /**
143
     * @param  \Illuminate\Http\Request  $request
144
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
145
     */
146
    public function create(Request $request)
147
    {
148 2
        $inputs = $this->validate ? $request->validate($this->validate) : array_filter($request->post(), function ($item) {
149
            return $item !== null;
150 2
        });
151 2
        if (isset($inputs['password'])) {
152 2
            $inputs['password'] = \Hash::make($inputs['password']);
153
        }
154 2
        if (!empty($this->files)) {
155
            $files = array_filter($inputs, function ($item, $key) {
156
                return in_array($key, $this->files) && $item instanceof UploadedFile;
157
            }, ARRAY_FILTER_USE_BOTH);
158
159
            foreach ($files as $key => $file) {
160
                $fileName = Str::random(32).".".$request->{$key}->extension();
161
                $request->{$key}->storePubliclyAs("public/{$this->getTable()}", $fileName);
162
163
                $inputs[$key] = $fileName;
164
            }
165
        }
166 2
        $model = $this->model::create($inputs);
167 2
        foreach ($this->getRelations() as $key => $relation) {
168
            if ($relation['type'] !== 'BelongsToMany') {
169
                continue;
170
            }
171
172
            if (!empty($inputs[$key])) {
173
                $model->{$relation['relation_name']}()->sync($inputs[$key]);
174
            }
175
        }
176
177 2
        $request->session()->flash('message', 'Create');
178
179 2
        return redirect(route("admin.{$this->getTable()}.show", [$model->id]));
180
    }
181
182
    /**
183
     * @param  int  $id
184
     * @return \Illuminate\Support\HtmlString
185
     *
186
     * @throws \Throwable
187
     */
188 1
    public function edit(int $id)
189
    {
190 1
        $model = $this->model::findOrFail($id);
191 1
        $columns = $this->getColumnsFromTable($model);
192 1
        $relations = $this->getRelations();
193
194 1
        return new HtmlString(
195 1
            view()->make(static::$defaultEditView, [
196 1
                'class' => $this->getClassName(),
197 1
                'table' => $this->getTable(),
198 1
                'layoutView' => static::$defaultLayoutView,
199 1
                'columns' => $columns,
200 1
                'model' => $model,
201 1
                'relations' => $relations,
202 1
                'files' => $this->files,
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) {
216
            return $item !== null;
217 1
        });
218 1
        if (isset($inputs['password'])) {
219 1
            $inputs['password'] = \Hash::make($inputs['password']);
220
        }
221 1
        if (!empty($this->files)) {
222
            $files = array_filter($inputs, function ($item, $key) {
223
                return in_array($key, $this->files) && $item instanceof UploadedFile;
224
            }, ARRAY_FILTER_USE_BOTH);
225
226
            foreach ($files as $key => $file) {
227
                $fileName = Str::random(32).".".$request->{$key}->extension();
228
                $request->{$key}->storePubliclyAs("public/{$this->getTable()}", $fileName);
229
230
                $inputs[$key] = $fileName;
231
            }
232
        }
233 1
        $model->update($inputs);
234 1
        foreach ($this->getRelations() as $key => $relation) {
235
            if ($relation['type'] !== 'BelongsToMany') {
236
                continue;
237
            }
238
239
            if (!empty($inputs[$key])) {
240
                $model->{$relation['relation_name']}()->sync($inputs[$key]);
241
            }
242
        }
243
244 1
        $request->session()->flash('message', 'Update');
245
246 1
        return redirect(route("admin.{$this->getTable()}.show", [$model->id]));
247
    }
248
249
    /**
250
     * @param  \Illuminate\Http\Request  $request
251
     * @param  int  $id
252
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
253
     */
254 1
    public function destroy(Request $request, int $id)
255
    {
256 1
        $model = $this->model::findOrFail($id);
257 1
        $model->delete();
258
259 1
        $request->session()->flash('message', 'Delete');
260
261 1
        return redirect(route("admin.{$this->getTable()}.index"));
262
    }
263
264
    /**
265
     * @param  \Illuminate\Http\Request  $request
266
     * @param  int  $id
267
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
268
     */
269 1
    public function comments(Request $request, int $id)
270
    {
271 1
        $model = $this->model::findOrFail($id);
272 1
        $inputs = $request->validate([
273 1
            'body' => 'required',
274
        ]);
275 1
        $model->comments()->create([
276 1
            'body' => $inputs['body'],
277
        ]);
278
279 1
        $request->session()->flash('message', 'Create comment');
280
281 1
        return redirect(route("admin.{$this->getTable()}.show", [$model->id]));
282
    }
283
284
    /**
285
     * @return string
286
     */
287 6
    protected function getTable()
288
    {
289 6
        return (new $this->model)->getTable();
290
    }
291
292
    /**
293
     * @return array
294
     */
295 2
    protected function getRelations()
296
    {
297 2
        $model = (new $this->model)->newInstance();
298
299 2
        $relations = [];
300
301
        try {
302 2
            $methods = (new ReflectionClass($model))->getMethods(ReflectionMethod::IS_PUBLIC);
303 2
            foreach($methods as $method) {
304
                if (
305 2
                    $method->class != get_class($model) ||
306 2
                    !empty($method->getParameters()) ||
307 2
                    $method->getName() == __FUNCTION__
308
                ) {
309 2
                    continue;
310
                }
311
312
                try {
313 2
                    $return = $method->invoke($model);
314
315 2
                    if ($return instanceof BelongsTo) {
316
                        $relations[$return->getForeignKey()] = [
317
                            'type' => (new ReflectionClass($return))->getShortName(),
318
                            'model' => (new ReflectionClass($return->getRelated()))->getName(),
319
                        ];
320 2
                    } elseif ($return instanceof BelongsToMany) {
321
                        $relations[$return->getRelatedPivotKeyName()] = [
322
                            'type' => (new ReflectionClass($return))->getShortName(),
323
                            'model' => (new ReflectionClass($return->getRelated()))->getName(),
324 2
                            'relation_name' => $return->getRelationName(),
325
                        ];
326
                    }
327 2
                } catch (ReflectionException $e) {
328
                    // Ignore exception
329
                }
330
            }
331
        } catch (ReflectionException $e) {
332
            // Ignore exception
333
        }
334
335 2
        return $relations;
336
    }
337
338
    /**
339
     * @return string
340
     */
341 6
    protected function getClassName()
342
    {
343
        try {
344 6
            return (new ReflectionClass($this))->getShortName();
345
        } catch (ReflectionException $e) {
346
            return '';
347
        }
348
    }
349
350
    /**
351
     * @param  \Illuminate\Database\Eloquent\Model $model
352
     * @return array
353
     *
354
     * @throws \Throwable
355
     */
356 6
    protected function getColumnsFromTable($model)
357
    {
358 6
        $table = $model->getConnection()->getTablePrefix().$model->getTable();
359 6
        $schema = $model->getConnection()->getDoctrineSchemaManager($table);
0 ignored issues
show
Unused Code introduced by
The call to Illuminate\Database\Conn...DoctrineSchemaManager() has too many arguments starting with $table. ( Ignorable by Annotation )

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

359
        $schema = $model->getConnection()->/** @scrutinizer ignore-call */ getDoctrineSchemaManager($table);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
360 6
        $databasePlatform = $schema->getDatabasePlatform();
361 6
        $databasePlatform->registerDoctrineTypeMapping('enum', 'string');
362
363 6
        $database = null;
364 6
        if (strpos($table, '.')) {
365
            list($database, $table) = explode('.', $table);
366
        }
367
368 6
        $listTableColumns = $schema->listTableColumns($table, $database);
369
370 6
        $columns = [];
371 6
        if ($listTableColumns) {
372 6
            foreach ($listTableColumns as $column) {
373 6
                $name = $column->getName();
374
375 6
                switch ($column->getType()->getName()) {
376 6
                    case 'string':
377 6
                        $type = 'string';
378 6
                        break;
379 6
                    case 'text':
380 4
                        $type = 'text';
381 4
                        break;
382 6
                    case 'date':
383
                        $type = 'date';
384
                        break;
385 6
                    case 'time':
386
                        $type = 'time';
387
                        break;
388 6
                    case 'datetimetz':
389 6
                    case 'datetime':
390 6
                        $type = 'datetime';
391 6
                        break;
392 6
                    case 'integer':
393
                    case 'bigint':
394
                    case 'smallint':
395 6
                        $type = 'integer';
396 6
                        break;
397
                    case 'boolean':
398
                        $type = 'boolean';
399
                        break;
400
                    case 'decimal':
401
                    case 'float':
402
                        $type = 'float';
403
                        break;
404
                    default:
405
                        $type = 'mixed';
406
                        break;
407
                }
408
409 6
                $columns[$name] = $type;
410
            }
411
        }
412
413 6
        return $columns;
414
    }
415
}
416