Completed
Push — master ( 4c7cc5...3ea27d )
by wen
12:34
created

Component::setRepository()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
3
namespace Sco\Admin\Component;
4
5
use BadMethodCallException;
6
use Illuminate\Database\Eloquent\Model;
7
use InvalidArgumentException;
8
use Illuminate\Foundation\Application;
9
use Sco\Admin\Component\Concerns\HasAccess;
10
use Sco\Admin\Component\Concerns\HasEvents;
11
use Sco\Admin\Component\Concerns\HasNavigation;
12
use Sco\Admin\Contracts\ComponentInterface;
13
use Sco\Admin\Contracts\Form\FormInterface;
14
use Sco\Admin\Contracts\RepositoryInterface;
15
use Sco\Admin\Contracts\Display\DisplayInterface;
16
17
abstract class Component implements ComponentInterface
18
{
19
    use HasAccess, HasEvents, HasNavigation;
20
21
    /**
22
     * @var
23
     */
24
    protected $name;
25
26
    /**
27
     * @var \Illuminate\Foundation\Application
28
     */
29
    protected $app;
30
31
    /**
32
     * The component display name
33
     *
34
     * @var string
35
     */
36
    protected $title;
37
38
    /**
39
     * @var mixed|\Sco\Admin\Contracts\RepositoryInterface
40
     */
41
    protected $repository;
42
43
    /**
44
     * @var \Illuminate\Database\Eloquent\Model
45
     */
46
    protected $model;
47
48
    protected static $booted = [];
49
50
    /**
51
     * @var \Illuminate\Contracts\Events\Dispatcher
52
     */
53
    protected static $dispatcher;
54
55
    abstract public function model();
56
57
    public function __construct(Application $app)
58
    {
59
        $this->app = $app;
60
61
        $this->bootIfNotBooted();
62
    }
63
64
    /**
65
     * {@inheritdoc}
66
     */
67
    public function getName()
68
    {
69
        if (is_null($this->name)) {
70
            $this->setName($this->getDefaultName());
71
        }
72
73
        return $this->name;
74
    }
75
76
    /**
77
     * {@inheritdoc}
78
     */
79
    public function setName(string $value)
80
    {
81
        $this->name = $value;
82
83
        return $this;
84
    }
85
86
    /**
87
     * {@inheritdoc}
88
     */
89
    public function getTitle()
90
    {
91
        return $this->title;
92
    }
93
94
    /**
95
     * {@inheritdoc}
96
     */
97
    public function setTitle(string $value)
98
    {
99
        $this->title = $value;
100
101
        return $this;
102
    }
103
104
    protected function getDefaultName()
105
    {
106
        return $this->getModelClassName();
107
    }
108
109
    /**
110
     * @return string
111
     */
112
    protected function getModelClassName()
113
    {
114
        return snake_case( // 蛇形命名
115
            str_plural( // 复数
116
                class_basename(
117
                    get_class($this->getModel())
118
                )
119
            )
120
        );
121
    }
122
123
    /**
124
     * {@inheritdoc}
125
     */
126
    public function setModel(Model $model)
127
    {
128
        $this->model = $model;
129
130
        return $this;
131
    }
132
133
    /**
134
     * {@inheritdoc}
135
     */
136
    public function getModel()
137
    {
138
        if (is_null($this->model)) {
139
            $this->setModel($this->makeModel());
140
        }
141
142
        return $this->model;
143
    }
144
145
    /**
146
     * @return \Illuminate\Database\Eloquent\Model|mixed
147
     */
148
    protected function makeModel()
149
    {
150
        $class = $this->model();
151
        if (empty($class)) {
152
            throw new InvalidArgumentException(
153
                sprintf(
154
                    'The component(%s) method "model()" not found value',
155
                    get_class($this)
156
                )
157
            );
158
        }
159
160
        $model = $this->app->make($this->model());
161
162
        if (! ($model instanceof Model)) {
163
            throw new InvalidArgumentException(
164
                sprintf(
165
                    "Class %s must be an instance of %s",
166
                    $this->model(),
167
                    Model::class
168
                )
169
            );
170
        }
171
172
        return $model;
173
    }
174
175
    /**
176
     * {@inheritdoc}
177
     */
178
    public function getRepository()
179
    {
180
        if (is_null($this->repository)) {
181
            $this->setRepository($this->makeRepository());
182
        }
183
184
        return $this->repository;
185
    }
186
187
    /**
188
     * {@inheritdoc}
189
     */
190
    public function setRepository(RepositoryInterface $repository)
191
    {
192
        $this->repository = $repository;
193
194
        return $this;
195
    }
196
197
    protected function makeRepository()
198
    {
199
        $repository = $this->app->make(RepositoryInterface::class);
200
        $repository->setModel($this->getModel());
201
202
        return $repository;
203
    }
204
205
    /**
206
     * {@inheritdoc}
207
     */
208
    public function getConfigs()
209
    {
210
        return collect([
211
            'title'    => $this->getTitle(),
212
            'accesses' => $this->getAccesses(),
213
            'display'  => $this->fireDisplay(),
214
        ]);
215
    }
216
217
    /**
218
     * {@inheritdoc}
219
     */
220 View Code Duplication
    final public function fireDisplay()
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
221
    {
222
        if (! method_exists($this, 'callDisplay')) {
223
            throw new BadMethodCallException('Not Found Method "callDisplay"');
224
        }
225
226
        $display = $this->app->call([$this, 'callDisplay']);
227
228
        if (! ($display instanceof DisplayInterface)) {
229
            throw new InvalidArgumentException(
230
                sprintf(
231
                    'callDisplay must be instanced of "%s".',
232
                    DisplayInterface::class
233
                )
234
            );
235
        }
236
237
        $display->setModel($this->getModel());
0 ignored issues
show
Bug introduced by
It seems like $this->getModel() can be null; however, setModel() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
238
        $display->initialize();
239
240
        return $display;
241
    }
242
243
    public function get()
244
    {
245
        $display = $this->fireDisplay();
246
247
        return $display->get();
248
    }
249
250
    /**
251
     * {@inheritdoc}
252
     */
253 View Code Duplication
    final public function fireCreate()
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
254
    {
255
        if (! method_exists($this, 'callCreate')) {
256
            return;
257
        }
258
259
        $form = $this->app->call([$this, 'callCreate']);
260
        if (! $form instanceof FormInterface) {
261
            throw new InvalidArgumentException(
262
                sprintf(
263
                    'callCreate must be instanced of "%s".',
264
                    FormInterface::class
265
                )
266
            );
267
        }
268
269
        $form->setModel($this->getModel());
270
271
        return $form;
272
    }
273
274
    /**
275
     * {@inheritdoc}
276
     */
277
    public function store()
278
    {
279
        $form = $this->fireCreate();
280
281
        $form->validate()->save();
282
    }
283
284
    /**
285
     * {@inheritdoc}
286
     */
287
    final public function fireEdit($id)
288
    {
289
        if (! method_exists($this, 'callEdit')) {
290
            return;
291
        }
292
293
        $form = $this->app->call([$this, 'callEdit'], ['id' => $id]);
294
295
        if (! $form instanceof FormInterface) {
296
            throw new InvalidArgumentException(
297
                sprintf(
298
                    'callEdit must be instanced of "%s".',
299
                    FormInterface::class
300
                )
301
            );
302
        }
303
304
        $model = $this->getRepository()->findOrFail($id);
305
306
        $form->setModel($model);
307
308
        return $form;
309
    }
310
311
    /**
312
     * {@inheritdoc}
313
     */
314
    public function update($id)
315
    {
316
        $form = $this->fireEdit($id);
317
        $form->validate()->save();
318
    }
319
320
    public function delete($id)
321
    {
322
        $this->getRepository()->delete($id);
323
324
        return true;
325
    }
326
327
    public function forceDelete($id)
328
    {
329
        $this->getRepository()->forceDelete($id);
330
331
        return true;
332
    }
333
334
    public function restore($id)
335
    {
336
        $this->getRepository()->restore($id);
337
338
        return true;
339
    }
340
341
    protected function bootIfNotBooted()
342
    {
343
        if (! isset(static::$booted[static::class])) {
344
            static::$booted[static::class] = true;
345
346
            $this->fireEvent('booting', false);
347
348
            $this->boot();
349
350
            $this->fireEvent('booted', false);
351
        }
352
    }
353
354
    /**
355
     * The "booting" method of the model.
356
     *
357
     * @return void
358
     */
359
    protected function boot()
360
    {
361
        $this->bootTraits();
362
    }
363
364
    /**
365
     * Boot all of the bootable traits on the model.
366
     *
367
     * @return void
368
     */
369
    protected function bootTraits()
370
    {
371
        foreach (class_uses_recursive($this) as $trait) {
372
            if (method_exists($this, $method = 'boot' . class_basename($trait))) {
373
                $this->$method();
374
            }
375
        }
376
    }
377
}
378