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:
1 | <?php |
||
18 | class BelongsTo extends HasOne |
||
19 | { |
||
20 | /** |
||
21 | * Relation type, required to fetch record class from relation definition. |
||
22 | */ |
||
23 | const RELATION_TYPE = RecordEntity::BELONGS_TO; |
||
24 | |||
25 | /** |
||
26 | * {@inheritdoc} |
||
27 | */ |
||
28 | public function isLoaded() |
||
29 | { |
||
30 | $this->fromCache(); |
||
31 | |||
32 | if (empty($this->parent->getField($this->definition[RecordEntity::INNER_KEY], false))) { |
||
33 | return true; |
||
34 | } |
||
35 | |||
36 | return $this->loaded; |
||
37 | } |
||
38 | |||
39 | /** |
||
40 | * {@inheritdoc} |
||
41 | */ |
||
42 | public function getRelated() |
||
43 | { |
||
44 | $this->fromCache(); |
||
45 | |||
46 | return parent::getRelated(); |
||
47 | } |
||
48 | |||
49 | /** |
||
50 | * {@inheritdoc} |
||
51 | * |
||
52 | * Parent record MUST be saved in order to preserve parent association. |
||
53 | */ |
||
54 | public function associate(EntityInterface $related = null) |
||
55 | { |
||
56 | if ($related === null) { |
||
57 | $this->deassociate(); |
||
58 | |||
59 | return; |
||
60 | } |
||
61 | |||
62 | /** |
||
63 | * @var RecordEntity $related |
||
64 | */ |
||
65 | if (!$related->isLoaded()) { |
||
66 | throw new RelationException( |
||
67 | "Unable to set 'belongs to' parent, parent has be fetched from database." |
||
68 | ); |
||
69 | } |
||
70 | |||
71 | parent::associate($related); |
||
72 | |||
73 | //Key in parent record |
||
74 | $outerKey = $this->definition[RecordEntity::OUTER_KEY]; |
||
75 | |||
76 | //Key in child record |
||
77 | $innerKey = $this->definition[RecordEntity::INNER_KEY]; |
||
78 | |||
79 | View Code Duplication | if ($this->parent->getField($innerKey, false) != $related->getField($outerKey, false)) { |
|
|
|||
80 | //We are going to set relation keys right on assertion |
||
81 | $this->parent->setField($innerKey, $related->getField($outerKey, false)); |
||
82 | } |
||
83 | } |
||
84 | |||
85 | /** |
||
86 | * {@inheritdoc} |
||
87 | */ |
||
88 | protected function mountRelation(EntityInterface $record) |
||
89 | { |
||
90 | //Nothing to do, children can not update parent relation |
||
91 | return $record; |
||
92 | } |
||
93 | |||
94 | /** |
||
95 | * {@inheritdoc} |
||
96 | * |
||
97 | * @throws RelationException |
||
98 | */ |
||
99 | protected function createSelector() |
||
100 | { |
||
101 | if (empty($this->parent->getField($this->definition[RecordEntity::INNER_KEY], false))) { |
||
102 | throw new RelationException( |
||
103 | "Belongs-to selector can not be constructed when inner key (" |
||
104 | . $this->definition[RecordEntity::INNER_KEY] |
||
105 | . ") is null." |
||
106 | ); |
||
107 | } |
||
108 | |||
109 | return parent::createSelector(); |
||
110 | } |
||
111 | |||
112 | /** |
||
113 | * {@inheritdoc} |
||
114 | * |
||
115 | * Belongs-to can not automatically create parent. |
||
116 | */ |
||
117 | protected function emptyRecord() |
||
121 | |||
122 | /** |
||
123 | * De associate related record. |
||
124 | */ |
||
125 | protected function deassociate() |
||
126 | { |
||
140 | |||
141 | /** |
||
142 | * Loadable when parent is loaded as well. |
||
143 | * |
||
144 | * @return bool |
||
145 | */ |
||
146 | protected function isLoadable() |
||
150 | |||
151 | /** |
||
152 | * Try to fetch outer model using entity cache. |
||
153 | */ |
||
154 | private function fromCache() |
||
178 | } |
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.