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 ProductToShop 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 ProductToShop, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 47 | class ProductToShop implements ProductToShopBase |
||
| 48 | { |
||
| 49 | const RELATION_TYPE_RELATED = 'relationships'; |
||
| 50 | const RELATION_TYPE_SIMILAR = 'similar'; |
||
| 51 | |||
| 52 | /** |
||
| 53 | * @var Helper |
||
| 54 | */ |
||
| 55 | private $helper; |
||
| 56 | |||
| 57 | /** |
||
| 58 | * @var ModelManager |
||
| 59 | */ |
||
| 60 | private $manager; |
||
| 61 | |||
| 62 | /** |
||
| 63 | * @var \ShopwarePlugins\Connect\Components\Config |
||
| 64 | */ |
||
| 65 | private $config; |
||
| 66 | |||
| 67 | /** |
||
| 68 | * @var ImageImport |
||
| 69 | */ |
||
| 70 | private $imageImport; |
||
| 71 | |||
| 72 | /** |
||
| 73 | * @var \ShopwarePlugins\Connect\Components\VariantConfigurator |
||
| 74 | */ |
||
| 75 | private $variantConfigurator; |
||
| 76 | |||
| 77 | /** |
||
| 78 | * @var MarketplaceGateway |
||
| 79 | */ |
||
| 80 | private $marketplaceGateway; |
||
| 81 | |||
| 82 | /** |
||
| 83 | * @var ProductTranslationsGateway |
||
| 84 | */ |
||
| 85 | private $productTranslationsGateway; |
||
| 86 | |||
| 87 | /** |
||
| 88 | * @var \Shopware\Models\Shop\Repository |
||
| 89 | */ |
||
| 90 | private $shopRepository; |
||
| 91 | |||
| 92 | private $localeRepository; |
||
| 93 | |||
| 94 | /** |
||
| 95 | * @var CategoryResolver |
||
| 96 | */ |
||
| 97 | private $categoryResolver; |
||
| 98 | |||
| 99 | /** |
||
| 100 | * @var \Shopware\Connect\Gateway |
||
| 101 | */ |
||
| 102 | private $connectGateway; |
||
| 103 | |||
| 104 | /** |
||
| 105 | * @var \Enlight_Event_EventManager |
||
| 106 | */ |
||
| 107 | private $eventManager; |
||
| 108 | |||
| 109 | /** |
||
| 110 | * @var CategoryDenormalization |
||
| 111 | */ |
||
| 112 | private $categoryDenormalization; |
||
| 113 | |||
| 114 | /** |
||
| 115 | * @param Helper $helper |
||
| 116 | * @param ModelManager $manager |
||
| 117 | * @param ImageImport $imageImport |
||
| 118 | * @param \ShopwarePlugins\Connect\Components\Config $config |
||
| 119 | * @param VariantConfigurator $variantConfigurator |
||
| 120 | * @param \ShopwarePlugins\Connect\Components\Marketplace\MarketplaceGateway $marketplaceGateway |
||
| 121 | * @param ProductTranslationsGateway $productTranslationsGateway |
||
| 122 | * @param CategoryResolver $categoryResolver |
||
| 123 | * @param Gateway $connectGateway |
||
| 124 | * @param \Enlight_Event_EventManager $eventManager |
||
| 125 | * @param CategoryDenormalization $categoryDenormalization |
||
| 126 | */ |
||
| 127 | public function __construct( |
||
| 128 | Helper $helper, |
||
| 129 | ModelManager $manager, |
||
| 130 | ImageImport $imageImport, |
||
| 131 | Config $config, |
||
| 132 | VariantConfigurator $variantConfigurator, |
||
| 133 | MarketplaceGateway $marketplaceGateway, |
||
| 134 | ProductTranslationsGateway $productTranslationsGateway, |
||
| 135 | CategoryResolver $categoryResolver, |
||
| 136 | Gateway $connectGateway, |
||
| 137 | \Enlight_Event_EventManager $eventManager, |
||
| 138 | CategoryDenormalization $categoryDenormalization |
||
| 139 | ) { |
||
| 140 | $this->helper = $helper; |
||
| 141 | $this->manager = $manager; |
||
| 142 | $this->config = $config; |
||
| 143 | $this->imageImport = $imageImport; |
||
| 144 | $this->variantConfigurator = $variantConfigurator; |
||
| 145 | $this->marketplaceGateway = $marketplaceGateway; |
||
| 146 | $this->productTranslationsGateway = $productTranslationsGateway; |
||
| 147 | $this->categoryResolver = $categoryResolver; |
||
| 148 | $this->connectGateway = $connectGateway; |
||
| 149 | $this->eventManager = $eventManager; |
||
| 150 | $this->categoryDenormalization = $categoryDenormalization; |
||
| 151 | } |
||
| 152 | |||
| 153 | /** |
||
| 154 | * Start transaction |
||
| 155 | * |
||
| 156 | * Starts a transaction, which includes all insertOrUpdate and delete |
||
| 157 | * operations, as well as the revision updates. |
||
| 158 | * |
||
| 159 | * @return void |
||
| 160 | */ |
||
| 161 | public function startTransaction() |
||
| 162 | { |
||
| 163 | $this->manager->getConnection()->beginTransaction(); |
||
| 164 | } |
||
| 165 | |||
| 166 | /** |
||
| 167 | * Commit transaction |
||
| 168 | * |
||
| 169 | * Commits the transactions, once all operations are queued. |
||
| 170 | * |
||
| 171 | * @return void |
||
| 172 | */ |
||
| 173 | public function commit() |
||
| 174 | { |
||
| 175 | $this->manager->getConnection()->commit(); |
||
| 176 | } |
||
| 177 | |||
| 178 | /** |
||
| 179 | * Import or update given product |
||
| 180 | * |
||
| 181 | * Store product in your shop database as an external product. The |
||
| 182 | * associated sourceId |
||
| 183 | * |
||
| 184 | * @param Product $product |
||
| 185 | */ |
||
| 186 | public function insertOrUpdate(Product $product) |
||
| 187 | { |
||
| 188 | /** @var Product $product */ |
||
| 189 | $product = $this->eventManager->filter( |
||
| 190 | 'Connect_ProductToShop_InsertOrUpdate_Before', |
||
| 191 | $product |
||
| 192 | ); |
||
| 193 | |||
| 194 | // todo@dn: Set dummy values and make product inactive |
||
| 195 | if (empty($product->title) || empty($product->vendor)) { |
||
| 196 | return; |
||
| 197 | } |
||
| 198 | |||
| 199 | $number = $this->generateSKU($product); |
||
| 200 | |||
| 201 | $detail = $this->helper->getArticleDetailModelByProduct($product); |
||
| 202 | $detail = $this->eventManager->filter( |
||
| 203 | 'Connect_Merchant_Get_Article_Detail_After', |
||
| 204 | $detail, |
||
| 205 | [ |
||
| 206 | 'product' => $product, |
||
| 207 | 'subject' => $this |
||
| 208 | ] |
||
| 209 | ); |
||
| 210 | |||
| 211 | $isMainVariant = false; |
||
| 212 | if ($detail === null) { |
||
| 213 | $active = $this->config->getConfig('activateProductsAutomatically', false) ? true : false; |
||
| 214 | |||
| 215 | $model = $this->getSWProductModel($product, $active, $isMainVariant); |
||
| 216 | |||
| 217 | $detail = $this->generateNewDetail($product, $model); |
||
| 218 | } else { |
||
| 219 | /** @var ProductModel $model */ |
||
| 220 | $model = $detail->getArticle(); |
||
| 221 | // fix for isMainVariant flag |
||
| 222 | // in connect attribute table |
||
| 223 | $mainDetail = $model->getMainDetail(); |
||
| 224 | $isMainVariant = $this->checkIfMainVariant($detail, $mainDetail); |
||
| 225 | $this->variantConfigurator->configureVariantAttributes($product, $detail); |
||
| 226 | $this->updateConfiguratorSetTypeFromProduct($model, $product); |
||
| 227 | |||
| 228 | $this->cleanUpConfiguratorSet($model, $product); |
||
| 229 | } |
||
| 230 | |||
| 231 | $detail->setNumber($number); |
||
| 232 | |||
| 233 | $detailAttribute = $this->getOrCreateAttributeModel($detail, $model); |
||
| 234 | |||
| 235 | $connectAttribute = $this->helper->getConnectAttributeByModel($detail) ?: new ConnectAttribute; |
||
| 236 | // configure main variant and groupId |
||
| 237 | if ($isMainVariant === true) { |
||
| 238 | $connectAttribute->setIsMainVariant(true); |
||
| 239 | } |
||
| 240 | $connectAttribute->setGroupId($product->groupId); |
||
| 241 | |||
| 242 | list($updateFields, $flag) = $this->getUpdateFields($model, $detail, $connectAttribute, $product); |
||
| 243 | $this->setPropertiesForNewProducts($updateFields, $model, $detailAttribute, $product); |
||
| 244 | |||
| 245 | $this->saveVat($product, $model); |
||
| 246 | |||
| 247 | $this->applyProductProperties($model, $product); |
||
| 248 | |||
| 249 | $detailAttribute = $this->applyMarketplaceAttributes($detailAttribute, $product); |
||
| 250 | |||
| 251 | $this->setConnectAttributesFromProduct($connectAttribute, $product); |
||
| 252 | |||
| 253 | // store product categories to connect attribute |
||
| 254 | $connectAttribute->setCategory($product->categories); |
||
| 255 | |||
| 256 | $connectAttribute->setLastUpdateFlag($flag); |
||
| 257 | |||
| 258 | $connectAttribute->setPurchasePriceHash($product->purchasePriceHash); |
||
| 259 | $connectAttribute->setOfferValidUntil($product->offerValidUntil); |
||
| 260 | |||
| 261 | $this->updateDetailFromProduct($detail, $product); |
||
| 262 | |||
| 263 | // some shops have feature "sell not in stock", |
||
| 264 | // then end customer should be able to by the product with stock = 0 |
||
| 265 | $shopConfiguration = $this->connectGateway->getShopConfiguration($product->shopId); |
||
| 266 | if ($shopConfiguration && $shopConfiguration->sellNotInStock) { |
||
| 267 | $model->setLastStock(false); |
||
| 268 | } else { |
||
| 269 | $model->setLastStock(true); |
||
| 270 | } |
||
| 271 | |||
| 272 | $this->detailSetUnit($detail, $product, $detailAttribute); |
||
| 273 | |||
| 274 | $this->detailSetAttributes($detail, $product); |
||
| 275 | |||
| 276 | $this->connectAttributeSetLastUpdate($connectAttribute, $product); |
||
| 277 | |||
| 278 | if ($model->getMainDetail() === null) { |
||
| 279 | $model->setMainDetail($detail); |
||
| 280 | } |
||
| 281 | |||
| 282 | if ($detail->getAttribute() === null) { |
||
| 283 | $detail->setAttribute($detailAttribute); |
||
| 284 | $detailAttribute->setArticle($model); |
||
| 285 | } |
||
| 286 | |||
| 287 | $connectAttribute->setArticle($model); |
||
| 288 | $connectAttribute->setArticleDetail($detail); |
||
| 289 | |||
| 290 | $this->eventManager->notify( |
||
| 291 | 'Connect_Merchant_Saving_ArticleAttribute_Before', |
||
| 292 | [ |
||
| 293 | 'subject' => $this, |
||
| 294 | 'connectAttribute' => $connectAttribute |
||
| 295 | ] |
||
| 296 | ); |
||
| 297 | |||
| 298 | //article has to be flushed |
||
| 299 | $this->manager->persist($model); |
||
| 300 | $this->manager->persist($connectAttribute); |
||
| 301 | $this->manager->persist($detail); |
||
| 302 | $this->manager->flush(); |
||
| 303 | |||
| 304 | $this->categoryResolver->storeRemoteCategories($product->categories, $model->getId(), $product->shopId); |
||
| 305 | $categories = $this->categoryResolver->resolve($product->categories, $product->shopId, $product->stream); |
||
| 306 | if (count($categories) > 0) { |
||
| 307 | $detailAttribute->setConnectMappedCategory(true); |
||
| 308 | } |
||
| 309 | |||
| 310 | $this->manager->persist($detailAttribute); |
||
| 311 | $this->manager->flush(); |
||
| 312 | |||
| 313 | $this->categoryDenormalization($model, $categories); |
||
| 314 | |||
| 315 | $defaultCustomerGroup = $this->helper->getDefaultCustomerGroup(); |
||
| 316 | // Only set prices, if fixedPrice is active or price updates are configured |
||
| 317 | if (count($detail->getPrices()) == 0 || $connectAttribute->getFixedPrice() || $updateFields['price']) { |
||
| 318 | $this->setPrice($model, $detail, $product); |
||
| 319 | } |
||
| 320 | // If the price is not being update, update the purchasePrice anyway |
||
| 321 | $this->setPurchasePrice($detail, $product->purchasePrice, $defaultCustomerGroup); |
||
| 322 | |||
| 323 | $this->manager->clear(); |
||
| 324 | |||
| 325 | $this->addArticleTranslations($model, $product); |
||
| 326 | |||
| 327 | if ($isMainVariant || $product->groupId === null) { |
||
| 328 | $this->applyCrossSelling($model->getId(), $product); |
||
| 329 | } |
||
| 330 | |||
| 331 | //clear cache for that article |
||
| 332 | $this->helper->clearArticleCache($model->getId()); |
||
| 333 | |||
| 334 | if ($updateFields['image']) { |
||
| 335 | // Reload the model in order to not to work an the already flushed model |
||
| 336 | $model = $this->helper->getArticleModelByProduct($product); |
||
| 337 | // import only global images for article |
||
| 338 | $this->imageImport->importImagesForArticle(array_diff($product->images, $product->variantImages), $model); |
||
|
|
|||
| 339 | if ($updateFields['mainImage'] && isset($product->images[0])) { |
||
| 340 | $this->imageImport->importMainImage($product->images[0], $model->getId()); |
||
| 341 | } |
||
| 342 | // Reload the article detail model in order to not to work an the already flushed model |
||
| 343 | $detail = $this->helper->getArticleDetailModelByProduct($product); |
||
| 344 | // import only specific images for variant |
||
| 345 | $this->imageImport->importImagesForDetail($product->variantImages, $detail); |
||
| 346 | } |
||
| 347 | |||
| 348 | $this->eventManager->notify( |
||
| 349 | 'Connect_ProductToShop_InsertOrUpdate_After', |
||
| 350 | [ |
||
| 351 | 'connectProduct' => $product, |
||
| 352 | 'shopArticleDetail' => $detail |
||
| 353 | ] |
||
| 354 | ); |
||
| 355 | |||
| 356 | $stream = $this->getOrCreateStream($product); |
||
| 357 | $this->addProductToStream($stream, $model); |
||
| 358 | } |
||
| 359 | |||
| 360 | /** |
||
| 361 | * @param Product $product |
||
| 362 | * @return string |
||
| 363 | */ |
||
| 364 | private function generateSKU(Product $product) |
||
| 365 | { |
||
| 366 | if (!empty($product->sku)) { |
||
| 367 | $number = 'SC-' . $product->shopId . '-' . $product->sku; |
||
| 368 | $duplicatedDetail = $this->helper->getDetailByNumber($number); |
||
| 369 | if ($duplicatedDetail |
||
| 370 | && $this->helper->getConnectAttributeByModel($duplicatedDetail)->getSourceId() != $product->sourceId |
||
| 371 | ) { |
||
| 372 | $this->deleteDetail($duplicatedDetail); |
||
| 373 | } |
||
| 374 | } else { |
||
| 375 | $number = 'SC-' . $product->shopId . '-' . $product->sourceId; |
||
| 376 | } |
||
| 377 | |||
| 378 | return $number; |
||
| 379 | } |
||
| 380 | |||
| 381 | /** |
||
| 382 | * @param DetailModel $detailModel |
||
| 383 | */ |
||
| 384 | private function deleteDetail(DetailModel $detailModel) |
||
| 385 | { |
||
| 386 | $this->eventManager->notify( |
||
| 387 | 'Connect_Merchant_Delete_Product_Before', |
||
| 388 | [ |
||
| 389 | 'subject' => $this, |
||
| 390 | 'articleDetail' => $detailModel |
||
| 391 | ] |
||
| 392 | ); |
||
| 393 | |||
| 394 | $article = $detailModel->getArticle(); |
||
| 395 | // Not sure why, but the Attribute can be NULL |
||
| 396 | $attribute = $this->helper->getConnectAttributeByModel($detailModel); |
||
| 397 | $this->manager->remove($detailModel); |
||
| 398 | |||
| 399 | if ($attribute) { |
||
| 400 | $this->manager->remove($attribute); |
||
| 401 | } |
||
| 402 | |||
| 403 | // if removed variant is main variant |
||
| 404 | // find first variant which is not main and mark it |
||
| 405 | if ($detailModel->getKind() === 1) { |
||
| 406 | /** @var \Shopware\Models\Article\Detail $variant */ |
||
| 407 | foreach ($article->getDetails() as $variant) { |
||
| 408 | if ($variant->getId() != $detailModel->getId()) { |
||
| 409 | $variant->setKind(1); |
||
| 410 | $article->setMainDetail($variant); |
||
| 411 | $connectAttribute = $this->helper->getConnectAttributeByModel($variant); |
||
| 412 | if (!$connectAttribute) { |
||
| 413 | continue; |
||
| 414 | } |
||
| 415 | $connectAttribute->setIsMainVariant(true); |
||
| 416 | $this->manager->persist($connectAttribute); |
||
| 417 | $this->manager->persist($article); |
||
| 418 | $this->manager->persist($variant); |
||
| 419 | break; |
||
| 420 | } |
||
| 421 | } |
||
| 422 | } |
||
| 423 | |||
| 424 | if (count($details = $article->getDetails()) === 1) { |
||
| 425 | $details->clear(); |
||
| 426 | $this->manager->remove($article); |
||
| 427 | } |
||
| 428 | |||
| 429 | //save category Ids before flush |
||
| 430 | $oldCategoryIds = array_map(function ($category) { |
||
| 431 | return $category->getId(); |
||
| 432 | }, $article->getCategories()->toArray()); |
||
| 433 | |||
| 434 | // Do not remove flush. It's needed when remove article, |
||
| 435 | // because duplication of ordernumber. Even with remove before |
||
| 436 | // persist calls mysql throws exception "Duplicate entry" |
||
| 437 | $this->manager->flush(); |
||
| 438 | // always clear entity manager, because $article->getDetails() returns |
||
| 439 | // more than 1 detail, but all of them were removed except main one. |
||
| 440 | $this->manager->clear(); |
||
| 441 | |||
| 442 | // call this after flush because article has to be deleted that this works |
||
| 443 | if (count($oldCategoryIds) > 0) { |
||
| 444 | $this->categoryResolver->deleteEmptyConnectCategories($oldCategoryIds); |
||
| 445 | } |
||
| 446 | } |
||
| 447 | |||
| 448 | /** |
||
| 449 | * @param Product $product |
||
| 450 | * @param $active |
||
| 451 | * @param $isMainVariant |
||
| 452 | * @return null|Article |
||
| 453 | */ |
||
| 454 | private function getSWProductModel(Product $product, $active, &$isMainVariant) |
||
| 455 | { |
||
| 456 | if ($product->groupId !== null) { |
||
| 457 | $model = $this->helper->getArticleByRemoteProduct($product); |
||
| 458 | if (!$model instanceof \Shopware\Models\Article\Article) { |
||
| 459 | $model = $this->helper->createProductModel($product); |
||
| 460 | $model->setActive($active); |
||
| 461 | $isMainVariant = true; |
||
| 462 | } |
||
| 463 | } else { |
||
| 464 | $model = $this->helper->getConnectArticleModel($product->sourceId, $product->shopId); |
||
| 465 | if (!$model instanceof \Shopware\Models\Article\Article) { |
||
| 466 | $model = $this->helper->createProductModel($product); |
||
| 467 | $model->setActive($active); |
||
| 468 | } |
||
| 469 | } |
||
| 470 | |||
| 471 | return $model; |
||
| 472 | } |
||
| 473 | |||
| 474 | /** |
||
| 475 | * @param Product $product |
||
| 476 | * @param $model |
||
| 477 | * @return DetailModel |
||
| 478 | */ |
||
| 479 | private function generateNewDetail(Product $product, $model) |
||
| 480 | { |
||
| 481 | $detail = new DetailModel(); |
||
| 482 | $detail->setActive($model->getActive()); |
||
| 483 | // added for 5.4 compatibility |
||
| 484 | if (method_exists($detail, 'setLastStock')) { |
||
| 485 | $detail->setLastStock($product->lastStock); |
||
| 486 | } |
||
| 487 | $this->manager->persist($detail); |
||
| 488 | $detail->setArticle($model); |
||
| 489 | $model->getDetails()->add($detail); |
||
| 490 | $this->variantConfigurator->configureVariantAttributes($product, $detail); |
||
| 491 | |||
| 492 | return $detail; |
||
| 493 | } |
||
| 494 | |||
| 495 | /** |
||
| 496 | * @param DetailModel $detail |
||
| 497 | * @param DetailModel $mainDetail |
||
| 498 | * @return bool |
||
| 499 | */ |
||
| 500 | private function checkIfMainVariant(DetailModel $detail, DetailModel $mainDetail) |
||
| 504 | |||
| 505 | /** |
||
| 506 | * @param ProductModel $model |
||
| 507 | * @param Product $product |
||
| 508 | */ |
||
| 509 | private function updateConfiguratorSetTypeFromProduct(ProductModel $model, Product $product) |
||
| 510 | { |
||
| 511 | $configSet = $model->getConfiguratorSet(); |
||
| 512 | if (!empty($product->variant) && $configSet instanceof Set) { |
||
| 513 | $configSet->setType($product->configuratorSetType); |
||
| 514 | } |
||
| 515 | } |
||
| 516 | |||
| 517 | /** |
||
| 518 | * @param ProductModel $model |
||
| 519 | * @param Product $product |
||
| 520 | */ |
||
| 521 | private function cleanUpConfiguratorSet(ProductModel $model, Product $product) |
||
| 530 | |||
| 531 | /** |
||
| 532 | * @param DetailModel $detail |
||
| 533 | * @param ProductModel $model |
||
| 534 | * @return AttributeModel |
||
| 535 | */ |
||
| 536 | private function getOrCreateAttributeModel(DetailModel $detail, ProductModel $model) |
||
| 549 | |||
| 550 | /** |
||
| 551 | * Get array of update info for the known fields |
||
| 552 | * |
||
| 553 | * @param $model |
||
| 554 | * @param $detail |
||
| 555 | * @param $attribute |
||
| 556 | * @param $product |
||
| 557 | * @return array |
||
| 558 | */ |
||
| 559 | public function getUpdateFields($model, $detail, $attribute, $product) |
||
| 592 | |||
| 593 | /** |
||
| 594 | * Helper method to determine if a given $fields may/must be updated. |
||
| 595 | * This method will check for the model->id in order to determine, if it is a new entity. Therefore |
||
| 596 | * this method cannot be used after the model in question was already flushed. |
||
| 597 | * |
||
| 598 | * @param $field |
||
| 599 | * @param $model ProductModel |
||
| 600 | * @param $attribute ConnectAttribute |
||
| 601 | * @throws \RuntimeException |
||
| 602 | * @return bool|null |
||
| 603 | */ |
||
| 604 | public function isFieldUpdateAllowed($field, ProductModel $model, ConnectAttribute $attribute) |
||
| 640 | |||
| 641 | /** |
||
| 642 | * Determine if a given field has changed |
||
| 643 | * |
||
| 644 | * @param $field |
||
| 645 | * @param ProductModel $model |
||
| 646 | * @param DetailModel $detail |
||
| 647 | * @param Product $product |
||
| 648 | * @return bool |
||
| 649 | */ |
||
| 650 | public function hasFieldChanged($field, ProductModel $model, DetailModel $detail, Product $product) |
||
| 684 | |||
| 685 | /** |
||
| 686 | * @param array $updateFields |
||
| 687 | * @param ProductModel $model |
||
| 688 | * @param AttributeModel $detailAttribute |
||
| 689 | * @param Product $product |
||
| 690 | */ |
||
| 691 | private function setPropertiesForNewProducts(array $updateFields, ProductModel $model, AttributeModel $detailAttribute, Product $product) |
||
| 729 | |||
| 730 | /** |
||
| 731 | * @param $vendor |
||
| 732 | * @return Supplier |
||
| 733 | */ |
||
| 734 | private function createSupplier($vendor) |
||
| 762 | |||
| 763 | /** |
||
| 764 | * @param ProductModel $article |
||
| 765 | * @param Product $product |
||
| 766 | */ |
||
| 767 | private function applyProductProperties(ProductModel $article, Product $product) |
||
| 846 | |||
| 847 | /** |
||
| 848 | * Read product attributes mapping and set to shopware attribute model |
||
| 849 | * |
||
| 850 | * @param AttributeModel $detailAttribute |
||
| 851 | * @param Product $product |
||
| 852 | * @return AttributeModel |
||
| 853 | */ |
||
| 854 | private function applyMarketplaceAttributes(AttributeModel $detailAttribute, Product $product) |
||
| 869 | |||
| 870 | /** |
||
| 871 | * @param ConnectAttribute $connectAttribute |
||
| 872 | * @param Product $product |
||
| 873 | */ |
||
| 874 | private function setConnectAttributesFromProduct(ConnectAttribute $connectAttribute, Product $product) |
||
| 887 | |||
| 888 | /** |
||
| 889 | * @param DetailModel $detail |
||
| 890 | * @param Product $product |
||
| 891 | */ |
||
| 892 | private function updateDetailFromProduct(DetailModel $detail, Product $product) |
||
| 902 | |||
| 903 | /** |
||
| 904 | * @param DetailModel $detail |
||
| 905 | * @param Product $product |
||
| 906 | * @param $detailAttribute |
||
| 907 | */ |
||
| 908 | private function detailSetUnit(DetailModel $detail, Product $product, $detailAttribute) |
||
| 935 | |||
| 936 | /** |
||
| 937 | * @param DetailModel $detail |
||
| 938 | * @param Product $product |
||
| 939 | */ |
||
| 940 | private function detailSetAttributes(DetailModel $detail, Product $product) |
||
| 974 | |||
| 975 | /** |
||
| 976 | * @param ConnectAttribute $connectAttribute |
||
| 977 | * @param Product $product |
||
| 978 | */ |
||
| 979 | private function connectAttributeSetLastUpdate(ConnectAttribute $connectAttribute, Product $product) |
||
| 995 | |||
| 996 | /** |
||
| 997 | * @param ProductModel $model |
||
| 998 | * @param array $categories |
||
| 999 | */ |
||
| 1000 | private function categoryDenormalization(ProductModel $model, array $categories) |
||
| 1021 | |||
| 1022 | /** |
||
| 1023 | * @param Product $product |
||
| 1024 | * @return ProductStream |
||
| 1025 | */ |
||
| 1026 | private function getOrCreateStream(Product $product) |
||
| 1053 | |||
| 1054 | /** |
||
| 1055 | * @param ProductStream $stream |
||
| 1056 | * @param ProductModel $article |
||
| 1057 | * @throws \Doctrine\DBAL\DBALException |
||
| 1058 | */ |
||
| 1059 | private function addProductToStream(ProductStream $stream, ProductModel $article) |
||
| 1068 | |||
| 1069 | /** |
||
| 1070 | * Set detail purchase price with plain SQL |
||
| 1071 | * Entity usage throws exception when error handlers are disabled |
||
| 1072 | * |
||
| 1073 | * @param ProductModel $article |
||
| 1074 | * @param DetailModel $detail |
||
| 1075 | * @param Product $product |
||
| 1076 | * @throws \Doctrine\DBAL\DBALException |
||
| 1077 | */ |
||
| 1078 | private function setPrice(ProductModel $article, DetailModel $detail, Product $product) |
||
| 1116 | |||
| 1117 | /** |
||
| 1118 | * @param ProductModel $article |
||
| 1119 | * @param DetailModel $detail |
||
| 1120 | * @param array $priceRanges |
||
| 1121 | * @param Group $group |
||
| 1122 | * @throws \Doctrine\DBAL\ConnectionException |
||
| 1123 | * @throws \Exception |
||
| 1124 | */ |
||
| 1125 | private function setPriceRange(ProductModel $article, DetailModel $detail, array $priceRanges, Group $group) |
||
| 1161 | |||
| 1162 | /** |
||
| 1163 | * Set detail purchase price with plain SQL |
||
| 1164 | * Entity usage throws exception when error handlers are disabled |
||
| 1165 | * |
||
| 1166 | * @param DetailModel $detail |
||
| 1167 | * @param float $purchasePrice |
||
| 1168 | * @param Group $defaultGroup |
||
| 1169 | * @throws \Doctrine\DBAL\DBALException |
||
| 1170 | */ |
||
| 1171 | private function setPurchasePrice(DetailModel $detail, $purchasePrice, Group $defaultGroup) |
||
| 1199 | |||
| 1200 | /** |
||
| 1201 | * Adds translation record for given article |
||
| 1202 | * |
||
| 1203 | * @param ProductModel $article |
||
| 1204 | * @param Product $sdkProduct |
||
| 1205 | */ |
||
| 1206 | private function addArticleTranslations(ProductModel $article, Product $sdkProduct) |
||
| 1221 | |||
| 1222 | /** |
||
| 1223 | * dsadsa |
||
| 1224 | * @return \Shopware\Components\Model\ModelRepository |
||
| 1225 | */ |
||
| 1226 | private function getLocaleRepository() |
||
| 1234 | |||
| 1235 | private function getShopRepository() |
||
| 1243 | |||
| 1244 | /** |
||
| 1245 | * Delete product or product variant with given shopId and sourceId. |
||
| 1246 | * |
||
| 1247 | * Only the combination of both identifies a product uniquely. Do NOT |
||
| 1248 | * delete products just by their sourceId. |
||
| 1249 | * |
||
| 1250 | * You might receive delete requests for products, which are not available |
||
| 1251 | * in your shop. Just ignore them. |
||
| 1252 | * |
||
| 1253 | * @param string $shopId |
||
| 1254 | * @param string $sourceId |
||
| 1255 | * @return void |
||
| 1256 | */ |
||
| 1257 | public function delete($shopId, $sourceId) |
||
| 1269 | |||
| 1270 | public function update($shopId, $sourceId, ProductUpdate $product) |
||
| 1322 | |||
| 1323 | public function changeAvailability($shopId, $sourceId, $availability) |
||
| 1347 | |||
| 1348 | /** |
||
| 1349 | * @inheritDoc |
||
| 1350 | */ |
||
| 1351 | public function makeMainVariant($shopId, $sourceId, $groupId) |
||
| 1384 | |||
| 1385 | /** |
||
| 1386 | * Updates the status of an Order |
||
| 1387 | * |
||
| 1388 | * @param string $localOrderId |
||
| 1389 | * @param string $orderStatus |
||
| 1390 | * @param string $trackingNumber |
||
| 1391 | * @return void |
||
| 1392 | */ |
||
| 1393 | public function updateOrderStatus($localOrderId, $orderStatus, $trackingNumber) |
||
| 1403 | |||
| 1404 | /** |
||
| 1405 | * @param string $localOrderId |
||
| 1406 | * @param string $orderStatus |
||
| 1407 | */ |
||
| 1408 | private function updateDeliveryStatus($localOrderId, $orderStatus) |
||
| 1429 | |||
| 1430 | /** |
||
| 1431 | * @param string $localOrderId |
||
| 1432 | * @param string $trackingNumber |
||
| 1433 | */ |
||
| 1434 | private function updateTrackingNumber($localOrderId, $trackingNumber) |
||
| 1461 | |||
| 1462 | /** |
||
| 1463 | * @param string $newTrackingCode |
||
| 1464 | * @param string $currentTrackingCode |
||
| 1465 | * @return string |
||
| 1466 | */ |
||
| 1467 | private function combineTrackingNumbers($newTrackingCode, $currentTrackingCode) |
||
| 1476 | |||
| 1477 | /** |
||
| 1478 | * @param string $trackingCode |
||
| 1479 | * @return string[] |
||
| 1480 | */ |
||
| 1481 | private function getTrackingNumberAsArray($trackingCode) |
||
| 1489 | |||
| 1490 | /** |
||
| 1491 | * @param Product $product |
||
| 1492 | * @param ProductModel $model |
||
| 1493 | */ |
||
| 1494 | private function saveVat(Product $product, ProductModel $model) |
||
| 1512 | |||
| 1513 | /** |
||
| 1514 | * @param int $articleId |
||
| 1515 | * @param Product $product |
||
| 1516 | */ |
||
| 1517 | private function applyCrossSelling($articleId, Product $product) |
||
| 1525 | |||
| 1526 | /** |
||
| 1527 | * @param int $articleId |
||
| 1528 | * @param Product $product |
||
| 1529 | */ |
||
| 1530 | private function storeCrossSellingInformationOwningSide($articleId, $product) |
||
| 1540 | |||
| 1541 | /** |
||
| 1542 | * @param int $articleId |
||
| 1543 | * @param int $shopId |
||
| 1544 | * @param int $relatedId |
||
| 1545 | * @param string $relationType |
||
| 1546 | */ |
||
| 1547 | private function insertNewRelations($articleId, $shopId, $relatedId, $relationType) |
||
| 1574 | |||
| 1575 | /** |
||
| 1576 | * @param int $articleId |
||
| 1577 | * @param string $sourceId |
||
| 1578 | * @param int $shopId |
||
| 1579 | */ |
||
| 1580 | private function storeCrossSellingInformationInverseSide($articleId, $sourceId, $shopId) |
||
| 1595 | |||
| 1596 | /** |
||
| 1597 | * @param $articleId |
||
| 1598 | * @param $product |
||
| 1599 | */ |
||
| 1600 | private function deleteRemovedRelations($articleId, $product) |
||
| 1678 | |||
| 1679 | /** |
||
| 1680 | * @param Property $property |
||
| 1681 | * @return PropertyGroup |
||
| 1682 | */ |
||
| 1683 | private function createPropertyGroup(Property $property) |
||
| 1702 | } |
||
| 1703 |
Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code: