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 User 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 User, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
54 | class User |
||
55 | { |
||
56 | const ERROR_UNDEFINED_PARAMETER = 'Following parameter must to be defined: '; |
||
57 | const ERROR_USER_ADD = 'Account could not be created. '; |
||
58 | const ERROR_USER_CANNOT_CREATE_USER = 'User account could not be created. '; |
||
59 | const ERROR_USER_CANNOT_CREATE_USERDATA = 'Entry for user data could not be created. '; |
||
60 | const ERROR_USER_CANNOT_DELETE_USER = 'User account could not be deleted. '; |
||
61 | const ERROR_USER_CANNOT_DELETE_USERDATA = 'Entry for user data could not be deleted. '; |
||
62 | const ERROR_USER_CANNOT_UPDATE_USERDATA = 'Entry for user data could not be updated. '; |
||
63 | const ERROR_USER_CHANGE = 'Account could not be updated. '; |
||
64 | const ERROR_USER_DELETE = 'Account could not be deleted. '; |
||
65 | const ERROR_USER_INCORRECT_LOGIN = 'Specified login could not be found. '; |
||
66 | const ERROR_USER_INCORRECT_PASSWORD = 'Specified password is not correct.'; |
||
67 | const ERROR_USER_INVALID_STATUS = 'Undefined user status.'; |
||
68 | const ERROR_USER_LOGINNAME_TOO_SHORT = 'The chosen loginname is too short.'; |
||
69 | const ERROR_USER_LOGIN_NOT_UNIQUE = 'Specified login name already exists. '; |
||
70 | const ERROR_USER_LOGIN_INVALID = 'The chosen login is invalid. A valid login has at least four characters. Only letters, numbers and underscore _ are allowed. The first letter must be a letter. '; |
||
71 | const ERROR_USER_NO_AUTH = 'No authentication method specified. '; |
||
72 | const ERROR_USER_NO_DB = 'No database specified.'; |
||
73 | const ERROR_USER_NO_PERM = 'No permission container specified.'; |
||
74 | const ERROR_USER_NO_USERID = 'No user-ID found. '; |
||
75 | const ERROR_USER_NO_USERLOGINDATA = 'No user login data found. '; |
||
76 | const ERROR_USER_NOT_FOUND = 'User account could not be found. '; |
||
77 | const ERROR_USER_NOWRITABLE = 'No authentication object is writable. '; |
||
78 | const ERROR_USER_NO_LOGIN_DATA = 'A username and password must be provided. '; |
||
79 | const ERROR_USER_TOO_MANY_FAILED_LOGINS = 'You exceeded the maximum amounts of login attempts and are temporarily blocked. Please try again later.'; |
||
80 | |||
81 | const STATUS_USER_PROTECTED = 'User account is protected. '; |
||
82 | const STATUS_USER_BLOCKED = 'User account is blocked. '; |
||
83 | const STATUS_USER_ACTIVE = 'User account is active. '; |
||
84 | |||
85 | // --- ATTRIBUTES --- |
||
86 | |||
87 | /** |
||
88 | * Permission container. |
||
89 | * |
||
90 | * @var BasicPermission|MediumPermission |
||
91 | */ |
||
92 | public $perm = null; |
||
93 | |||
94 | /** |
||
95 | * User-data storage container. |
||
96 | * |
||
97 | * @var UserData |
||
98 | */ |
||
99 | public $userdata = null; |
||
100 | |||
101 | /** |
||
102 | * Default Authentication properties. |
||
103 | * |
||
104 | * @var array |
||
105 | */ |
||
106 | private $authData = [ |
||
107 | 'authSource' => [ |
||
108 | 'name' => 'database', |
||
109 | 'type' => 'local', |
||
110 | ], |
||
111 | 'encType' => PMF_ENCRYPTION_TYPE, |
||
112 | 'readOnly' => false, |
||
113 | ]; |
||
114 | |||
115 | /** |
||
116 | * Public array that contains error messages. |
||
117 | * |
||
118 | * @var array |
||
119 | */ |
||
120 | public $errors = []; |
||
121 | |||
122 | /** |
||
123 | * authentication container. |
||
124 | * |
||
125 | * @var Driver[] |
||
126 | */ |
||
127 | protected $authContainer = []; |
||
128 | |||
129 | /** |
||
130 | * login string. |
||
131 | * |
||
132 | * @var string |
||
133 | */ |
||
134 | private $login = ''; |
||
135 | |||
136 | /** |
||
137 | * minimum length of login string (default: 2). |
||
138 | * |
||
139 | * @var int |
||
140 | */ |
||
141 | private $loginMinLength = 2; |
||
142 | |||
143 | /** |
||
144 | * regular expression to find invalid login strings |
||
145 | * (default: /^[a-z0-9][\w\.\-@]+/i ). |
||
146 | * |
||
147 | * @var string |
||
148 | */ |
||
149 | private $validUsername = '/^[a-z0-9][\w\.\-@]+/i'; |
||
150 | |||
151 | /** |
||
152 | * user ID. |
||
153 | * |
||
154 | * @var int |
||
155 | */ |
||
156 | private $userId = -1; |
||
157 | |||
158 | /** |
||
159 | * Status of user. |
||
160 | * |
||
161 | * @var string |
||
162 | */ |
||
163 | private $status = ''; |
||
164 | |||
165 | /** |
||
166 | * IS the user a super admin? |
||
167 | * @var bool |
||
168 | */ |
||
169 | private $isSuperAdmin = false; |
||
170 | |||
171 | /** |
||
172 | * array of allowed values for status. |
||
173 | * |
||
174 | * @var array |
||
175 | */ |
||
176 | private $allowedStatus = [ |
||
177 | 'active' => self::STATUS_USER_ACTIVE, |
||
178 | 'blocked' => self::STATUS_USER_BLOCKED, |
||
179 | 'protected' => self::STATUS_USER_PROTECTED, |
||
180 | ]; |
||
181 | |||
182 | /** |
||
183 | * Configuration. |
||
184 | * |
||
185 | * @var Configuration |
||
186 | */ |
||
187 | protected $config = null; |
||
188 | |||
189 | /** |
||
190 | * Constructor. |
||
191 | * |
||
192 | * @param Configuration $config |
||
193 | */ |
||
194 | public function __construct(Configuration $config) |
||
227 | |||
228 | /** |
||
229 | * adds a permission object to the user. |
||
230 | * |
||
231 | * @param Permission $perm Permission object |
||
232 | * |
||
233 | * @return bool |
||
234 | */ |
||
235 | public function addPerm(Permission $perm) |
||
245 | |||
246 | /** |
||
247 | * Returns the User ID of the user. |
||
248 | * |
||
249 | * @return int |
||
250 | */ |
||
251 | public function getUserId() |
||
261 | |||
262 | /** |
||
263 | * Loads basic user information from the database selecting the user with |
||
264 | * specified user-ID. |
||
265 | * |
||
266 | * @param int $userId User ID |
||
267 | * @param bool $allowBlockedUsers Allow blocked users as well, e.g. in admin |
||
268 | * |
||
269 | * @return bool |
||
270 | */ |
||
271 | public function getUserById($userId, $allowBlockedUsers = false) |
||
328 | |||
329 | /** |
||
330 | * loads basic user information from the database selecting the user with |
||
331 | * specified login. |
||
332 | * |
||
333 | * @param string $login Login name |
||
334 | * @param bool $raiseError Raise error? |
||
335 | * |
||
336 | * @return bool |
||
337 | */ |
||
338 | View Code Duplication | public function getUserByLogin($login, $raiseError = true) |
|
374 | |||
375 | /** |
||
376 | * loads basic user information from the database selecting the user with |
||
377 | * specified cookie information. |
||
378 | * |
||
379 | * @param string $cookie |
||
380 | * |
||
381 | * @return bool |
||
382 | */ |
||
383 | View Code Duplication | public function getUserByCookie($cookie) |
|
423 | |||
424 | /** |
||
425 | * Checks if display name is already used. Returns true, if already in use. |
||
426 | * |
||
427 | * @param string $name |
||
428 | * |
||
429 | * @return bool |
||
430 | */ |
||
431 | View Code Duplication | public function checkDisplayName($name) |
|
443 | |||
444 | /** |
||
445 | * Checks if email address is already used. Returns true, if already in use. |
||
446 | * |
||
447 | * @param string $name |
||
448 | * |
||
449 | * @return bool |
||
450 | */ |
||
451 | View Code Duplication | public function checkMailAddress($name) |
|
463 | |||
464 | /** |
||
465 | * search users by login. |
||
466 | * |
||
467 | * @param string $search Login name |
||
468 | * |
||
469 | * @return array |
||
470 | */ |
||
471 | public function searchUsers($search) |
||
498 | |||
499 | /** |
||
500 | * Creates a new user and stores basic data in the database. |
||
501 | * |
||
502 | * @param string $login |
||
503 | * @param string $pass |
||
504 | * @param string $domain |
||
505 | * @param int $userId |
||
506 | * |
||
507 | * @return boolean |
||
508 | */ |
||
509 | public function createUser($login, $pass = '', $domain = '', $userId = 0) |
||
590 | |||
591 | /** |
||
592 | * deletes the user from the database. |
||
593 | * |
||
594 | * @return bool |
||
595 | */ |
||
596 | public function deleteUser() |
||
665 | |||
666 | /** |
||
667 | * changes the user's password. If $pass is omitted, a new |
||
668 | * password is generated using the createPassword() method. |
||
669 | * |
||
670 | * @param string $pass Password |
||
671 | * |
||
672 | * @return bool |
||
673 | */ |
||
674 | public function changePassword($pass = '') |
||
701 | |||
702 | /** |
||
703 | * returns the user's status. |
||
704 | * |
||
705 | * @return string |
||
706 | */ |
||
707 | public function getStatus() |
||
715 | |||
716 | /** |
||
717 | * Sets the user's status and updates the database entry. |
||
718 | * |
||
719 | * @param string $status Status |
||
720 | * @return bool |
||
721 | */ |
||
722 | public function setStatus($status) |
||
754 | |||
755 | /** |
||
756 | * Returns a string with error messages. |
||
757 | * |
||
758 | * The string returned by error() contains messages for all errors that |
||
759 | * during object procesing. Messages are separated by new lines. |
||
760 | * |
||
761 | * Error messages are stored in the public array errors. |
||
762 | * |
||
763 | * @return string |
||
764 | */ |
||
765 | public function error() |
||
775 | |||
776 | /** |
||
777 | * returns true if login is a valid login string. |
||
778 | * |
||
779 | * $this->loginMinLength defines the minimum length the |
||
780 | * login string. If login has more characters than allowed, |
||
781 | * false is returned. |
||
782 | * $this->login_invalidRegExp is a regular expression. |
||
783 | * If login matches this false is returned. |
||
784 | * |
||
785 | * @param string $login Login name |
||
786 | * |
||
787 | * @return bool |
||
788 | */ |
||
789 | public function isValidLogin($login) |
||
801 | |||
802 | /** |
||
803 | * adds a new authentication object to the user object. |
||
804 | * |
||
805 | * @param Driver $auth Driver object |
||
806 | * @param string $name Auth name |
||
807 | * |
||
808 | * @return bool |
||
809 | */ |
||
810 | public function addAuth($auth, $name) |
||
820 | |||
821 | /** |
||
822 | * Returns true if auth is a valid authentication object. |
||
823 | * |
||
824 | * @param Driver $auth Auth object |
||
825 | * |
||
826 | * @return bool |
||
827 | */ |
||
828 | protected function checkAuth($auth) |
||
840 | |||
841 | /** |
||
842 | * Returns the data aof the auth container. |
||
843 | * |
||
844 | * @return Driver[] |
||
845 | */ |
||
846 | public function getAuthContainer() |
||
850 | |||
851 | /** |
||
852 | * Returns a specific entry from the auth data source array. |
||
853 | * |
||
854 | * @param string $key |
||
855 | * |
||
856 | * @return string|null |
||
857 | */ |
||
858 | public function getAuthSource($key) |
||
866 | |||
867 | /** |
||
868 | * Returns a specific entry from the auth data array. |
||
869 | * |
||
870 | * @param string $key |
||
871 | * |
||
872 | * @return string|null |
||
873 | */ |
||
874 | public function getAuthData($key) |
||
882 | |||
883 | /** |
||
884 | * returns true if perm is a valid permission object. |
||
885 | * |
||
886 | * @param Permission $perm Permission object |
||
887 | * |
||
888 | * @return bool |
||
889 | */ |
||
890 | private function checkPerm($perm) |
||
899 | |||
900 | /** |
||
901 | * returns the user's login. |
||
902 | * |
||
903 | * @return string |
||
904 | */ |
||
905 | public function getLogin() |
||
909 | |||
910 | /** |
||
911 | * Returns the data of the current user. |
||
912 | * |
||
913 | * @param string $field Field |
||
914 | * |
||
915 | * @return array|string|int |
||
916 | */ |
||
917 | public function getUserData($field = '*') |
||
925 | |||
926 | /** |
||
927 | * Adds user data. |
||
928 | * |
||
929 | * @param array $data Array with user data |
||
930 | * |
||
931 | * @return bool |
||
932 | */ |
||
933 | public function setUserData(Array $data) |
||
942 | |||
943 | /** |
||
944 | * Returns an array with the user-IDs of all users found in |
||
945 | * the database. By default, the Anonymous User will not be returned. |
||
946 | * |
||
947 | * @param bool $withoutAnonymous Without anonymous? |
||
948 | * @param bool $allowBlockedUsers Allow blocked users as well, e.g. in admin |
||
949 | * |
||
950 | * @return array |
||
951 | */ |
||
952 | View Code Duplication | public function getAllUsers($withoutAnonymous = true, $allowBlockedUsers = true) |
|
982 | |||
983 | /** |
||
984 | * Returns an array of all users found in the database. By default, the |
||
985 | * anonymous User will not be returned. The returned array contains the |
||
986 | * user ID as key, the values are login name, account status, authentication |
||
987 | * source and the user creation date. |
||
988 | * |
||
989 | * @param bool $withoutAnonymous Without anonymous? |
||
990 | * |
||
991 | * @return array |
||
992 | */ |
||
993 | View Code Duplication | public function getAllUserData($withoutAnonymous = true) |
|
1018 | |||
1019 | /** |
||
1020 | * Get all users in <option> tags. |
||
1021 | * |
||
1022 | * @param int $id Selected user ID |
||
1023 | * @param bool $allowBlockedUsers Allow blocked users as well, e.g. in admin |
||
1024 | * |
||
1025 | * @return string |
||
1026 | */ |
||
1027 | public function getAllUserOptions($id = 1, $allowBlockedUsers = false) |
||
1047 | |||
1048 | /** |
||
1049 | * sets the minimum login string length. |
||
1050 | * |
||
1051 | * @param int $loginMinLength Minimum length of login name |
||
1052 | */ |
||
1053 | public function setLoginMinLength($loginMinLength) |
||
1059 | |||
1060 | /** |
||
1061 | * Returns a new password. |
||
1062 | * |
||
1063 | * @param int $minimumLength |
||
1064 | * @param bool $allowUnderscore |
||
1065 | * |
||
1066 | * @return string |
||
1067 | */ |
||
1068 | public function createPassword($minimumLength = 8, $allowUnderscore = true) |
||
1113 | |||
1114 | /** |
||
1115 | * Sends mail to the current user. |
||
1116 | * |
||
1117 | * @param string $subject |
||
1118 | * @param string $message |
||
1119 | * @return bool |
||
1120 | */ |
||
1121 | public function mailUser($subject, $message) |
||
1132 | |||
1133 | /** |
||
1134 | * Returns true on success. |
||
1135 | * |
||
1136 | * This will change a users status to active, and send an email with a new password. |
||
1137 | * |
||
1138 | * @return bool |
||
1139 | */ |
||
1140 | public function activateUser() |
||
1164 | |||
1165 | /** |
||
1166 | * Returns true, if a user is a super admin. |
||
1167 | * @return bool |
||
1168 | */ |
||
1169 | public function isSuperAdmin() |
||
1173 | |||
1174 | /** |
||
1175 | * Sets the users "is_superadmin" flag and updates the database entry. |
||
1176 | * @param $isSuperAdmin |
||
1177 | * @return bool |
||
1178 | */ |
||
1179 | public function setSuperAdmin($isSuperAdmin) |
||
1202 | } |
||
1203 |
This check looks at variables that are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.