Complex classes like UserService 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 UserService, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
64 | class UserService implements UserServiceInterface |
||
65 | { |
||
66 | /** @var \eZ\Publish\API\Repository\Repository */ |
||
67 | protected $repository; |
||
68 | |||
69 | /** @var \eZ\Publish\SPI\Persistence\User\Handler */ |
||
70 | protected $userHandler; |
||
71 | |||
72 | /** @var \eZ\Publish\SPI\Persistence\Content\Location\Handler */ |
||
73 | private $locationHandler; |
||
74 | |||
75 | /** @var array */ |
||
76 | protected $settings; |
||
77 | |||
78 | /** @var \Psr\Log\LoggerInterface|null */ |
||
79 | protected $logger; |
||
80 | |||
81 | /** @var \eZ\Publish\API\Repository\PermissionResolver */ |
||
82 | private $permissionResolver; |
||
83 | |||
84 | /** @var \eZ\Publish\Core\Repository\User\PasswordHashServiceInterface */ |
||
85 | private $passwordHashService; |
||
86 | |||
87 | public function setLogger(LoggerInterface $logger = null) |
||
91 | |||
92 | /** |
||
93 | * Setups service with reference to repository object that created it & corresponding handler. |
||
94 | * |
||
95 | * @param \eZ\Publish\API\Repository\Repository $repository |
||
96 | * @param \eZ\Publish\SPI\Persistence\User\Handler $userHandler |
||
97 | * @param \eZ\Publish\SPI\Persistence\Content\Location\Handler $locationHandler |
||
98 | * @param array $settings |
||
99 | */ |
||
100 | public function __construct( |
||
122 | |||
123 | /** |
||
124 | * Creates a new user group using the data provided in the ContentCreateStruct parameter. |
||
125 | * |
||
126 | * In 4.x in the content type parameter in the profile is ignored |
||
127 | * - the content type is determined via configuration and can be set to null. |
||
128 | * The returned version is published. |
||
129 | * |
||
130 | * @param \eZ\Publish\API\Repository\Values\User\UserGroupCreateStruct $userGroupCreateStruct a structure for setting all necessary data to create this user group |
||
131 | * @param \eZ\Publish\API\Repository\Values\User\UserGroup $parentGroup |
||
132 | * |
||
133 | * @return \eZ\Publish\API\Repository\Values\User\UserGroup |
||
134 | * |
||
135 | * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to create a user group |
||
136 | * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if the input structure has invalid data |
||
137 | * @throws \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException if a field in the $userGroupCreateStruct is not valid |
||
138 | * @throws \eZ\Publish\API\Repository\Exceptions\ContentValidationException if a required field is missing or set to an empty value |
||
139 | */ |
||
140 | public function createUserGroup(APIUserGroupCreateStruct $userGroupCreateStruct, APIUserGroup $parentGroup) |
||
173 | |||
174 | /** |
||
175 | * Loads a user group for the given id. |
||
176 | * |
||
177 | * @param mixed $id |
||
178 | * @param string[] $prioritizedLanguages Used as prioritized language code on translated properties of returned object. |
||
179 | * |
||
180 | * @return \eZ\Publish\API\Repository\Values\User\UserGroup |
||
181 | * |
||
182 | * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to create a user group |
||
183 | * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if the user group with the given id was not found |
||
184 | */ |
||
185 | public function loadUserGroup($id, array $prioritizedLanguages = []) |
||
191 | |||
192 | /** |
||
193 | * Loads the sub groups of a user group. |
||
194 | * |
||
195 | * @param \eZ\Publish\API\Repository\Values\User\UserGroup $userGroup |
||
196 | * @param int $offset the start offset for paging |
||
197 | * @param int $limit the number of user groups returned |
||
198 | * @param string[] $prioritizedLanguages Used as prioritized language code on translated properties of returned object. |
||
199 | * |
||
200 | * @return \eZ\Publish\API\Repository\Values\User\UserGroup[] |
||
201 | * |
||
202 | * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to read the user group |
||
203 | */ |
||
204 | public function loadSubUserGroups(APIUserGroup $userGroup, $offset = 0, $limit = 25, array $prioritizedLanguages = []) |
||
238 | |||
239 | /** |
||
240 | * Returns (searches) subgroups of a user group described by its main location. |
||
241 | * |
||
242 | * @param \eZ\Publish\API\Repository\Values\Content\Location $location |
||
243 | * @param int $offset |
||
244 | * @param int $limit |
||
245 | * |
||
246 | * @return \eZ\Publish\API\Repository\Values\Content\Search\SearchResult |
||
247 | */ |
||
248 | protected function searchSubGroups(Location $location, $offset = 0, $limit = 25) |
||
264 | |||
265 | /** |
||
266 | * Removes a user group. |
||
267 | * |
||
268 | * the users which are not assigned to other groups will be deleted. |
||
269 | * |
||
270 | * @param \eZ\Publish\API\Repository\Values\User\UserGroup $userGroup |
||
271 | * |
||
272 | * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to create a user group |
||
273 | */ |
||
274 | public function deleteUserGroup(APIUserGroup $userGroup) |
||
290 | |||
291 | /** |
||
292 | * Moves the user group to another parent. |
||
293 | * |
||
294 | * @param \eZ\Publish\API\Repository\Values\User\UserGroup $userGroup |
||
295 | * @param \eZ\Publish\API\Repository\Values\User\UserGroup $newParent |
||
296 | * |
||
297 | * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to move the user group |
||
298 | */ |
||
299 | public function moveUserGroup(APIUserGroup $userGroup, APIUserGroup $newParent) |
||
330 | |||
331 | /** |
||
332 | * Updates the group profile with fields and meta data. |
||
333 | * |
||
334 | * 4.x: If the versionUpdateStruct is set in $userGroupUpdateStruct, this method internally creates a content draft, updates ts with the provided data |
||
335 | * and publishes the draft. If a draft is explicitly required, the user group can be updated via the content service methods. |
||
336 | * |
||
337 | * @param \eZ\Publish\API\Repository\Values\User\UserGroup $userGroup |
||
338 | * @param \eZ\Publish\API\Repository\Values\User\UserGroupUpdateStruct $userGroupUpdateStruct |
||
339 | * |
||
340 | * @return \eZ\Publish\API\Repository\Values\User\UserGroup |
||
341 | * |
||
342 | * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to update the user group |
||
343 | * @throws \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException if a field in the $userGroupUpdateStruct is not valid |
||
344 | * @throws \eZ\Publish\API\Repository\Exceptions\ContentValidationException if a required field is set empty |
||
345 | */ |
||
346 | public function updateUserGroup(APIUserGroup $userGroup, UserGroupUpdateStruct $userGroupUpdateStruct) |
||
387 | |||
388 | /** |
||
389 | * Create a new user. The created user is published by this method. |
||
390 | * |
||
391 | * @param \eZ\Publish\API\Repository\Values\User\UserCreateStruct $userCreateStruct the data used for creating the user |
||
392 | * @param \eZ\Publish\API\Repository\Values\User\UserGroup[] $parentGroups the groups which are assigned to the user after creation |
||
393 | * |
||
394 | * @return \eZ\Publish\API\Repository\Values\User\User |
||
395 | * |
||
396 | * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to move the user group |
||
397 | * @throws \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException if a field in the $userCreateStruct is not valid |
||
398 | * @throws \eZ\Publish\API\Repository\Exceptions\ContentValidationException if a required field is missing or set to an empty value |
||
399 | * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if a user with provided login already exists |
||
400 | */ |
||
401 | public function createUser(APIUserCreateStruct $userCreateStruct, array $parentGroups) |
||
455 | |||
456 | /** |
||
457 | * Loads a user. |
||
458 | * |
||
459 | * @param mixed $userId |
||
460 | * @param string[] $prioritizedLanguages Used as prioritized language code on translated properties of returned object. |
||
461 | * |
||
462 | * @return \eZ\Publish\API\Repository\Values\User\User |
||
463 | * |
||
464 | * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if a user with the given id was not found |
||
465 | */ |
||
466 | public function loadUser($userId, array $prioritizedLanguages = []) |
||
497 | |||
498 | /** |
||
499 | * Loads a user for the given login and password. |
||
500 | * |
||
501 | * If the password hash type differs from that configured for the service, it will be updated to the configured one. |
||
502 | * |
||
503 | * {@inheritdoc} |
||
504 | * |
||
505 | * @param string $login |
||
506 | * @param string $password the plain password |
||
507 | * @param string[] $prioritizedLanguages Used as prioritized language code on translated properties of returned object. |
||
508 | * |
||
509 | * @return \eZ\Publish\API\Repository\Values\User\User |
||
510 | * |
||
511 | * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if credentials are invalid |
||
512 | * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if a user with the given credentials was not found |
||
513 | */ |
||
514 | public function loadUserByCredentials($login, $password, array $prioritizedLanguages = []) |
||
534 | |||
535 | /** |
||
536 | * Update password hash to the type configured for the service, if they differ. |
||
537 | * |
||
538 | * @param string $login User login |
||
539 | * @param string $password User password |
||
540 | * @param \eZ\Publish\SPI\Persistence\User $spiUser |
||
541 | * |
||
542 | * @throws \eZ\Publish\Core\Base\Exceptions\BadStateException if the password is not correctly saved, in which case the update is reverted |
||
543 | */ |
||
544 | private function updatePasswordHash($login, $password, SPIUser $spiUser) |
||
573 | |||
574 | /** |
||
575 | * Loads a user for the given login. |
||
576 | * |
||
577 | * {@inheritdoc} |
||
578 | * |
||
579 | * @param string $login |
||
580 | * @param string[] $prioritizedLanguages Used as prioritized language code on translated properties of returned object. |
||
581 | * |
||
582 | * @return \eZ\Publish\API\Repository\Values\User\User |
||
583 | * |
||
584 | * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if a user with the given credentials was not found |
||
585 | */ |
||
586 | public function loadUserByLogin($login, array $prioritizedLanguages = []) |
||
596 | |||
597 | /** |
||
598 | * Loads a user for the given email. |
||
599 | * |
||
600 | * {@inheritdoc} |
||
601 | * |
||
602 | * @param string $email |
||
603 | * @param string[] $prioritizedLanguages Used as prioritized language code on translated properties of returned object. |
||
604 | * |
||
605 | * @return \eZ\Publish\API\Repository\Values\User\User[] |
||
606 | */ |
||
607 | public function loadUsersByEmail($email, array $prioritizedLanguages = []) |
||
620 | |||
621 | /** |
||
622 | * Loads a user for the given token. |
||
623 | * |
||
624 | * {@inheritdoc} |
||
625 | * |
||
626 | * @param string $hash |
||
627 | * @param string[] $prioritizedLanguages Used as prioritized language code on translated properties of returned object. |
||
628 | * |
||
629 | * @return \eZ\Publish\API\Repository\Values\User\User |
||
630 | * |
||
631 | * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException |
||
632 | * @throws \eZ\Publish\Core\Base\Exceptions\InvalidArgumentValue |
||
633 | */ |
||
634 | public function loadUserByToken($hash, array $prioritizedLanguages = []) |
||
644 | |||
645 | /** |
||
646 | * This method deletes a user. |
||
647 | * |
||
648 | * @param \eZ\Publish\API\Repository\Values\User\User $user |
||
649 | * |
||
650 | * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to delete the user |
||
651 | */ |
||
652 | public function deleteUser(APIUser $user) |
||
670 | |||
671 | /** |
||
672 | * Updates a user. |
||
673 | * |
||
674 | * 4.x: If the versionUpdateStruct is set in the user update structure, this method internally creates a content draft, updates ts with the provided data |
||
675 | * and publishes the draft. If a draft is explicitly required, the user group can be updated via the content service methods. |
||
676 | * |
||
677 | * @param \eZ\Publish\API\Repository\Values\User\User $user |
||
678 | * @param \eZ\Publish\API\Repository\Values\User\UserUpdateStruct $userUpdateStruct |
||
679 | * |
||
680 | * @throws \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException if a field in the $userUpdateStruct is not valid |
||
681 | * @throws \eZ\Publish\API\Repository\Exceptions\ContentValidationException if a required field is set empty |
||
682 | * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to update the user |
||
683 | * |
||
684 | * @return \eZ\Publish\API\Repository\Values\User\User |
||
685 | */ |
||
686 | public function updateUser(APIUser $user, UserUpdateStruct $userUpdateStruct) |
||
782 | |||
783 | /** |
||
784 | * Update the user token information specified by the user token struct. |
||
785 | * |
||
786 | * @param \eZ\Publish\API\Repository\Values\User\User $user |
||
787 | * @param \eZ\Publish\API\Repository\Values\User\UserTokenUpdateStruct $userTokenUpdateStruct |
||
788 | * |
||
789 | * @throws \eZ\Publish\Core\Base\Exceptions\InvalidArgumentValue |
||
790 | * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException |
||
791 | * @throws \RuntimeException |
||
792 | * @throws \Exception |
||
793 | * |
||
794 | * @return \eZ\Publish\API\Repository\Values\User\User |
||
795 | */ |
||
796 | public function updateUserToken(APIUser $user, UserTokenUpdateStruct $userTokenUpdateStruct) |
||
827 | |||
828 | /** |
||
829 | * Expires user token with user hash. |
||
830 | * |
||
831 | * @param string $hash |
||
832 | */ |
||
833 | public function expireUserToken($hash) |
||
844 | |||
845 | /** |
||
846 | * Assigns a new user group to the user. |
||
847 | * |
||
848 | * @param \eZ\Publish\API\Repository\Values\User\User $user |
||
849 | * @param \eZ\Publish\API\Repository\Values\User\UserGroup $userGroup |
||
850 | * |
||
851 | * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to assign the user group to the user |
||
852 | * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if the user is already in the given user group |
||
853 | */ |
||
854 | public function assignUserToUserGroup(APIUser $user, APIUserGroup $userGroup) |
||
891 | |||
892 | /** |
||
893 | * Removes a user group from the user. |
||
894 | * |
||
895 | * @param \eZ\Publish\API\Repository\Values\User\User $user |
||
896 | * @param \eZ\Publish\API\Repository\Values\User\UserGroup $userGroup |
||
897 | * |
||
898 | * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to remove the user group from the user |
||
899 | * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if the user is not in the given user group |
||
900 | * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException If $userGroup is the last assigned user group |
||
901 | */ |
||
902 | public function unAssignUserFromUserGroup(APIUser $user, APIUserGroup $userGroup) |
||
939 | |||
940 | /** |
||
941 | * Loads the user groups the user belongs to. |
||
942 | * |
||
943 | * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed read the user or user group |
||
944 | * |
||
945 | * @param \eZ\Publish\API\Repository\Values\User\User $user |
||
946 | * @param int $offset the start offset for paging |
||
947 | * @param int $limit the number of user groups returned |
||
948 | * @param string[] $prioritizedLanguages Used as prioritized language code on translated properties of returned object. |
||
949 | * |
||
950 | * @return \eZ\Publish\API\Repository\Values\User\UserGroup[] |
||
951 | */ |
||
952 | public function loadUserGroupsOfUser(APIUser $user, $offset = 0, $limit = 25, array $prioritizedLanguages = []) |
||
998 | |||
999 | /** |
||
1000 | * Loads the users of a user group. |
||
1001 | * |
||
1002 | * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to read the users or user group |
||
1003 | * |
||
1004 | * @param \eZ\Publish\API\Repository\Values\User\UserGroup $userGroup |
||
1005 | * @param int $offset the start offset for paging |
||
1006 | * @param int $limit the number of users returned |
||
1007 | * @param string[] $prioritizedLanguages Used as prioritized language code on translated properties of returned object. |
||
1008 | * |
||
1009 | * @return \eZ\Publish\API\Repository\Values\User\User[] |
||
1010 | */ |
||
1011 | public function loadUsersOfUserGroup( |
||
1056 | |||
1057 | /** |
||
1058 | * {@inheritdoc} |
||
1059 | */ |
||
1060 | public function isUser(APIContent $content): bool |
||
1077 | |||
1078 | /** |
||
1079 | * {@inheritdoc} |
||
1080 | */ |
||
1081 | public function isUserGroup(APIContent $content): bool |
||
1085 | |||
1086 | /** |
||
1087 | * Instantiate a user create class. |
||
1088 | * |
||
1089 | * @param string $login the login of the new user |
||
1090 | * @param string $email the email of the new user |
||
1091 | * @param string $password the plain password of the new user |
||
1092 | * @param string $mainLanguageCode the main language for the underlying content object |
||
1093 | * @param \eZ\Publish\API\Repository\Values\ContentType\ContentType $contentType 5.x the content type for the underlying content object. In 4.x it is ignored and taken from the configuration |
||
1094 | * |
||
1095 | * @return \eZ\Publish\API\Repository\Values\User\UserCreateStruct |
||
1096 | */ |
||
1097 | public function newUserCreateStruct($login, $email, $password, $mainLanguageCode, $contentType = null) |
||
1138 | |||
1139 | /** |
||
1140 | * Instantiate a user group create class. |
||
1141 | * |
||
1142 | * @param string $mainLanguageCode The main language for the underlying content object |
||
1143 | * @param null|\eZ\Publish\API\Repository\Values\ContentType\ContentType $contentType 5.x the content type for the underlying content object. In 4.x it is ignored and taken from the configuration |
||
1144 | * |
||
1145 | * @return \eZ\Publish\API\Repository\Values\User\UserGroupCreateStruct |
||
1146 | */ |
||
1147 | public function newUserGroupCreateStruct($mainLanguageCode, $contentType = null) |
||
1163 | |||
1164 | /** |
||
1165 | * Instantiate a new user update struct. |
||
1166 | * |
||
1167 | * @return \eZ\Publish\API\Repository\Values\User\UserUpdateStruct |
||
1168 | */ |
||
1169 | public function newUserUpdateStruct() |
||
1173 | |||
1174 | /** |
||
1175 | * Instantiate a new user group update struct. |
||
1176 | * |
||
1177 | * @return \eZ\Publish\API\Repository\Values\User\UserGroupUpdateStruct |
||
1178 | */ |
||
1179 | public function newUserGroupUpdateStruct() |
||
1183 | |||
1184 | /** |
||
1185 | * {@inheritdoc} |
||
1186 | */ |
||
1187 | public function validatePassword(string $password, PasswordValidationContext $context = null): array |
||
1232 | |||
1233 | /** |
||
1234 | * Builds the domain UserGroup object from provided Content object. |
||
1235 | * |
||
1236 | * @param \eZ\Publish\API\Repository\Values\Content\Content $content |
||
1237 | * |
||
1238 | * @return \eZ\Publish\API\Repository\Values\User\UserGroup |
||
1239 | */ |
||
1240 | protected function buildDomainUserGroupObject(APIContent $content) |
||
1258 | |||
1259 | /** |
||
1260 | * Builds the domain user object from provided persistence user object. |
||
1261 | * |
||
1262 | * @param \eZ\Publish\SPI\Persistence\User $spiUser |
||
1263 | * @param \eZ\Publish\API\Repository\Values\Content\Content|null $content |
||
1264 | * @param string[] $prioritizedLanguages Used as prioritized language code on translated properties of returned object. |
||
1265 | * |
||
1266 | * @return \eZ\Publish\API\Repository\Values\User\User |
||
1267 | */ |
||
1268 | protected function buildDomainUserObject( |
||
1293 | |||
1294 | public function getPasswordInfo(APIUser $user): PasswordInfo |
||
1325 | |||
1326 | private function getUserFieldDefinition(ContentType $contentType): ?FieldDefinition |
||
1336 | |||
1337 | /** |
||
1338 | * Verifies if the provided login and password are valid for eZ\Publish\SPI\Persistence\User. |
||
1339 | * |
||
1340 | * @param string $login User login |
||
1341 | * @param string $password User password |
||
1342 | * @param \eZ\Publish\SPI\Persistence\User $spiUser Loaded user handler |
||
1343 | * |
||
1344 | * @return bool return true if the login and password are sucessfully validated and false, if not. |
||
1345 | */ |
||
1346 | protected function comparePasswordHashForSPIUser(string $login, string $password, SPIUser $spiUser): bool |
||
1350 | |||
1351 | /** |
||
1352 | * Verifies if the provided login and password are valid for eZ\Publish\API\Repository\Values\User\User. |
||
1353 | * |
||
1354 | * @param string $login User login |
||
1355 | * @param string $password User password |
||
1356 | * @param \eZ\Publish\API\Repository\Values\User\User $apiUser Loaded user |
||
1357 | * |
||
1358 | * @return bool return true if the login and password are sucessfully validated and false, if not. |
||
1359 | */ |
||
1360 | protected function comparePasswordHashForAPIUser(string $login, string $password, APIUser $apiUser): bool |
||
1364 | |||
1365 | /** |
||
1366 | * Verifies if the provided login and password are valid against given password hash and hash type. |
||
1367 | * |
||
1368 | * @param string $login User login |
||
1369 | * @param string $plainPassword User password |
||
1370 | * @param string $passwordHash User password hash |
||
1371 | * @param int $hashAlgorithm Hash type |
||
1372 | * |
||
1373 | * @return bool return true if the login and password are sucessfully validated and false, if not. |
||
1374 | */ |
||
1375 | private function comparePasswordHashes( |
||
1383 | |||
1384 | /** |
||
1385 | * Return true if any of the UserUpdateStruct properties refers to User Profile (Content) update. |
||
1386 | * |
||
1387 | * @param UserUpdateStruct $userUpdateStruct |
||
1388 | * |
||
1389 | * @return bool |
||
1390 | */ |
||
1391 | private function isUserProfileUpdateRequested(UserUpdateStruct $userUpdateStruct) |
||
1400 | |||
1401 | private function getDateTime(?int $timestamp): ?DateTimeInterface |
||
1413 | } |
||
1414 |
This check marks calls to methods that do not seem to exist on an object.
This is most likely the result of a method being renamed without all references to it being renamed likewise.