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 |
||
12 | class Field extends \samsonframework\orm\Record |
||
13 | { |
||
14 | /** Store entity name */ |
||
15 | const ENTITY = __CLASS__; |
||
16 | |||
17 | /** Entity field names constants for using in code */ |
||
18 | const F_PRIMARY = 'FieldID'; |
||
19 | const F_IDENTIFIER = 'Name'; |
||
20 | const F_DESCRIPTION = 'Description'; |
||
21 | const F_TYPE = 'Type'; |
||
22 | const F_DELETION = 'Active'; |
||
23 | const F_DEFAULT = 'Value'; |
||
24 | const F_LOCALIZED = 'local'; |
||
25 | |||
26 | /** Additional field storing text value */ |
||
27 | const TYPE_TEXT = 0; |
||
28 | /** Additional field storing resource link */ |
||
29 | const TYPE_RESOURCE = 1; |
||
30 | /** Additional field storing date value */ |
||
31 | const TYPE_DATE = 3; |
||
32 | /** Additional field storing options value */ |
||
33 | const TYPE_OPTIONS = 4; |
||
34 | /** Additional field storing other entity identifier */ |
||
35 | const TYPE_ENTITYID = 6; |
||
36 | /** Additional field storing numeric value */ |
||
37 | const TYPE_NUMERIC = 7; |
||
38 | /** Additional field storing long text value */ |
||
39 | const TYPE_LONGTEXT = 8; |
||
40 | /** Additional field storing gallery value */ |
||
41 | const TYPE_GALLERY = 9; |
||
42 | /** Additional field storing datetime value */ |
||
43 | const TYPE_DATETIME = 10; |
||
44 | /** Additional field storing boolean value */ |
||
45 | const TYPE_BOOL = 11; |
||
46 | /** Additional field navigation identifier value */ |
||
47 | const TYPE_NAVIGATION = 12; |
||
48 | /** Additional field external picture identifier value */ |
||
49 | const TYPE_EXTERNALPICTURE = 13; |
||
50 | |||
51 | /** @var array Collection of field type to php variable type relations */ |
||
52 | protected static $phpTYPE = array( |
||
53 | self::TYPE_TEXT => 'string', |
||
54 | self::TYPE_RESOURCE => 'string', |
||
55 | self::TYPE_OPTIONS => 'string', |
||
56 | self::TYPE_LONGTEXT => 'string', |
||
57 | self::TYPE_BOOL => 'bool', |
||
58 | self::TYPE_ENTITYID => 'int', |
||
59 | self::TYPE_NUMERIC => 'int', |
||
60 | self::TYPE_DATETIME => 'int', |
||
61 | self::TYPE_DATE => 'int', |
||
62 | self::TYPE_GALLERY => 'int', |
||
63 | self::TYPE_NAVIGATION => 'int', |
||
64 | self::TYPE_EXTERNALPICTURE => 'string' |
||
65 | ); |
||
66 | |||
67 | /** |
||
68 | * Get additional field type in form of Field constant name |
||
69 | * by database additional field type identifier. |
||
70 | * |
||
71 | * @param integer $fieldType Additional field type identifier |
||
72 | * |
||
73 | * @return string Additional field type constant |
||
74 | * @throws AdditionalFieldTypeNotFound |
||
75 | */ |
||
76 | public static function phpType($fieldType) |
||
77 | { |
||
78 | $pointer = &static::$phpTYPE[$fieldType]; |
||
79 | if (isset($pointer)) { |
||
80 | return $pointer; |
||
81 | } else { |
||
82 | throw new AdditionalFieldTypeNotFound($fieldType); |
||
83 | } |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * Get internal field type in form of Field constant name |
||
88 | * by php originial type. |
||
89 | * |
||
90 | * @param string $fieldType PHP type |
||
91 | * |
||
92 | * @return string Additional field type constant |
||
93 | * @throws AdditionalFieldTypeNotFound |
||
94 | */ |
||
95 | public static function internalType($fieldType) |
||
96 | { |
||
97 | $types = array_flip(static::$phpTYPE); |
||
98 | if (array_key_exists($fieldType, $types)) { |
||
99 | return $types[$fieldType]; |
||
100 | } else { |
||
101 | throw new AdditionalFieldTypeNotFound($fieldType); |
||
102 | } |
||
103 | } |
||
104 | |||
105 | /** |
||
106 | * Get current entity instances collection by navigation identifier. |
||
107 | * |
||
108 | * @param QueryInterface $query Database query |
||
109 | * @param string $navigationID Navigation identifier |
||
110 | * @param self[]|array|null $return Variable where request result would be returned |
||
111 | * |
||
112 | * @return bool|self[] True if field entities has been found and $return is passed |
||
113 | * or self[] if only two parameters is passed. |
||
114 | */ |
||
115 | public static function byNavigationID(QueryInterface $query, $navigationID, &$return = array()) |
||
116 | { |
||
117 | /** @var array $fieldIDs Collection of entity identifiers filtered by additional field */ |
||
118 | $fieldIDs = null; |
||
119 | if (static::idsByNavigationID($query, $navigationID, $fieldIDs)) { |
||
120 | static::byIDs($query, $fieldIDs, $return); |
||
121 | } |
||
122 | |||
123 | // If only one argument is passed - return null, otherwise bool |
||
124 | return func_num_args() > 2 ? sizeof($return) : $return; |
||
125 | } |
||
126 | |||
127 | /** |
||
128 | * Get current entity identifiers collection by navigation identifier. |
||
129 | * |
||
130 | * @param QueryInterface $query Database query |
||
131 | * @param string $navigationID Navigation identifier |
||
132 | * @param array $return Variable where request result would be returned |
||
133 | * @param array $materialIDs Collection of material identifiers for filtering query |
||
134 | * |
||
135 | * @return bool|array True if field entities has been found and $return is passed |
||
136 | * or collection of identifiers if only two parameters is passed. |
||
137 | */ |
||
138 | public static function idsByNavigationID( |
||
139 | QueryInterface $query, |
||
140 | $navigationID, |
||
141 | &$return = array(), |
||
142 | $materialIDs = null |
||
143 | ) |
||
144 | { |
||
|
|||
145 | // Prepare query |
||
146 | $query->entity(CMS::FIELD_NAVIGATION_RELATION_ENTITY) |
||
147 | ->where('StructureID', $navigationID) |
||
148 | ->where('Active', 1); |
||
149 | |||
150 | // Add material identifier filter if passed |
||
151 | if (isset($materialIDs)) { |
||
152 | $query->where('MaterialID', $materialIDs); |
||
153 | } |
||
154 | |||
155 | // Perform database query and get only material identifiers collection |
||
156 | $return = $query->fields('FieldID'); |
||
157 | |||
158 | // If only one argument is passed - return null, otherwise bool |
||
159 | return func_num_args() > 2 ? sizeof($return) : $return; |
||
160 | } |
||
161 | |||
162 | /** |
||
163 | * Get current entity instances collection by their identifiers. |
||
164 | * Method can accept different query executors. |
||
165 | * |
||
166 | * @param QueryInterface $query Database query |
||
167 | * @param string|array $fieldIDs Field identifier or their colleciton |
||
168 | * @param self[]|array|null $return Variable where request result would be returned |
||
169 | * @param string $executor Method name for query execution |
||
170 | * |
||
171 | * @return bool|self[] True if material entities has been found and $return is passed |
||
172 | * or self[] if only two parameters is passed. |
||
173 | */ |
||
174 | View Code Duplication | public static function byIDs(QueryInterface $query, $fieldIDs, &$return = array(), $executor = 'exec') |
|
175 | { |
||
176 | $return = $query->entity(get_called_class()) |
||
177 | ->where('FieldID', $fieldIDs) |
||
178 | ->where('Active', 1) |
||
179 | ->orderBy('priority') |
||
180 | ->$executor(); |
||
181 | |||
182 | // If only one argument is passed - return null, otherwise bool |
||
183 | return func_num_args() > 2 ? sizeof($return) : $return; |
||
184 | } |
||
185 | |||
186 | /** |
||
187 | * Find additional field database record by Name. |
||
188 | * This is generic method that should be used in nested classes to find its |
||
189 | * records by some its primary key value. |
||
190 | * |
||
191 | * @param QueryInterface $query Query object instance |
||
192 | * @param string $name Additional field name |
||
193 | * @param self $return Variable to return found database record |
||
194 | * |
||
195 | * @return bool|null|self Field instance or null if 3rd parameter not passed |
||
196 | */ |
||
197 | public static function byName(QueryInterface $query, $name, self & $return = null) |
||
198 | { |
||
199 | // Get field record by name column |
||
200 | $return = static::oneByColumn($query, 'Name', $name); |
||
201 | |||
202 | // If only one argument is passed - return null, otherwise bool |
||
203 | return func_num_args() > 1 ? $return == null : $return; |
||
204 | } |
||
205 | |||
206 | /** |
||
207 | * Find additional field database record by Name or ID. |
||
208 | * This is generic method that should be used in nested classes to find its |
||
209 | * records by some its primary key value. |
||
210 | * |
||
211 | * @param QueryInterface $query Query object instance |
||
212 | * @param string $nameOrID Additional field name or identifier |
||
213 | * @param self $return Variable to return found database record |
||
214 | * |
||
215 | *@return bool|null|self Field instance or null if 3rd parameter not passed |
||
216 | */ |
||
217 | public static function byNameOrID(QueryInterface $query, $nameOrID, self & $return = null) |
||
218 | { |
||
219 | // Create id or URL condition |
||
220 | $idOrUrl = new Condition('OR'); |
||
221 | $idOrUrl->add('FieldID', $nameOrID)->add('Name', $nameOrID); |
||
222 | |||
223 | // Perform query |
||
224 | $return = $query->entity(get_called_class())->whereCondition($idOrUrl)->first(); |
||
225 | |||
226 | // If only one argument is passed - return null, otherwise bool |
||
227 | return func_num_args() > 1 ? $return == null : $return; |
||
228 | } |
||
229 | |||
230 | /** |
||
231 | * If this field has defined key=>value set. |
||
232 | * |
||
233 | * @return array|mixed Grouped collection of field key => value possible values or value for key passed. |
||
234 | */ |
||
235 | public function options($key = null) |
||
249 | |||
250 | /** @return string Get additional field value field name depending on its type */ |
||
251 | public function valueFieldName() |
||
255 | |||
256 | /** @return string Get additional field value field name depending on its type */ |
||
257 | public static function valueColumn($type) |
||
258 | { |
||
259 | switch ($type) { |
||
260 | case self::TYPE_DATETIME: |
||
261 | case self::TYPE_DATE: |
||
262 | case self::TYPE_NUMERIC: |
||
263 | return MaterialField::F_NUMERIC; |
||
264 | case self::TYPE_ENTITYID: |
||
265 | case self::TYPE_NAVIGATION: |
||
266 | return MaterialField::F_KEY; |
||
267 | default: |
||
268 | return MaterialField::F_VALUE; |
||
269 | } |
||
270 | } |
||
271 | |||
272 | /** @return bool True if field is localized */ |
||
273 | public function localized() |
||
277 | } |
||
278 |