Complex classes like ModelAdmin often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use ModelAdmin, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
13 | class ModelAdmin extends Admin implements ModelQueryable |
||
14 | { |
||
15 | use ModelQuerying; |
||
16 | use ModelSaving; |
||
17 | |||
18 | /** |
||
19 | * Class of Model to Manage. |
||
20 | * |
||
21 | * @var string |
||
22 | */ |
||
23 | protected $managedModel; |
||
24 | |||
25 | /** |
||
26 | * ModelAdmin Icon. |
||
27 | * |
||
28 | * Font Awesome Defined Icon, eg 'user' = 'fa-user' |
||
29 | * |
||
30 | * @var string |
||
31 | */ |
||
32 | protected $icon = ''; |
||
33 | |||
34 | /** |
||
35 | * Validation Rules for onCreate, onEdit actions. |
||
36 | * |
||
37 | * @var array |
||
38 | */ |
||
39 | protected $rules = []; |
||
40 | |||
41 | /** |
||
42 | * Columns for Model. |
||
43 | * |
||
44 | * Defines which fields to show in the listing tables output. |
||
45 | * |
||
46 | * @var array |
||
47 | */ |
||
48 | protected $columns = []; |
||
49 | |||
50 | /** |
||
51 | * Map Model Attributes to AttributeTypes with |
||
52 | * additional parameters which will be output |
||
53 | * as fields when viewing, editting or adding |
||
54 | * a new model entry. |
||
55 | * |
||
56 | * @var array |
||
57 | */ |
||
58 | protected $fields = []; |
||
59 | |||
60 | /** |
||
61 | * Columns for Model are Sortable. |
||
62 | * |
||
63 | * @var bool |
||
64 | */ |
||
65 | protected $sortable = true; |
||
66 | |||
67 | /** |
||
68 | * The Controller to be used by the Model Admin. |
||
69 | * |
||
70 | * This defaults to parent::getController() |
||
71 | * if it has been left undefined. |
||
72 | * |
||
73 | * @var string |
||
74 | */ |
||
75 | protected $controller = '\LaravelFlare\Flare\Admin\Models\ModelAdminController'; |
||
76 | |||
77 | /** |
||
78 | * The Policy used for the Model Authorization logic. |
||
79 | * |
||
80 | * This class should implement the ModelAdminPoliceable which |
||
81 | * includes authorization checks for the create, view, edit and delete actions. |
||
82 | * |
||
83 | * @var string |
||
84 | */ |
||
85 | protected $policy = '\LaravelFlare\Flare\Permissions\ModelAdminPolicy'; |
||
86 | |||
87 | /** |
||
88 | * The current model to be managed. |
||
89 | * |
||
90 | * @var Model |
||
91 | */ |
||
92 | public $model; |
||
93 | |||
94 | /** |
||
95 | * __construct. |
||
96 | */ |
||
97 | public function __construct() |
||
98 | { |
||
99 | $this->getManagedModel(); |
||
100 | |||
101 | $this->model = $this->model(); |
||
102 | |||
103 | $this->formatFields(); |
||
104 | } |
||
105 | |||
106 | /** |
||
107 | * Returns a Model Instance. |
||
108 | * |
||
109 | * @return Model |
||
110 | */ |
||
111 | public function model() |
||
112 | { |
||
113 | if (!$this->model) { |
||
114 | $class = $this->getManagedModel(); |
||
115 | |||
116 | return $this->model = new $class(); |
||
117 | } |
||
118 | |||
119 | return $this->model; |
||
120 | } |
||
121 | |||
122 | /** |
||
123 | * Returns a New Model Instance. |
||
124 | * |
||
125 | * @return Model |
||
126 | */ |
||
127 | public function newModel() |
||
128 | { |
||
129 | $class = self::getManagedModel(); |
||
130 | |||
131 | return new $class(); |
||
132 | } |
||
133 | |||
134 | /** |
||
135 | * Returns the Managed Model Class. |
||
136 | * |
||
137 | * @return string |
||
138 | */ |
||
139 | public function getManagedModel() |
||
140 | { |
||
141 | if (!isset($this->managedModel) || $this->managedModel === null) { |
||
142 | throw new ModelAdminException('You have a ModelAdmin which does not have a model assigned to it. ModelAdmins must include a model to manage.', 1); |
||
143 | } |
||
144 | |||
145 | return $this->managedModel; |
||
146 | } |
||
147 | |||
148 | /** |
||
149 | * Set the Managed Model Class. |
||
150 | * |
||
151 | * @param string $managedModel |
||
152 | */ |
||
153 | public function setManagedModel($managedModel = null) |
||
154 | { |
||
155 | $this->managedModel = $managedModel; |
||
156 | } |
||
157 | |||
158 | /** |
||
159 | * Returns the Route Paramets. |
||
160 | * |
||
161 | * @return array |
||
162 | */ |
||
163 | public function routeParameters() |
||
164 | { |
||
165 | return array_merge(parent::routeParameters(), [ |
||
166 | 'model' => $this->managedModel, |
||
167 | ]); |
||
168 | } |
||
169 | |||
170 | /** |
||
171 | * Formats and returns the Columns. |
||
172 | * |
||
173 | * This is really gross, I'm removing it soon. |
||
174 | * |
||
175 | * @return |
||
176 | */ |
||
177 | public function getColumns() |
||
178 | { |
||
179 | $columns = []; |
||
180 | |||
181 | foreach ($this->columns as $field => $fieldTitle) { |
||
182 | if (in_array($field, $this->model->getFillable())) { |
||
183 | if (!$field) { |
||
184 | $field = $fieldTitle; |
||
185 | $fieldTitle = Str::title($fieldTitle); |
||
186 | } |
||
187 | $columns[$field] = $fieldTitle; |
||
188 | continue; |
||
189 | } |
||
190 | |||
191 | // We can replace this with data_get() I believe. |
||
192 | if (($methodBreaker = strpos($field, '.')) !== false) { |
||
193 | $method = substr($field, 0, $methodBreaker); |
||
194 | if (method_exists($this->model, $method)) { |
||
195 | if (method_exists($this->model->$method(), $submethod = str_replace($method.'.', '', $field))) { |
||
196 | $this->model->$method()->$submethod(); |
||
197 | |||
198 | $columns[$field] = $fieldTitle; |
||
199 | continue; |
||
200 | } |
||
201 | } |
||
202 | } |
||
203 | |||
204 | if (is_numeric($field)) { |
||
205 | $field = $fieldTitle; |
||
206 | $fieldTitle = Str::title($fieldTitle); |
||
207 | } |
||
208 | |||
209 | $columns[$field] = $fieldTitle; |
||
210 | } |
||
211 | |||
212 | if (count($columns)) { |
||
213 | return $columns; |
||
214 | } |
||
215 | |||
216 | return [$this->model->getKeyName() => $this->model->getKeyName()]; |
||
217 | } |
||
218 | |||
219 | /** |
||
220 | * Gets an Attribute by the provided key |
||
221 | * on either the current model or a provided model instance. |
||
222 | * |
||
223 | * @param string $key |
||
224 | * @param mixed $model |
||
225 | * |
||
226 | * @return mixed |
||
227 | */ |
||
228 | public function getAttribute($key, $model = false) |
||
229 | { |
||
230 | if (!$key) { |
||
231 | return; |
||
232 | } |
||
233 | |||
234 | if (!$model) { |
||
235 | $model = $this->model; |
||
236 | } |
||
237 | |||
238 | if ($this->hasGetAccessor($key)) { |
||
239 | $method = 'get'.Str::studly($key).'Attribute'; |
||
240 | |||
241 | return $this->{$method}($model); |
||
242 | } |
||
243 | |||
244 | if ($this->hasRelatedKey($key, $model)) { |
||
245 | return $this->relatedKey($key, $model); |
||
246 | } |
||
247 | |||
248 | return $model->getAttribute($key); |
||
249 | } |
||
250 | |||
251 | /** |
||
252 | * Determine if a get accessor exists for an attribute. |
||
253 | * |
||
254 | * @param string $key |
||
255 | * |
||
256 | * @return bool |
||
257 | */ |
||
258 | public function hasGetAccessor($key) |
||
262 | |||
263 | /** |
||
264 | * Determines if a key resolved a related Model. |
||
265 | * |
||
266 | * @param string $key |
||
267 | * @param mixed $model |
||
268 | * |
||
269 | * @return bool |
||
270 | */ |
||
271 | public function hasRelatedKey($key, $model = false) |
||
286 | |||
287 | /** |
||
288 | * Resolves a relation based on the key provided, |
||
289 | * either on the current model or a provided model instance. |
||
290 | * |
||
291 | * @param string $key |
||
292 | * @param mixed $model |
||
293 | * |
||
294 | * @return mixed |
||
295 | */ |
||
296 | public function relatedKey($key, $model = false) |
||
319 | |||
320 | /** |
||
321 | * Set a given attribute on the model. |
||
322 | * |
||
323 | * @param string $key |
||
324 | * @param mixed $value |
||
325 | */ |
||
326 | public function setAttribute($key, $value) |
||
336 | |||
337 | /** |
||
338 | * Determine if a set mutator exists for an attribute. |
||
339 | * |
||
340 | * @param string $key |
||
341 | * |
||
342 | * @return bool |
||
343 | */ |
||
344 | public function hasSetMutator($key) |
||
348 | |||
349 | /** |
||
350 | * Determine if a get mutator exists for an attribute. |
||
351 | * |
||
352 | * @param string $key |
||
353 | * |
||
354 | * @return bool |
||
355 | */ |
||
356 | public function hasGetMutator($key) |
||
360 | |||
361 | /** |
||
362 | * Returns an array of Attribute Fields ready for output. |
||
363 | * |
||
364 | * @param string $type |
||
365 | * |
||
366 | * @return array |
||
367 | */ |
||
368 | public function outputFields($type = 'view') |
||
372 | |||
373 | /** |
||
374 | * Gets the Managed Model Mapping. |
||
375 | * |
||
376 | * @return array |
||
377 | */ |
||
378 | public function getFields() |
||
379 | { |
||
380 | $this->setFields($this->fields); |
||
384 | |||
385 | /** |
||
386 | * Sets the Managed Model Mapping. |
||
387 | * |
||
388 | * @param array $fields |
||
389 | */ |
||
390 | public function setFields($fields = []) |
||
396 | |||
397 | /** |
||
398 | * Format the provided Attribute Fields into a more usable format. |
||
399 | * |
||
400 | * @return void |
||
401 | */ |
||
402 | protected function formatFields() |
||
412 | |||
413 | /** |
||
414 | * Determine if the Model Admin is sortable in it's list view. |
||
415 | * |
||
416 | * @return bool |
||
417 | */ |
||
418 | public function isSortable() |
||
422 | |||
423 | /** |
||
424 | * Determine if the Model Admin is sortable by a defined key / column. |
||
425 | * |
||
426 | * @param string $key |
||
427 | * |
||
428 | * @return bool |
||
429 | */ |
||
430 | public function isSortableBy($key) |
||
449 | |||
450 | /** |
||
451 | * Determine if the Model Admin has Viewing Capabilities. |
||
452 | * |
||
453 | * @return bool |
||
454 | */ |
||
455 | public function hasViewing() |
||
459 | |||
460 | /** |
||
461 | * Determine if the Model Admin has Creating Capabilities. |
||
462 | * |
||
463 | * @return bool |
||
464 | */ |
||
465 | public function hasCreating() |
||
469 | |||
470 | /** |
||
471 | * Determine if the Model Admin has Cloning Capabilities. |
||
472 | * |
||
473 | * @return bool |
||
474 | */ |
||
475 | public function hasCloning() |
||
479 | |||
480 | /** |
||
481 | * Determine if the Model Admin has Editting Capabilities. |
||
482 | * |
||
483 | * @return bool |
||
484 | */ |
||
485 | public function hasEditting() |
||
489 | |||
490 | /** |
||
491 | * Determine if the Model Admin has Deleting Capabilities. |
||
492 | * |
||
493 | * @return bool |
||
494 | */ |
||
495 | public function hasDeleting() |
||
499 | |||
500 | /** |
||
501 | * Determine if the Managed Model is using the SoftDeletes Trait. |
||
502 | * |
||
503 | * This is guarded by hasDeleting, since we shouldn't allow SoftDeleting |
||
504 | * without the deleting trait (even though it isn't really required). |
||
505 | * |
||
506 | * @return bool |
||
507 | */ |
||
508 | public function hasSoftDeleting() |
||
522 | |||
523 | /** |
||
524 | * Determine if the Model Admin has Validating Capabilities. |
||
525 | * |
||
526 | * @return bool |
||
527 | */ |
||
528 | public function hasValidating() |
||
532 | |||
533 | /** |
||
534 | * Determine if the Managed Model has a Trait and Contract |
||
535 | * |
||
536 | * @return bool |
||
537 | */ |
||
538 | public function hasTraitAndContract($trait = null, $contract = null) |
||
542 | |||
543 | /** |
||
544 | * Returns whether the current ModelAdmin has a given trait. |
||
545 | * |
||
546 | * @param string $trait |
||
547 | * |
||
548 | * @return boolean |
||
549 | */ |
||
550 | public function hasTrait($trait = null) |
||
558 | |||
559 | /** |
||
560 | * Returns whether the current ModelAdmin has a given contract. |
||
561 | * |
||
562 | * @param string $contract |
||
563 | * |
||
564 | * @return boolean |
||
565 | */ |
||
566 | public function hasContract($contract = null) |
||
574 | } |
||
575 |
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.