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 |
||
| 36 | class DefaultEntityHydrator implements EntityHydrator |
||
| 37 | { |
||
| 38 | /** |
||
| 39 | * @var \Doctrine\ORM\EntityManager |
||
| 40 | */ |
||
| 41 | private $em; |
||
| 42 | |||
| 43 | /** |
||
| 44 | * @var \Doctrine\ORM\UnitOfWork |
||
| 45 | */ |
||
| 46 | private $uow; |
||
| 47 | |||
| 48 | /** |
||
| 49 | * The IdentifierFlattener used for manipulating identifiers |
||
| 50 | * |
||
| 51 | * @var \Doctrine\ORM\Utility\IdentifierFlattener |
||
| 52 | */ |
||
| 53 | private $identifierFlattener; |
||
| 54 | |||
| 55 | /** |
||
| 56 | * @var array |
||
| 57 | */ |
||
| 58 | private static $hints = [Query::HINT_CACHE_ENABLED => true]; |
||
| 59 | |||
| 60 | /** |
||
| 61 | * @param \Doctrine\ORM\EntityManagerInterface $em The entity manager. |
||
| 62 | */ |
||
| 63 | 213 | public function __construct(EntityManagerInterface $em) |
|
| 69 | |||
| 70 | /** |
||
| 71 | * {@inheritdoc} |
||
| 72 | */ |
||
| 73 | 116 | public function buildCacheEntry(ClassMetadata $metadata, EntityCacheKey $key, $entity) |
|
| 74 | { |
||
| 75 | 116 | $data = $this->uow->getOriginalEntityData($entity); |
|
| 76 | 116 | $data = array_merge($data, $metadata->getIdentifierValues($entity)); // why update has no identifier values ? |
|
| 77 | |||
| 78 | 116 | foreach ($metadata->associationMappings as $name => $assoc) { |
|
| 79 | 70 | if ( ! isset($data[$name])) { |
|
| 80 | 26 | continue; |
|
| 81 | } |
||
| 82 | |||
| 83 | 69 | if ( ! ($assoc['type'] & ClassMetadata::TO_ONE)) { |
|
| 84 | 59 | unset($data[$name]); |
|
| 85 | |||
| 86 | 59 | continue; |
|
| 87 | } |
||
| 88 | |||
| 89 | 68 | if ( ! isset($assoc['cache'])) { |
|
| 90 | 5 | $targetClassMetadata = $this->em->getClassMetadata($assoc['targetEntity']); |
|
| 91 | 5 | $owningAssociation = ( ! $assoc['isOwningSide']) |
|
| 92 | 1 | ? $targetClassMetadata->associationMappings[$assoc['mappedBy']] |
|
| 93 | 5 | : $assoc; |
|
| 94 | 5 | $associationIds = $this->identifierFlattener->flattenIdentifier( |
|
| 95 | 5 | $targetClassMetadata, |
|
| 96 | 5 | $targetClassMetadata->getIdentifierValues($data[$name]) |
|
| 97 | ); |
||
| 98 | |||
| 99 | 5 | unset($data[$name]); |
|
| 100 | |||
| 101 | 5 | foreach ($associationIds as $fieldName => $fieldValue) { |
|
| 102 | 5 | if (isset($targetClassMetadata->fieldMappings[$fieldName])) { |
|
| 103 | 5 | $fieldMapping = $targetClassMetadata->fieldMappings[$fieldName]; |
|
| 104 | |||
| 105 | 5 | $data[$owningAssociation['targetToSourceKeyColumns'][$fieldMapping['columnName']]] = $fieldValue; |
|
| 106 | |||
| 107 | 5 | continue; |
|
| 108 | } |
||
| 109 | |||
| 110 | 1 | $targetAssoc = $targetClassMetadata->associationMappings[$fieldName]; |
|
| 111 | |||
| 112 | 1 | foreach($assoc['targetToSourceKeyColumns'] as $referencedColumn => $localColumn) { |
|
| 113 | 1 | if (isset($targetAssoc['sourceToTargetKeyColumns'][$referencedColumn])) { |
|
| 114 | 1 | $data[$localColumn] = $fieldValue; |
|
| 115 | } |
||
| 116 | } |
||
| 117 | } |
||
| 118 | |||
| 119 | 5 | continue; |
|
| 120 | } |
||
| 121 | |||
| 122 | 64 | if ( ! isset($assoc['id'])) { |
|
| 123 | 64 | $targetClass = ClassUtils::getClass($data[$name]); |
|
| 124 | 64 | $targetId = $this->uow->getEntityIdentifier($data[$name]); |
|
| 125 | 64 | $data[$name] = new AssociationCacheEntry($targetClass, $targetId); |
|
| 126 | |||
| 127 | 64 | continue; |
|
| 128 | } |
||
| 129 | |||
| 130 | // handle association identifier |
||
| 131 | 4 | $targetId = is_object($data[$name]) && $this->uow->isInIdentityMap($data[$name]) |
|
| 132 | 4 | ? $this->uow->getEntityIdentifier($data[$name]) |
|
| 133 | 4 | : $data[$name]; |
|
| 134 | |||
| 135 | // @TODO - fix it ! |
||
| 136 | // handle UnitOfWork#createEntity hash generation |
||
| 137 | 4 | if ( ! is_array($targetId)) { |
|
| 138 | $data[reset($assoc['joinColumnFieldNames'])] = $targetId; |
||
| 139 | |||
| 140 | $targetEntity = $this->em->getClassMetadata($assoc['targetEntity']); |
||
| 141 | $targetId = [$targetEntity->identifier[0] => $targetId]; |
||
| 142 | } |
||
| 143 | |||
| 144 | 4 | $data[$name] = new AssociationCacheEntry($assoc['targetEntity'], $targetId); |
|
| 145 | } |
||
| 146 | |||
| 147 | 116 | return new EntityCacheEntry($metadata->name, $data); |
|
| 148 | } |
||
| 149 | |||
| 150 | /** |
||
| 151 | * {@inheritdoc} |
||
| 152 | */ |
||
| 153 | 41 | public function loadCacheEntry(ClassMetadata $metadata, EntityCacheKey $key, EntityCacheEntry $entry, $entity = null) |
|
| 201 | } |
||
| 202 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.
Either this assignment is in error or an instanceof check should be added for that assignment.