We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.
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 CrudTrait 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 CrudTrait, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
12 | trait CrudTrait |
||
13 | { |
||
14 | use HasIdentifiableAttribute; |
||
15 | |||
16 | public static function hasCrudTrait() |
||
20 | |||
21 | /* |
||
22 | |-------------------------------------------------------------------------- |
||
23 | | Methods for ENUM and SELECT crud fields. |
||
24 | |-------------------------------------------------------------------------- |
||
25 | */ |
||
26 | |||
27 | public static function getPossibleEnumValues($field_name) |
||
43 | |||
44 | public static function getEnumValuesAsAssociativeArray($field_name) |
||
57 | |||
58 | /** |
||
59 | * Register aditional types in doctrine schema manager for the current connection. |
||
60 | * |
||
61 | * @return DB |
||
62 | */ |
||
63 | public function getConnectionWithExtraTypeMappings() |
||
64 | { |
||
65 | $instance = new self; |
||
66 | |||
67 | $conn = DB::connection($instance->getConnectionName()); |
||
68 | |||
69 | // register the enum, json and jsonb column type, because Doctrine doesn't support it |
||
70 | $conn->getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string'); |
||
71 | $conn->getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('json', 'json_array'); |
||
72 | $conn->getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('jsonb', 'json_array'); |
||
73 | |||
74 | return $conn; |
||
75 | } |
||
76 | |||
77 | /** |
||
78 | * Get the model's table name, with the prefix added from the configuration file. |
||
79 | * |
||
80 | * @return string Table name with prefix |
||
81 | */ |
||
82 | public function getTableWithPrefix() |
||
83 | { |
||
84 | $prefix = Config::get('database.connections.'.$this->getConnectionName().'.prefix'); |
||
85 | $tableName = $this->getTable(); |
||
86 | |||
87 | return $prefix.$tableName; |
||
88 | } |
||
89 | |||
90 | /** |
||
91 | * Get the column type for a certain db column. |
||
92 | * |
||
93 | * @param string $columnName Name of the column in the db table. |
||
94 | * @return string Db column type. |
||
95 | */ |
||
96 | public function getColumnType($columnName) |
||
103 | |||
104 | /** |
||
105 | * Checks if the given column name is nullable. |
||
106 | * |
||
107 | * @param string $column_name The name of the db column. |
||
108 | * @return bool |
||
109 | */ |
||
110 | public static function isColumnNullable($column_name) |
||
134 | |||
135 | /* |
||
136 | |-------------------------------------------------------------------------- |
||
137 | | Methods for Fake Fields functionality (used in PageManager). |
||
138 | |-------------------------------------------------------------------------- |
||
139 | */ |
||
140 | |||
141 | /** |
||
142 | * Add fake fields as regular attributes, even though they are stored as JSON. |
||
143 | * |
||
144 | * @param array $columns - the database columns that contain the JSONs |
||
145 | */ |
||
146 | public function addFakes($columns = ['extras']) |
||
166 | |||
167 | /** |
||
168 | * Return the entity with fake fields as attributes. |
||
169 | * |
||
170 | * @param array $columns - the database columns that contain the JSONs |
||
171 | * |
||
172 | * @return Model |
||
173 | */ |
||
174 | public function withFakes($columns = []) |
||
188 | |||
189 | /** |
||
190 | * Determine if this fake column should be json_decoded. |
||
191 | * |
||
192 | * @param $column string fake column name |
||
193 | * |
||
194 | * @return bool |
||
195 | */ |
||
196 | public function shouldDecodeFake($column) |
||
200 | |||
201 | /** |
||
202 | * Determine if this fake column should get json_encoded or not. |
||
203 | * |
||
204 | * @param $column string fake column name |
||
205 | * |
||
206 | * @return bool |
||
207 | */ |
||
208 | public function shouldEncodeFake($column) |
||
212 | |||
213 | /* |
||
214 | |-------------------------------------------------------------------------- |
||
215 | | Methods for storing uploaded files (used in CRUD). |
||
216 | |-------------------------------------------------------------------------- |
||
217 | */ |
||
218 | |||
219 | /** |
||
220 | * Handle file upload and DB storage for a file: |
||
221 | * - on CREATE |
||
222 | * - stores the file at the destination path |
||
223 | * - generates a name |
||
224 | * - stores the full path in the DB; |
||
225 | * - on UPDATE |
||
226 | * - if the value is null, deletes the file and sets null in the DB |
||
227 | * - if the value is different, stores the different file and updates DB value. |
||
228 | * |
||
229 | * @param string $value Value for that column sent from the input. |
||
230 | * @param string $attribute_name Model attribute name (and column in the db). |
||
231 | * @param string $disk Filesystem disk used to store files. |
||
232 | * @param string $destination_path Path in disk where to store the files. |
||
233 | */ |
||
234 | public function uploadFileToDisk($value, $attribute_name, $disk, $destination_path) |
||
263 | |||
264 | /** |
||
265 | * Handle multiple file upload and DB storage: |
||
266 | * - if files are sent |
||
267 | * - stores the files at the destination path |
||
268 | * - generates random names |
||
269 | * - stores the full path in the DB, as JSON array; |
||
270 | * - if a hidden input is sent to clear one or more files |
||
271 | * - deletes the file |
||
272 | * - removes that file from the DB. |
||
273 | * |
||
274 | * @param string $value Value for that column sent from the input. |
||
275 | * @param string $attribute_name Model attribute name (and column in the db). |
||
276 | * @param string $disk Filesystem disk used to store files. |
||
277 | * @param string $destination_path Path in disk where to store the files. |
||
278 | */ |
||
279 | public function uploadMultipleFilesToDisk($value, $attribute_name, $disk, $destination_path) |
||
317 | |||
318 | /* |
||
319 | |-------------------------------------------------------------------------- |
||
320 | | Methods for working with translatable models. |
||
321 | |-------------------------------------------------------------------------- |
||
322 | */ |
||
323 | |||
324 | /** |
||
325 | * Get the attributes that were casted in the model. |
||
326 | * Used for translations because Spatie/Laravel-Translatable |
||
327 | * overwrites the getCasts() method. |
||
328 | * |
||
329 | * @return self |
||
330 | */ |
||
331 | public function getCastedAttributes() |
||
335 | |||
336 | /** |
||
337 | * Check if a model is translatable. |
||
338 | * All translation adaptors must have the translationEnabledForModel() method. |
||
339 | * |
||
340 | * @return bool |
||
341 | */ |
||
342 | public function translationEnabled() |
||
350 | } |
||
351 |
This check looks for methods that are used by a trait but not required by it.
To illustrate, let’s look at the following code example
The trait
Idable
provides a methodequalsId
that in turn relies on the methodgetId()
. If this method does not exist on a class mixing in this trait, the method will fail.Adding the
getId()
as an abstract method to the trait will make sure it is available.