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 CircleProvider 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 CircleProvider, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 50 | class CircleProvider extends CircleProviderRequestBuilder implements IShareProvider { |
||
| 51 | |||
| 52 | private $misc; |
||
| 53 | |||
| 54 | |||
| 55 | /** @var ILogger */ |
||
| 56 | private $logger; |
||
| 57 | |||
| 58 | /** @var ISecureRandom */ |
||
| 59 | private $secureRandom; |
||
| 60 | |||
| 61 | /** @var IUserManager */ |
||
| 62 | private $userManager; |
||
| 63 | |||
| 64 | /** @var IRootFolder */ |
||
| 65 | private $rootFolder; |
||
| 66 | |||
| 67 | /** @var IL10N */ |
||
| 68 | private $l; |
||
| 69 | |||
| 70 | /** @var IURLGenerator */ |
||
| 71 | private $urlGenerator; |
||
| 72 | |||
| 73 | |||
| 74 | /** |
||
| 75 | * DefaultShareProvider constructor. |
||
| 76 | * |
||
| 77 | * @param IDBConnection $connection |
||
| 78 | * @param ISecureRandom $secureRandom |
||
| 79 | * @param IUserManager $userManager |
||
| 80 | * @param IRootFolder $rootFolder |
||
| 81 | * @param IL10N $l |
||
| 82 | * @param ILogger $logger |
||
| 83 | * @param IURLGenerator $urlGenerator |
||
| 84 | */ |
||
| 85 | public function __construct( |
||
| 102 | |||
| 103 | |||
| 104 | /** |
||
| 105 | * Return the identifier of this provider. |
||
| 106 | * |
||
| 107 | * @return string |
||
| 108 | */ |
||
| 109 | public function identifier() { |
||
| 112 | |||
| 113 | |||
| 114 | /** |
||
| 115 | * Create a share if it does not exist already. |
||
| 116 | * |
||
| 117 | * @param IShare $share |
||
| 118 | * |
||
| 119 | * @return IShare The share object |
||
| 120 | * @throws \Exception |
||
| 121 | */ |
||
| 122 | // TODO: check if user can create a share in this circle ! |
||
| 123 | public function create(IShare $share) { |
||
| 140 | |||
| 141 | |||
| 142 | /** |
||
| 143 | * Update a share |
||
| 144 | * permissions right, owner and initiator |
||
| 145 | * |
||
| 146 | * @param IShare $share |
||
| 147 | * |
||
| 148 | * @return IShare The share object |
||
| 149 | */ |
||
| 150 | public function update(IShare $share) { |
||
| 161 | |||
| 162 | |||
| 163 | /** |
||
| 164 | * Delete a share, and it's children |
||
| 165 | * |
||
| 166 | * @param IShare $share |
||
| 167 | */ |
||
| 168 | public function delete(IShare $share) { |
||
| 175 | |||
| 176 | |||
| 177 | /** |
||
| 178 | * Unshare a file from self as recipient. |
||
| 179 | * Because every circles share are group shares, we will set permissions to 0 |
||
| 180 | * |
||
| 181 | * @param IShare $share |
||
| 182 | * @param string $userId |
||
| 183 | */ |
||
| 184 | public function deleteFromSelf(IShare $share, $userId) { |
||
| 195 | |||
| 196 | |||
| 197 | /** |
||
| 198 | * Move a share as a recipient. |
||
| 199 | * |
||
| 200 | * @param IShare $share |
||
| 201 | * @param string $userId |
||
| 202 | * |
||
| 203 | * @return IShare |
||
| 204 | * |
||
| 205 | */ |
||
| 206 | View Code Duplication | public function move(IShare $share, $userId) { |
|
| 218 | |||
| 219 | |||
| 220 | /** |
||
| 221 | * return the child ID of a share |
||
| 222 | * |
||
| 223 | * @param IShare $share |
||
| 224 | * @param $userId |
||
| 225 | * |
||
| 226 | * @return bool |
||
| 227 | */ |
||
| 228 | View Code Duplication | private function getShareChildId(IShare $share, $userId) { |
|
| 242 | |||
| 243 | |||
| 244 | /** |
||
| 245 | * Create a child and returns its ID |
||
| 246 | * |
||
| 247 | * @param IShare $share |
||
| 248 | * |
||
| 249 | * @return int |
||
| 250 | */ |
||
| 251 | private function createShare($share) { |
||
| 258 | |||
| 259 | |||
| 260 | /** |
||
| 261 | * Create a child and returns its ID |
||
| 262 | * |
||
| 263 | * @param string $userId |
||
| 264 | * @param IShare $share |
||
| 265 | * |
||
| 266 | * @return int |
||
| 267 | */ |
||
| 268 | private function createShareChild($userId, $share) { |
||
| 278 | |||
| 279 | |||
| 280 | /** |
||
| 281 | * Get all shares by the given user in a folder |
||
| 282 | * |
||
| 283 | * @param string $userId |
||
| 284 | * @param Folder $node |
||
| 285 | * @param bool $reshares Also get the shares where $user is the owner instead of just the |
||
| 286 | * shares where $user is the initiator |
||
| 287 | * |
||
| 288 | * @return IShare[] |
||
| 289 | */ |
||
| 290 | public function getSharesInFolder($userId, Folder $node, $reshares) { |
||
| 305 | |||
| 306 | |||
| 307 | /** |
||
| 308 | * Get all shares by the given user |
||
| 309 | * |
||
| 310 | * @param string $userId |
||
| 311 | * @param int $shareType |
||
| 312 | * @param Node|null $node |
||
| 313 | * @param bool $reShares |
||
| 314 | * @param int $limit The maximum number of shares to be returned, -1 for all shares |
||
| 315 | * @param int $offset |
||
| 316 | * |
||
| 317 | * @return IShare[] |
||
| 318 | * @internal param bool $reshares Also get the shares where $user is the owner instead of just |
||
| 319 | * the shares where $user is the initiator |
||
| 320 | */ |
||
| 321 | public function getSharesBy($userId, $shareType, $node, $reShares, $limit, $offset) { |
||
| 340 | |||
| 341 | |||
| 342 | /** |
||
| 343 | * returns a better formatted string to display more information about |
||
| 344 | * the circle to the Sharing UI |
||
| 345 | * |
||
| 346 | * @param $data |
||
| 347 | * |
||
| 348 | * @return mixed |
||
| 349 | */ |
||
| 350 | private function editShareEntry($data) { |
||
| 356 | |||
| 357 | |||
| 358 | /** |
||
| 359 | * Get share by its id |
||
| 360 | * |
||
| 361 | * @param int $shareId |
||
| 362 | * @param string|null $recipientId |
||
| 363 | * |
||
| 364 | * @return IShare |
||
| 365 | * @throws ShareNotFound |
||
| 366 | */ |
||
| 367 | public function getShareById($shareId, $recipientId = null) { |
||
| 387 | |||
| 388 | |||
| 389 | /** |
||
| 390 | * Get shares for a given path |
||
| 391 | * |
||
| 392 | * @param Node $path |
||
| 393 | * |
||
| 394 | * @return IShare[] |
||
| 395 | */ |
||
| 396 | public function getSharesByPath(Node $path) { |
||
| 399 | |||
| 400 | |||
| 401 | /** |
||
| 402 | * Get shared with the given user |
||
| 403 | * |
||
| 404 | * @param string $userId get shares where this user is the recipient |
||
| 405 | * @param int $shareType |
||
| 406 | * @param Node|null $node |
||
| 407 | * @param int $limit The max number of entries returned, -1 for all |
||
| 408 | * @param int $offset |
||
| 409 | * |
||
| 410 | * @return IShare[] |
||
| 411 | */ |
||
| 412 | public function getSharedWith($userId, $shareType, $node, $limit, $offset) { |
||
| 433 | |||
| 434 | |||
| 435 | private static function editShareFromParentEntry(& $data) { |
||
| 444 | |||
| 445 | |||
| 446 | /** |
||
| 447 | * Get a share by token |
||
| 448 | * |
||
| 449 | * @param string $token |
||
| 450 | * |
||
| 451 | * @return IShare |
||
| 452 | * @throws ShareNotFound |
||
| 453 | */ |
||
| 454 | public function getShareByToken($token) { |
||
| 457 | /** @noinspection PhpUnusedParameterInspection */ |
||
| 458 | |||
| 459 | |||
| 460 | /** |
||
| 461 | * We don't return a thing about children. |
||
| 462 | * The call to this function is deprecated and should be removed in next release of NC. |
||
| 463 | * Also, we get the children in the delete() method. |
||
| 464 | * |
||
| 465 | * @param IShare $parent |
||
| 466 | * |
||
| 467 | * @deprecated |
||
| 468 | * @return array |
||
| 469 | */ |
||
| 470 | public function getChildren(IShare $parent) { |
||
| 473 | |||
| 474 | |||
| 475 | /** |
||
| 476 | * A user is deleted from the system |
||
| 477 | * So clean up the relevant shares. |
||
| 478 | * |
||
| 479 | * @param string $uid |
||
| 480 | * @param int $shareType |
||
| 481 | */ |
||
| 482 | public function userDeleted($uid, $shareType) { |
||
| 486 | |||
| 487 | |||
| 488 | /** |
||
| 489 | * A group is deleted from the system. |
||
| 490 | * We handle our own groups. |
||
| 491 | * |
||
| 492 | * @param string $gid |
||
| 493 | */ |
||
| 494 | public function groupDeleted($gid) { |
||
| 497 | |||
| 498 | |||
| 499 | /** |
||
| 500 | * A user is deleted from a group. |
||
| 501 | * We handle our own groups. |
||
| 502 | * |
||
| 503 | * @param string $uid |
||
| 504 | * @param string $gid |
||
| 505 | */ |
||
| 506 | public function userDeletedFromGroup($uid, $gid) { |
||
| 509 | |||
| 510 | |||
| 511 | /** |
||
| 512 | * Create a share object from an database row |
||
| 513 | * |
||
| 514 | * @param array $data |
||
| 515 | * |
||
| 516 | * @return IShare |
||
| 517 | * @throws InvalidShare |
||
| 518 | * @throws ShareNotFound |
||
| 519 | */ |
||
| 520 | private function createShareObject($data) { |
||
| 556 | |||
| 557 | |||
| 558 | /** |
||
| 559 | * Returns whether the given database result can be interpreted as |
||
| 560 | * a share with accessible file (not trashed, not deleted) |
||
| 561 | * |
||
| 562 | * Complete copy/paste from others ShareProvider |
||
| 563 | * |
||
| 564 | * @param $data |
||
| 565 | * |
||
| 566 | * @return bool |
||
| 567 | */ |
||
| 568 | private static function isAccessibleResult($data) { |
||
| 582 | |||
| 583 | |||
| 584 | /** |
||
| 585 | * @param IShare $share |
||
| 586 | * |
||
| 587 | * @return \Exception |
||
| 588 | */ |
||
| 589 | private function errorShareAlreadyExist($share) { |
||
| 601 | |||
| 602 | } |
||
| 603 |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.