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_Agent 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_Agent, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
40 | class absences_Agent extends absences_Record |
||
41 | { |
||
42 | /** |
||
43 | * |
||
44 | * @var int |
||
45 | */ |
||
46 | protected $id_user; |
||
47 | |||
48 | /** |
||
49 | * |
||
50 | * @var absences_Organization |
||
51 | */ |
||
52 | protected $organization; |
||
53 | |||
54 | |||
55 | /** |
||
56 | * |
||
57 | * @var absences_Collection |
||
58 | */ |
||
59 | protected $collection; |
||
60 | |||
61 | /** |
||
62 | * Cache for user directory entry |
||
63 | * @var array |
||
64 | */ |
||
65 | private $direntry; |
||
66 | |||
67 | /** |
||
68 | * Cache for user organization chart main entity |
||
69 | * @var array |
||
70 | */ |
||
71 | private $ocentity; |
||
72 | |||
73 | |||
74 | /** |
||
75 | * Cache for approbation scheme |
||
76 | * @var array |
||
77 | */ |
||
78 | private $approbation; |
||
79 | |||
80 | /** |
||
81 | * |
||
82 | * @var absences_AgentCet |
||
83 | */ |
||
84 | private $cet; |
||
85 | |||
86 | |||
87 | /** |
||
88 | * |
||
89 | * @var absences_Agent |
||
90 | */ |
||
91 | private static $currentAgent; |
||
92 | |||
93 | |||
94 | /** |
||
95 | * |
||
96 | * @var Array |
||
97 | */ |
||
98 | private $calendar_entities; |
||
99 | |||
100 | |||
101 | /** |
||
102 | * |
||
103 | * @var Array |
||
104 | */ |
||
105 | private $managed_entities; |
||
106 | |||
107 | |||
108 | /** |
||
109 | * Get the agent using the id_user |
||
110 | * @param int $id_user |
||
111 | * @return absences_Agent |
||
112 | */ |
||
113 | 13 | public static function getFromIdUser($id_user) |
|
120 | |||
121 | /** |
||
122 | * Get the logged in agent |
||
123 | * @return absences_Agent |
||
124 | */ |
||
125 | public static function getCurrentUser() |
||
140 | |||
141 | |||
142 | |||
143 | /** |
||
144 | * Get Agent using the ID in "personnel" table |
||
145 | * @return absences_Agent |
||
146 | */ |
||
147 | public static function getFromIdPersonnel($id) |
||
154 | |||
155 | /** |
||
156 | * @return int |
||
157 | */ |
||
158 | 16 | public function getIdUser() |
|
168 | |||
169 | |||
170 | /** |
||
171 | * Regime |
||
172 | * @param absences_Collection $collection |
||
173 | */ |
||
174 | public function setCollection(absences_Collection $collection) |
||
179 | |||
180 | /** |
||
181 | * Regime |
||
182 | * @return absences_Collection |
||
183 | */ |
||
184 | View Code Duplication | public function getCollection() |
|
195 | |||
196 | |||
197 | |||
198 | |||
199 | |||
200 | |||
201 | /** |
||
202 | * Organisme |
||
203 | * @param absences_Organization $organization |
||
204 | */ |
||
205 | public function setOrganization(absences_Organization $organization) |
||
210 | |||
211 | /** |
||
212 | * Organisme |
||
213 | * @return absences_Organization |
||
214 | */ |
||
215 | public function getOrganization() |
||
216 | { |
||
217 | |||
218 | if (!isset($this->organization)) |
||
219 | { |
||
220 | require_once dirname(__FILE__).'/organization.class.php'; |
||
221 | $row = $this->getRow(); |
||
222 | if($row['id_organization'] == 0){ |
||
223 | return null; |
||
224 | } |
||
225 | $this->organization = absences_Organization::getById($row['id_organization']); |
||
226 | } |
||
227 | |||
228 | try { |
||
229 | $this->organization->getRow(); |
||
230 | } catch (Exception $e) { |
||
231 | return null; |
||
232 | } |
||
233 | |||
234 | return $this->organization; |
||
235 | } |
||
236 | |||
237 | |||
238 | |||
239 | |||
240 | |||
241 | /** |
||
242 | * @return string |
||
243 | */ |
||
244 | 8 | public function getName() |
|
248 | |||
249 | |||
250 | |||
251 | /** |
||
252 | * Table row as an array |
||
253 | * @return array |
||
254 | */ |
||
255 | 4 | public function getRow() |
|
287 | |||
288 | |||
289 | /** |
||
290 | * Test if agent exists in personnel members |
||
291 | * @return bool |
||
292 | */ |
||
293 | public function exists() |
||
304 | |||
305 | |||
306 | |||
307 | /** |
||
308 | * All agent requests sorted by creation date |
||
309 | * |
||
310 | * @return absences_RequestIterator |
||
311 | */ |
||
312 | public function getRequestIterator() |
||
319 | |||
320 | |||
321 | |||
322 | /** |
||
323 | * iterateur des droits d'un agent, vue utilisateur au moment de la demande |
||
324 | * droit ouverts, ordonnes alphabetiquement |
||
325 | * |
||
326 | * @return absences_AgentRightUserIterator |
||
327 | */ |
||
328 | public function getAgentRightUserIterator() |
||
336 | |||
337 | |||
338 | |||
339 | /** |
||
340 | * iterateur des droits d'un agent, vue gestionnaire |
||
341 | * tout les droits associes a l'agent, ordonnes par annees, puis alphabetiquement |
||
342 | * |
||
343 | * @return absences_AgentRightManagerIterator |
||
344 | */ |
||
345 | public function getAgentRightManagerIterator() |
||
353 | |||
354 | |||
355 | |||
356 | |||
357 | |||
358 | /** |
||
359 | * Add a vacation right to the agent |
||
360 | * return true if inserted or if already exists |
||
361 | * |
||
362 | * @param absences_Right $right |
||
363 | * @return bool |
||
364 | */ |
||
365 | public function addRight(absences_Right $right) |
||
375 | |||
376 | |||
377 | /** |
||
378 | * Add fixed entry if the right is FIXED |
||
379 | * |
||
380 | * @throws absences_EntryException |
||
381 | * |
||
382 | * @param absences_Right $right |
||
383 | * @param bool $notify |
||
384 | * |
||
385 | * @return bool |
||
386 | */ |
||
387 | public function addFixedEntry(absences_Right $right, $notify = true) |
||
406 | |||
407 | |||
408 | /** |
||
409 | * Add fixed entry if the right is FIXED |
||
410 | * |
||
411 | * @throws absences_EntryException |
||
412 | * |
||
413 | * @param absences_Right $right |
||
414 | * @param bool $notify |
||
415 | * |
||
416 | * @return bool |
||
417 | */ |
||
418 | public function addFixedEntryIfNotExists(absences_Right $right, $notify = true) |
||
430 | |||
431 | |||
432 | |||
433 | /** |
||
434 | * Remove vacation right from agent |
||
435 | * Ne pas autoriser si le regime de l'agent est liee au droit |
||
436 | * return true if link removed or does not exists, return false if remove failed (ex because of collection assignement) |
||
437 | * |
||
438 | * @param absences_Right $right |
||
439 | * @return bool |
||
440 | */ |
||
441 | public function removeRight(absences_Right $right) |
||
470 | |||
471 | /** |
||
472 | * remove fixed entry if the right is FIXED |
||
473 | * @param absences_Right $right |
||
474 | * @param bool $notify |
||
475 | * @return absences_Agent |
||
476 | */ |
||
477 | public function removeFixedEntry(absences_Right $right, $notify = true) |
||
509 | |||
510 | |||
511 | |||
512 | /** |
||
513 | * Test if right is linked to collection |
||
514 | * @param absences_Right $right |
||
515 | * @return boolean |
||
516 | */ |
||
517 | View Code Duplication | public function isLinkedToRight(absences_Right $right) |
|
532 | |||
533 | |||
534 | /** |
||
535 | * Get organizational chart main entity or null |
||
536 | * @return array |
||
537 | */ |
||
538 | public function getMainEntity() |
||
550 | |||
551 | /** |
||
552 | * Get approbation scheme informations |
||
553 | * @return array |
||
554 | */ |
||
555 | public function getApprobation() |
||
570 | |||
571 | |||
572 | /** |
||
573 | * Get superior if the agent is in organizational chart |
||
574 | * @return array |
||
575 | */ |
||
576 | public function getSuperior() |
||
577 | { |
||
578 | require_once $GLOBALS['babInstallPath'].'utilit/afincl.php'; |
||
579 | |||
580 | $id_oc = absences_getVacationOption('id_chart'); |
||
581 | |||
582 | $superior = bab_getSupervisor((int) $this->id_user, $id_oc, 0); |
||
583 | |||
584 | if (!isset($superior['name']) || 0 === count($superior['name'])) { |
||
585 | return null; |
||
586 | } |
||
587 | |||
588 | return $superior; |
||
589 | } |
||
590 | |||
591 | |||
592 | |||
593 | /** |
||
594 | * Get directory entry |
||
595 | * @return array |
||
596 | */ |
||
597 | 1 | public function getDirEntry() |
|
606 | |||
607 | |||
608 | /** |
||
609 | * Date contenue dans la fiche d'annuaire |
||
610 | * formats autorises : |
||
611 | * DD/MM/YYYY |
||
612 | * DD/MM/YY |
||
613 | * D/M/YYYY |
||
614 | * DD-MM-YYYY |
||
615 | * DD-MM-YY |
||
616 | * D-M-YYYY |
||
617 | * |
||
618 | * @param string $fieldname |
||
619 | * |
||
620 | * @return string ISO date |
||
621 | */ |
||
622 | public function getDirEntryDate($fieldname) |
||
644 | |||
645 | |||
646 | |||
647 | /** |
||
648 | * @return bab_dirEntryPhoto |
||
649 | */ |
||
650 | private function getDirEntryPhoto() |
||
660 | |||
661 | /** |
||
662 | * Get icon url only if thumbnailer is present (16x16) |
||
663 | * @return string |
||
664 | */ |
||
665 | public function getIcon() |
||
677 | |||
678 | /** |
||
679 | * Get a small photo to display in agent page or requests page (64x64) |
||
680 | * if the thumbnailer is not present photo is not resized |
||
681 | * @return string |
||
682 | */ |
||
683 | public function getPhoto() |
||
693 | |||
694 | |||
695 | |||
696 | /** |
||
697 | * @return bool |
||
698 | */ |
||
699 | 2 | public function isInPersonnel() |
|
720 | |||
721 | /** |
||
722 | * Test if the user have access to at least one vacation right |
||
723 | * si les droits accessibles ont un solde a 0, la fonction renvoi true malgre tout, seul le nombre de droit accessible est teste |
||
724 | * (certains droits peuvent accepter les soldes negatifs) |
||
725 | * @return bool |
||
726 | */ |
||
727 | public function haveRights() |
||
733 | |||
734 | |||
735 | |||
736 | /** |
||
737 | * @return bool |
||
738 | */ |
||
739 | public function isManager() |
||
744 | |||
745 | /** |
||
746 | * Test si l'agent est un approbateur |
||
747 | * @param int $id_user test si l'agent est l'approbateur d'un demandeur en particulier |
||
748 | * @return bool |
||
749 | */ |
||
750 | public function isApprover($id_user = null) |
||
769 | |||
770 | |||
771 | |||
772 | |||
773 | /** |
||
774 | * Liste des entites gerees par la gestion deleguee |
||
775 | * @return array |
||
776 | */ |
||
777 | public function getManagedEntities() |
||
800 | |||
801 | /** |
||
802 | * Access a la gestion delegee |
||
803 | * @return bool |
||
804 | */ |
||
805 | public function isEntityManager() |
||
811 | |||
812 | |||
813 | /** |
||
814 | * Gestionnaire delegue de l'entite |
||
815 | * @param int $id_entity |
||
816 | * @return bool |
||
817 | */ |
||
818 | public function isEntityManagerOf($id_entity) |
||
832 | |||
833 | |||
834 | |||
835 | /** |
||
836 | * Tester si l'agent est le supperieur d'un autre agent |
||
837 | * @param absences_Agent $agent |
||
838 | * @return bool |
||
839 | */ |
||
840 | public function isSuperiorOf(absences_Agent $agent) |
||
859 | |||
860 | |||
861 | |||
862 | |||
863 | /** |
||
864 | * Liste des entites autorises pour les visualisation de planning |
||
865 | * @return array |
||
866 | */ |
||
867 | public function getCalendarEntities() |
||
889 | |||
890 | /** |
||
891 | * Tester si l'agent a les droits pour voir le planning d'un autre agent |
||
892 | * @param absences_Agent $agent |
||
893 | * @return bool |
||
894 | */ |
||
895 | public function canViewCalendarOf(absences_Agent $agent) |
||
896 | { |
||
897 | if ($this->isManager()) |
||
898 | { |
||
899 | return true; |
||
900 | } |
||
901 | |||
902 | if ($this->isSuperiorOf($agent)) |
||
903 | { |
||
904 | return true; |
||
905 | } |
||
906 | |||
907 | if ($this->isApprover($agent->getIdUser())) |
||
908 | { |
||
909 | return true; |
||
910 | } |
||
911 | |||
912 | if (!$agent->isInPersonnel()) |
||
913 | { |
||
914 | return false; |
||
915 | } |
||
916 | |||
917 | if ($this->getIdUser() === $agent->getIdUser()) |
||
918 | { |
||
919 | return true; |
||
920 | } |
||
921 | |||
922 | if ($this->isSharedCalendarEntity($agent)) |
||
923 | { |
||
924 | return true; |
||
925 | } |
||
926 | |||
927 | if ($this->isInSameEntityPlanning($agent)) |
||
928 | { |
||
929 | return true; |
||
930 | } |
||
931 | |||
932 | return false; |
||
933 | } |
||
934 | |||
935 | |||
936 | |||
937 | |||
938 | /** |
||
939 | * listes des entities de l'agent |
||
940 | * @return array |
||
941 | */ |
||
942 | public function getMemberEntities() |
||
948 | |||
949 | /** |
||
950 | * Liste des ID des entites de l'agent |
||
951 | * @return array |
||
952 | */ |
||
953 | public function getMemberEntityIds() |
||
963 | |||
964 | |||
965 | /** |
||
966 | * Tester si l'agent a acces au planning de l'agent passe en parametre en passant par le partage de planning des entites |
||
967 | * @param absences_Agent $agent |
||
968 | * @return bool |
||
969 | */ |
||
970 | public function isSharedCalendarEntity(absences_Agent $agent) |
||
986 | |||
987 | |||
988 | |||
989 | /** |
||
990 | * Tester si l'agent passe en parametre est dans le meme planning de service et que la visualisation du planning de service est activee |
||
991 | * @param absences_Agent $agent |
||
992 | * @return bool |
||
993 | */ |
||
994 | public function isInSameEntityPlanning(absences_Agent $agent) |
||
1017 | |||
1018 | |||
1019 | public function canViewCustomPlanning($id_planning) |
||
1023 | |||
1024 | |||
1025 | /** |
||
1026 | * Tester si l'agent peut voir le planning d'une autre entite |
||
1027 | * |
||
1028 | * @return bool |
||
1029 | */ |
||
1030 | public function canViewEntityPlanning($id_entity = null) |
||
1063 | |||
1064 | /** |
||
1065 | * Tester si l'agent peut voir le planning de son entite principale |
||
1066 | */ |
||
1067 | public function canViewMainEntityPlanning() |
||
1073 | |||
1074 | |||
1075 | |||
1076 | /** |
||
1077 | * Declaration de jours travailles donnant droit a recuperation |
||
1078 | * @return bool |
||
1079 | */ |
||
1080 | public function canCreateWorkperiodRecoverRequest() |
||
1096 | |||
1097 | |||
1098 | /** |
||
1099 | * @return absences_AgentCet |
||
1100 | */ |
||
1101 | public function Cet() |
||
1112 | |||
1113 | |||
1114 | /** |
||
1115 | * Approbation sheme ID |
||
1116 | * @return int |
||
1117 | */ |
||
1118 | public function getApprobationId() |
||
1122 | |||
1123 | |||
1124 | /** |
||
1125 | * Approbation sheme ID from recover request |
||
1126 | * @return int |
||
1127 | */ |
||
1128 | public function getRecoverApprobationId() |
||
1138 | |||
1139 | |||
1140 | /** |
||
1141 | * Approbation sheme ID from cet request |
||
1142 | * @return int |
||
1143 | */ |
||
1144 | public function getCetApprobationId() |
||
1154 | |||
1155 | |||
1156 | /** |
||
1157 | * Create reports for expired rights of agent |
||
1158 | * |
||
1159 | */ |
||
1160 | public function createReports() |
||
1172 | |||
1173 | |||
1174 | |||
1175 | private function getRecoveryRgroup($quantity_unit) |
||
1190 | |||
1191 | |||
1192 | |||
1193 | /** |
||
1194 | * Create a recovery right for the agent |
||
1195 | * and return the id_right |
||
1196 | * |
||
1197 | * @param string $begin ISO date YYYY-MM-DD |
||
1198 | * @param string $end ISO date YYYY-MM-DD |
||
1199 | * @parap string $description |
||
1200 | * @param float $quantity |
||
1201 | * @param string $quantity_unit D|H |
||
1202 | * |
||
1203 | * @return int |
||
1204 | */ |
||
1205 | public function createRecoveryRight($begin, $end, $description, $quantity, $quantity_unit) |
||
1296 | |||
1297 | |||
1298 | |||
1299 | /** |
||
1300 | * Movements related to the agent |
||
1301 | * @return absences_MovementIterator |
||
1302 | */ |
||
1303 | public function getMovementIterator() |
||
1312 | |||
1313 | |||
1314 | /** |
||
1315 | * |
||
1316 | * @param string $message Generated message |
||
1317 | * @param string $comment Author comment |
||
1318 | */ |
||
1319 | public function addMovement($message, $comment = '') |
||
1329 | |||
1330 | |||
1331 | public function delete() |
||
1353 | |||
1354 | |||
1355 | |||
1356 | public function setEmails($emails) |
||
1363 | |||
1364 | /** |
||
1365 | * @return array |
||
1366 | */ |
||
1367 | public function getEmails() |
||
1371 | |||
1372 | |||
1373 | |||
1374 | |||
1375 | |||
1376 | |||
1377 | |||
1378 | |||
1379 | |||
1380 | |||
1381 | |||
1382 | |||
1383 | |||
1384 | /** |
||
1385 | * Set organization of agent from the "organizationname" field of the directory entry |
||
1386 | * if possible or return false if the organization does not exists |
||
1387 | * |
||
1388 | * @return bool |
||
1389 | */ |
||
1390 | public function setOrganizationFromDirEntry() |
||
1423 | } |
||
1424 | |||
1542 | } |
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.