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 UserBase 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 UserBase, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
27 | abstract class UserBase extends BaseServiceTest |
||
28 | { |
||
29 | /** |
||
30 | * Test a new class and default values on properties. |
||
31 | * |
||
32 | * @covers \eZ\Publish\API\Repository\Values\User\User::__construct |
||
33 | * @covers \eZ\Publish\API\Repository\Values\User\UserGroup::__construct |
||
34 | */ |
||
35 | public function testNewClass() |
||
63 | |||
64 | /** |
||
65 | * Test retrieving missing property. |
||
66 | * |
||
67 | * @covers \eZ\Publish\API\Repository\Values\User\User::__get |
||
68 | * @covers \eZ\Publish\API\Repository\Values\User\UserGroup::__get |
||
69 | */ |
||
70 | public function testMissingProperty() |
||
86 | |||
87 | /** |
||
88 | * Test setting read only property. |
||
89 | * |
||
90 | * @covers \eZ\Publish\API\Repository\Values\User\User::__set |
||
91 | * @covers \eZ\Publish\API\Repository\Values\User\UserGroup::__set |
||
92 | */ |
||
93 | public function testReadOnlyProperty() |
||
109 | |||
110 | /** |
||
111 | * Test if property exists. |
||
112 | * |
||
113 | * @covers \eZ\Publish\API\Repository\Values\User\User::__isset |
||
114 | * @covers \eZ\Publish\API\Repository\Values\User\UserGroup::__isset |
||
115 | */ |
||
116 | View Code Duplication | public function testIsPropertySet() |
|
132 | |||
133 | /** |
||
134 | * Test unsetting a property. |
||
135 | * |
||
136 | * @covers \eZ\Publish\API\Repository\Values\User\User::__unset |
||
137 | * @covers \eZ\Publish\API\Repository\Values\User\UserGroup::__unset |
||
138 | */ |
||
139 | public function testUnsetProperty() |
||
155 | |||
156 | /** |
||
157 | * Test creating new user group. |
||
158 | * |
||
159 | * @covers \eZ\Publish\API\Repository\UserService::createUserGroup |
||
160 | */ |
||
161 | View Code Duplication | public function testCreateUserGroup() |
|
176 | |||
177 | /** |
||
178 | * Test creating new user group throwing ContentFieldValidationException. |
||
179 | * |
||
180 | * @expectedException \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException |
||
181 | * @covers \eZ\Publish\API\Repository\UserService::createUserGroup |
||
182 | */ |
||
183 | public function testCreateUserGroupRequiredFieldEmpty() |
||
184 | { |
||
185 | $userService = $this->repository->getUserService(); |
||
186 | |||
187 | $parentGroup = $userService->loadUserGroup(4); |
||
188 | $userGroupCreateStruct = $userService->newUserGroupCreateStruct('eng-GB'); |
||
189 | $userGroupCreateStruct->ownerId = 14; |
||
190 | $userGroupCreateStruct->sectionId = 1; |
||
191 | $userGroupCreateStruct->setField('name', ''); |
||
192 | |||
193 | $userService->createUserGroup($userGroupCreateStruct, $parentGroup); |
||
194 | } |
||
195 | |||
196 | /** |
||
197 | * Test creating new user group throwing ContentFieldValidationException. |
||
198 | * |
||
199 | * @expectedException \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException |
||
200 | * @covers \eZ\Publish\API\Repository\UserService::createUserGroup |
||
201 | */ |
||
202 | public function testCreateUserGroupRequiredFieldMissing() |
||
203 | { |
||
204 | $userService = $this->repository->getUserService(); |
||
205 | |||
206 | $parentGroup = $userService->loadUserGroup(4); |
||
207 | $userGroupCreateStruct = $userService->newUserGroupCreateStruct('eng-GB'); |
||
208 | |||
209 | $userService->createUserGroup($userGroupCreateStruct, $parentGroup); |
||
210 | } |
||
211 | |||
212 | /** |
||
213 | * Test loading a group. |
||
214 | * |
||
215 | * @covers \eZ\Publish\API\Repository\UserService::loadUserGroup |
||
216 | */ |
||
217 | public function testLoadUserGroup() |
||
223 | |||
224 | /** |
||
225 | * Test loading a group throwing NotFoundException. |
||
226 | * |
||
227 | * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException |
||
228 | * @covers \eZ\Publish\API\Repository\UserService::loadUserGroup |
||
229 | */ |
||
230 | public function testLoadUserGroupThrowsNotFoundException() |
||
235 | |||
236 | /** |
||
237 | * Test loading sub groups. |
||
238 | * |
||
239 | * @covers \eZ\Publish\API\Repository\UserService::loadSubUserGroups |
||
240 | */ |
||
241 | public function testLoadSubUserGroups() |
||
259 | |||
260 | /** |
||
261 | * Test loading sub groups throwing NotFoundException. |
||
262 | * |
||
263 | * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException |
||
264 | * @covers \eZ\Publish\API\Repository\UserService::loadSubUserGroups |
||
265 | */ |
||
266 | View Code Duplication | public function testLoadSubUserGroupsThrowsNotFoundException() |
|
284 | |||
285 | /** |
||
286 | * Test deleting user group. |
||
287 | * |
||
288 | * @covers \eZ\Publish\API\Repository\UserService::deleteUserGroup |
||
289 | */ |
||
290 | public function testDeleteUserGroup() |
||
303 | |||
304 | /** |
||
305 | * Test deleting user group throwing NotFoundException. |
||
306 | * |
||
307 | * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException |
||
308 | * @covers \eZ\Publish\API\Repository\UserService::deleteUserGroup |
||
309 | */ |
||
310 | View Code Duplication | public function testDeleteUserGroupThrowsNotFoundException() |
|
328 | |||
329 | /** |
||
330 | * Test moving a user group below another group. |
||
331 | * |
||
332 | * @covers \eZ\Publish\API\Repository\UserService::moveUserGroup |
||
333 | */ |
||
334 | public function testMoveUserGroup() |
||
351 | |||
352 | /** |
||
353 | * Test moving a user group below another group throwing NotFoundException. |
||
354 | * |
||
355 | * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException |
||
356 | * @covers \eZ\Publish\API\Repository\UserService::moveUserGroup |
||
357 | */ |
||
358 | public function testMoveUserGroupThrowsNotFoundException() |
||
388 | |||
389 | /** |
||
390 | * Test updating a user group. |
||
391 | * |
||
392 | * @covers \eZ\Publish\API\Repository\UserService::updateUserGroup |
||
393 | */ |
||
394 | public function testUpdateUserGroup() |
||
412 | |||
413 | /** |
||
414 | * Test updating a user group throwing ContentFieldValidationException. |
||
415 | * |
||
416 | * @expectedException \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException |
||
417 | * @covers \eZ\Publish\API\Repository\UserService::updateUserGroup |
||
418 | */ |
||
419 | View Code Duplication | public function testUpdateUserGroupRequiredFieldEmpty() |
|
420 | { |
||
421 | $userService = $this->repository->getUserService(); |
||
422 | $contentService = $this->repository->getContentService(); |
||
423 | |||
424 | $userGroup = $userService->loadUserGroup(42); |
||
425 | $userGroupUpdateStruct = $userService->newUserGroupUpdateStruct(); |
||
426 | $userGroupUpdateStruct->contentUpdateStruct = $contentService->newContentUpdateStruct(); |
||
427 | $userGroupUpdateStruct->contentUpdateStruct->setField('name', '', 'eng-US'); |
||
428 | |||
429 | $userService->updateUserGroup($userGroup, $userGroupUpdateStruct); |
||
430 | } |
||
431 | |||
432 | /** |
||
433 | * Test creating a user. |
||
434 | * |
||
435 | * @covers \eZ\Publish\API\Repository\UserService::createUser |
||
436 | */ |
||
437 | public function testCreateUser() |
||
454 | |||
455 | /** |
||
456 | * Test creating a user throwing NotFoundException. |
||
457 | * |
||
458 | * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException |
||
459 | * @covers \eZ\Publish\API\Repository\UserService::createUser |
||
460 | */ |
||
461 | public function testCreateUserThrowsNotFoundException() |
||
485 | |||
486 | /** |
||
487 | * Test creating a user throwing ContentFieldValidationException. |
||
488 | * |
||
489 | * @expectedException \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException |
||
490 | * @covers \eZ\Publish\API\Repository\UserService::createUser |
||
491 | */ |
||
492 | View Code Duplication | public function testCreateUserRequiredFieldsEmpty() |
|
493 | { |
||
494 | $userService = $this->repository->getUserService(); |
||
495 | |||
496 | $userCreateStruct = $userService->newUserCreateStruct('new_user', '[email protected]', 'password', 'eng-GB'); |
||
497 | $userCreateStruct->setField('first_name', '', 'eng-GB'); |
||
498 | $userCreateStruct->setField('last_name', '', 'eng-GB'); |
||
499 | |||
500 | $parentGroup = $userService->loadUserGroup(12); |
||
501 | $userService->createUser($userCreateStruct, array($parentGroup)); |
||
502 | } |
||
503 | |||
504 | /** |
||
505 | * Test creating a user throwing InvalidArgumentException. |
||
506 | * |
||
507 | * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException |
||
508 | * @covers \eZ\Publish\API\Repository\UserService::createUser |
||
509 | */ |
||
510 | View Code Duplication | public function testCreateUserThrowsInvalidArgumentException() |
|
521 | |||
522 | /** |
||
523 | * Test loading a user. |
||
524 | * |
||
525 | * @covers \eZ\Publish\API\Repository\UserService::loadUser |
||
526 | */ |
||
527 | View Code Duplication | public function testLoadUser() |
|
536 | |||
537 | /** |
||
538 | * Test loading a user throwing NotFoundException. |
||
539 | * |
||
540 | * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException |
||
541 | * @covers \eZ\Publish\API\Repository\UserService::loadUser |
||
542 | */ |
||
543 | public function testLoadUserThrowsNotFoundException() |
||
549 | |||
550 | /** |
||
551 | * Test loading anonymous user. |
||
552 | * |
||
553 | * @covers \eZ\Publish\API\Repository\UserService::loadAnonymousUser |
||
554 | */ |
||
555 | View Code Duplication | public function testLoadAnonymousUser() |
|
564 | |||
565 | /** |
||
566 | * Test loading a user by credentials. |
||
567 | * |
||
568 | * @covers \eZ\Publish\API\Repository\UserService::loadUserByCredentials |
||
569 | */ |
||
570 | View Code Duplication | public function testLoadUserByCredentials() |
|
590 | |||
591 | /** |
||
592 | * Test loading a user by credentials throwing NotFoundException. |
||
593 | * |
||
594 | * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException |
||
595 | * @covers \eZ\Publish\API\Repository\UserService::loadUser |
||
596 | */ |
||
597 | public function testLoadUserByCredentialsThrowsNotFoundException() |
||
603 | |||
604 | /** |
||
605 | * Test loading a user by credentials throwing NotFoundException because of bad password. |
||
606 | * |
||
607 | * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException |
||
608 | * @covers \eZ\Publish\API\Repository\UserService::loadUser |
||
609 | */ |
||
610 | public function testLoadUserByCredentialsThrowsNotFoundExceptionBadPassword() |
||
616 | |||
617 | /** |
||
618 | * Test updating a user. |
||
619 | * |
||
620 | * @covers \eZ\Publish\API\Repository\UserService::updateUser |
||
621 | */ |
||
622 | public function testUpdateUser() |
||
647 | |||
648 | /** |
||
649 | * Test updating a user throwing ContentValidationException. |
||
650 | * |
||
651 | * @expectedException \eZ\Publish\API\Repository\Exceptions\ContentValidationException |
||
652 | * @covers \eZ\Publish\API\Repository\UserService::updateUser |
||
653 | */ |
||
654 | View Code Duplication | public function testUpdateUserThrowsContentValidationException() |
|
666 | |||
667 | /** |
||
668 | * Test assigning a user group to user. |
||
669 | * |
||
670 | * @covers \eZ\Publish\API\Repository\UserService::assignUserToUserGroup |
||
671 | */ |
||
672 | public function testAssignUserToUserGroup() |
||
700 | |||
701 | /** |
||
702 | * Test assigning a user group to user throwing InvalidArgumentException. |
||
703 | * |
||
704 | * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException |
||
705 | * @covers \eZ\Publish\API\Repository\UserService::assignUserToUserGroup |
||
706 | */ |
||
707 | View Code Duplication | public function testAssignUserToUserGroupThrowsInvalidArgumentException() |
|
715 | |||
716 | /** |
||
717 | * Test removing a user from user group. |
||
718 | * |
||
719 | * @covers \eZ\Publish\API\Repository\UserService::unAssignUserFromUserGroup |
||
720 | * @depends testAssignUserToUserGroup |
||
721 | */ |
||
722 | public function testUnAssignUserFromUserGroup() |
||
760 | |||
761 | /** |
||
762 | * Test removing a user from user group throwing BadState for removing last group. |
||
763 | * |
||
764 | * @expectedException \eZ\Publish\API\Repository\Exceptions\BadStateException |
||
765 | * @covers \eZ\Publish\API\Repository\UserService::unAssignUserFromUserGroup |
||
766 | */ |
||
767 | View Code Duplication | public function testUnAssignUserFromUserGroupThrowsBadStateException() |
|
776 | |||
777 | /** |
||
778 | * Test removing a user from user group throwing InvalidArgumentException. |
||
779 | * |
||
780 | * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException |
||
781 | * @covers \eZ\Publish\API\Repository\UserService::unAssignUserFromUserGroup |
||
782 | */ |
||
783 | View Code Duplication | public function testUnAssignUserFromUserGroupThrowsInvalidArgumentException() |
|
791 | |||
792 | /** |
||
793 | * Test loading user groups the user belongs to. |
||
794 | * |
||
795 | * @covers \eZ\Publish\API\Repository\UserService::loadUserGroupsOfUser |
||
796 | */ |
||
797 | public function testLoadUserGroupsOfUser() |
||
824 | |||
825 | /** |
||
826 | * Test loading user groups the user belongs to. |
||
827 | * |
||
828 | * @covers \eZ\Publish\API\Repository\UserService::loadUsersOfUserGroup |
||
829 | */ |
||
830 | public function testLoadUsersOfUserGroup() |
||
852 | |||
853 | /** |
||
854 | * Test creating new UserCreateStruct. |
||
855 | * |
||
856 | * @covers \eZ\Publish\API\Repository\UserService::newUserCreateStruct |
||
857 | */ |
||
858 | View Code Duplication | public function testNewUserCreateStruct() |
|
877 | |||
878 | /** |
||
879 | * Test creating new UserGroupCreateStruct. |
||
880 | * |
||
881 | * @covers \eZ\Publish\API\Repository\UserService::newUserGroupCreateStruct |
||
882 | */ |
||
883 | public function testNewUserGroupCreateStruct() |
||
891 | |||
892 | /** |
||
893 | * Test creating new UserUpdateStruct. |
||
894 | * |
||
895 | * @covers \eZ\Publish\API\Repository\UserService::newUserUpdateStruct |
||
896 | */ |
||
897 | public function testNewUserUpdateStruct() |
||
921 | |||
922 | /** |
||
923 | * Test creating new UserGroupUpdateStruct. |
||
924 | * |
||
925 | * @covers \eZ\Publish\API\Repository\UserService::newUserGroupUpdateStruct |
||
926 | */ |
||
927 | public function testNewUserGroupUpdateStruct() |
||
941 | } |
||
942 |
Since your code implements the magic setter
_set
, this function will be called for any write access on an undefined variable. You can add the@property
annotation to your class or interface to document the existence of this variable.Since the property has write access only, you can use the @property-write annotation instead.
Of course, you may also just have mistyped another name, in which case you should fix the error.
See also the PhpDoc documentation for @property.