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 Helper 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 Helper, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 27 | class Helper |
||
| 28 | { |
||
| 29 | /** |
||
| 30 | * @var ModelManager |
||
| 31 | */ |
||
| 32 | private $manager; |
||
| 33 | |||
| 34 | private $connectCategoryQuery; |
||
| 35 | |||
| 36 | /** @var \ShopwarePlugins\Connect\Components\ProductQuery */ |
||
| 37 | private $connectProductQuery; |
||
| 38 | |||
| 39 | /** |
||
| 40 | * @param ModelManager $manager |
||
| 41 | * @param CategoryQuery |
||
| 42 | * @param ProductQuery |
||
| 43 | */ |
||
| 44 | public function __construct( |
||
| 45 | ModelManager $manager, |
||
| 46 | CategoryQuery $connectCategoryQuery, |
||
| 47 | ProductQuery $connectProductQuery |
||
| 48 | ) { |
||
| 49 | $this->manager = $manager; |
||
| 50 | $this->connectCategoryQuery = $connectCategoryQuery; |
||
| 51 | $this->connectProductQuery = $connectProductQuery; |
||
| 52 | } |
||
| 53 | |||
| 54 | /** |
||
| 55 | * @return \Shopware\Models\Customer\Group |
||
| 56 | */ |
||
| 57 | public function getDefaultCustomerGroup() |
||
| 58 | { |
||
| 59 | $repository = $this->manager->getRepository('Shopware\Models\Customer\Group'); |
||
| 60 | $customerGroup = $repository->findOneBy(['key' => 'EK']); |
||
| 61 | |||
| 62 | return $customerGroup; |
||
| 63 | } |
||
| 64 | |||
| 65 | /** |
||
| 66 | * Returns an article model for a given (sdk) product. |
||
| 67 | * |
||
| 68 | * @param Product $product |
||
| 69 | * @param int $mode |
||
| 70 | * @return null|ProductModel |
||
| 71 | */ |
||
| 72 | View Code Duplication | public function getArticleModelByProduct(Product $product, $mode = Query::HYDRATE_OBJECT) |
|
| 96 | |||
| 97 | /** |
||
| 98 | * @param Product $product |
||
| 99 | * @param int $mode |
||
| 100 | * @return null|ProductDetail |
||
| 101 | */ |
||
| 102 | View Code Duplication | public function getArticleDetailModelByProduct(Product $product, $mode = Query::HYDRATE_OBJECT) |
|
| 128 | |||
| 129 | public function getConnectArticleModel($sourceId, $shopId) |
||
| 155 | |||
| 156 | /** |
||
| 157 | * @param array $orderNumbers |
||
| 158 | * @return array |
||
| 159 | */ |
||
| 160 | View Code Duplication | public function getArticleIdsByNumber(array $orderNumbers) |
|
| 175 | |||
| 176 | /** |
||
| 177 | * Returns article detail model by |
||
| 178 | * given sourceId and shopId |
||
| 179 | * |
||
| 180 | * @param string $sourceId |
||
| 181 | * @param int $shopId |
||
| 182 | * @return null|ProductDetail |
||
| 183 | */ |
||
| 184 | public function getConnectArticleDetailModel($sourceId, $shopId) |
||
| 190 | |||
| 191 | /** |
||
| 192 | * Helper to update the connect_items table |
||
| 193 | */ |
||
| 194 | public function updateConnectProducts() |
||
| 229 | |||
| 230 | /** |
||
| 231 | * Returns a remote connectProduct e.g. for checkout maniputlations |
||
| 232 | * |
||
| 233 | * @param array $ids |
||
| 234 | * @param int $shopId |
||
| 235 | * @return array |
||
| 236 | */ |
||
| 237 | public function getRemoteProducts(array $ids, $shopId) |
||
| 241 | |||
| 242 | /** |
||
| 243 | * Returns a local connectProduct for export |
||
| 244 | * |
||
| 245 | * @param array $sourceIds |
||
| 246 | * @return Product[] |
||
| 247 | */ |
||
| 248 | public function getLocalProduct(array $sourceIds) |
||
| 252 | |||
| 253 | /** |
||
| 254 | * Does the current basket contain connect products? |
||
| 255 | * |
||
| 256 | * @param $session |
||
| 257 | * @return bool |
||
| 258 | */ |
||
| 259 | public function hasBasketConnectProducts($session, $userId = null) |
||
| 285 | |||
| 286 | /** |
||
| 287 | * Will return the connectAttribute for a given model. The model can be an Article\Article or Article\Detail |
||
| 288 | * |
||
| 289 | * @param $model ProductModel|ProductDetail |
||
| 290 | * @return ConnectAttribute |
||
| 291 | */ |
||
| 292 | public function getConnectAttributeByModel($model) |
||
| 311 | |||
| 312 | /** |
||
| 313 | * Returns connectAttributes for all article details by given article object |
||
| 314 | * |
||
| 315 | * @param ProductModel $article |
||
| 316 | * @return \Shopware\CustomModels\Connect\Attribute[] |
||
| 317 | */ |
||
| 318 | public function getConnectAttributesByArticle(ProductModel $article) |
||
| 332 | |||
| 333 | /** |
||
| 334 | * Returns true when product is exported to Connect |
||
| 335 | * |
||
| 336 | * @param Attribute $connectAttribute |
||
| 337 | * @return bool |
||
| 338 | */ |
||
| 339 | public function isProductExported(Attribute $connectAttribute) |
||
| 360 | |||
| 361 | /** |
||
| 362 | * Verifies that at least one variant from |
||
| 363 | * same article is exported. |
||
| 364 | * |
||
| 365 | * @param Attribute $connectAttribute |
||
| 366 | * @return bool |
||
| 367 | */ |
||
| 368 | public function hasExportedVariants(Attribute $connectAttribute) |
||
| 383 | |||
| 384 | /** |
||
| 385 | * Helper method to create a connect attribute on the fly |
||
| 386 | * |
||
| 387 | * @param $model |
||
| 388 | * @throws \RuntimeException |
||
| 389 | * @return ConnectAttribute |
||
| 390 | */ |
||
| 391 | public function getOrCreateConnectAttributeByModel($model) |
||
| 422 | |||
| 423 | /** |
||
| 424 | * Returns connect attributes for article |
||
| 425 | * and all variants. |
||
| 426 | * If connect attribute does not exist |
||
| 427 | * it will be created. |
||
| 428 | * |
||
| 429 | * @param ProductModel $article |
||
| 430 | * @return array |
||
| 431 | */ |
||
| 432 | public function getOrCreateConnectAttributes(ProductModel $article) |
||
| 442 | |||
| 443 | /** |
||
| 444 | * Generate sourceId |
||
| 445 | * |
||
| 446 | * @param ProductDetail $detail |
||
| 447 | * @return string |
||
| 448 | */ |
||
| 449 | public function generateSourceId(ProductDetail $detail) |
||
| 463 | |||
| 464 | /** |
||
| 465 | * @param $id |
||
| 466 | * @return array |
||
| 467 | */ |
||
| 468 | public function getConnectCategoryForProduct($id) |
||
| 472 | |||
| 473 | /** |
||
| 474 | * @param Product $product |
||
| 475 | * @return \Shopware\Models\Category\Category[] |
||
| 476 | */ |
||
| 477 | public function getCategoriesByProduct(Product $product) |
||
| 481 | |||
| 482 | protected function getCategoryQuery() |
||
| 486 | |||
| 487 | public function getMostRelevantConnectCategory($categories) |
||
| 499 | |||
| 500 | /** |
||
| 501 | * Defines the update flags |
||
| 502 | * |
||
| 503 | * @return array |
||
| 504 | */ |
||
| 505 | public function getUpdateFlags() |
||
| 509 | |||
| 510 | /** |
||
| 511 | * Returns shopware unit entity |
||
| 512 | * |
||
| 513 | * @param $unitKey |
||
| 514 | * @return \Shopware\Models\Article\Unit |
||
| 515 | */ |
||
| 516 | public function getUnit($unitKey) |
||
| 522 | |||
| 523 | /** |
||
| 524 | * Clear article cache |
||
| 525 | */ |
||
| 526 | public function clearArticleCache($articleId) |
||
| 533 | |||
| 534 | /** |
||
| 535 | * Replace unit and ref quantity |
||
| 536 | * @param $products |
||
| 537 | * @return mixed |
||
| 538 | */ |
||
| 539 | public function prepareConnectUnit($products) |
||
| 563 | |||
| 564 | /** |
||
| 565 | * Removes connect reservation from session |
||
| 566 | */ |
||
| 567 | public function clearConnectReservation() |
||
| 571 | |||
| 572 | /** |
||
| 573 | * Collect sourceIds by given article ids |
||
| 574 | * |
||
| 575 | * @param array $articleIds |
||
| 576 | * @return array |
||
| 577 | */ |
||
| 578 | public function getArticleSourceIds(array $articleIds) |
||
| 589 | |||
| 590 | private function getSourceIds(array $articleIds, $kind) |
||
| 623 | |||
| 624 | /** |
||
| 625 | * Get ShopProductId struct by given article detail id |
||
| 626 | * It contains product sourceId and shopId. |
||
| 627 | * If $articleDetailId is local product, $shopProductId->shopId will be null. |
||
| 628 | * |
||
| 629 | * @param int $articleDetailId |
||
| 630 | * @return ShopProductId |
||
| 631 | */ |
||
| 632 | public function getShopProductId($articleDetailId) |
||
| 645 | |||
| 646 | /** |
||
| 647 | * Check if given articleDetailId is remote product |
||
| 648 | * |
||
| 649 | * @param int $articleDetailId |
||
| 650 | * @return bool |
||
| 651 | */ |
||
| 652 | public function isRemoteArticleDetail($articleDetailId) |
||
| 669 | |||
| 670 | /** |
||
| 671 | * Check if given articleDetailId is remote product |
||
| 672 | * |
||
| 673 | * @param int $articleDetailId |
||
| 674 | * @return bool |
||
| 675 | */ |
||
| 676 | public function isRemoteArticleDetailDBAL($articleDetailId) |
||
| 687 | |||
| 688 | /** |
||
| 689 | * Extract article ID and detail ID |
||
| 690 | * from source ID |
||
| 691 | * |
||
| 692 | * @param $sourceId |
||
| 693 | * @return array |
||
| 694 | */ |
||
| 695 | public function explodeArticleId($sourceId) |
||
| 707 | |||
| 708 | /** |
||
| 709 | * Creates Shopware product model |
||
| 710 | * |
||
| 711 | * @param Product $product |
||
| 712 | * @return ProductModel |
||
| 713 | */ |
||
| 714 | public function createProductModel(Product $product) |
||
| 724 | |||
| 725 | /** |
||
| 726 | * Returns main article detail by given groupId |
||
| 727 | * |
||
| 728 | * @param $product |
||
| 729 | * @param int $mode |
||
| 730 | * @return null|ProductModel |
||
| 731 | */ |
||
| 732 | View Code Duplication | public function getArticleByRemoteProduct(Product $product, $mode = Query::HYDRATE_OBJECT) |
|
| 758 | |||
| 759 | /** |
||
| 760 | * @param $articleId |
||
| 761 | * @return array |
||
| 762 | */ |
||
| 763 | public function getSourceIdsFromArticleId($articleId) |
||
| 774 | |||
| 775 | /** |
||
| 776 | * @param Unit $localUnit |
||
| 777 | * @param string $remoteUnit |
||
| 778 | */ |
||
| 779 | public function updateUnitInRelatedProducts(Unit $localUnit, $remoteUnit) |
||
| 791 | |||
| 792 | /** |
||
| 793 | * Checks whether given sourceId is main variant. |
||
| 794 | * Works only with local products. |
||
| 795 | * SourceIds pattern is articleId-variantId (58-142) |
||
| 796 | * |
||
| 797 | * For remote product check is_main_variant flag in |
||
| 798 | * s_plugin_connect_items |
||
| 799 | * |
||
| 800 | * @param string $sourceId |
||
| 801 | * @return bool |
||
| 802 | */ |
||
| 803 | public function isMainVariant($sourceId) |
||
| 819 | |||
| 820 | /** |
||
| 821 | * @return array |
||
| 822 | */ |
||
| 823 | View Code Duplication | public function getAllNonConnectArticleIds() |
|
| 836 | } |
||
| 837 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.