Complex classes like UsersController 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 UsersController, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 57 | class UsersController extends Controller { |
||
| 58 | /** @var IL10N */ |
||
| 59 | private $l10n; |
||
| 60 | /** @var IUserSession */ |
||
| 61 | private $userSession; |
||
| 62 | /** @var bool */ |
||
| 63 | private $isAdmin; |
||
| 64 | /** @var IUserManager */ |
||
| 65 | private $userManager; |
||
| 66 | /** @var IGroupManager */ |
||
| 67 | private $groupManager; |
||
| 68 | /** @var IConfig */ |
||
| 69 | private $config; |
||
| 70 | /** @var ILogger */ |
||
| 71 | private $log; |
||
| 72 | /** @var \OC_Defaults */ |
||
| 73 | private $defaults; |
||
| 74 | /** @var IMailer */ |
||
| 75 | private $mailer; |
||
| 76 | /** @var string */ |
||
| 77 | private $fromMailAddress; |
||
| 78 | /** @var IURLGenerator */ |
||
| 79 | private $urlGenerator; |
||
| 80 | /** @var bool contains the state of the encryption app */ |
||
| 81 | private $isEncryptionAppEnabled; |
||
| 82 | /** @var bool contains the state of the admin recovery setting */ |
||
| 83 | private $isRestoreEnabled = false; |
||
| 84 | /** @var IAvatarManager */ |
||
| 85 | private $avatarManager; |
||
| 86 | /** @var AccountManager */ |
||
| 87 | private $accountManager; |
||
| 88 | |||
| 89 | /** |
||
| 90 | * @param string $appName |
||
| 91 | * @param IRequest $request |
||
| 92 | * @param IUserManager $userManager |
||
| 93 | * @param IGroupManager $groupManager |
||
| 94 | * @param IUserSession $userSession |
||
| 95 | * @param IConfig $config |
||
| 96 | * @param bool $isAdmin |
||
| 97 | * @param IL10N $l10n |
||
| 98 | * @param ILogger $log |
||
| 99 | * @param \OC_Defaults $defaults |
||
| 100 | * @param IMailer $mailer |
||
| 101 | * @param string $fromMailAddress |
||
| 102 | * @param IURLGenerator $urlGenerator |
||
| 103 | * @param IAppManager $appManager |
||
| 104 | * @param IAvatarManager $avatarManager |
||
| 105 | * @param AccountManager $accountManager |
||
| 106 | */ |
||
| 107 | public function __construct($appName, |
||
| 147 | |||
| 148 | /** |
||
| 149 | * @param IUser $user |
||
| 150 | * @param array $userGroups |
||
| 151 | * @return array |
||
| 152 | */ |
||
| 153 | private function formatUserForIndex(IUser $user, array $userGroups = null) { |
||
| 213 | |||
| 214 | /** |
||
| 215 | * @param array $userIDs Array with schema [$uid => $displayName] |
||
| 216 | * @return IUser[] |
||
| 217 | */ |
||
| 218 | private function getUsersForUID(array $userIDs) { |
||
| 225 | |||
| 226 | /** |
||
| 227 | * @NoAdminRequired |
||
| 228 | * |
||
| 229 | * @param int $offset |
||
| 230 | * @param int $limit |
||
| 231 | * @param string $gid GID to filter for |
||
| 232 | * @param string $pattern Pattern to search for in the username |
||
| 233 | * @param string $backend Backend to filter for (class-name) |
||
| 234 | * @return DataResponse |
||
| 235 | * |
||
| 236 | * TODO: Tidy up and write unit tests - code is mainly static method calls |
||
| 237 | */ |
||
| 238 | public function index($offset = 0, $limit = 10, $gid = '', $pattern = '', $backend = '') { |
||
| 310 | |||
| 311 | /** |
||
| 312 | * @NoAdminRequired |
||
| 313 | * @PasswordConfirmationRequired |
||
| 314 | * |
||
| 315 | * @param string $username |
||
| 316 | * @param string $password |
||
| 317 | * @param array $groups |
||
| 318 | * @param string $email |
||
| 319 | * @return DataResponse |
||
| 320 | */ |
||
| 321 | public function create($username, $password, array $groups=array(), $email='') { |
||
| 443 | |||
| 444 | /** |
||
| 445 | * @NoAdminRequired |
||
| 446 | * @PasswordConfirmationRequired |
||
| 447 | * |
||
| 448 | * @param string $id |
||
| 449 | * @return DataResponse |
||
| 450 | */ |
||
| 451 | public function destroy($id) { |
||
| 452 | $userId = $this->userSession->getUser()->getUID(); |
||
| 453 | $user = $this->userManager->get($id); |
||
| 454 | |||
| 455 | if($userId === $id) { |
||
| 456 | return new DataResponse( |
||
| 457 | array( |
||
| 458 | 'status' => 'error', |
||
| 459 | 'data' => array( |
||
| 460 | 'message' => (string)$this->l10n->t('Unable to delete user.') |
||
| 461 | ) |
||
| 462 | ), |
||
| 463 | Http::STATUS_FORBIDDEN |
||
| 464 | ); |
||
| 465 | } |
||
| 466 | |||
| 467 | if(!$this->isAdmin && !$this->groupManager->getSubAdmin()->isUserAccessible($this->userSession->getUser(), $user)) { |
||
| 468 | return new DataResponse( |
||
| 469 | array( |
||
| 470 | 'status' => 'error', |
||
| 471 | 'data' => array( |
||
| 472 | 'message' => (string)$this->l10n->t('Authentication error') |
||
| 473 | ) |
||
| 474 | ), |
||
| 475 | Http::STATUS_FORBIDDEN |
||
| 476 | ); |
||
| 477 | } |
||
| 478 | |||
| 479 | if($user) { |
||
| 480 | if($user->delete()) { |
||
| 481 | return new DataResponse( |
||
| 482 | array( |
||
| 483 | 'status' => 'success', |
||
| 484 | 'data' => array( |
||
| 485 | 'username' => $id |
||
| 486 | ) |
||
| 487 | ), |
||
| 488 | Http::STATUS_NO_CONTENT |
||
| 489 | ); |
||
| 490 | } |
||
| 491 | } |
||
| 492 | |||
| 493 | return new DataResponse( |
||
| 494 | array( |
||
| 495 | 'status' => 'error', |
||
| 496 | 'data' => array( |
||
| 497 | 'message' => (string)$this->l10n->t('Unable to delete user.') |
||
| 498 | ) |
||
| 499 | ), |
||
| 500 | Http::STATUS_FORBIDDEN |
||
| 501 | ); |
||
| 502 | } |
||
| 503 | |||
| 504 | /** |
||
| 505 | * @NoAdminRequired |
||
| 506 | * @NoSubadminRequired |
||
| 507 | * @PasswordConfirmationRequired |
||
| 508 | * |
||
| 509 | * @param string $avatarScope |
||
| 510 | * @param string $displayname |
||
| 511 | * @param string $displaynameScope |
||
| 512 | * @param string $phone |
||
| 513 | * @param string $phoneScope |
||
| 514 | * @param string $email |
||
| 515 | * @param string $emailScope |
||
| 516 | * @param string $website |
||
| 517 | * @param string $websiteScope |
||
| 518 | * @param string $address |
||
| 519 | * @param string $addressScope |
||
| 520 | * @param string $twitter |
||
| 521 | * @param string $twitterScope |
||
| 522 | * @return DataResponse |
||
| 523 | */ |
||
| 524 | public function setUserSettings($avatarScope, |
||
| 525 | $displayname, |
||
| 526 | $displaynameScope, |
||
| 527 | $phone, |
||
| 528 | $phoneScope, |
||
| 529 | $email, |
||
| 530 | $emailScope, |
||
| 531 | $website, |
||
| 532 | $websiteScope, |
||
| 533 | $address, |
||
| 534 | $addressScope, |
||
| 535 | $twitter, |
||
| 536 | $twitterScope |
||
| 537 | ) { |
||
| 538 | |||
| 539 | |||
| 540 | if(!empty($email) && !$this->mailer->validateMailAddress($email)) { |
||
| 541 | return new DataResponse( |
||
| 542 | array( |
||
| 543 | 'status' => 'error', |
||
| 544 | 'data' => array( |
||
| 545 | 'message' => (string)$this->l10n->t('Invalid mail address') |
||
| 546 | ) |
||
| 547 | ), |
||
| 548 | Http::STATUS_UNPROCESSABLE_ENTITY |
||
| 549 | ); |
||
| 550 | } |
||
| 551 | |||
| 552 | $user = $this->userSession->getUser(); |
||
| 553 | |||
| 554 | $data = [ |
||
| 555 | AccountManager::PROPERTY_AVATAR => ['scope' => $avatarScope], |
||
| 556 | AccountManager::PROPERTY_DISPLAYNAME => ['value' => $displayname, 'scope' => $displaynameScope], |
||
| 557 | AccountManager::PROPERTY_EMAIL=> ['value' => $email, 'scope' => $emailScope], |
||
| 558 | AccountManager::PROPERTY_WEBSITE => ['value' => $website, 'scope' => $websiteScope], |
||
| 559 | AccountManager::PROPERTY_ADDRESS => ['value' => $address, 'scope' => $addressScope], |
||
| 560 | AccountManager::PROPERTY_PHONE => ['value' => $phone, 'scope' => $phoneScope], |
||
| 561 | AccountManager::PROPERTY_TWITTER => ['value' => $twitter, 'scope' => $twitterScope] |
||
| 562 | ]; |
||
| 563 | |||
| 564 | $this->accountManager->updateUser($user, $data); |
||
| 565 | |||
| 566 | try { |
||
| 567 | $this->saveUserSettings($user, $data); |
||
| 568 | return new DataResponse( |
||
| 569 | array( |
||
| 570 | 'status' => 'success', |
||
| 571 | 'data' => array( |
||
| 572 | 'userId' => $user->getUID(), |
||
| 573 | 'avatarScope' => $avatarScope, |
||
| 574 | 'displayname' => $displayname, |
||
| 575 | 'displaynameScope' => $displaynameScope, |
||
| 576 | 'email' => $email, |
||
| 577 | 'emailScope' => $emailScope, |
||
| 578 | 'website' => $website, |
||
| 579 | 'websiteScope' => $websiteScope, |
||
| 580 | 'address' => $address, |
||
| 581 | 'addressScope' => $addressScope, |
||
| 582 | 'message' => (string)$this->l10n->t('Settings saved') |
||
| 583 | ) |
||
| 584 | ), |
||
| 585 | Http::STATUS_OK |
||
| 586 | ); |
||
| 587 | } catch (ForbiddenException $e) { |
||
| 588 | return new DataResponse([ |
||
| 589 | 'status' => 'error', |
||
| 590 | 'data' => [ |
||
| 591 | 'message' => $e->getMessage() |
||
| 592 | ], |
||
| 593 | ]); |
||
| 594 | } |
||
| 595 | |||
| 596 | } |
||
| 597 | |||
| 598 | |||
| 599 | /** |
||
| 600 | * update account manager with new user data |
||
| 601 | * |
||
| 602 | * @param IUser $user |
||
| 603 | * @param array $data |
||
| 604 | * @throws ForbiddenException |
||
| 605 | */ |
||
| 606 | private function saveUserSettings(IUser $user, $data) { |
||
| 627 | |||
| 628 | /** |
||
| 629 | * Count all unique users visible for the current admin/subadmin. |
||
| 630 | * |
||
| 631 | * @NoAdminRequired |
||
| 632 | * |
||
| 633 | * @return DataResponse |
||
| 634 | */ |
||
| 635 | public function stats() { |
||
| 664 | |||
| 665 | |||
| 666 | /** |
||
| 667 | * Set the displayName of a user |
||
| 668 | * |
||
| 669 | * @NoAdminRequired |
||
| 670 | * @NoSubadminRequired |
||
| 671 | * @PasswordConfirmationRequired |
||
| 672 | * @todo merge into saveUserSettings |
||
| 673 | * |
||
| 674 | * @param string $username |
||
| 675 | * @param string $displayName |
||
| 676 | * @return DataResponse |
||
| 677 | */ |
||
| 678 | public function setDisplayName($username, $displayName) { |
||
| 723 | } |
||
| 724 |
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.