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 |
||
15 | abstract class AbstractElasticaToModelTransformer extends BaseTransformer |
||
16 | { |
||
17 | /** |
||
18 | * Manager registry. |
||
19 | * |
||
20 | * @var ManagerRegistry |
||
21 | */ |
||
22 | protected $registry = null; |
||
23 | |||
24 | /** |
||
25 | * Class of the model to map to the elastica documents. |
||
26 | * |
||
27 | * @var string |
||
28 | */ |
||
29 | protected $objectClass = null; |
||
30 | |||
31 | /** |
||
32 | * Optional parameters. |
||
33 | * |
||
34 | * @var array |
||
35 | */ |
||
36 | protected $options = array( |
||
37 | 'hints' => array(), |
||
38 | 'hydrate' => true, |
||
39 | 'identifier' => 'id', |
||
40 | 'ignore_missing' => false, |
||
41 | 'query_builder_method' => 'createQueryBuilder', |
||
42 | ); |
||
43 | |||
44 | /** |
||
45 | * Instantiates a new Mapper. |
||
46 | * |
||
47 | * @param ManagerRegistry $registry |
||
48 | * @param string $objectClass |
||
49 | * @param array $options |
||
50 | */ |
||
51 | 12 | public function __construct(ManagerRegistry $registry, $objectClass, array $options = array()) |
|
57 | |||
58 | /** |
||
59 | * Returns the object class that is used for conversion. |
||
60 | * |
||
61 | * @return string |
||
62 | */ |
||
63 | 1 | public function getObjectClass() |
|
64 | { |
||
65 | 1 | return $this->objectClass; |
|
66 | } |
||
67 | |||
68 | /** |
||
69 | * Transforms an array of elastica objects into an array of |
||
70 | * model objects fetched from the doctrine repository. |
||
71 | * |
||
72 | * @param array $elasticaObjects of elastica objects |
||
73 | * |
||
74 | * @throws \RuntimeException |
||
75 | * |
||
76 | * @return array |
||
77 | **/ |
||
78 | 7 | public function transform(array $elasticaObjects) |
|
79 | { |
||
80 | 7 | $ids = $highlights = array(); |
|
81 | 7 | foreach ($elasticaObjects as $elasticaObject) { |
|
82 | 7 | $ids[] = $elasticaObject->getId(); |
|
83 | 7 | $highlights[$elasticaObject->getId()] = $elasticaObject->getHighlights(); |
|
84 | } |
||
85 | |||
86 | 7 | $objects = $this->findByIdentifiers($ids, $this->options['hydrate']); |
|
87 | 7 | $objectsCnt = count($objects); |
|
88 | 7 | $elasticaObjectsCnt = count($elasticaObjects); |
|
89 | 7 | if (!$this->options['ignore_missing'] && $objectsCnt < $elasticaObjectsCnt) { |
|
90 | 1 | throw new \RuntimeException(sprintf('Cannot find corresponding Doctrine objects (%d) for all Elastica results (%d). IDs: %s', $objectsCnt, $elasticaObjectsCnt, join(', ', $ids))); |
|
91 | }; |
||
92 | |||
93 | 6 | $propertyAccessor = $this->propertyAccessor; |
|
94 | 6 | $identifier = $this->options['identifier']; |
|
95 | 6 | foreach ($objects as $object) { |
|
96 | 5 | if ($object instanceof HighlightableModelInterface) { |
|
97 | 4 | $id = $propertyAccessor->getValue($object, $identifier); |
|
98 | 5 | $object->setElasticHighlights($highlights[$id]); |
|
99 | } |
||
100 | } |
||
101 | |||
102 | // sort objects in the order of ids |
||
103 | 6 | $idPos = array_flip($ids); |
|
104 | 6 | View Code Duplication | usort($objects, function($a, $b) use ($idPos, $identifier, $propertyAccessor) |
|
|||
105 | { |
||
106 | 5 | return $idPos[$propertyAccessor->getValue($a, $identifier)] > $idPos[$propertyAccessor->getValue($b, $identifier)]; |
|
107 | 6 | }); |
|
108 | |||
109 | 6 | return $objects; |
|
110 | } |
||
111 | |||
112 | 2 | public function hybridTransform(array $elasticaObjects) |
|
113 | { |
||
114 | 2 | $indexedElasticaResults = array(); |
|
115 | 2 | foreach ($elasticaObjects as $elasticaObject) { |
|
116 | 2 | $indexedElasticaResults[$elasticaObject->getId()] = $elasticaObject; |
|
117 | } |
||
118 | |||
119 | 2 | $objects = $this->transform($elasticaObjects); |
|
120 | |||
121 | 2 | $result = array(); |
|
122 | 2 | foreach ($objects as $object) { |
|
123 | 2 | $id = $this->propertyAccessor->getValue($object, $this->options['identifier']); |
|
124 | 2 | $result[] = new HybridResult($indexedElasticaResults[$id], $object); |
|
125 | } |
||
126 | |||
127 | 2 | return $result; |
|
128 | } |
||
129 | |||
130 | /** |
||
131 | * {@inheritDoc} |
||
132 | */ |
||
133 | 1 | public function getIdentifierField() |
|
134 | { |
||
135 | 1 | return $this->options['identifier']; |
|
136 | } |
||
137 | |||
138 | /** |
||
139 | * Fetches objects by theses identifier values. |
||
140 | * |
||
141 | * @param array $identifierValues ids values |
||
142 | * @param Boolean $hydrate whether or not to hydrate the objects, false returns arrays |
||
143 | * |
||
144 | * @return array of objects or arrays |
||
145 | */ |
||
146 | abstract protected function findByIdentifiers(array $identifierValues, $hydrate); |
||
147 | } |
||
148 |
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.