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 |
||
19 | class RecordHandler |
||
20 | { |
||
21 | /** |
||
22 | * Available order logic for score. |
||
23 | */ |
||
24 | const ORDER_ASC = "ASC"; |
||
25 | const ORDER_DESC = "DESC"; |
||
26 | |||
27 | /** |
||
28 | * List of event types |
||
29 | */ |
||
30 | const EVENT_TYPE_FIRST_TIME = 'first_time'; |
||
31 | const EVENT_TYPE_SAME_SCORE = 'same_score'; |
||
32 | const EVENT_TYPE_SAME_POS = 'same_position'; |
||
33 | const EVENT_TYPE_BETTER_POS = 'better_position'; |
||
34 | |||
35 | /** |
||
36 | * List of data in the associative array returned. |
||
37 | */ |
||
38 | const COL_EVENT = 'event'; |
||
39 | const COL_RECORD = 'record'; |
||
40 | const COL_OLD_RECORD = 'old_record'; |
||
41 | const COL_POS = 'position'; |
||
42 | const COL_OLD_POS = 'old_position'; |
||
43 | const COL_RECORDS = 'records'; |
||
44 | const COL_PLUGIN = 'plugin'; |
||
45 | |||
46 | /** @var ConfigInterface */ |
||
47 | protected $nbRecords; |
||
48 | |||
49 | /** @var string */ |
||
50 | protected $ordering; |
||
51 | |||
52 | /** @var RecordQueryBuilder */ |
||
53 | protected $recordQueryBuilder; |
||
54 | |||
55 | /** @var PlayerDb */ |
||
56 | protected $playerDb; |
||
57 | |||
58 | /** @var Record[] */ |
||
59 | protected $records = []; |
||
60 | |||
61 | /** @var Record[] */ |
||
62 | protected $recordsPerPlayer = []; |
||
63 | |||
64 | /** @var int[] */ |
||
65 | protected $positionPerPlayer = []; |
||
66 | |||
67 | /** @var int */ |
||
68 | protected $currentNbLaps; |
||
69 | |||
70 | /** @var string */ |
||
71 | protected $currentMapUid; |
||
72 | |||
73 | /** |
||
74 | * RecordHandler constructor. |
||
75 | * |
||
76 | * @param RecordQueryBuilder $recordQueryBuilder |
||
77 | * @param PlayerDb $playerDb |
||
78 | * @param ConfigInterface $nbRecords |
||
79 | * @param string $ordering |
||
80 | */ |
||
81 | 14 | View Code Duplication | public function __construct( |
|
|||
82 | RecordQueryBuilder $recordQueryBuilder, |
||
83 | PlayerDb $playerDb, |
||
84 | ConfigInterface $nbRecords, |
||
85 | $ordering = self::ORDER_ASC |
||
86 | ) { |
||
87 | 14 | $this->recordQueryBuilder = $recordQueryBuilder; |
|
88 | 14 | $this->nbRecords = $nbRecords; |
|
89 | 14 | $this->ordering = $ordering; |
|
90 | 14 | $this->playerDb = $playerDb; |
|
91 | 14 | } |
|
92 | |||
93 | /** |
||
94 | * @return int |
||
95 | */ |
||
96 | public function getCurrentNbLaps(): int |
||
100 | |||
101 | /** |
||
102 | * @return Record[] |
||
103 | */ |
||
104 | 7 | public function getRecords() |
|
105 | { |
||
106 | 7 | return $this->records; |
|
107 | } |
||
108 | |||
109 | /** |
||
110 | * Get the position of a player |
||
111 | * |
||
112 | * @param string $login |
||
113 | * |
||
114 | * @return integer|null |
||
115 | */ |
||
116 | 5 | public function getPlayerPosition($login) |
|
117 | { |
||
118 | 5 | return isset($this->positionPerPlayer[$login]) ? $this->positionPerPlayer[$login] : null; |
|
119 | } |
||
120 | |||
121 | /** |
||
122 | * Get a players record information. |
||
123 | * |
||
124 | * @param $login |
||
125 | * |
||
126 | * @return Record|null |
||
127 | */ |
||
128 | 2 | public function getPlayerRecord($login) |
|
129 | { |
||
130 | 2 | return isset($this->recordsPerPlayer[$login]) ? $this->recordsPerPlayer[$login] : null; |
|
131 | } |
||
132 | |||
133 | /** |
||
134 | * Load records for a certain map. |
||
135 | * |
||
136 | * @param string $mapUid |
||
137 | * @param integer $nbLaps |
||
138 | * @throws \Propel\Runtime\Exception\PropelException |
||
139 | */ |
||
140 | 12 | public function loadForMap($mapUid, $nbLaps) |
|
141 | { |
||
142 | // Free old records from memory first. |
||
143 | 12 | foreach ($this->records as $record) { |
|
144 | $record->clearAllReferences(false); |
||
145 | unset($record); |
||
146 | } |
||
147 | 12 | foreach ($this->recordsPerPlayer as $record) { |
|
148 | $record->clearAllReferences(false); |
||
149 | unset($record); |
||
150 | } |
||
151 | 12 | RecordTableMap::clearInstancePool(); |
|
152 | |||
153 | // Load them amm new. |
||
154 | 12 | $this->recordsPerPlayer = []; |
|
155 | 12 | $this->positionPerPlayer = []; |
|
156 | |||
157 | 12 | $this->currentMapUid = $mapUid; |
|
158 | 12 | $this->currentNbLaps = $nbLaps; |
|
159 | |||
160 | 12 | $this->records = $this->recordQueryBuilder |
|
161 | 12 | ->getMapRecords($mapUid, $nbLaps, $this->getScoreOrdering(), $this->nbRecords->get()); |
|
162 | |||
163 | 12 | $position = 1; |
|
164 | 12 | foreach ($this->records as $record) { |
|
165 | 11 | $this->recordsPerPlayer[$record->getPlayer()->getLogin()] = $record; |
|
166 | 11 | $this->positionPerPlayer[$record->getPlayer()->getLogin()] = $position++; |
|
167 | } |
||
168 | 12 | } |
|
169 | |||
170 | /** |
||
171 | * Load records for certain players only. |
||
172 | * |
||
173 | * @param $mapUid |
||
174 | * @param $nbLaps |
||
175 | * @param $logins |
||
176 | * @throws \Propel\Runtime\Exception\PropelException |
||
177 | */ |
||
178 | 1 | public function loadForPlayers($mapUid, $nbLaps, $logins) |
|
179 | { |
||
180 | 1 | $logins = array_diff($logins, array_keys($this->recordsPerPlayer)); |
|
181 | |||
182 | 1 | if (!empty($logins)) { |
|
183 | 1 | $records = $this->recordQueryBuilder->getPlayerMapRecords($mapUid, $nbLaps, $logins); |
|
184 | |||
185 | 1 | foreach ($records as $record) { |
|
186 | 1 | $this->recordsPerPlayer[$record->getPlayer()->getLogin()] = $record; |
|
187 | } |
||
188 | } |
||
189 | 1 | } |
|
190 | |||
191 | /** |
||
192 | * Save all new records. |
||
193 | * |
||
194 | * @throws \Propel\Runtime\Exception\PropelException |
||
195 | */ |
||
196 | public function save() |
||
210 | |||
211 | /** |
||
212 | * Add a new record |
||
213 | * |
||
214 | * @param string $login |
||
215 | * @param int $score |
||
216 | * @param int[] $checkpoints |
||
217 | * |
||
218 | * @return array|null Data for the new records. |
||
219 | * @throws \Propel\Runtime\Exception\PropelException |
||
220 | */ |
||
221 | 12 | public function addRecord($login, $score, $checkpoints) |
|
310 | |||
311 | /** |
||
312 | * Get a new record instance. |
||
313 | * |
||
314 | * @param string $login |
||
315 | * |
||
316 | * @return Record |
||
317 | */ |
||
318 | 6 | protected function getNewRecord($login) |
|
328 | |||
329 | /** |
||
330 | * Update Records statistics. |
||
331 | * |
||
332 | * @param Record $record |
||
333 | * @param integer $score |
||
334 | */ |
||
335 | 12 | protected function updateRecordStats(Record $record, $score) |
|
342 | |||
343 | |||
344 | /** |
||
345 | * Get ordering use for sorting. |
||
346 | * |
||
347 | * @return string |
||
348 | */ |
||
349 | 13 | protected function getScoreOrdering() |
|
353 | |||
354 | /** |
||
355 | * @param int $newScore |
||
356 | * @param Record $record |
||
357 | * |
||
358 | * @return bool |
||
359 | */ |
||
360 | 11 | protected function compareNewScore($record, $newScore) |
|
368 | } |
||
369 |
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.