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 UserContext 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 UserContext, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 25 | class UserContext implements Context |
||
| 26 | { |
||
| 27 | use RepositoryContext; |
||
| 28 | |||
| 29 | const DEFAULT_LANGUAGE = 'eng-GB'; |
||
| 30 | |||
| 31 | /** |
||
| 32 | * These values are set by the default eZ Publish installation. |
||
| 33 | */ |
||
| 34 | const USER_IDENTIFIER = 'user'; |
||
| 35 | |||
| 36 | const USERGROUP_ROOT_CONTENT_ID = 4; |
||
| 37 | const USERGROUP_ROOT_LOCATION = 5; |
||
| 38 | const USERGROUP_ROOT_SUBTREE = '/1/5/'; |
||
| 39 | const USERGROUP_CONTENT_IDENTIFIER = 'user_group'; |
||
| 40 | |||
| 41 | /** |
||
| 42 | * @var \eZ\Publish\API\Repository\UserService |
||
| 43 | */ |
||
| 44 | protected $userService; |
||
| 45 | |||
| 46 | /** |
||
| 47 | * @var \eZ\Publish\API\Repository\SearchService |
||
| 48 | */ |
||
| 49 | protected $searchService; |
||
| 50 | |||
| 51 | /** |
||
| 52 | * @injectService $repository @ezpublish.api.repository |
||
| 53 | * @injectService $userService @ezpublish.api.service.user |
||
| 54 | * @injectService $searchService @ezpublish.api.service.search |
||
| 55 | */ |
||
| 56 | public function __construct(Repository $repository, UserService $userService, SearchService $searchService) |
||
| 62 | |||
| 63 | /** |
||
| 64 | * Search User with given username, optionally at given location. |
||
| 65 | * |
||
| 66 | * @param string $username name of User to search for |
||
| 67 | * @param string $parentGroupLocationId where to search, in User Group tree |
||
|
|
|||
| 68 | * |
||
| 69 | * @return User found |
||
| 70 | */ |
||
| 71 | public function searchUserByLogin($username, $parentGroupId = null) |
||
| 93 | |||
| 94 | /** |
||
| 95 | * Search User Groups with given name. |
||
| 96 | * |
||
| 97 | * @param string $name name of User Group to search for |
||
| 98 | * @param string $parentLocationId (optional) parent location id to search in |
||
| 99 | * |
||
| 100 | * @return search results |
||
| 101 | */ |
||
| 102 | public function searchUserGroups($name, $parentLocationId = null) |
||
| 119 | |||
| 120 | /** |
||
| 121 | * Create user inside given User Group; DELETES existing User if login already exists! |
||
| 122 | * |
||
| 123 | * @param $username username of the user to create |
||
| 124 | * @param $email email address of user to create |
||
| 125 | * @param $password account password for user to create |
||
| 126 | * @param $parentGroup pathstring wherein to create user |
||
| 127 | * |
||
| 128 | * @return eZ\Publish\API\Repository\Values\User\User |
||
| 129 | */ |
||
| 130 | protected function createUser($username, $email, $password, $parentGroup = null, $fields = array()) |
||
| 160 | |||
| 161 | /** |
||
| 162 | * Create new User Group inside existing parent User Group. |
||
| 163 | * |
||
| 164 | * @param string $name User Group name |
||
| 165 | * @param \eZ\Publish\API\Repository\Values\User\UserGroup $parentGroup (optional) parent user group, defaults to UserGroup "/Users" |
||
| 166 | * |
||
| 167 | * @return \eZ\Publish\API\Repository\Values\User\UserGroup |
||
| 168 | */ |
||
| 169 | public function createUserGroup($name, $parentGroup = null) |
||
| 180 | |||
| 181 | /** |
||
| 182 | * Make sure a User with name $username, $email and $password exists in parent group. |
||
| 183 | * |
||
| 184 | * @param string $username User name |
||
| 185 | * @param string $email User's email |
||
| 186 | * @param string $password User's password |
||
| 187 | * @param string $parentGroupName (optional) name of the parent group to check |
||
| 188 | * |
||
| 189 | * @return \eZ\Publish\API\Repository\Values\User\User |
||
| 190 | */ |
||
| 191 | public function ensureUserExists($username, $email, $password, $parentGroupName = null) |
||
| 229 | |||
| 230 | /** |
||
| 231 | * Make sure a User with name $username does not exist (in parent group). |
||
| 232 | * |
||
| 233 | * @param string $username User name |
||
| 234 | * @param string $parentGroupName (optional) name of the parent group to check |
||
| 235 | */ |
||
| 236 | public function ensureUserDoesntExist($username, $parentGroupName = null) |
||
| 267 | |||
| 268 | /** |
||
| 269 | * Checks if the User with username $username exists. |
||
| 270 | * |
||
| 271 | * @param string $username User name |
||
| 272 | * @param string $parentGroupName User group name to search inside |
||
| 273 | * |
||
| 274 | * @return bool true if it exists, false if user or group don't exist |
||
| 275 | */ |
||
| 276 | public function checkUserExistenceByUsername($username, $parentGroupName = null) |
||
| 293 | |||
| 294 | /** |
||
| 295 | * Checks if the User with email $email exists. |
||
| 296 | * |
||
| 297 | * @param string $email User email |
||
| 298 | * @param string $parentGroupName User group name to search inside |
||
| 299 | * |
||
| 300 | * @return bool true if it exists, false if not |
||
| 301 | */ |
||
| 302 | public function checkUserExistenceByEmail($email, $parentGroupName = null) |
||
| 321 | |||
| 322 | View Code Duplication | public function createPasswordHash($login, $password, $type) |
|
| 340 | |||
| 341 | /** |
||
| 342 | * @Given there is a User with name :username |
||
| 343 | * |
||
| 344 | * Ensures a user with username ':username' exists, creating a new one if necessary. |
||
| 345 | * |
||
| 346 | * @return \eZ\Publish\API\Repository\Values\User\User |
||
| 347 | */ |
||
| 348 | public function iHaveUser($username) |
||
| 354 | |||
| 355 | /** |
||
| 356 | * @Given there is a User with name :username, email :email and password :password |
||
| 357 | * |
||
| 358 | * Ensures a user exists with given username/email/password, creating a new one if necessary. |
||
| 359 | * |
||
| 360 | * @return \eZ\Publish\API\Repository\Values\User\User |
||
| 361 | */ |
||
| 362 | public function iHaveUserWithUsernameEmailAndPassword($username, $email, $password) |
||
| 366 | /** |
||
| 367 | * @Given there is a User with name :username in :parentGroup group |
||
| 368 | * |
||
| 369 | * Ensures a user with username ':username' exists as a child of ':parentGroup' user group, can create either one. |
||
| 370 | * |
||
| 371 | * @return \eZ\Publish\API\Repository\Values\User\User |
||
| 372 | */ |
||
| 373 | public function iHaveUserInGroup($username, $parentGroupName) |
||
| 379 | /** |
||
| 380 | * @Given there is a User with name :username, email :email and password :password in :parentGroup group |
||
| 381 | * |
||
| 382 | * Ensures a user with given username/email/password as a child of ':parentGroup' user group, can create either one. |
||
| 383 | * |
||
| 384 | * @return \eZ\Publish\API\Repository\Values\User\User |
||
| 385 | */ |
||
| 386 | public function iHaveUserWithUsernameEmailAndPasswordInGroup($username, $email, $password, $parentGroupName) |
||
| 390 | |||
| 391 | /** |
||
| 392 | * @Given there isn't a User with name :username |
||
| 393 | * |
||
| 394 | * Makes sure a user with username ':username' doesn't exist, removing it if necessary. |
||
| 395 | */ |
||
| 396 | public function iDontHaveUser($username) |
||
| 400 | /** |
||
| 401 | * @Given there isn't a User with name :username in :parentGroup group |
||
| 402 | * |
||
| 403 | * Makes sure a user with username ':username' doesn't exist as a chield of group ':parentGroup', removing it if necessary. |
||
| 404 | */ |
||
| 405 | public function iDontHaveUserInGroup($username, $parentGroup) |
||
| 409 | |||
| 410 | /** |
||
| 411 | * @Given there are the following Users: |
||
| 412 | * |
||
| 413 | * Make sure that users in the provided table exist in their respective parent group. Example: |
||
| 414 | * | username | parentGroup | |
||
| 415 | * | testUser1 | Members | |
||
| 416 | * | testUser2 | Editors | |
||
| 417 | * | testUser3 | NewParent | # Both user and group should be created |
||
| 418 | */ |
||
| 419 | public function iHaveTheFollowingUsers(TableNode $table) |
||
| 428 | |||
| 429 | /** |
||
| 430 | * @Given a User with name :username already exists |
||
| 431 | * @Then User with name :username exists |
||
| 432 | * |
||
| 433 | * Checks that user ':username' exists. |
||
| 434 | */ |
||
| 435 | public function assertUserWithNameExists($username) |
||
| 442 | |||
| 443 | /** |
||
| 444 | * @Then User with name :username doesn't exist |
||
| 445 | * |
||
| 446 | * Checks that user ':username' does not exist. |
||
| 447 | */ |
||
| 448 | public function assertUserWithNameDoesntExist($username) |
||
| 455 | |||
| 456 | /** |
||
| 457 | * @Then User with name :username exists in group :parentGroup |
||
| 458 | * @Then User with name :username exists in :parentGroup group |
||
| 459 | * |
||
| 460 | * Checks that user ':username' exists as a child of group ':parentGroup'. |
||
| 461 | */ |
||
| 462 | public function assertUserWithNameExistsInGroup($username, $parentGroup) |
||
| 469 | |||
| 470 | /** |
||
| 471 | * @Then User with name :username doesn't exist in group :parentGroup |
||
| 472 | * @Then User with name :username doesn't exist in :parentGroup group |
||
| 473 | * |
||
| 474 | * Checks that user ':username' does not exist as a child of group ':parentGroup'. |
||
| 475 | */ |
||
| 476 | public function assertUserWithNameDoesntExistInGroup($username, $parentGroup) |
||
| 483 | |||
| 484 | /** |
||
| 485 | * @Then User with name :username doesn't exist in the following groups: |
||
| 486 | * |
||
| 487 | * Checks that user ':username' does not exist in any of the provided groups. Example: |
||
| 488 | * | parentGroup | |
||
| 489 | * | Partners | |
||
| 490 | * | Anonymous Users | |
||
| 491 | * | Editors | |
||
| 492 | * | Administrator users | |
||
| 493 | */ |
||
| 494 | public function assertUserWithNameDoesntExistInGroups($username, TableNode $table) |
||
| 506 | |||
| 507 | /** |
||
| 508 | * @Then User with name :username has the following fields: |
||
| 509 | * @Then User with name :username exists with the following fields: |
||
| 510 | * |
||
| 511 | * Checks that user ':username' exists with the values provided in the field/value table. example: |
||
| 512 | * | Name | value | |
||
| 513 | * | email | [email protected] | |
||
| 514 | * | password | testuser | |
||
| 515 | * | first_name | Test | |
||
| 516 | * | last_name | User | |
||
| 517 | */ |
||
| 518 | public function assertUserWithNameExistsWithFields($username, TableNode $table) |
||
| 549 | |||
| 550 | /** |
||
| 551 | * Find a non existing User email. |
||
| 552 | * |
||
| 553 | * @return string A not used email |
||
| 554 | * |
||
| 555 | * @throws \Exception Possible endless loop |
||
| 556 | */ |
||
| 557 | private function findNonExistingUserEmail($username = 'User') |
||
| 573 | |||
| 574 | /** |
||
| 575 | * Find a non existing User name. |
||
| 576 | * |
||
| 577 | * @return string A not used name |
||
| 578 | * |
||
| 579 | * @throws \Exception Possible endless loop |
||
| 580 | */ |
||
| 581 | private function findNonExistingUserName() |
||
| 592 | } |
||
| 593 |
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.
Consider the following example. The parameter
$italyis not defined by the methodfinale(...).The most likely cause is that the parameter was removed, but the annotation was not.