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 EntityProperty 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 EntityProperty, and based on these observations, apply Extract Interface, too.
| 1 | <?php  | 
            ||
| 19 | class EntityProperty  | 
            ||
| 20 | { | 
            ||
| 21 | |||
| 22 | const STRING = 'string';  | 
            ||
| 23 | const INTEGER = 'integer';  | 
            ||
| 24 | const FLOAT = 'float';  | 
            ||
| 25 | const DOUBLE = 'double';  | 
            ||
| 26 | const BOOL = 'bool';  | 
            ||
| 27 | |||
| 28 | const DATE = 'date';  | 
            ||
| 29 | const DATETIME = 'datetime';  | 
            ||
| 30 | |||
| 31 | const VARBINARY = 'varbinary';  | 
            ||
| 32 | |||
| 33 | const UUID = 'uuid';  | 
            ||
| 34 | |||
| 35 | const ENUM = 'enum';  | 
            ||
| 36 | |||
| 37 | /**  | 
            ||
| 38 | * @var string Entity property type  | 
            ||
| 39 | */  | 
            ||
| 40 | protected $type;  | 
            ||
| 41 | |||
| 42 | /**  | 
            ||
| 43 | * @var int Entity property max length  | 
            ||
| 44 | */  | 
            ||
| 45 | protected $length;  | 
            ||
| 46 | |||
| 47 | /**  | 
            ||
| 48 | * @var array Allowed values  | 
            ||
| 49 | */  | 
            ||
| 50 | protected $values;  | 
            ||
| 51 | |||
| 52 | /**  | 
            ||
| 53 | * @param string|array $type  | 
            ||
| 54 | */  | 
            ||
| 55 | 13 | public function __construct($type)  | 
            |
| 84 | |||
| 85 | /**  | 
            ||
| 86 | * Set entity property type  | 
            ||
| 87 | *  | 
            ||
| 88 | * @param string $type  | 
            ||
| 89 | *  | 
            ||
| 90 | * @throws EntityPropertyTypeNonexistentException  | 
            ||
| 91 | */  | 
            ||
| 92 | 13 | protected function setType(string $type)  | 
            |
| 100 | |||
| 101 | /**  | 
            ||
| 102 | * Validate value for entity property  | 
            ||
| 103 | *  | 
            ||
| 104 | * @param mixed $value Entity property value  | 
            ||
| 105 | *  | 
            ||
| 106 | * @return bool TRUE if valid, otherwise FALSE  | 
            ||
| 107 | *  | 
            ||
| 108 | * @throws EntityPropertyTypeNotImplementedException If entity property type is not implemented  | 
            ||
| 109 | * @throws EntityPropertyValueExceedingLengthException If value is exceeding allowed length for entity property  | 
            ||
| 110 | * @throws InvalidENUMValueForEntityPropertyException If ENUM value is invalid for entity property  | 
            ||
| 111 | * @throws InvalidUUIDValueForEntityPropertyException If UUID value is invalid for entity property  | 
            ||
| 112 | * @throws InvalidValueTypeForEntityPropertyException If value is invalid for entity property  | 
            ||
| 113 | */  | 
            ||
| 114 | public function validateValue($value): bool  | 
            ||
| 213 | |||
| 214 | /**  | 
            ||
| 215 | * Format value according to entity property type  | 
            ||
| 216 | *  | 
            ||
| 217 | * @param mixed $value Value  | 
            ||
| 218 | *  | 
            ||
| 219 | * @return mixed Value  | 
            ||
| 220 | *  | 
            ||
| 221 | * @throws EntityPropertyTypeNotImplementedException If entity property type is not implemented  | 
            ||
| 222 | */  | 
            ||
| 223 | public function formatValueForEntity($value)  | 
            ||
| 273 | |||
| 274 | /**  | 
            ||
| 275 | * Format value for insertion into the database  | 
            ||
| 276 | *  | 
            ||
| 277 | * @param mixed $value Value  | 
            ||
| 278 | *  | 
            ||
| 279 | * @return mixed Value  | 
            ||
| 280 | */  | 
            ||
| 281 | public function formatValueForDatabase($value)  | 
            ||
| 301 | }  | 
            ||
| 302 | 
This check looks for accesses to local static members using the fully qualified name instead of
self::.While this is perfectly valid, the fully qualified name of
Certificate::TRIPLEDES_CBCcould just as well be replaced byself::TRIPLEDES_CBC. Referencing local members withself::assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.