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 UrlRewriteObserver 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 UrlRewriteObserver, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
42 | class UrlRewriteObserver extends AbstractProductImportObserver implements ObserverFactoryInterface |
||
43 | { |
||
44 | |||
45 | /** |
||
46 | * The entity type to load the URL rewrites for. |
||
47 | * |
||
48 | * @var string |
||
49 | */ |
||
50 | const ENTITY_TYPE = 'product'; |
||
51 | |||
52 | /** |
||
53 | * The key for the category in the metadata. |
||
54 | * |
||
55 | * @var string |
||
56 | */ |
||
57 | const CATEGORY_ID = 'category_id'; |
||
58 | |||
59 | /** |
||
60 | * The URL key from the CSV file column that has to be processed by the observer. |
||
61 | * |
||
62 | * @var string |
||
63 | */ |
||
64 | protected $urlKey; |
||
65 | |||
66 | /** |
||
67 | * The actual category ID to process. |
||
68 | * |
||
69 | * @var integer |
||
70 | */ |
||
71 | protected $categoryId; |
||
72 | |||
73 | /** |
||
74 | * The actual entity ID to process. |
||
75 | * |
||
76 | * @var integer |
||
77 | */ |
||
78 | protected $entityId; |
||
79 | |||
80 | /** |
||
81 | * The ID of the recently created URL rewrite. |
||
82 | * |
||
83 | * @var integer |
||
84 | */ |
||
85 | protected $urlRewriteId; |
||
86 | |||
87 | /** |
||
88 | * The array with the URL rewrites that has to be created. |
||
89 | * |
||
90 | * @var array |
||
91 | */ |
||
92 | protected $urlRewrites = array(); |
||
93 | |||
94 | /** |
||
95 | * The array with the category IDs related with the product. |
||
96 | * |
||
97 | * @var array |
||
98 | */ |
||
99 | protected $productCategoryIds = array(); |
||
100 | |||
101 | /** |
||
102 | * The array with the root categories. |
||
103 | * |
||
104 | * @var array |
||
105 | */ |
||
106 | protected $rootCategories = array(); |
||
107 | |||
108 | /** |
||
109 | * The product bunch processor instance. |
||
110 | * |
||
111 | * @var \TechDivision\Import\Product\UrlRewrite\Services\ProductUrlRewriteProcessorInterface |
||
112 | 5 | */ |
|
113 | protected $productUrlRewriteProcessor; |
||
114 | 5 | ||
115 | 5 | /** |
|
116 | * Initialize the observer with the passed product URL rewrite processor instance. |
||
117 | * |
||
118 | * @param \TechDivision\Import\Product\UrlRewrite\Services\ProductUrlRewriteProcessorInterface $productUrlRewriteProcessor The product URL rewrite processor instance |
||
119 | */ |
||
120 | public function __construct(ProductUrlRewriteProcessorInterface $productUrlRewriteProcessor) |
||
124 | 3 | ||
125 | /** |
||
126 | * Will be invoked by the observer visitor when a factory has been defined to create the observer instance. |
||
127 | * |
||
128 | * @param \TechDivision\Import\Subjects\SubjectInterface $subject The subject instance |
||
129 | * |
||
130 | * @return \TechDivision\Import\Observers\ObserverInterface The observer instance |
||
131 | */ |
||
132 | public function createObserver(SubjectInterface $subject) |
||
147 | |||
148 | /** |
||
149 | * Return's the product bunch processor instance. |
||
150 | * |
||
151 | * @return \TechDivision\Import\Product\Services\ProductBunchProcessorInterface The product bunch processor instance |
||
152 | */ |
||
153 | protected function getProductUrlRewriteProcessor() |
||
157 | |||
158 | /** |
||
159 | 3 | * Will be invoked by the action on the events the listener has been registered for. |
|
160 | 3 | * |
|
161 | * @param \TechDivision\Import\Subjects\SubjectInterface $subject The subject instance |
||
162 | * |
||
163 | * @return array The modified row |
||
164 | * @throws \Exception Is thrown, if the product is not available or no URL key has been specified |
||
165 | * @see \TechDivision\Import\Observers\ObserverInterface::handle() |
||
166 | */ |
||
167 | public function handle(SubjectInterface $subject) |
||
272 | |||
273 | 2 | /** |
|
274 | 2 | * Process the observer's business logic. |
|
275 | * |
||
276 | * @return void |
||
277 | */ |
||
278 | 2 | protected function process() |
|
323 | 3 | ||
324 | /** |
||
325 | * Initialize the category product with the passed attributes and returns an instance. |
||
326 | * |
||
327 | 3 | * @param array $attr The category product attributes |
|
328 | 3 | * |
|
329 | * @return array The initialized category product |
||
330 | */ |
||
331 | protected function initializeUrlRewrite(array $attr) |
||
335 | |||
336 | /** |
||
337 | * Initialize the URL rewrite product => category relation with the passed attributes |
||
338 | * and returns an instance. |
||
339 | * |
||
340 | * @param array $attr The URL rewrite product => category relation attributes |
||
341 | * |
||
342 | * @return array The initialized URL rewrite product => category relation |
||
343 | */ |
||
344 | protected function initializeUrlRewriteProductCategory($attr) |
||
348 | 3 | ||
349 | /** |
||
350 | * Prepare's the URL rewrites that has to be created/updated. |
||
351 | 3 | * |
|
352 | * @return void |
||
353 | */ |
||
354 | 3 | protected function prepareUrlRewrites() |
|
417 | 2 | ||
418 | /** |
||
419 | 2 | * Resolve's the parent categories of the category with the passed ID and relate's |
|
420 | * it with the product with the passed ID, if the category is top level OR has the |
||
421 | * anchor flag set. |
||
422 | * |
||
423 | * @param integer $categoryId The ID of the category to resolve the parents |
||
424 | * @param boolean $topLevel TRUE if the passed category has top level, else FALSE |
||
425 | * @param string $storeViewCode The store view code to resolve the category IDs for |
||
426 | * |
||
427 | * @return void |
||
428 | */ |
||
429 | 4 | protected function resolveCategoryIds($categoryId, $topLevel = false, $storeViewCode = StoreViewCodes::ADMIN) |
|
446 | 3 | ||
447 | 3 | /** |
|
448 | 3 | * Adds the entity product relation if necessary. |
|
449 | * |
||
450 | * @param array $category The category to create the relation for |
||
451 | 2 | * @param boolean $topLevel Whether or not the category has top level |
|
452 | 2 | * |
|
453 | 2 | * @return void |
|
454 | 2 | */ |
|
455 | 2 | protected function createProductCategoryRelation($category, $topLevel) |
|
486 | |||
487 | /** |
||
488 | 3 | * Returns the option value for whether or not to generate product catalog rewrites as well. |
|
489 | * |
||
490 | * @return bool |
||
491 | 3 | */ |
|
492 | 3 | protected function getGenerateCategoryProductRewritesOptionValue() |
|
499 | 3 | ||
500 | 3 | /** |
|
501 | 3 | * Prepare the attributes of the entity that has to be persisted. |
|
502 | 3 | * |
|
503 | 3 | * @param string $storeViewCode The store view code to prepare the attributes for |
|
504 | 3 | * |
|
505 | 3 | * @return array The prepared attributes |
|
506 | 3 | */ |
|
507 | protected function prepareAttributes($storeViewCode) |
||
536 | 3 | ||
537 | /** |
||
538 | * Prepare's the URL rewrite product => category relation attributes. |
||
539 | * |
||
540 | 3 | * @return array The prepared attributes |
|
541 | 3 | */ |
|
542 | protected function prepareUrlRewriteProductCategoryAttributes() |
||
554 | |||
555 | /** |
||
556 | * Prepare's the target path for a URL rewrite. |
||
557 | * |
||
558 | 3 | * @param array $category The categroy with the URL path |
|
559 | * |
||
560 | * @return string The target path |
||
561 | */ |
||
562 | 3 | protected function prepareTargetPath(array $category) |
|
575 | |||
576 | /** |
||
577 | * Prepare's the request path for a URL rewrite or the target path for a 301 redirect. |
||
578 | * |
||
579 | * @param array $category The categroy with the URL path |
||
580 | * |
||
581 | * @return string The request path |
||
582 | * @throws \RuntimeException Is thrown, if the passed category has no or an empty value for attribute "url_path" |
||
583 | */ |
||
584 | protected function prepareRequestPath(array $category) |
||
611 | |||
612 | /** |
||
613 | * Prepare's the URL rewrite's metadata with the passed category values. |
||
614 | * |
||
615 | * @param array $category The category used for preparation |
||
616 | 3 | * |
|
617 | * @return array|null The metadata |
||
618 | 3 | */ |
|
619 | protected function prepareMetadata(array $category) |
||
636 | |||
637 | /** |
||
638 | * Query whether or not the actual entity is visible. |
||
639 | * |
||
640 | * @return boolean TRUE if the entity is visible, else FALSE |
||
641 | 3 | */ |
|
642 | protected function isVisible() |
||
646 | |||
647 | /** |
||
648 | * Return's the visibility for the passed entity ID, if it already has been mapped. The mapping will be created |
||
649 | * by calling <code>\TechDivision\Import\Product\Subjects\BunchSubject::getVisibilityIdByValue</code> which will |
||
650 | * be done by the <code>\TechDivision\Import\Product\Callbacks\VisibilityCallback</code>. |
||
651 | * |
||
652 | * @return integer The visibility ID |
||
653 | 3 | * @throws \Exception Is thrown, if the entity ID has not been mapped |
|
654 | * @see \TechDivision\Import\Product\Subjects\BunchSubject::getVisibilityIdByValue() |
||
655 | */ |
||
656 | protected function getEntityIdVisibilityIdMapping() |
||
660 | 3 | ||
661 | /** |
||
662 | * Return's the root category for the actual view store. |
||
663 | * |
||
664 | * @return array The store's root category |
||
665 | * @throws \Exception Is thrown if the root category for the passed store code is NOT available |
||
666 | */ |
||
667 | protected function getRootCategory() |
||
671 | 2 | ||
672 | /** |
||
673 | 2 | * Return's TRUE if the passed category IS the root category, else FALSE. |
|
674 | * |
||
675 | * @param array $category The category to query |
||
676 | * |
||
677 | * @return boolean TRUE if the passed category IS the root category |
||
678 | */ |
||
679 | protected function isRootCategory(array $category) |
||
683 | |||
684 | 2 | /** |
|
685 | * Return's the category with the passed path. |
||
686 | 2 | * |
|
687 | * @param string $path The path of the category to return |
||
688 | * @param string $storeViewCode The store view code of the category to return |
||
689 | * |
||
690 | * @return array The category |
||
691 | */ |
||
692 | protected function getCategoryByPath($path, $storeViewCode = StoreViewCodes::ADMIN) |
||
696 | 3 | ||
697 | /** |
||
698 | 3 | * Return's the category with the passed ID. |
|
699 | * |
||
700 | * @param integer $categoryId The ID of the category to return |
||
701 | * @param string $storeViewCode The store view code of category to return |
||
702 | * |
||
703 | * @return array The category data |
||
704 | */ |
||
705 | protected function getCategory($categoryId, $storeViewCode = StoreViewCodes::ADMIN) |
||
709 | |||
710 | 2 | /** |
|
711 | * Persist's the URL rewrite with the passed data. |
||
712 | * |
||
713 | * @param array $row The URL rewrite to persist |
||
714 | * |
||
715 | * @return string The ID of the persisted entity |
||
716 | */ |
||
717 | protected function persistUrlRewrite($row) |
||
721 | 3 | ||
722 | /** |
||
723 | 3 | * Persist's the URL rewrite product => category relation with the passed data. |
|
724 | * |
||
725 | * @param array $row The URL rewrite product => category relation to persist |
||
726 | * |
||
727 | * @return void |
||
728 | */ |
||
729 | protected function persistUrlRewriteProductCategory($row) |
||
733 | 3 | ||
734 | /** |
||
735 | 3 | * Queries whether or not the passed SKU and store view code has already been processed. |
|
736 | 3 | * |
|
737 | * @param string $sku The SKU to check been processed |
||
738 | * @param string $storeViewCode The store view code to check been processed |
||
739 | * |
||
740 | * @return boolean TRUE if the SKU and store view code has been processed, else FALSE |
||
741 | */ |
||
742 | protected function storeViewHasBeenProcessed($sku, $storeViewCode) |
||
746 | |||
747 | 3 | /** |
|
748 | 3 | * Add the entity ID => visibility mapping for the actual entity ID. |
|
749 | * |
||
750 | * @param string $visibility The visibility of the actual entity to map |
||
751 | * |
||
752 | * @return void |
||
753 | */ |
||
754 | protected function addEntityIdVisibilityIdMapping($visibility) |
||
758 | |||
759 | 3 | /** |
|
760 | * Set's the ID of the product that has been created recently. |
||
761 | * |
||
762 | * @param string $lastEntityId The entity ID |
||
763 | * |
||
764 | * @return void |
||
765 | */ |
||
766 | protected function setLastEntityId($lastEntityId) |
||
770 | |||
771 | /** |
||
772 | * Load's and return's the product with the passed SKU. |
||
773 | * |
||
774 | * @param string $sku The SKU of the product to load |
||
775 | * |
||
776 | * @return array The product |
||
777 | */ |
||
778 | protected function loadProduct($sku) |
||
782 | } |
||
783 |
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.
This is most likely a typographical error or the method has been renamed.