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 absences_viewVacationCalendarCls 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 absences_viewVacationCalendarCls, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
137 | class absences_viewVacationCalendarCls |
||
138 | { |
||
139 | var $entries = array(); |
||
140 | var $fullname; |
||
141 | var $vacwaitingtxt; |
||
142 | var $vacapprovedtxt; |
||
143 | var $print; |
||
144 | var $close; |
||
145 | var $emptylines = true; |
||
146 | |||
147 | public $display_types; |
||
148 | |||
149 | |||
150 | public $public = false; |
||
151 | public $total = null; |
||
152 | |||
153 | public $loadmore = null; |
||
154 | public $loadall = false; |
||
155 | |||
156 | public $nbmonth; |
||
157 | |||
158 | public $limit; |
||
159 | |||
160 | |||
161 | /** |
||
162 | * |
||
163 | * @param array $users Users displayed by default |
||
164 | * @param bool $period Allow period selection (vacation request creation first step) |
||
165 | * @param bool $display_types Display types color and legend on planning |
||
166 | * @param int $nbmonth Number of month to load |
||
167 | * @param bool $dispusers Display user names column |
||
168 | */ |
||
169 | public function __construct($users, $period, $display_types, $nbmonth, $dispusers, $shiftmonth = 0, $legend = true) |
||
170 | { |
||
171 | global $babBody; |
||
172 | |||
173 | include_once $GLOBALS['babInstallPath']."utilit/dateTime.php"; |
||
174 | include_once $GLOBALS['babInstallPath']."utilit/urlincl.php"; |
||
175 | |||
176 | $month = isset($_REQUEST['month']) ? (int) $_REQUEST['month'] : (date("n") + $shiftmonth); |
||
177 | $year = isset($_REQUEST['year']) ? (int) $_REQUEST['year'] : date("Y"); |
||
178 | |||
179 | global $babDB; |
||
180 | $this->month = $month; |
||
181 | $this->year = $year; |
||
182 | |||
183 | $this->dispusers = $dispusers; |
||
184 | $this->display_types = $display_types; |
||
185 | $this->display_legend = $legend; |
||
186 | |||
187 | $this->userNameArr = array(); |
||
188 | |||
189 | foreach ($users as $uid) |
||
190 | { |
||
191 | $uid = (int) $uid; |
||
192 | $this->userNameArr[$uid] = bab_getUserName($uid); |
||
193 | } |
||
194 | |||
195 | bab_sort::natcasesort($this->userNameArr); |
||
196 | |||
197 | |||
198 | $this->idusers = array_keys($this->userNameArr); |
||
199 | $this->nbusers = count($this->idusers); |
||
200 | $this->firstuser = bab_toHtml(current($this->userNameArr)); |
||
201 | $this->display_firstuser = 1 === $this->nbusers; |
||
202 | |||
203 | $this->period = $period; |
||
204 | $this->vacwaitingtxt = absences_translate("Waiting vacation request"); |
||
205 | $this->vacapprovedtxt = absences_translate("Approved vacation request"); |
||
206 | $this->t_selected = absences_translate("Selected period"); |
||
207 | $this->print = absences_translate("Print"); |
||
208 | $this->close = absences_translate("Close"); |
||
209 | $this->t_noresult = absences_translate("No results found for this search query"); |
||
210 | |||
211 | $this->t_previousmonth = absences_translate("Previous month"); |
||
212 | $this->t_previousyear = absences_translate("Previous year"); |
||
213 | $this->t_nextmonth = absences_translate("Next month"); |
||
214 | $this->t_nextyear = absences_translate("Next year"); |
||
215 | |||
216 | $this->t_nonworking = absences_translate("Non-working day"); |
||
217 | $this->t_weekend = absences_translate("Week-end"); |
||
218 | $this->t_rotate = absences_translate("Print in landscape"); |
||
219 | $this->t_non_used = $this->display_types ? absences_translate("Non-used days") : absences_translate("Absences"); |
||
220 | $this->t_waiting = absences_translate("Waiting vacation request"); |
||
221 | $this->t_previsional = absences_translate("Previsional vacation request"); |
||
222 | $this->t_waiting_vac = absences_translate("Waiting vacation request"); |
||
223 | $this->t_legend = absences_translate("Legend"); |
||
224 | |||
225 | $this->id_request = isset($_REQUEST['id']) ? $_REQUEST['id'] : 0; |
||
226 | |||
227 | $this->nbmonth = $nbmonth; |
||
228 | |||
229 | $this->limit = absences_getSearchLimit($nbmonth); |
||
230 | |||
231 | $urltmp = bab_url::get_request_gp(); |
||
232 | $urltmp->search = null; // the search button, disabled for navigation |
||
233 | $this->nwd_color = 'yellow'; // default color for non working days if no categories |
||
234 | |||
235 | if( $GLOBALS['babBody']->babsite['id_calendar_cat'] != 0) |
||
236 | { |
||
237 | include_once $GLOBALS['babInstallPath']."utilit/calapi.php"; |
||
238 | $idcat = bab_calGetCategories($GLOBALS['babBody']->babsite['id_calendar_cat']); |
||
239 | if( isset($idcat[0]['color'])) |
||
240 | { |
||
241 | $this->nwd_color = $idcat[0]['color']; |
||
242 | } |
||
243 | } |
||
244 | |||
245 | if (!empty($_REQUEST['popup'])) |
||
246 | { |
||
247 | $this->popup = true; |
||
248 | } |
||
249 | |||
250 | if (!isset($_REQUEST['ide'])) |
||
251 | { |
||
252 | $urltmp->idu = implode(',',$this->idusers); |
||
253 | } |
||
254 | |||
255 | $switchurl = clone $urltmp; |
||
256 | |||
257 | if (1 == $this->nbmonth) { |
||
258 | |||
259 | $switchurl->nbmonth = 12; |
||
260 | $this->switchurl = $switchurl->toString(); |
||
261 | $this->switchlabel = absences_translate("Year view"); |
||
262 | |||
263 | |||
264 | |||
265 | $this->prevmonthclass = 'prev1'; |
||
266 | $this->prevyearclass = 'prev2'; |
||
267 | |||
268 | $this->nextmonthclass = 'next1'; |
||
269 | $this->nextyearclass = 'next2'; |
||
270 | |||
271 | } else { |
||
272 | $switchurl->nbmonth = 1; |
||
273 | $this->switchurl = $switchurl->toString(); |
||
274 | $this->switchlabel = absences_translate("Month view"); |
||
275 | |||
276 | $this->prevmonthclass = 'prev2'; |
||
277 | $this->prevyearclass = 'prev1'; |
||
278 | |||
279 | $this->nextmonthclass = 'next2'; |
||
280 | $this->nextyearclass = 'next1'; |
||
281 | } |
||
282 | |||
283 | $urltmp->nbmonth = $this->nbmonth; |
||
284 | |||
285 | |||
286 | $previousmonth = clone $urltmp; |
||
287 | $previousmonth->month = date("n", mktime( 0,0,0, $month-1, 1, $year)); |
||
288 | $previousmonth->year = date("Y", mktime( 0,0,0, $month-1, 1, $year)); |
||
289 | $this->previousmonth = $previousmonth->toString(); |
||
290 | |||
291 | $nextmonth = clone $urltmp; |
||
292 | $nextmonth->month = date("n", mktime( 0,0,0, $month+1, 1, $year)); |
||
293 | $nextmonth->year = date("Y", mktime( 0,0,0, $month+1, 1, $year)); |
||
294 | $this->nextmonth = $nextmonth->toString(); |
||
295 | |||
296 | $previousyear = clone $urltmp; |
||
297 | $previousyear->month = date("n", mktime( 0,0,0, $month, 1, $year-1)); |
||
298 | $previousyear->year = date("Y", mktime( 0,0,0, $month, 1, $year-1)); |
||
299 | $this->previousyear = $previousyear->toString(); |
||
300 | |||
301 | $nextyear = clone $urltmp; |
||
302 | $nextyear->month = date("n", mktime( 0,0,0, $month, 1, $year+1)); |
||
303 | $nextyear->year = date("Y", mktime( 0,0,0, $month, 1, $year+1)); |
||
304 | $this->nextyear = $nextyear->toString(); |
||
305 | |||
306 | $dateb = new BAB_DateTime($year, $month, 1); |
||
307 | $datee = $dateb->cloneDate(); |
||
308 | $datee->add($this->nbmonth, BAB_DATETIME_MONTH); |
||
309 | |||
310 | |||
311 | |||
312 | $this->yearname = $this->getTitle($dateb, $datee); |
||
313 | |||
314 | |||
315 | |||
316 | |||
317 | |||
318 | |||
319 | |||
320 | if ($this->display_types) |
||
321 | { |
||
322 | $this->restypes = $babDB->db_query(" |
||
323 | |||
324 | SELECT |
||
325 | t.* |
||
326 | FROM |
||
327 | ".ABSENCES_TYPES_TBL." t, |
||
328 | absences_rights r, |
||
329 | absences_users_rights ur, |
||
330 | ".ABSENCES_PERSONNEL_TBL." p |
||
331 | WHERE |
||
332 | p.id_user IN(".$babDB->quote($this->idusers).") |
||
333 | AND p.id_user=ur.id_user |
||
334 | AND ur.id_right=r.id |
||
335 | AND r.id_type=t.id |
||
336 | GROUP BY |
||
337 | t.id |
||
338 | "); |
||
339 | |||
340 | } |
||
341 | |||
342 | |||
343 | // filtre par service |
||
344 | |||
345 | $W = bab_Widgets(); |
||
346 | $departments = $W->Multiselect(); |
||
347 | $departments->setName('departments')->setValue(bab_rp('departments')); |
||
348 | |||
349 | $entities = absences_getEntites(); |
||
350 | foreach($entities as $e) { |
||
351 | $departments->addOption($e['id'], $e['name']); |
||
352 | } |
||
353 | |||
354 | $this->departments = ''; |
||
355 | |||
356 | if (count($entities) > 0) { |
||
357 | $this->departments = $departments->display($W->HtmlCanvas()); |
||
358 | } |
||
359 | |||
360 | |||
361 | // filtre recherche par date |
||
362 | |||
363 | $this->datefilter = $this->getDateFilter()->display($W->HtmlCanvas()); |
||
364 | } |
||
365 | |||
366 | |||
367 | |||
368 | private function getDateFilter() |
||
369 | { |
||
370 | $W = bab_Widgets(); |
||
371 | |||
372 | switch (bab_rp('searchtype')) { |
||
373 | View Code Duplication | case '2': |
|
374 | $dateb = bab_rp('dateb'); |
||
375 | $datee = bab_rp('datee'); |
||
376 | $_date = null; |
||
377 | break; |
||
378 | |||
379 | default: |
||
380 | View Code Duplication | case '1': |
|
381 | $dateb = null; |
||
382 | $datee = null; |
||
383 | $_date = bab_rp('date'); |
||
384 | break; |
||
385 | } |
||
386 | |||
387 | $periodpicker = $W->PeriodPicker()->setNames('dateb', 'datee')->setValues($dateb, $datee); |
||
388 | |||
389 | $period = $W->LabelledWidget( |
||
390 | absences_translate('Date'), |
||
391 | $periodpicker |
||
392 | ); |
||
393 | |||
394 | $picker = $W->DatePicker() |
||
395 | ->setValue($_date) |
||
396 | ->addClass('absences-search-by-date'); |
||
397 | |||
398 | if (method_exists($picker, 'setDefaultDate')) { |
||
399 | $picker->setDefaultDate($this->year.'-'.$this->month.'-01'); |
||
400 | $periodpicker->setDefaultDate($this->year.'-'.$this->month.'-01'); |
||
401 | } |
||
402 | |||
403 | $date = $W->LabelledWidget( |
||
404 | absences_translate('Date'), |
||
405 | $picker, |
||
406 | 'date' |
||
407 | ); |
||
408 | |||
409 | $begin = $picker->getISODate($dateb); |
||
410 | $end = $picker->getISODate($datee); |
||
411 | $d = $picker->getISODate($_date); |
||
412 | |||
413 | if ('0000-00-00' !== $d) { |
||
414 | $begin = $d; |
||
415 | $end = $d; |
||
416 | } |
||
417 | |||
418 | if ('0000-00-00' !== $begin && '0000-00-00' !== $end) { |
||
419 | $picker->setMetadata('dateb', $begin); |
||
420 | $picker->setMetadata('datee', $end); |
||
421 | } |
||
422 | |||
423 | |||
424 | $frame = $W->Frame(null , $W->HBoxItems()); |
||
425 | |||
426 | |||
427 | $frame->addItem( |
||
428 | $W->LabelledWidget( |
||
429 | absences_translate('Search by date'), |
||
430 | $W->Select() |
||
431 | ->setAssociatedDisplayable($date, array('1')) |
||
432 | ->setAssociatedDisplayable($period, array('2')) |
||
433 | ->addOption('1', absences_translate("Absences on a date")) |
||
434 | ->addOption('2', absences_translate("Absences in a period")) |
||
435 | ->setValue(bab_rp('searchtype', 1)), |
||
436 | 'searchtype' |
||
437 | ) |
||
438 | ); |
||
439 | |||
440 | |||
441 | $frame->addItem($period); |
||
442 | $frame->addItem($date); |
||
443 | |||
444 | return $frame; |
||
445 | } |
||
446 | |||
447 | |||
448 | /** |
||
449 | * @param BAB_DateTime $dateb |
||
450 | * @param BAB_DateTime $datee |
||
451 | * |
||
452 | * @return string |
||
453 | */ |
||
454 | private function getTitle(BAB_DateTime $dateb, BAB_DateTime $datee) |
||
469 | |||
470 | |||
471 | |||
472 | |||
473 | public function getnexthidden() |
||
490 | |||
491 | |||
492 | |||
493 | public function getdayname() |
||
505 | |||
506 | |||
507 | /** |
||
508 | * |
||
509 | */ |
||
510 | public function getmonth() |
||
530 | |||
531 | |||
532 | |||
533 | |||
534 | |||
535 | public function getnextuser() |
||
574 | |||
575 | |||
576 | /** |
||
577 | * |
||
578 | * @return boolean |
||
579 | */ |
||
580 | public function getday() |
||
597 | |||
598 | public function getnexttype() |
||
615 | |||
616 | |||
617 | public function entity($ide, $all = false) |
||
618 | { |
||
619 | // permettre de charger les sous-entites fusionnes dans le meme planning |
||
620 | |||
621 | $url = bab_url::get_request_gp(); |
||
622 | $url->all = $all ? '0' : '1'; |
||
623 | |||
624 | $this->mergedurl = false; |
||
625 | |||
626 | if (bab_OCGetChildCount($ide)) { |
||
627 | $this->mergedurl = bab_toHtml($url->toString()); |
||
628 | } |
||
629 | |||
630 | if ($all) { |
||
631 | $this->t_merged = absences_translate('View the entity only'); |
||
632 | } else { |
||
633 | $this->t_merged = absences_translate('View users from all entities'); |
||
634 | } |
||
635 | } |
||
636 | |||
637 | |||
638 | public function publiccalendar($total) |
||
639 | { |
||
640 | $this->display_firstuser = false; |
||
641 | $this->public = true; |
||
642 | $this->t_search_name = absences_translate('Search by name'); |
||
643 | $this->t_search_entity = absences_translate('By entity'); |
||
644 | $this->keyword = bab_rp('keyword'); |
||
645 | $this->t_ok = absences_translate('Ok'); |
||
646 | |||
647 | $this->total = $total; |
||
648 | $this->t_total = sprintf(absences_translate('%d result found', '%d results found', $total), $total); |
||
649 | |||
650 | |||
651 | // prepare button for first load |
||
652 | |||
653 | $this->t_use_month_view = false; |
||
654 | |||
655 | $this->t_loadall = absences_translate('View all results'); |
||
656 | $this->t_viewBegin = absences_translate('View the first 30 only'); |
||
657 | |||
658 | if ($total > $this->nbusers) |
||
659 | { |
||
660 | $last = $total - $this->nbusers; |
||
661 | |||
662 | if (1 < $this->nbmonth) |
||
663 | { |
||
664 | $this->t_use_month_view = sprintf(absences_translate('The planning display only %d results from %d total results, use the month view to fetch next results'), $this->nbusers, $total); |
||
665 | $this->loadmore = false; |
||
666 | $this->loadall = false; |
||
667 | } else { |
||
668 | |||
669 | $this->loadall = false; |
||
670 | $this->loadmore = $this->limit < $last ? $this->limit : $last; |
||
671 | $this->t_loadmore = sprintf(absences_translate('Load the next %d results'), $this->loadmore); |
||
672 | } |
||
673 | } else { |
||
674 | $this->loadmore = false; |
||
675 | $this->loadall = false; |
||
676 | } |
||
677 | } |
||
678 | |||
679 | |||
680 | public function getHtml() |
||
681 | { |
||
682 | // dans les vielles versions d'ovidentia |
||
683 | // l'access a l'api des organigramme renvoi un message d'erreur si on a pas les droits de lecture |
||
684 | // dans le planning le bouton qui permet d'acceder au sous-entites a besoin de cette api |
||
685 | // on supprime le message d'erreur pour eviter qui apparaisse sur le planning perso |
||
686 | // dans le vielles versions d'ovidentia < 8.4.0 le bouton pour afficher les sous-entites dans le meme planning sera probablement inoperant |
||
687 | // tant que l'organigramme n'est pas accessible en lecture |
||
688 | |||
689 | $babBody = bab_getBody(); |
||
690 | |||
691 | if ($babBody->msgerror === bab_translate('Error: Right insufficient')) { |
||
692 | bab_debug($babBody->msgerror); |
||
693 | $babBody->msgerror = null; |
||
694 | } |
||
695 | |||
696 | return bab_printTemplate($this, absences_addon()->getRelativePath()."vacuser.html", "calendarbyuser"); |
||
697 | } |
||
698 | |||
699 | |||
700 | |||
701 | public function printhtml() |
||
723 | } |
||
724 | |||
725 | |||
726 | |||
727 | |||
728 | |||
853 |
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.