|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace App\Presenters; |
|
4
|
|
|
|
|
5
|
|
|
use App\Components\Forms\Factories\IVisitorFormFactory; |
|
6
|
|
|
use App\Components\Forms\VisitorForm; |
|
7
|
|
|
use App\Models\MeetingModel; |
|
8
|
|
|
use App\Services\Emailer; |
|
9
|
|
|
use App\Repositories\VisitorRepository; |
|
10
|
|
|
use Exception; |
|
11
|
|
|
|
|
12
|
|
|
/** |
|
13
|
|
|
* Visitor controller |
|
14
|
|
|
* |
|
15
|
|
|
* This file handles the retrieval and serving of visitors |
|
16
|
|
|
* |
|
17
|
|
|
* @author Tomas Litera |
|
18
|
|
|
* @copyright 2013-06-12 <[email protected]> |
|
19
|
|
|
* @package srazvs |
|
20
|
|
|
*/ |
|
21
|
|
|
class VisitorPresenter extends BasePresenter |
|
22
|
|
|
{ |
|
23
|
|
|
|
|
24
|
|
|
const TEMPLATE_DIR = __DIR__ . '/../templates/visitor/'; |
|
25
|
|
|
const TEMPLATE_EXT = 'latte'; |
|
26
|
|
|
const REDIRECT_DEFAULT = 'Visitor:listing'; |
|
27
|
|
|
|
|
28
|
|
|
/** |
|
29
|
|
|
* @var Emailer |
|
30
|
|
|
*/ |
|
31
|
|
|
protected $emailer; |
|
32
|
|
|
|
|
33
|
|
|
/** |
|
34
|
|
|
* @var MeetingModel |
|
35
|
|
|
*/ |
|
36
|
|
|
protected $meetingModel; |
|
37
|
|
|
|
|
38
|
|
|
/** |
|
39
|
|
|
* @var VisitorRepository |
|
40
|
|
|
*/ |
|
41
|
|
|
protected $visitorRepository; |
|
42
|
|
|
|
|
43
|
|
|
/** |
|
44
|
|
|
* @var IVisitorFormFactory |
|
45
|
|
|
*/ |
|
46
|
|
|
private $visitorFormFactory; |
|
47
|
|
|
|
|
48
|
|
|
/** |
|
49
|
|
|
* @param MeetingModel $meetings |
|
50
|
|
|
* @param Emailer $emailer |
|
51
|
|
|
* @param VisitorRepository $visitor |
|
52
|
|
|
*/ |
|
53
|
|
|
public function __construct( |
|
54
|
|
|
MeetingModel $meetings, |
|
55
|
|
|
Emailer $emailer, |
|
56
|
|
|
VisitorRepository $visitor |
|
57
|
|
|
) { |
|
58
|
|
|
$this->setMeetingModel($meetings); |
|
59
|
|
|
$this->setEmailer($emailer); |
|
60
|
|
|
$this->setVisitorRepository($visitor); |
|
61
|
|
|
} |
|
62
|
|
|
|
|
63
|
|
|
/** |
|
64
|
|
|
* @return IVisitorFormFactory |
|
65
|
|
|
*/ |
|
66
|
|
|
public function getVisitorFormFactory(): IVisitorFormFactory |
|
67
|
|
|
{ |
|
68
|
|
|
return $this->visitorFormFactory; |
|
69
|
|
|
} |
|
70
|
|
|
|
|
71
|
|
|
/** |
|
72
|
|
|
* Injector |
|
73
|
|
|
* |
|
74
|
|
|
* @param IVisitorFormFactory $factory |
|
75
|
|
|
*/ |
|
76
|
|
|
public function injectVisitorFormFactory(IVisitorFormFactory $factory) |
|
77
|
|
|
{ |
|
78
|
|
|
$this->visitorFormFactory = $factory; |
|
79
|
|
|
} |
|
80
|
|
|
|
|
81
|
|
|
/** |
|
82
|
|
|
* @return void |
|
83
|
|
|
*/ |
|
84
|
|
|
public function startup() |
|
85
|
|
|
{ |
|
86
|
|
|
parent::startup(); |
|
87
|
|
|
|
|
88
|
|
|
$this->getMeetingModel()->setMeetingId($this->getMeetingId()); |
|
89
|
|
|
$this->getVisitorRepository()->setMeeting($this->getMeetingId()) |
|
90
|
|
|
; } |
|
91
|
|
|
|
|
92
|
|
|
/** |
|
93
|
|
|
* Process data from form |
|
94
|
|
|
* |
|
95
|
|
|
* @return void |
|
96
|
|
|
*/ |
|
97
|
|
View Code Duplication |
public function actionCreate($visitor) |
|
|
|
|
|
|
98
|
|
|
{ |
|
99
|
|
|
try { |
|
100
|
|
|
$guid = $this->getVisitorRepository()->create($visitor); |
|
101
|
|
|
$result = $this->sendRegistrationSummary($visitor, $guid); |
|
102
|
|
|
|
|
103
|
|
|
$this->logInfo('Creation of visitor('. $guid .') successfull, result: ' . json_encode($result)); |
|
104
|
|
|
$this->flashSuccess('Účastník(' . $guid . ') byl úspěšně vytvořen.'); |
|
105
|
|
|
} catch(Exception $e) { |
|
106
|
|
|
$this->logError('Creation of visitor('. $guid .') failed, result: ' . $e->getMessage()); |
|
107
|
|
|
$this->flashError('Creation of visitor failed, result: ' . $e->getMessage()); |
|
108
|
|
|
} |
|
109
|
|
|
|
|
110
|
|
|
return $result; |
|
|
|
|
|
|
111
|
|
|
} |
|
112
|
|
|
|
|
113
|
|
|
/** |
|
114
|
|
|
* Process data from editing |
|
115
|
|
|
* |
|
116
|
|
|
* @param integer $id |
|
117
|
|
|
* @return void |
|
118
|
|
|
*/ |
|
119
|
|
View Code Duplication |
public function actionUpdate($id, $visitor) |
|
|
|
|
|
|
120
|
|
|
{ |
|
121
|
|
|
try { |
|
122
|
|
|
$result = $this->getVisitorRepository()->update($id, $visitor); |
|
123
|
|
|
$result = $this->sendRegistrationSummary($visitor, $id); |
|
124
|
|
|
|
|
125
|
|
|
$this->logInfo('Modification of visitor('. $id .') successfull, result: ' . json_encode($result)); |
|
126
|
|
|
$this->flashSuccess('Účastník(' . $id . ') byl úspěšně upraven.'); |
|
127
|
|
|
} catch(Exception $e) { |
|
128
|
|
|
$this->logError('Modification of visitor('. $id .') failed, result: ' . $e->getMessage()); |
|
129
|
|
|
$this->flashFailure('Modification of visitor failed, result: ' . $e->getMessage()); |
|
130
|
|
|
$result = false; |
|
131
|
|
|
} |
|
132
|
|
|
|
|
133
|
|
|
return $result; |
|
134
|
|
|
} |
|
135
|
|
|
|
|
136
|
|
|
/** |
|
137
|
|
|
* @param int $id |
|
138
|
|
|
* @return void |
|
139
|
|
|
*/ |
|
140
|
|
View Code Duplication |
public function actionDelete($id) |
|
|
|
|
|
|
141
|
|
|
{ |
|
142
|
|
|
try { |
|
143
|
|
|
$result = $this->getVisitorRepository()->delete($id); |
|
144
|
|
|
|
|
145
|
|
|
$this->logInfo('Destroying of visitor('. $id .') successfull, result: ' . json_encode($result)); |
|
146
|
|
|
$this->flashSuccess('Položka byla úspěšně smazána'); |
|
147
|
|
|
} catch(Exception $e) { |
|
148
|
|
|
$this->logError('Destroying of visitor('. $id .') failed, result: ' . $e->getMessage()); |
|
149
|
|
|
$this->flashFailure('Destroying of visitor failed, result: ' . $e->getMessage()); |
|
150
|
|
|
} |
|
151
|
|
|
|
|
152
|
|
|
$this->redirect(self::REDIRECT_DEFAULT); |
|
153
|
|
|
} |
|
154
|
|
|
|
|
155
|
|
|
/** |
|
156
|
|
|
* Prepare mass mail form |
|
157
|
|
|
* |
|
158
|
|
|
* @return void |
|
159
|
|
|
*/ |
|
160
|
|
|
public function actionSend() |
|
161
|
|
|
{ |
|
162
|
|
|
try { |
|
163
|
|
|
$request = $this->getHttpRequest(); |
|
164
|
|
|
$subject = $request->getPost('subject', ''); |
|
165
|
|
|
$message = $request->getPost('message', ''); |
|
166
|
|
|
$bcc = explode(',', preg_replace("/\s+/", "", $request->getPost('recipients', ''))); |
|
167
|
|
|
// fill bcc name and address |
|
168
|
|
|
$bcc = array_combine($bcc, $bcc); |
|
169
|
|
|
|
|
170
|
|
|
$mailParameters = $this->getContainer()->parameters['mail']; |
|
171
|
|
|
$recipient = [ |
|
172
|
|
|
$mailParameters['senderAddress'] => $mailParameters['senderName'], |
|
173
|
|
|
]; |
|
174
|
|
|
|
|
175
|
|
|
$template = $this->createMailTemplate(); |
|
176
|
|
|
$template->subject = $subject; |
|
|
|
|
|
|
177
|
|
|
$template->message = $message; |
|
|
|
|
|
|
178
|
|
|
|
|
179
|
|
|
$result = $this->getEmailer()->sendMail($recipient, $subject, (string) $template, $bcc); |
|
180
|
|
|
|
|
181
|
|
|
$this->logInfo('E-mail was send successfully, result: ' . json_encode($result)); |
|
182
|
|
|
$this->flashSuccess('E-mail byl úspěšně odeslán'); |
|
183
|
|
|
} catch(Exception $e) { |
|
184
|
|
|
$this->logError('Sending of e-mail failed, result: ' . $e->getMessage()); |
|
185
|
|
|
$this->flashFailure('Sending of e-mail failed, result: ' . $e->getMessage()); |
|
186
|
|
|
} |
|
187
|
|
|
|
|
188
|
|
|
$this->redirect(self::REDIRECT_DEFAULT); |
|
189
|
|
|
} |
|
190
|
|
|
|
|
191
|
|
|
/** |
|
192
|
|
|
* @param integer|string $ids |
|
|
|
|
|
|
193
|
|
|
* @return void |
|
194
|
|
|
*/ |
|
195
|
|
View Code Duplication |
public function actionPay($id) |
|
|
|
|
|
|
196
|
|
|
{ |
|
197
|
|
|
try { |
|
198
|
|
|
if(!$id) { |
|
199
|
|
|
$id = $this->getHttpRequest()->getPost('checker'); |
|
200
|
|
|
} |
|
201
|
|
|
|
|
202
|
|
|
$visitor = $this->getVisitorRepository(); |
|
203
|
|
|
$visitor->payCostCharge($id); |
|
204
|
|
|
$recipients = $visitor->findRecipients($id); |
|
205
|
|
|
$this->getEmailer()->sendPaymentInfo($recipients, 'cost'); |
|
206
|
|
|
|
|
207
|
|
|
$this->logInfo('Visitor: Action pay cost for id %s executed successfully.', [json_encode($id)]); |
|
208
|
|
|
$this->flashSuccess('Platba byla zaplacena.'); |
|
209
|
|
|
} catch(Exception $e) { |
|
210
|
|
|
$this->logError('Visitor: Action pay for id %s failed, result: %s', [ |
|
211
|
|
|
json_encode($id), |
|
212
|
|
|
$e->getMessage() |
|
213
|
|
|
]); |
|
214
|
|
|
$this->flashFailure('Visitor: Action pay for id ' . $id . ' failed, result: ' . $e->getMessage()); |
|
215
|
|
|
} |
|
216
|
|
|
|
|
217
|
|
|
$this->redirect(self::REDIRECT_DEFAULT); |
|
218
|
|
|
} |
|
219
|
|
|
|
|
220
|
|
|
/** |
|
221
|
|
|
* @param string|interger $ids |
|
|
|
|
|
|
222
|
|
|
* @return void |
|
223
|
|
|
*/ |
|
224
|
|
View Code Duplication |
public function actionAdvance(int $id = null) |
|
|
|
|
|
|
225
|
|
|
{ |
|
226
|
|
|
try { |
|
227
|
|
|
if(!$id) { |
|
|
|
|
|
|
228
|
|
|
$id = $this->getHttpRequest()->getPost('checker'); |
|
229
|
|
|
} |
|
230
|
|
|
|
|
231
|
|
|
$visitor = $this->getVisitorRepository(); |
|
232
|
|
|
$visitor->payAdvanceCharge($id); |
|
233
|
|
|
$recipients = $visitor->findRecipients($id); |
|
234
|
|
|
$this->getEmailer()->sendPaymentInfo($recipients, 'advance'); |
|
235
|
|
|
|
|
236
|
|
|
$this->logInfo('Visitor: Action pay advance for id %s executed successfully.', [json_encode($id)]); |
|
237
|
|
|
$this->flashSuccess('Záloha byla zaplacena.'); |
|
238
|
|
|
} catch(Exception $e) { |
|
239
|
|
|
$this->logError( |
|
240
|
|
|
'Visitor: Action pay advance for id %s failed, result: %s', [ |
|
241
|
|
|
json_encode($id), |
|
242
|
|
|
$e->getMessage(), |
|
243
|
|
|
]); |
|
244
|
|
|
$this->flashFailure('Zaplacení zálohy pro účastníka s id '.json_encode($id).' neprošlo: '.$e->getMessage()); |
|
245
|
|
|
} |
|
246
|
|
|
|
|
247
|
|
|
$this->redirect(self::REDIRECT_DEFAULT); |
|
248
|
|
|
} |
|
249
|
|
|
|
|
250
|
|
|
/** |
|
251
|
|
|
* Set item as checked by id |
|
252
|
|
|
* |
|
253
|
|
|
* @param integer $id |
|
254
|
|
|
* @return void |
|
255
|
|
|
*/ |
|
256
|
|
View Code Duplication |
public function actionChecked($id) |
|
|
|
|
|
|
257
|
|
|
{ |
|
258
|
|
|
try { |
|
259
|
|
|
$result = $this->getVisitorRepository()->setChecked($id); |
|
260
|
|
|
$this->logInfo('Check of visitor('. $id .') successfull, result: ' . json_encode($result)); |
|
261
|
|
|
$this->flashSuccess('Položka byla úspěšně zkontrolována'); |
|
262
|
|
|
} catch(Exception $e) { |
|
263
|
|
|
$this->logError('Check of visitor('. $id .') failed, result: ' . $e->getMessage()); |
|
264
|
|
|
$this->flashFailure('Check of visitor failed, result: ' . $e->getMessage()); |
|
265
|
|
|
} |
|
266
|
|
|
|
|
267
|
|
|
$this->redirect(self::REDIRECT_DEFAULT); |
|
268
|
|
|
} |
|
269
|
|
|
|
|
270
|
|
|
/** |
|
271
|
|
|
* Set item as unchecked by id |
|
272
|
|
|
* |
|
273
|
|
|
* @param integer $id |
|
274
|
|
|
* @return void |
|
275
|
|
|
*/ |
|
276
|
|
View Code Duplication |
public function actionUnchecked($id) |
|
|
|
|
|
|
277
|
|
|
{ |
|
278
|
|
|
try { |
|
279
|
|
|
$result = $this->getVisitorRepository()->setUnchecked($id); |
|
280
|
|
|
$this->logInfo('Uncheck of visitor('. $id .') successfull, result: ' . json_encode($result)); |
|
281
|
|
|
$this->flashSuccess('Položka byla nastavena jako nekontrolována'); |
|
282
|
|
|
} catch(Exception $e) { |
|
283
|
|
|
$this->logError('Uncheck of visitor('. $id .') failed, result: ' . $e->getMessage()); |
|
284
|
|
|
$this->flashFailure('Uncheck of visitor failed, result: ' . $e->getMessage()); |
|
285
|
|
|
} |
|
286
|
|
|
|
|
287
|
|
|
$this->redirect(self::REDIRECT_DEFAULT); |
|
288
|
|
|
} |
|
289
|
|
|
|
|
290
|
|
|
/** |
|
291
|
|
|
* Prepare page for new item |
|
292
|
|
|
* |
|
293
|
|
|
* @return void |
|
294
|
|
|
*/ |
|
295
|
|
|
public function renderNew() |
|
296
|
|
|
{ |
|
297
|
|
|
$template = $this->getTemplate(); |
|
298
|
|
|
$template->heading = 'nový účastník'; |
|
|
|
|
|
|
299
|
|
|
} |
|
300
|
|
|
|
|
301
|
|
|
/** |
|
302
|
|
|
* @param integer $id |
|
303
|
|
|
* @return void |
|
304
|
|
|
*/ |
|
305
|
|
|
public function renderEdit($id) |
|
306
|
|
|
{ |
|
307
|
|
|
$visitor = $this->getVisitorRepository()->findExpandedById($id); |
|
308
|
|
|
|
|
309
|
|
|
$template = $this->getTemplate(); |
|
310
|
|
|
$template->heading = 'úprava účastníka'; |
|
|
|
|
|
|
311
|
|
|
|
|
312
|
|
|
$this['visitorForm']->setDefaults($visitor); |
|
313
|
|
|
} |
|
314
|
|
|
|
|
315
|
|
|
/** |
|
316
|
|
|
* Prepare mass mail form |
|
317
|
|
|
* |
|
318
|
|
|
* @return void |
|
319
|
|
|
*/ |
|
320
|
|
|
public function renderMail() |
|
321
|
|
|
{ |
|
322
|
|
|
$ids = $this->getHttpRequest()->getPost('checker'); |
|
323
|
|
|
|
|
324
|
|
|
$template = $this->getTemplate(); |
|
325
|
|
|
$template->recipientMailAddresses = $this->getVisitorRepository()->getSerializedMailAddress($ids); |
|
|
|
|
|
|
326
|
|
|
} |
|
327
|
|
|
|
|
328
|
|
|
|
|
329
|
|
|
/** |
|
330
|
|
|
* @return void |
|
331
|
|
|
*/ |
|
332
|
|
|
public function renderListing() |
|
333
|
|
|
{ |
|
334
|
|
|
$search = $this->getHttpRequest()->getQuery('search') ?: ''; |
|
335
|
|
|
|
|
336
|
|
|
$visitorRepository = $this->getVisitorRepository(); |
|
337
|
|
|
|
|
338
|
|
|
$template = $this->getTemplate(); |
|
339
|
|
|
$template->render = $visitorRepository->findBySearch($search); |
|
|
|
|
|
|
340
|
|
|
$template->visitorCount = $visitorRepository->count(); |
|
|
|
|
|
|
341
|
|
|
$template->meetingPrice = $this->getMeetingModel()->getPrice('cost'); |
|
|
|
|
|
|
342
|
|
|
$template->search = $search; |
|
|
|
|
|
|
343
|
|
|
} |
|
344
|
|
|
|
|
345
|
|
|
/** |
|
346
|
|
|
* @return VisitorFormControl |
|
347
|
|
|
*/ |
|
348
|
|
|
protected function createComponentVisitorForm(): VisitorForm |
|
349
|
|
|
{ |
|
350
|
|
|
$control = $this->visitorFormFactory->create(); |
|
351
|
|
|
$control->setMeetingId($this->getMeetingId()); |
|
352
|
|
|
|
|
353
|
|
View Code Duplication |
$control->onVisitorSave[] = function(VisitorForm $control, $visitor) { |
|
|
|
|
|
|
354
|
|
|
$id = $this->getParameter('id'); |
|
355
|
|
|
$this->setBacklinkFromArray($visitor); |
|
356
|
|
|
|
|
357
|
|
|
if($id) { |
|
358
|
|
|
$this->actionUpdate($id, $visitor); |
|
359
|
|
|
} else { |
|
360
|
|
|
$this->actionCreate($visitor); |
|
361
|
|
|
} |
|
362
|
|
|
|
|
363
|
|
|
$this->redirect($this->getBacklink() ?: self::REDIRECT_DEFAULT); |
|
364
|
|
|
}; |
|
365
|
|
|
|
|
366
|
|
|
$control->onVisitorReset[] = function(VisitorForm $control, $visitor) { |
|
367
|
|
|
$this->setBacklinkFromArray($visitor); |
|
368
|
|
|
|
|
369
|
|
|
$this->redirect($this->getBacklink() ?: self::REDIRECT_DEFAULT); |
|
370
|
|
|
}; |
|
371
|
|
|
|
|
372
|
|
|
return $control; |
|
373
|
|
|
} |
|
374
|
|
|
|
|
375
|
|
|
/** |
|
376
|
|
|
* @return Latte |
|
377
|
|
|
*/ |
|
378
|
|
|
protected function createMailTemplate() |
|
379
|
|
|
{ |
|
380
|
|
|
$template = $this->createTemplate(); |
|
381
|
|
|
$template->setFile( |
|
382
|
|
|
sprintf( |
|
383
|
|
|
'%s%s.%s', |
|
384
|
|
|
self::TEMPLATE_DIR, |
|
385
|
|
|
'mail_body', |
|
386
|
|
|
self::TEMPLATE_EXT |
|
387
|
|
|
) |
|
388
|
|
|
); |
|
389
|
|
|
|
|
390
|
|
|
return $template; |
|
391
|
|
|
} |
|
392
|
|
|
|
|
393
|
|
|
/** |
|
394
|
|
|
* @param array $visitor |
|
395
|
|
|
* @return boolean |
|
396
|
|
|
*/ |
|
397
|
|
|
protected function sendRegistrationSummary($visitor, $guid) |
|
398
|
|
|
{ |
|
399
|
|
|
$recipient = [ |
|
400
|
|
|
$visitor, |
|
401
|
|
|
]; |
|
402
|
|
|
|
|
403
|
|
|
$code4bank = $this->getVisitorRepository()->calculateCode4Bank( |
|
404
|
|
|
$visitor['name'], |
|
405
|
|
|
$visitor['surname'], |
|
406
|
|
|
$visitor['birthday']->format('d. m. Y') |
|
407
|
|
|
); |
|
408
|
|
|
$result = $this->getEmailer()->sendRegistrationSummary($recipient, $guid, $code4bank); |
|
409
|
|
|
|
|
410
|
|
|
return $result; |
|
411
|
|
|
} |
|
412
|
|
|
|
|
413
|
|
|
/** |
|
414
|
|
|
* @return MeetingModel |
|
415
|
|
|
*/ |
|
416
|
|
|
protected function getMeetingModel() |
|
417
|
|
|
{ |
|
418
|
|
|
return $this->meetingModel; |
|
419
|
|
|
} |
|
420
|
|
|
|
|
421
|
|
|
/** |
|
422
|
|
|
* @param MeetingModel $model |
|
423
|
|
|
* @return $this |
|
424
|
|
|
*/ |
|
425
|
|
|
protected function setMeetingModel(MeetingModel $model) |
|
426
|
|
|
{ |
|
427
|
|
|
$this->meetingModel = $model; |
|
428
|
|
|
|
|
429
|
|
|
return $this; |
|
430
|
|
|
} |
|
431
|
|
|
|
|
432
|
|
|
/** |
|
433
|
|
|
* @return Emailer |
|
434
|
|
|
*/ |
|
435
|
|
|
protected function getEmailer() |
|
436
|
|
|
{ |
|
437
|
|
|
return $this->emailer; |
|
438
|
|
|
} |
|
439
|
|
|
|
|
440
|
|
|
/** |
|
441
|
|
|
* @param Emailer $emailer |
|
442
|
|
|
* @return $this |
|
443
|
|
|
*/ |
|
444
|
|
|
protected function setEmailer(Emailer $emailer) |
|
445
|
|
|
{ |
|
446
|
|
|
$this->emailer = $emailer; |
|
447
|
|
|
|
|
448
|
|
|
return $this; |
|
449
|
|
|
} |
|
450
|
|
|
|
|
451
|
|
|
/** |
|
452
|
|
|
* @return VisitorRepository |
|
453
|
|
|
*/ |
|
454
|
|
|
protected function getVisitorRepository(): VisitorRepository |
|
455
|
|
|
{ |
|
456
|
|
|
return $this->visitorRepository; |
|
457
|
|
|
} |
|
458
|
|
|
|
|
459
|
|
|
/** |
|
460
|
|
|
* @param VisitorRepository $repository |
|
461
|
|
|
* @return self |
|
462
|
|
|
*/ |
|
463
|
|
|
protected function setVisitorRepository(VisitorRepository $repository): self |
|
464
|
|
|
{ |
|
465
|
|
|
$this->visitorRepository = $repository; |
|
466
|
|
|
|
|
467
|
|
|
return $this; |
|
468
|
|
|
} |
|
469
|
|
|
|
|
470
|
|
|
} |
|
471
|
|
|
|
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.