Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like EntryModel 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 EntryModel, and based on these observations, apply Extract Interface, too.
1 | <?php namespace Anomaly\Streams\Platform\Entry; |
||
26 | class EntryModel extends EloquentModel implements EntryInterface, PresentableInterface |
||
27 | { |
||
28 | |||
29 | use Searchable; |
||
30 | |||
31 | /** |
||
32 | * The foreign key for translations. |
||
33 | * |
||
34 | * @var string |
||
35 | */ |
||
36 | protected $translationForeignKey = 'entry_id'; |
||
37 | |||
38 | /** |
||
39 | * By default nothing is searchable. |
||
40 | * |
||
41 | * @var boolean |
||
42 | */ |
||
43 | protected $searchable = false; |
||
44 | |||
45 | /** |
||
46 | * The validation rules. These are |
||
47 | * overridden on the compiled models. |
||
48 | * |
||
49 | * @var array |
||
50 | */ |
||
51 | protected $rules = []; |
||
52 | |||
53 | /** |
||
54 | * The field slugs. These are |
||
55 | * overridden on compiled models. |
||
56 | * |
||
57 | * @var array |
||
58 | */ |
||
59 | protected $fields = []; |
||
60 | |||
61 | /** |
||
62 | * The entry relationships by field slug. |
||
63 | * |
||
64 | * @var array |
||
65 | */ |
||
66 | protected $relationships = []; |
||
67 | |||
68 | /** |
||
69 | * The compiled stream data. |
||
70 | * |
||
71 | * @var array|StreamInterface |
||
72 | */ |
||
73 | protected $stream = []; |
||
74 | |||
75 | /** |
||
76 | * Boot the model |
||
77 | */ |
||
78 | protected static function boot() |
||
101 | |||
102 | /** |
||
103 | * Sort the query. |
||
104 | * |
||
105 | * @param Builder $builder |
||
106 | * @param string $direction |
||
107 | */ |
||
108 | public function scopeSorted(Builder $builder, $direction = 'asc') |
||
112 | |||
113 | /** |
||
114 | * Get the ID. |
||
115 | * |
||
116 | * @return mixed |
||
117 | */ |
||
118 | public function getId() |
||
122 | |||
123 | /** |
||
124 | * Get the entry ID. |
||
125 | * |
||
126 | * @return mixed |
||
127 | */ |
||
128 | public function getEntryId() |
||
132 | |||
133 | /** |
||
134 | * Get the entry title. |
||
135 | * |
||
136 | * @return mixed |
||
137 | */ |
||
138 | public function getEntryTitle() |
||
142 | |||
143 | /** |
||
144 | * Get the model's bound name. |
||
145 | * |
||
146 | * @return string |
||
147 | */ |
||
148 | public function getBoundModelName() |
||
152 | |||
153 | /** |
||
154 | * Get the model's bound namespace. |
||
155 | * |
||
156 | * @return string |
||
157 | */ |
||
158 | public function getBoundModelNamespace() |
||
166 | |||
167 | /** |
||
168 | * Get the sort order. |
||
169 | * |
||
170 | * @return int |
||
171 | */ |
||
172 | public function getSortOrder() |
||
176 | |||
177 | /** |
||
178 | * Get the entries title. |
||
179 | * |
||
180 | * @return mixed |
||
181 | */ |
||
182 | public function getTitle() |
||
186 | |||
187 | /** |
||
188 | * Get a field value. |
||
189 | * |
||
190 | * @param $fieldSlug |
||
191 | * @param null $locale |
||
192 | * @return mixed |
||
193 | */ |
||
194 | public function getFieldValue($fieldSlug, $locale = null) |
||
232 | |||
233 | /** |
||
234 | * Set a field value. |
||
235 | * |
||
236 | * @param $fieldSlug |
||
237 | * @param $value |
||
238 | * @param null $locale |
||
239 | * @return $this |
||
240 | */ |
||
241 | public function setFieldValue($fieldSlug, $value, $locale = null) |
||
268 | |||
269 | /** |
||
270 | * Get an entry field. |
||
271 | * |
||
272 | * @param $slug |
||
273 | * @return FieldInterface|null |
||
274 | */ |
||
275 | public function getField($slug) |
||
285 | |||
286 | /** |
||
287 | * Return whether an entry has |
||
288 | * a field with a given slug. |
||
289 | * |
||
290 | * @param $slug |
||
291 | * @return bool |
||
292 | */ |
||
293 | public function hasField($slug) |
||
297 | |||
298 | /** |
||
299 | * Get the field type from a field slug. |
||
300 | * |
||
301 | * @param $fieldSlug |
||
302 | * @return null|FieldType |
||
303 | */ |
||
304 | View Code Duplication | public function getFieldType($fieldSlug) |
|
331 | |||
332 | /** |
||
333 | * Get the field type query. |
||
334 | * |
||
335 | * @param $fieldSlug |
||
336 | * @return FieldTypeQuery |
||
337 | */ |
||
338 | public function getFieldTypeQuery($fieldSlug) |
||
346 | |||
347 | /** |
||
348 | * Get the field type presenter. |
||
349 | * |
||
350 | * @param $fieldSlug |
||
351 | * @return FieldTypePresenter |
||
352 | */ |
||
353 | public function getFieldTypePresenter($fieldSlug) |
||
361 | |||
362 | /** |
||
363 | * Set a given attribute on the model. |
||
364 | * Override the behavior here to give |
||
365 | * the field types a chance to modify things. |
||
366 | * |
||
367 | * @param string $key |
||
368 | * @param mixed $value |
||
369 | * @return $this |
||
370 | */ |
||
371 | public function setAttribute($key, $value) |
||
381 | |||
382 | /** |
||
383 | * Get a given attribute on the model. |
||
384 | * Override the behavior here to give |
||
385 | * the field types a chance to modify things. |
||
386 | * |
||
387 | * @param string $key |
||
388 | * @return mixed |
||
389 | */ |
||
390 | public function getAttribute($key) |
||
406 | |||
407 | /** |
||
408 | * Get a raw unmodified attribute. |
||
409 | * |
||
410 | * @param $key |
||
411 | * @param bool $process |
||
412 | * @return mixed|null |
||
413 | */ |
||
414 | public function getRawAttribute($key, $process = true) |
||
422 | |||
423 | /** |
||
424 | * Set a raw unmodified attribute. |
||
425 | * |
||
426 | * @param $key |
||
427 | * @param $value |
||
428 | * @return $this |
||
429 | */ |
||
430 | public function setRawAttribute($key, $value) |
||
436 | |||
437 | /** |
||
438 | * Get the stream. |
||
439 | * |
||
440 | * @return StreamInterface |
||
441 | */ |
||
442 | public function getStream() |
||
446 | |||
447 | /** |
||
448 | * Get the stream namespace. |
||
449 | * |
||
450 | * @return string |
||
451 | */ |
||
452 | public function getStreamNamespace() |
||
458 | |||
459 | /** |
||
460 | * Get the stream slug. |
||
461 | * |
||
462 | * @return string |
||
463 | */ |
||
464 | public function getStreamSlug() |
||
470 | |||
471 | /** |
||
472 | * Get the entry's stream name. |
||
473 | * |
||
474 | * @return string |
||
475 | */ |
||
476 | public function getStreamName() |
||
482 | |||
483 | /** |
||
484 | * Get the stream prefix. |
||
485 | * |
||
486 | * @return string |
||
487 | */ |
||
488 | public function getStreamPrefix() |
||
494 | |||
495 | /** |
||
496 | * Get the table name. |
||
497 | * |
||
498 | * @return string |
||
499 | */ |
||
500 | public function getTableName() |
||
506 | |||
507 | /** |
||
508 | * Get the translations table name. |
||
509 | * |
||
510 | * @return string |
||
511 | */ |
||
512 | public function getTranslationsTableName() |
||
518 | |||
519 | /** |
||
520 | * Get all assignments. |
||
521 | * |
||
522 | * @return AssignmentCollection |
||
523 | */ |
||
524 | public function getAssignments() |
||
530 | |||
531 | /** |
||
532 | * Get the field slugs for assigned fields. |
||
533 | * |
||
534 | * @param null $prefix |
||
535 | * @return array |
||
536 | */ |
||
537 | public function getAssignmentFieldSlugs($prefix = null) |
||
543 | |||
544 | /** |
||
545 | * Get all assignments of the |
||
546 | * provided field type namespace. |
||
547 | * |
||
548 | * @param $fieldType |
||
549 | * @return AssignmentCollection |
||
550 | */ |
||
551 | public function getAssignmentsByFieldType($fieldType) |
||
557 | |||
558 | /** |
||
559 | * Get an assignment by field slug. |
||
560 | * |
||
561 | * @param $fieldSlug |
||
562 | * @return AssignmentInterface |
||
563 | */ |
||
564 | public function getAssignment($fieldSlug) |
||
570 | |||
571 | /** |
||
572 | * Return translated assignments. |
||
573 | * |
||
574 | * @return AssignmentCollection |
||
575 | */ |
||
576 | public function getTranslatableAssignments() |
||
583 | |||
584 | /** |
||
585 | * Return relation assignments. |
||
586 | * |
||
587 | * @return AssignmentCollection |
||
588 | */ |
||
589 | public function getRelationshipAssignments() |
||
596 | |||
597 | /** |
||
598 | * Get the translatable flag. |
||
599 | * |
||
600 | * @return bool |
||
601 | */ |
||
602 | public function isTranslatable() |
||
608 | |||
609 | /** |
||
610 | * Return whether the entry is trashable or not. |
||
611 | * |
||
612 | * @return bool |
||
613 | */ |
||
614 | public function isTrashable() |
||
620 | |||
621 | /** |
||
622 | * Return the last modified datetime. |
||
623 | * |
||
624 | * @return Carbon |
||
625 | */ |
||
626 | public function lastModified() |
||
630 | |||
631 | /** |
||
632 | * Return the related creator. |
||
633 | * |
||
634 | * @return Authenticatable |
||
635 | */ |
||
636 | public function getCreatedBy() |
||
640 | |||
641 | /** |
||
642 | * Return the creator relation. |
||
643 | * |
||
644 | * @return \Illuminate\Database\Eloquent\Relations\BelongsTo |
||
645 | */ |
||
646 | public function createdBy() |
||
650 | |||
651 | /** |
||
652 | * Return the related updater. |
||
653 | * |
||
654 | * @return Authenticatable |
||
655 | */ |
||
656 | public function getUpdatedBy() |
||
660 | |||
661 | /** |
||
662 | * Return the updater relation. |
||
663 | * |
||
664 | * @return \Illuminate\Database\Eloquent\Relations\BelongsTo |
||
665 | */ |
||
666 | public function updatedBy() |
||
670 | |||
671 | /** |
||
672 | * Return whether the title column is |
||
673 | * translatable or not. |
||
674 | * |
||
675 | * @return bool |
||
676 | */ |
||
677 | public function titleColumnIsTranslatable() |
||
681 | |||
682 | /** |
||
683 | * Return whether or not the assignment for |
||
684 | * the given field slug is translatable. |
||
685 | * |
||
686 | * @param $fieldSlug |
||
687 | * @return bool |
||
688 | */ |
||
689 | public function assignmentIsTranslatable($fieldSlug) |
||
693 | |||
694 | /** |
||
695 | * Return whether or not the assignment for |
||
696 | * the given field slug is a relationship. |
||
697 | * |
||
698 | * @param $fieldSlug |
||
699 | * @return bool |
||
700 | */ |
||
701 | public function assignmentIsRelationship($fieldSlug) |
||
707 | |||
708 | /** |
||
709 | * Fire field type events. |
||
710 | * |
||
711 | * @param $trigger |
||
712 | * @param array $payload |
||
713 | */ |
||
714 | public function fireFieldTypeEvents($trigger, $payload = []) |
||
733 | |||
734 | /** |
||
735 | * Return the related stream. |
||
736 | * |
||
737 | * @return StreamInterface|array |
||
738 | */ |
||
739 | public function stream() |
||
747 | |||
748 | /** |
||
749 | * @param array $items |
||
750 | * @return EntryCollection |
||
751 | */ |
||
752 | View Code Duplication | public function newCollection(array $items = []) |
|
762 | |||
763 | /** |
||
764 | * Return the entry presenter. |
||
765 | * |
||
766 | * This is against standards but required |
||
767 | * by the presentable interface. |
||
768 | * |
||
769 | * @return EntryPresenter |
||
770 | */ |
||
771 | View Code Duplication | public function getPresenter() |
|
781 | |||
782 | /** |
||
783 | * Return a new presenter instance. |
||
784 | * |
||
785 | * @return EntryPresenter |
||
786 | */ |
||
787 | public function newPresenter() |
||
791 | |||
792 | /** |
||
793 | * Return a model route. |
||
794 | * |
||
795 | * @return string |
||
796 | */ |
||
797 | public function route($route, array $parameters = []) |
||
803 | |||
804 | /** |
||
805 | * Return a new router instance. |
||
806 | * |
||
807 | * @return EntryRouter |
||
808 | */ |
||
809 | public function newRouter() |
||
813 | |||
814 | /** |
||
815 | * Get the router. |
||
816 | * |
||
817 | * @return EntryRouter |
||
818 | */ |
||
819 | public function getRouter() |
||
827 | |||
828 | /** |
||
829 | * Get the router name. |
||
830 | * |
||
831 | * @return string |
||
832 | */ |
||
833 | public function getRouterName() |
||
839 | |||
840 | /** |
||
841 | * Create a new Eloquent query builder for the model. |
||
842 | * |
||
843 | * @param \Illuminate\Database\Query\Builder $query |
||
844 | * @return \Illuminate\Database\Eloquent\Builder|static |
||
845 | */ |
||
846 | public function newEloquentBuilder($query) |
||
850 | |||
851 | /** |
||
852 | * Get the criteria class. |
||
853 | * |
||
854 | * @return string |
||
855 | */ |
||
856 | public function getCriteriaName() |
||
862 | |||
863 | /** |
||
864 | * Return whether the model is searchable or not. |
||
865 | * |
||
866 | * @return boolean |
||
867 | */ |
||
868 | public function isSearchable() |
||
872 | |||
873 | /** |
||
874 | * Return a searchable array. |
||
875 | * |
||
876 | * @return array |
||
877 | */ |
||
878 | public function toSearchableArray() |
||
891 | |||
892 | /** |
||
893 | * Override the __get method. |
||
894 | * |
||
895 | * @param string $key |
||
896 | * @return EntryPresenter|mixed |
||
897 | */ |
||
898 | public function __get($key) |
||
906 | } |
||
907 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.