ModelController::create()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 10
nc 2
nop 1
dl 0
loc 18
ccs 0
cts 11
cp 0
crap 6
rs 9.4285
c 1
b 0
f 0
1
<?php
2
3
namespace Anavel\Crud\Http\Controllers;
4
5
use ANavallaSuiza\Laravel\Database\Contracts\Manager\ModelManager;
6
use ANavallaSuiza\Laravel\Database\Repository\Eloquent\Repository;
7
use Anavel\Crud\Contracts\Abstractor\Model;
8
use Anavel\Crud\Contracts\Abstractor\ModelFactory as ModelAbstractorFactory;
9
use Anavel\Crud\Contracts\Controllers\CustomController;
10
use Anavel\Crud\Contracts\Form\Generator as FormGenerator;
11
use Anavel\Crud\Repository\Criteria\OrderByCriteria;
12
use Anavel\Crud\Repository\Criteria\SearchCriteria;
13
use Anavel\Crud\Repository\Criteria\WithCriteria;
14
use Anavel\Foundation\Http\Controllers\Controller;
15
use Anavel\Crud\Services\Export\Csv;
16
use App;
17
use Illuminate\Http\Request;
18
19
class ModelController extends Controller
20
{
21
    protected $modelFactory;
22
    protected $modelManager;
23
    protected $formGenerator;
24
25
    public function __construct(ModelAbstractorFactory $modelFactory, ModelManager $modelManager, FormGenerator $formGenerator)
26
    {
27
        $this->modelFactory = $modelFactory;
28
        $this->modelManager = $modelManager;
29
        $this->formGenerator = $formGenerator;
30
    }
31
32
    private function authorizeMethod(Model $modelAbstractor, $methodName)
33
    {
34
        $config = $modelAbstractor->getConfig();
35
36
        if (array_key_exists('authorize', $config) && $config['authorize'] === true) {
37
            $this->authorize($methodName, $modelAbstractor->getInstance());
38
        }
39
    }
40
41
    /**
42
     * @param Model $modelAbstractor
43
     *
44
     * @return null|CustomController
45
     */
46
    private function customController(Model $modelAbstractor)
47
    {
48
        if ($this instanceof CustomController) { //Avoid infinite recursion
49
            return;
50
        }
51
52
        $config = $modelAbstractor->getConfig();
53
54
        if (!array_key_exists('controller', $config) || empty($config['controller'])) {
55
            return;
56
        }
57
58
        /** @var CustomController $controller */
59
        $controller = App::make($config['controller']);
60
        $controller->setAbstractor($modelAbstractor);
61
62
        return $controller;
63
    }
64
65
    /**
66
     * Prepare contents to be used
67
     *
68
     * @param Request $request
69
     * @param Model $modelAbstractor
70
     * @param Repository  $repository
71
     *
72
     * @return void
73
     */
74
    public function getIndexRequirements(Request $request, Model $modelAbstractor, Repository $repository)
75
    {
76
        foreach ($modelAbstractor->getListFields()['main'] as $field) {
77
            if (strpos($field->getName(), '.')) {
78
                $repository->pushCriteria(new WithCriteria(preg_replace('/\.[^\.]+$/', '', $field->getName())));
79
            }
80
        }
81
82
        if ($search = $request->input('search')) {
83
            $searchByColumns = [];
84
85
            foreach ($modelAbstractor->getListFields()['main'] as $field) {
86
                $searchByColumns[] = $field->getName();
87
            }
88
89
            $repository->pushCriteria(new SearchCriteria($searchByColumns, $search));
90
        }
91
92
        $sort = $request->input('sort') ?: 'id';
93
        $direction = $request->input('direction') ?: 'desc';
94
95
        $repository->pushCriteria(new OrderByCriteria($sort, ($direction === 'desc') ? true : false));
96
    }
97
98
    /**
99
     * Display a listing of the resource.
100
     *
101
     * @param Request $request
102
     * @param string  $model
103
     *
104
     * @return Response
105
     */
106
    public function index(Request $request, $model)
107
    {
108
        $modelAbstractor = $this->modelFactory->getBySlug($model);
109
110
        $this->authorizeMethod($modelAbstractor, 'adminIndex');
111
112
        if ($customController = $this->customController($modelAbstractor)) {
113
            return $customController->index($request, $model);
114
        }
115
116
        $repository = $this->modelManager->getRepository($modelAbstractor->getModel());
117
118
        $this->getIndexRequirements($request, $modelAbstractor, $repository);
119
120
        return view('anavel-crud::pages.index', [
0 ignored issues
show
Bug Best Practice introduced by
The return type of return view('anavel-crud....list_max_results')))); (Illuminate\View\View|Ill...\Contracts\View\Factory) is incompatible with the return type documented by Anavel\Crud\Http\Control...\ModelController::index of type Anavel\Crud\Http\Controllers\Response.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
121
            'abstractor' => $modelAbstractor,
122
            'items'      => $repository->paginate(config('anavel-crud.list_max_results')),
123
        ]);
124
    }
125
126
    /**
127
     * Display a listing of the resource.
128
     *
129
     * @param Request $request
130
     * @param string  $model
131
     *
132
     * @return Response
133
     */
134
    public function exportCsv(Request $request, $model)
135
    {
136
        $modelAbstractor = $this->modelFactory->getBySlug($model);
137
138
        $this->authorizeMethod($modelAbstractor, 'exportCsv');
139
140
        if ($customController = $this->customController($modelAbstractor)) {
141
            return $customController->exportCsv($request, $model);
0 ignored issues
show
Bug introduced by
The method exportCsv() does not seem to exist on object<Anavel\Crud\Contr...llers\CustomController>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
142
        }
143
144
        $repository = $this->modelManager->getRepository($modelAbstractor->getModel());
145
146
        $this->getIndexRequirements($request, $modelAbstractor, $repository);
147
148
        $csv = (string)(new Csv)->fromArray($repository->all()->toArray());
149
150
        return response()->make($csv, 200, [
0 ignored issues
show
Bug Best Practice introduced by
The return type of return response()->make(...=' . $model . '.csv')); (Illuminate\Http\Response) is incompatible with the return type documented by Anavel\Crud\Http\Control...elController::exportCsv of type Anavel\Crud\Http\Controllers\Response.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
151
            'Content-Encoding' => 'UTF-8',
152
            'Content-Type' => 'application/octet-stream',
153
            'Content-disposition' => 'attachment; filename='.$model.'.csv',
154
        ]);
155
    }
156
157
    /**
158
     * Show the form for creating a new resource.
159
     *
160
     * @param string $model
161
     *
162
     * @return Response
163
     */
164
    public function create($model)
165
    {
166
        $modelAbstractor = $this->modelFactory->getBySlug($model);
167
168
        $this->authorizeMethod($modelAbstractor, 'adminCreate');
169
170
        if ($customController = $this->customController($modelAbstractor)) {
171
            return $customController->create($model);
172
        }
173
174
        $form = $modelAbstractor->getForm(route('anavel-crud.model.store', $modelAbstractor->getSlug()));
175
176
        return view('anavel-crud::pages.create', [
0 ignored issues
show
Bug Best Practice introduced by
The return type of return view('anavel-crud...ctor->getRelations())); (Illuminate\View\View|Ill...\Contracts\View\Factory) is incompatible with the return type documented by Anavel\Crud\Http\Control...ModelController::create of type Anavel\Crud\Http\Controllers\Response.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
177
            'abstractor' => $modelAbstractor,
178
            'form'       => $form,
179
            'relations'  => $modelAbstractor->getRelations(),
180
        ]);
181
    }
182
183
    /**
184
     * Store a newly created resource in storage.
185
     *
186
     * @param Request $request
187
     * @param string  $model
188
     *
189
     * @return Response
190
     */
191
    public function store(Request $request, $model)
192
    {
193
        $modelAbstractor = $this->modelFactory->getBySlug($model);
194
195
        $this->authorizeMethod($modelAbstractor, 'adminCreate');
196
197
        if ($customController = $this->customController($modelAbstractor)) {
198
            return $customController->store($request, $model);
199
        }
200
201
        // Sets the validation rules
202
        $modelAbstractor->getForm(route('anavel-crud.model.store', $modelAbstractor->getSlug()));
203
204
        $this->validate($request, $modelAbstractor->getValidationRules());
205
206
        $modelAbstractor->persist($request);
207
208
        session()->flash('anavel-alert', [
209
            'type'  => 'success',
210
            'icon'  => 'fa-check',
211
            'title' => trans('anavel-crud::messages.alert_success_model_store_title'),
212
            'text'  => trans('anavel-crud::messages.alert_success_model_store_text'),
213
        ]);
214
215
        return redirect()->route('anavel-crud.model.index', $model);
0 ignored issues
show
Documentation introduced by
$model is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Bug Best Practice introduced by
The return type of return redirect()->route....model.index', $model); (Illuminate\Http\RedirectResponse) is incompatible with the return type documented by Anavel\Crud\Http\Control...\ModelController::store of type Anavel\Crud\Http\Controllers\Response.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
216
    }
217
218
    /**
219
     * Display the specified resource.
220
     *
221
     * @param string $model
222
     * @param int    $id
223
     *
224
     * @return Response
225
     */
226
    public function show($model, $id)
227
    {
228
        $modelAbstractor = $this->modelFactory->getBySlug($model);
229
230
        $this->authorizeMethod($modelAbstractor, 'adminShow');
231
232
        if ($customController = $this->customController($modelAbstractor)) {
233
            return $customController->show($model, $id);
234
        }
235
236
        $repository = $this->modelManager->getRepository($modelAbstractor->getModel());
237
        $item = $repository->findByOrFail($repository->getModel()->getKeyName(), $id);
238
239
        return view('anavel-crud::pages.show', [
0 ignored issues
show
Bug Best Practice introduced by
The return type of return view('anavel-crud...tor, 'item' => $item)); (Illuminate\View\View|Ill...\Contracts\View\Factory) is incompatible with the return type documented by Anavel\Crud\Http\Controllers\ModelController::show of type Anavel\Crud\Http\Controllers\Response.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
240
            'abstractor' => $modelAbstractor,
241
            'item'       => $item,
242
        ]);
243
    }
244
245
    /**
246
     * Show the form for editing the specified resource.
247
     *
248
     * @param string $model
249
     * @param int    $id
250
     *
251
     * @return Response
252
     */
253
    public function edit($model, $id)
254
    {
255
        /** @var Model $modelAbstractor */
256
        $modelAbstractor = $this->modelFactory->getBySlug($model, $id);
257
258
        $this->authorizeMethod($modelAbstractor, 'adminUpdate');
259
260
        if ($customController = $this->customController($modelAbstractor)) {
261
            return $customController->edit($model, $id);
262
        }
263
264
        $form = $modelAbstractor->getForm(route('anavel-crud.model.update', [$modelAbstractor->getSlug(), $id]));
265
        $repository = $this->modelManager->getRepository($modelAbstractor->getModel());
266
        $item = $repository->findByOrFail($repository->getModel()->getKeyName(), $id);
267
268
        return view('anavel-crud::pages.edit', [
0 ignored issues
show
Bug Best Practice introduced by
The return type of return view('anavel-crud...ctor->getRelations())); (Illuminate\View\View|Ill...\Contracts\View\Factory) is incompatible with the return type documented by Anavel\Crud\Http\Controllers\ModelController::edit of type Anavel\Crud\Http\Controllers\Response.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
269
            'abstractor' => $modelAbstractor,
270
            'form'       => $form,
271
            'item'       => $item,
272
            'relations'  => $modelAbstractor->getRelations(),
273
        ]);
274
    }
275
276
    /**
277
     * Update the specified resource in storage.
278
     *
279
     * @param Request $request
280
     * @param string  $model
281
     * @param int     $id
282
     *
283
     * @return Response
284
     */
285
    public function update(Request $request, $model, $id)
286
    {
287
        $modelAbstractor = $this->modelFactory->getBySlug($model, $id);
288
289
        $this->authorizeMethod($modelAbstractor, 'adminUpdate');
290
291
        if ($customController = $this->customController($modelAbstractor)) {
292
            return $customController->update($request, $model, $id);
293
        }
294
295
        // Sets the validation rules
296
        $modelAbstractor->getForm(route('anavel-crud.model.update', [$modelAbstractor->getSlug(), $id]));
297
298
        $this->validate($request, $modelAbstractor->getValidationRules());
299
300
        $modelAbstractor->persist($request);
301
302
        session()->flash('anavel-alert', [
303
            'type'  => 'success',
304
            'icon'  => 'fa-check',
305
            'title' => trans('anavel-crud::messages.alert_success_model_update_title'),
306
            'text'  => trans('anavel-crud::messages.alert_success_model_update_text'),
307
        ]);
308
309
        return redirect()->route('anavel-crud.model.edit', [$model, $id]);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return redirect()->route...', array($model, $id)); (Illuminate\Http\RedirectResponse) is incompatible with the return type documented by Anavel\Crud\Http\Control...ModelController::update of type Anavel\Crud\Http\Controllers\Response.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
310
    }
311
312
    /**
313
     * Remove the specified resource from storage.
314
     *
315
     * @param Request $request
316
     * @param string  $model
317
     * @param int     $id
318
     *
319
     * @return Response
320
     */
321
    public function destroy(Request $request, $model, $id)
322
    {
323
        $modelAbstractor = $this->modelFactory->getBySlug($model);
324
325
        $this->authorizeMethod($modelAbstractor, 'adminDestroy');
326
327
        if ($customController = $this->customController($modelAbstractor)) {
328
            return $customController->destroy($request, $model, $id);
329
        }
330
331
        $repository = $this->modelManager->getRepository($modelAbstractor->getModel());
332
        $item = $repository->findByOrFail($repository->getModel()->getKeyName(), $id);
333
334
        $item->delete();
335
336
        session()->flash('anavel-alert', [
337
            'type'  => 'success',
338
            'icon'  => 'fa-check',
339
            'title' => trans('anavel-crud::messages.alert_success_model_destroy_title'),
340
            'text'  => trans('anavel-crud::messages.alert_success_model_destroy_text'),
341
        ]);
342
343
        return redirect()->route('anavel-crud.model.index', $model);
0 ignored issues
show
Documentation introduced by
$model is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Bug Best Practice introduced by
The return type of return redirect()->route....model.index', $model); (Illuminate\Http\RedirectResponse) is incompatible with the return type documented by Anavel\Crud\Http\Control...odelController::destroy of type Anavel\Crud\Http\Controllers\Response.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
344
    }
345
}
346