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 Handler 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 Handler, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 25 | class Handler implements UrlAliasHandlerInterface |
||
| 26 | { |
||
| 27 | const ROOT_LOCATION_ID = 1; |
||
| 28 | |||
| 29 | /** |
||
| 30 | * This is intentionally hardcoded for now as: |
||
| 31 | * 1. We don't implement this configuration option. |
||
| 32 | * 2. Such option should not be in this layer, should be handled higher up. |
||
| 33 | * |
||
| 34 | * @deprecated |
||
| 35 | */ |
||
| 36 | const CONTENT_REPOSITORY_ROOT_LOCATION_ID = 2; |
||
| 37 | |||
| 38 | /** |
||
| 39 | * UrlAlias Gateway. |
||
| 40 | * |
||
| 41 | * @var \eZ\Publish\Core\Persistence\Legacy\Content\UrlAlias\Gateway |
||
| 42 | */ |
||
| 43 | protected $gateway; |
||
| 44 | |||
| 45 | /** |
||
| 46 | * Gateway for handling location data. |
||
| 47 | * |
||
| 48 | * @var \eZ\Publish\Core\Persistence\Legacy\Content\Location\Gateway |
||
| 49 | */ |
||
| 50 | protected $locationGateway; |
||
| 51 | |||
| 52 | /** |
||
| 53 | * UrlAlias Mapper. |
||
| 54 | * |
||
| 55 | * @var \eZ\Publish\Core\Persistence\Legacy\Content\UrlAlias\Mapper |
||
| 56 | */ |
||
| 57 | protected $mapper; |
||
| 58 | |||
| 59 | /** |
||
| 60 | * Caching language handler. |
||
| 61 | * |
||
| 62 | * @var \eZ\Publish\Core\Persistence\Legacy\Content\Language\CachingHandler |
||
| 63 | */ |
||
| 64 | protected $languageHandler; |
||
| 65 | |||
| 66 | /** |
||
| 67 | * URL slug converter. |
||
| 68 | * |
||
| 69 | * @var \eZ\Publish\Core\Persistence\Legacy\Content\UrlAlias\SlugConverter |
||
| 70 | */ |
||
| 71 | protected $slugConverter; |
||
| 72 | |||
| 73 | /** |
||
| 74 | * Creates a new UrlAlias Handler. |
||
| 75 | * |
||
| 76 | * @param \eZ\Publish\Core\Persistence\Legacy\Content\UrlAlias\Gateway $gateway |
||
| 77 | * @param \eZ\Publish\Core\Persistence\Legacy\Content\UrlAlias\Mapper $mapper |
||
| 78 | * @param \eZ\Publish\Core\Persistence\Legacy\Content\Location\Gateway $locationGateway |
||
| 79 | * @param \eZ\Publish\SPI\Persistence\Content\Language\Handler $languageHandler |
||
| 80 | * @param \eZ\Publish\Core\Persistence\Legacy\Content\UrlAlias\SlugConverter $slugConverter |
||
| 81 | */ |
||
| 82 | public function __construct( |
||
| 95 | |||
| 96 | public function publishUrlAliasForLocation( |
||
| 115 | |||
| 116 | /** |
||
| 117 | * todo document |
||
| 118 | * |
||
| 119 | * @param int $locationId |
||
| 120 | * @param int $parentLocationId |
||
| 121 | * @param string $name |
||
| 122 | * @param int $languageId |
||
| 123 | * @param bool $alwaysAvailable |
||
| 124 | * @param bool $updatePathIdentificationString legacy storage specific for updating ezcontentobject_tree.path_identification_string |
||
| 125 | * |
||
| 126 | * @return int |
||
| 127 | */ |
||
| 128 | private function internalPublishUrlAliasForLocation( |
||
| 247 | |||
| 248 | /** |
||
| 249 | * Create a user chosen $alias pointing to $locationId in $languageCode. |
||
| 250 | * |
||
| 251 | * If $languageCode is null the $alias is created in the system's default |
||
| 252 | * language. $alwaysAvailable makes the alias available in all languages. |
||
| 253 | * |
||
| 254 | * @param mixed $locationId |
||
| 255 | * @param string $path |
||
| 256 | * @param bool $forwarding |
||
| 257 | * @param string $languageCode |
||
| 258 | * @param bool $alwaysAvailable |
||
| 259 | * |
||
| 260 | * @return \eZ\Publish\SPI\Persistence\Content\UrlAlias |
||
| 261 | */ |
||
| 262 | public function createCustomUrlAlias($locationId, $path, $forwarding = false, $languageCode = null, $alwaysAvailable = false) |
||
| 272 | |||
| 273 | /** |
||
| 274 | * Create a user chosen $alias pointing to a resource in $languageCode. |
||
| 275 | * This method does not handle location resources - if a user enters a location target |
||
| 276 | * the createCustomUrlAlias method has to be used. |
||
| 277 | * |
||
| 278 | * If $languageCode is null the $alias is created in the system's default |
||
| 279 | * language. $alwaysAvailable makes the alias available in all languages. |
||
| 280 | * |
||
| 281 | * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException if the path already exists for the given language |
||
| 282 | * |
||
| 283 | * @param string $resource |
||
| 284 | * @param string $path |
||
| 285 | * @param bool $forwarding |
||
| 286 | * @param string $languageCode |
||
| 287 | * @param bool $alwaysAvailable |
||
| 288 | * |
||
| 289 | * @return \eZ\Publish\SPI\Persistence\Content\UrlAlias |
||
| 290 | */ |
||
| 291 | public function createGlobalUrlAlias($resource, $path, $forwarding = false, $languageCode = null, $alwaysAvailable = false) |
||
| 301 | |||
| 302 | /** |
||
| 303 | * Internal method for creating global or custom URL alias (these are handled in the same way). |
||
| 304 | * |
||
| 305 | * @throws \eZ\Publish\Core\Base\Exceptions\ForbiddenException if the path already exists for the given language |
||
| 306 | * |
||
| 307 | * @param string $action |
||
| 308 | * @param string $path |
||
| 309 | * @param bool $forward |
||
| 310 | * @param string|null $languageCode |
||
| 311 | * @param bool $alwaysAvailable |
||
| 312 | * |
||
| 313 | * @return \eZ\Publish\SPI\Persistence\Content\UrlAlias |
||
| 314 | */ |
||
| 315 | protected function createUrlAlias($action, $path, $forward, $languageCode, $alwaysAvailable) |
||
| 390 | |||
| 391 | /** |
||
| 392 | * Convenience method for inserting nop type row. |
||
| 393 | * |
||
| 394 | * @param mixed $parentId |
||
| 395 | * @param string $text |
||
| 396 | * @param string $textMD5 |
||
| 397 | * |
||
| 398 | * @return mixed |
||
| 399 | */ |
||
| 400 | protected function insertNopEntry($parentId, $text, $textMD5) |
||
| 412 | |||
| 413 | /** |
||
| 414 | * List of user generated or autogenerated url entries, pointing to $locationId. |
||
| 415 | * |
||
| 416 | * @param mixed $locationId |
||
| 417 | * @param bool $custom if true the user generated aliases are listed otherwise the autogenerated |
||
| 418 | * |
||
| 419 | * @return \eZ\Publish\SPI\Persistence\Content\UrlAlias[] |
||
| 420 | */ |
||
| 421 | View Code Duplication | public function listURLAliasesForLocation($locationId, $custom = false) |
|
| 430 | |||
| 431 | /** |
||
| 432 | * List global aliases. |
||
| 433 | * |
||
| 434 | * @param string|null $languageCode |
||
| 435 | * @param int $offset |
||
| 436 | * @param int $limit |
||
| 437 | * |
||
| 438 | * @return \eZ\Publish\SPI\Persistence\Content\UrlAlias[] |
||
| 439 | */ |
||
| 440 | View Code Duplication | public function listGlobalURLAliases($languageCode = null, $offset = 0, $limit = -1) |
|
| 449 | |||
| 450 | /** |
||
| 451 | * Removes url aliases. |
||
| 452 | * |
||
| 453 | * Autogenerated aliases are not removed by this method. |
||
| 454 | * |
||
| 455 | * @param \eZ\Publish\SPI\Persistence\Content\UrlAlias[] $urlAliases |
||
| 456 | * |
||
| 457 | * @return bool |
||
| 458 | */ |
||
| 459 | public function removeURLAliases(array $urlAliases) |
||
| 472 | |||
| 473 | /** |
||
| 474 | * Looks up a url alias for the given url. |
||
| 475 | * |
||
| 476 | * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException |
||
| 477 | * @throws \RuntimeException |
||
| 478 | * @throws \eZ\Publish\Core\Base\Exceptions\NotFoundException |
||
| 479 | * |
||
| 480 | * @param string $url |
||
| 481 | * |
||
| 482 | * @return \eZ\Publish\SPI\Persistence\Content\UrlAlias |
||
| 483 | */ |
||
| 484 | public function lookup($url) |
||
| 516 | |||
| 517 | /** |
||
| 518 | * Loads URL alias by given $id. |
||
| 519 | * |
||
| 520 | * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException |
||
| 521 | * |
||
| 522 | * @param string $id |
||
| 523 | * |
||
| 524 | * @return \eZ\Publish\SPI\Persistence\Content\UrlAlias |
||
| 525 | */ |
||
| 526 | public function loadUrlAlias($id) |
||
| 539 | |||
| 540 | /** |
||
| 541 | * Notifies the underlying engine that a location has moved. |
||
| 542 | * |
||
| 543 | * This method triggers the change of the autogenerated aliases. |
||
| 544 | * |
||
| 545 | * @param mixed $locationId |
||
| 546 | * @param mixed $oldParentId |
||
| 547 | * @param mixed $newParentId |
||
| 548 | */ |
||
| 549 | public function locationMoved($locationId, $oldParentId, $newParentId) |
||
| 569 | |||
| 570 | /** |
||
| 571 | * Notifies the underlying engine that a location was copied. |
||
| 572 | * |
||
| 573 | * This method triggers the creation of the autogenerated aliases for the copied locations |
||
| 574 | * |
||
| 575 | * @param mixed $locationId |
||
| 576 | * @param mixed $newLocationId |
||
| 577 | * @param mixed $newParentId |
||
| 578 | */ |
||
| 579 | public function locationCopied($locationId, $newLocationId, $newParentId) |
||
| 592 | |||
| 593 | public function locationSwapped($location1Id, $location1ParentId, $location2Id, $location2ParentId) |
||
| 639 | |||
| 640 | /** |
||
| 641 | * Cleans up URL aliases after performing Location swap. |
||
| 642 | * |
||
| 643 | * Old URL aliases in languages not present on the swapped Content are downgraded. |
||
| 644 | * |
||
| 645 | * @param int $locationId Location ID for which cleanup is performed. |
||
| 646 | * @param int $locationNewAliasId ID of the autogenerated alias for the Location. |
||
| 647 | * @param int[] $languages1 Languages of the Content being swapped in. |
||
| 648 | * @param int[] $languages2 Languages of the Content being swapped out. |
||
| 649 | */ |
||
| 650 | private function cleanupAfterSwap( |
||
| 673 | |||
| 674 | /** |
||
| 675 | * Generates language mask from the given array of language IDs. |
||
| 676 | * |
||
| 677 | * @param int[] $languageIds |
||
| 678 | * |
||
| 679 | * @return int |
||
| 680 | */ |
||
| 681 | private function generateLanguageMask(array $languageIds) |
||
| 691 | |||
| 692 | /** |
||
| 693 | * Extracts every language Ids contained in $languageMask. |
||
| 694 | * |
||
| 695 | * @param int $languageMask |
||
| 696 | * |
||
| 697 | * @return int[] An array of language IDs |
||
| 698 | */ |
||
| 699 | private function extractLanguageIdsFromMask($languageMask) |
||
| 715 | |||
| 716 | /** |
||
| 717 | * Returns possibly corrected alias id for given $locationId !! For use as parent id in logic. |
||
| 718 | * |
||
| 719 | * First level entries must have parent id set to 0 instead of their parent location alias id. |
||
| 720 | * There are two cases when alias id needs to be corrected: |
||
| 721 | * 1) location is special location without URL alias (location with id=1 in standard installation) |
||
| 722 | * 2) location is site root location, having special root entry in the ezurlalias_ml table (location with id=2 |
||
| 723 | * in standard installation) |
||
| 724 | * |
||
| 725 | * @param mixed $locationId |
||
| 726 | * |
||
| 727 | * @return mixed |
||
| 728 | */ |
||
| 729 | protected function getRealAliasId($locationId) |
||
| 747 | |||
| 748 | /** |
||
| 749 | * Recursively copies aliases from old parent under new parent. |
||
| 750 | * |
||
| 751 | * @param array $actionMap |
||
| 752 | * @param mixed $oldParentAliasId |
||
| 753 | * @param mixed $newParentAliasId |
||
| 754 | */ |
||
| 755 | protected function copySubtree($actionMap, $oldParentAliasId, $newParentAliasId) |
||
| 779 | |||
| 780 | /** |
||
| 781 | * @param mixed $oldParentId |
||
| 782 | * @param mixed $newParentId |
||
| 783 | * |
||
| 784 | * @return array |
||
| 785 | */ |
||
| 786 | protected function getCopiedLocationsMap($oldParentId, $newParentId) |
||
| 798 | |||
| 799 | /** |
||
| 800 | * Notifies the underlying engine that a location was deleted or moved to trash. |
||
| 801 | * |
||
| 802 | * @param mixed $locationId |
||
| 803 | */ |
||
| 804 | public function locationDeleted($locationId) |
||
| 811 | |||
| 812 | /** |
||
| 813 | * Recursively removes aliases by given $id and $action. |
||
| 814 | * |
||
| 815 | * $original parameter is used to limit removal of moved Location aliases to history entries only. |
||
| 816 | * |
||
| 817 | * @param mixed $id |
||
| 818 | * @param string $action |
||
| 819 | * @param mixed $original |
||
| 820 | */ |
||
| 821 | protected function removeSubtree($id, $action, $original) |
||
| 841 | |||
| 842 | /** |
||
| 843 | * @param string $text |
||
| 844 | * |
||
| 845 | * @return string |
||
| 846 | */ |
||
| 847 | protected function getHash($text) |
||
| 851 | } |
||
| 852 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.
Either this assignment is in error or an instanceof check should be added for that assignment.