/** * Does the actual import */ public function import() { $row = Shopware()->Db()->fetchAll(' SELECT * FROM plenty_mapping_category WHERE plentyID LIKE "' . $this->Category->CategoryID . ';%" LIMIT 1 '); if (!$row) { // PyLog()->message('Sync:Item:Category', 'Skipping the category »' . $this->Category->Name . '« (not found)'); return; } $index = explode(PlentymarketsMappingEntityCategory::DELIMITER, $row[0]['shopwareID']); $categoryId = $index[0]; /** @var Shopware\Models\Category\Category $Category */ $Category = Shopware()->Models()->find('Shopware\\Models\\Category\\Category', $categoryId); // If the shopware category wasn't found, something is terribly wrong if (!$Category) { PyLog()->message('Sync:Item:Category', 'Skipping the category »' . $this->Category->Name . '« (not found)'); return; } // Update the category only if the name's changed if ($Category->getName() != $this->Category->Name || $Category->getPosition() != $this->Category->Position) { PyLog()->message('Sync:Item:Category', 'Updating the category »' . $this->Category->Name . '«'); $Category->setName($this->Category->Name); $Category->setPosition($this->Category->Position); Shopware()->Models()->persist($Category); Shopware()->Models()->flush(); } }
/** * generate the thumbnails */ public function generate() { if (!count($this->media)) { return; } $manager = Shopware()->Container()->get('thumbnail_manager'); PyLog()->message('Sync:Item:Image:Thumbnail', 'Starting to generate thumbnails for ' . count($this->media) . ' media resources'); while ($media = array_pop($this->media)) { $manager->createMediaThumbnail($media, array(), true); } PyLog()->message('Sync:Item:Image:Thumbnail', 'Finished generating thumbnails'); }
/** * Does the actual import */ public function import() { try { $SHOPWARE_id = PlentymarketsMappingController::getPropertyGroupByPlentyID($this->Group->PropertyGroupID); PyLog()->message('Sync:Item:Producer', 'Updating the property group »' . $this->Group->FrontendName . '«'); } catch (PlentymarketsMappingExceptionNotExistant $E) { PyLog()->message('Sync:Item:Producer', 'Skipping the property group »' . $this->Group->FrontendName . '«'); return; } /** @var Shopware\Models\Property\Group $Group */ $Group = Shopware()->Models()->find('Shopware\\Models\\Property\\Group', $SHOPWARE_id); // Set the new data $Group->setName($this->Group->FrontendName); Shopware()->Models()->persist($Group); Shopware()->Models()->flush(); }
/** * Does the actual import */ public function import() { try { $SHOPWARE_id = PlentymarketsMappingController::getProducerByPlentyID($this->Producer->ProducerID); PyLog()->message('Sync:Item:Producer', 'Updating the producer »' . $this->Producer->ProducerName . '«'); } catch (PlentymarketsMappingExceptionNotExistant $E) { PyLog()->message('Sync:Item:Producer', 'Skipping the producer »' . $this->Producer->ProducerName . '«'); return; } /** @var Shopware\Models\Article\Supplier $Supplier */ $Supplier = Shopware()->Models()->find('Shopware\\Models\\Article\\Supplier', $SHOPWARE_id); // Set the new data $Supplier->setName($this->Producer->ProducerName); Shopware()->Models()->persist($Supplier); Shopware()->Models()->flush(); }
/** * Does the actual import */ public function import() { try { $SHOPWARE_id = PlentymarketsMappingController::getPropertyByPlentyID($this->Option->PropertyID); PyLog()->message('Sync:Item:Property:Option', 'Updating the property option »' . $this->Option->PropertyFrontendName . '«'); } catch (PlentymarketsMappingExceptionNotExistant $E) { PyLog()->message('Sync:Item:Property:Option', 'Skipping the property option »' . $this->Option->PropertyFrontendName . '«'); return; } $propertyParts = explode(';', $SHOPWARE_id); $optionId = $propertyParts[1]; /** @var Shopware\Models\Property\Option $Option */ $Option = Shopware()->Models()->find('Shopware\\Models\\Property\\Option', $optionId); // Set the new data $Option->setName($this->Option->PropertyFrontendName); Shopware()->Models()->persist($Option); Shopware()->Models()->flush(); }
/** * Deletes all existing images of the item */ public function purge() { /** * @var \Shopware\Components\Api\Resource\Media $MediaResource * @var \Shopware\Components\Api\Resource\Article $ArticleResource */ $MediaResource = \Shopware\Components\Api\Manager::getResource('Media'); $ArticleResource = \Shopware\Components\Api\Manager::getResource('Article'); $article = $ArticleResource->getOne($this->SHOPWARE_itemId); foreach ($article['images'] as $image) { try { $MediaResource->delete($image['mediaId']); } catch (Exception $E) { PyLog()->error('Sync:Item:Image', 'The media resource with the id »' . $image['mediaId'] . '« of the item image »' . $image['description'] . '« could not be deleted (' . $E->getMessage() . ')'); } } $ArticleResource->update($this->SHOPWARE_itemId, array('images' => array())); }
/** * Does the actual import work */ public function import() { PlentymarketsLogger::getInstance()->message('Sync:Item:Bundle', 'LastUpdate: ' . date('r', PlentymarketsConfig::getInstance()->getImportItemBundleLastUpdateTimestamp(time()))); $numberOfBundlesUpdated = 0; $timestamp = PlentymarketsConfig::getInstance()->getImportItemBundleLastUpdateTimestamp(1); $now = time(); // Get all bundles $Request_GetItemBundles = new PlentySoapRequest_GetItemBundles(); $Request_GetItemBundles->LastUpdate = $timestamp; $Request_GetItemBundles->Page = 0; do { /** @var PlentySoapResponse_GetItemBundles $Response_GetItemBundles */ $Response_GetItemBundles = PlentymarketsSoapClient::getInstance()->GetItemBundles($Request_GetItemBundles); $pages = max($Response_GetItemBundles->Pages, 1); PlentymarketsLogger::getInstance()->message('Sync:Item:Bundle', 'Page: ' . ($Request_GetItemBundles->Page + 1) . '/' . $pages); foreach ($Response_GetItemBundles->ItemBundles->item as $PlentySoapObject_Bundle) { $PlentymarketsImportEntityItemBundle = new PlentymarketsImportEntityItemBundle($PlentySoapObject_Bundle); try { $PlentymarketsImportEntityItemBundle->import(); ++$numberOfBundlesUpdated; } catch (PlentymarketsImportException $e) { PyLog()->error('Sync:Item:Bundle', $e->getMessage(), $e->getCode()); } } } while (++$Request_GetItemBundles->Page < $Response_GetItemBundles->Pages); PlentymarketsConfig::getInstance()->setImportItemBundleLastUpdateTimestamp($now); // Log if ($numberOfBundlesUpdated == 0) { PlentymarketsLogger::getInstance()->message('Sync:Item:Bundle', 'No item bundle has been updated or created.'); } else { if ($numberOfBundlesUpdated == 1) { PlentymarketsLogger::getInstance()->message('Sync:Item:Bundle', '1 item bundle has been updated or created.'); } else { PlentymarketsLogger::getInstance()->message('Sync:Item:Bundle', $numberOfBundlesUpdated . ' item bundles have been updated or created.'); } } }
/** * Deletes all existing images of the item */ public function purge() { /** * @var \Shopware\Components\Api\Resource\Media $MediaResource * @var \Shopware\Components\Api\Resource\Article $ArticleResource */ $MediaResource = \Shopware\Components\Api\Manager::getResource('Media'); $ArticleResource = \Shopware\Components\Api\Manager::getResource('Article'); $article = $ArticleResource->getOne($this->SHOPWARE_itemId); foreach ($article['images'] as $image) { try { $MediaResource->delete($image['mediaId']); } catch (Exception $E) { PyLog()->error('Sync:Item:Image', 'The media resource with the id »' . $image['mediaId'] . '« of the item image »' . $image['description'] . '« could not be deleted (' . $E->getMessage() . ')'); } } // Delete all variant image mappings of the item // Add the main detail $article['details'][] = $article['mainDetail']; foreach ($article['details'] as $detail) { Shopware()->Db()->query("DELETE FROM `s_articles_img` WHERE article_detail_id = ?", array($detail['id'])); } $ArticleResource->update($this->SHOPWARE_itemId, array('images' => array())); }
/** * Fixes the item with an empty order number */ public function fixEmptyItemDetailNumberAction() { $articleRepository = Shopware()->Models()->getRepository('Shopware\\Models\\Article\\Detail'); /** @var Shopware\Models\Article\Detail $detail */ $detail = $articleRepository->findOneBy(array('number' => '')); if ($detail) { $number = PlentymarketsImportItemHelper::getItemNumber(); $detail->setNumber($number); Shopware()->Models()->persist($detail); Shopware()->Models()->flush(); PyLog()->message('Fix:Item:Detail:Number', 'The number of the item detail with the id »' . $detail->getId() . '« has been set to »' . $number . '«.'); } else { PyLog()->message('Fix:Item:Detail:Number', 'No item without a number has been found'); } }
/** * Update the prices for a variant * * @param integer $detailId * @return bool */ public function updateVariant($detailId) { $Detail = Shopware()->Models()->find('Shopware\\Models\\Article\\Detail', $detailId); if (!$Detail instanceof Shopware\Models\Article\Detail) { return PlentymarketsLogger::getInstance()->error('Sync:Item:Price', 'The price of the item detail with the id »' . $detailId . '« could not be updated (item corrupt)', 3610); } $currentPrice = $this->PLENTY_PriceSet->Price + $this->PLENTY_markup; $Article = $Detail->getArticle(); $ArticleResource = \Shopware\Components\Api\Manager::getResource('Article'); // Update $ArticleResource->update($Article->getId(), array('variants' => array(array('number' => $Detail->getNumber(), 'prices' => $this->getPrices())))); PyLog()->message('Sync:Item:Price', 'The price of the variant with the number »' . $Detail->getNumber() . '« has been set to »' . money_format('%.2n', $currentPrice) . '«.'); }
/** * Imports the item bundle * * @throws Exception */ protected function importBundle() { // Get the bundle head $Request_GetItemsBase = new PlentySoapRequest_GetItemsBase(); $Request_GetItemsBase->GetAttributeValueSets = false; $Request_GetItemsBase->GetCategories = false; $Request_GetItemsBase->GetCategoryNames = false; $Request_GetItemsBase->GetItemAttributeMarkup = false; $Request_GetItemsBase->GetItemOthers = false; $Request_GetItemsBase->GetItemProperties = false; $Request_GetItemsBase->GetItemSuppliers = false; $Request_GetItemsBase->GetItemURL = 0; $Request_GetItemsBase->GetLongDescription = false; $Request_GetItemsBase->GetMetaDescription = false; $Request_GetItemsBase->GetShortDescription = false; $Request_GetItemsBase->GetTechnicalData = false; $Request_GetItemsBase->ItemID = $this->PLENTY_bundleHeadId; $Request_GetItemsBase->Page = 0; /** @var PlentySoapResponse_GetItemsBase $Response_GetItemsBase */ $Response_GetItemsBase = PlentymarketsSoapClient::getInstance()->GetItemsBase($Request_GetItemsBase); if ($Response_GetItemsBase->Success == false || !isset($Response_GetItemsBase->ItemsBase->item[0])) { throw new PlentymarketsImportException('The item bundle with SKU »' . $this->PLENTY_bundle->SKU . '« can not be imported (SOAP call failed).', 3701); } /** @var PlentySoapObject_ItemBase $ItemBase */ $ItemBase = $Response_GetItemsBase->ItemsBase->item[0]; try { // Get the existing bundle $shopwareBundleId = PlentymarketsMappingController::getItemBundleByPlentyID($this->PLENTY_bundleHeadId); /** @var Shopware\CustomModels\Bundle\Bundle $Bundle */ $Bundle = Shopware()->Models()->find('Shopware\\CustomModels\\Bundle\\Bundle', $shopwareBundleId); $currentShopwareBundleHeadItemDetailId = $Bundle->getArticle()->getMainDetail()->getId(); if (!isset($this->SHOPWARE_bundleItemDetailList[$currentShopwareBundleHeadItemDetailId])) { // If the item which is the bundle head in shopware // has been removed in plentymarkets, the bundle has to get a new // head item. If this is not possible, the bundle will be delete. try { $mainDetail = $this->getShopwareBundleItemDetail(); /** @var Shopware\Models\Article\Article $Article */ $Article = $mainDetail->getArticle(); PyLog()->message('Sync:Item:Bundle', 'The item »' . $Article->getName() . '« with the number »' . $mainDetail->getNumber() . '« is now the master item of the item bundle with the number »' . $Bundle->getNumber() . '«.'); $Bundle->setArticle($Article); } catch (PlentymarketsImportException $e) { PlentymarketsMappingController::deleteItemBundleByShopwareID($Bundle->getId()); PyLog()->message('Sync:Item:Bundle', 'The item bundle with the number »' . $Bundle->getNumber() . '« will be deleted because no item can be identified as the master item. The previous master item with the number »' . $Bundle->getArticle()->getMainDetail()->getNumber() . '« is no longer part of the item bundle.'); // Delete the bundle Shopware()->Models()->remove($Bundle); Shopware()->Models()->flush(); throw $e; } } $action = 'update'; } catch (PlentymarketsMappingExceptionNotExistant $E) { $action = 'create'; // Create a new one $Bundle = new Shopware\CustomModels\Bundle\Bundle(); $mainDetail = $this->getShopwareBundleItemDetail(); /** @var Shopware\Models\Article\Article $Article */ $Article = $mainDetail->getArticle(); PyLog()->message('Sync:Item:Bundle', 'The item »' . $Article->getName() . '« with the number »' . $mainDetail->getNumber() . '« will be the master item of the item bundle with the number »' . $ItemBase->ItemNo . '«.'); // Set the stuff which needs to be set just one $Bundle->setArticle($Article); $Bundle->setType(1); $Bundle->setDiscountType('abs'); $Bundle->setQuantity(0); $Bundle->setCreated(); $Bundle->setSells(0); if (method_exists($Bundle, 'setDisplayGlobal')) { $Bundle->setDisplayGlobal(true); } } // $Bundle->setName($ItemBase->Texts->Name); $Bundle->setShowName(0); $Bundle->setNumber($ItemBase->ItemNo); $isLimited = $ItemBase->Stock->Limitation == 1; $Bundle->setLimited($isLimited); $isActive = $ItemBase->Availability->Inactive == 0 && $ItemBase->Availability->Webshop == 1; $Bundle->setActive($isActive); /**@var Shopware\Models\Customer\Group $CG */ $CG = $this->getCustomerGroup(); $shopwareBundleHeadItemId = $Bundle->getArticle()->getId(); $items = array(); foreach ($Bundle->getArticles() as $item) { /** @var Shopware\CustomModels\Bundle\Article $item */ $itemDetailId = $item->getArticleDetail()->getId(); // Not in the bundle or already done if (!isset($this->SHOPWARE_bundleItemDetailList[$itemDetailId])) { continue; } $quantity = $this->SHOPWARE_bundleItemDetailList[$itemDetailId]['quantity']; // If it is also the main item, the quantity needs to be reduced by one if ($item->getArticleDetail()->getArticle()->getId() == $shopwareBundleHeadItemId) { // If there is just one, the item is skipped since it is the HEAD - it will not be added as an item if ($quantity == 1) { unset($this->SHOPWARE_bundleItemDetailList[$itemDetailId]); continue; } // If the amount is higher - reduce item - the item is the HEAD and inside the bundle // in plenty it is just inside the bundle $quantity -= 1; } // Unset the detail - the rest of this array will be added as new items to the bundle unset($this->SHOPWARE_bundleItemDetailList[$itemDetailId]); // Update the quantity if changed if ($item->getQuantity() != $quantity) { $item->setQuantity($quantity); } $items[] = $item; } // Add all items, which aren't yet in the bundle foreach ($this->SHOPWARE_bundleItemDetailList as $config) { /** @var Shopware\Models\Article\Detail $detail */ $detail = $config['detail']; // If the head is inside the bundle too, the amount needs to be reduced if ($detail->getArticle()->getId() == $shopwareBundleHeadItemId) { if ($config['quantity'] > 1) { $config['quantity'] -= 1; } else { if ($config['quantity'] == 1) { continue; } } } $ArticleNew = new Shopware\CustomModels\Bundle\Article(); $ItemDetail = $detail; $quantity = $config['quantity']; $ArticleNew->setArticleDetail($ItemDetail); $ArticleNew->setQuantity($quantity); $items[] = $ArticleNew; } // Set the bundle items $Bundle->setArticles($items); $newPrice = $ItemBase->PriceSet->Price; $newPrice /= (100 + $ItemBase->PriceSet->VAT) / 100; $isPriceFound = false; $prices = array(); foreach ($Bundle->getPrices() as $price) { /** @var Shopware\CustomModels\Bundle\Price $price */ if ($price->getCustomerGroup()->getKey() == $CG->getKey()) { $price->setPrice($newPrice); $isPriceFound = true; } $prices[] = $price; } if (!$isPriceFound) { $Price = new Shopware\CustomModels\Bundle\Price(); $Price->setBundle($Bundle); $Price->setCustomerGroup($CG); $Price->setPrice($newPrice); $prices[] = $Price; $Bundle->setPrices($prices); } $Bundle->setCustomerGroups(array($CG)); Shopware()->Models()->persist($Bundle); Shopware()->Models()->flush(); if ($action == 'create') { PlentymarketsMappingController::addItemBundle($Bundle->getId(), $this->PLENTY_bundleHeadId); PyLog()->message('Sync:Item:Bundle', 'The item bundle »' . $ItemBase->Texts->Name . '« with the number »' . $ItemBase->ItemNo . '« has been created'); } else { PyLog()->message('Sync:Item:Bundle', 'The item bundle »' . $ItemBase->Texts->Name . '« with the number »' . $ItemBase->ItemNo . '« has been updated'); } }
/** * Deletes a page of invalid data * * @param integer $start * @param integer $offset */ public function deleteInvalidData($start, $offset) { // Controller $controller = new PlentymarketsImportControllerItem(); // StoreIds $stores = Shopware()->Db()->fetchAll(' SELECT plentyID FROM plenty_mapping_shop '); // Customer group $customerGroupKey = PlentymarketsConfig::getInstance()->getDefaultCustomerGroupKey(); $customerGroupRepository = Shopware()->Models()->getRepository('Shopware\\Models\\Customer\\Group'); $customerGroups = $customerGroupRepository->findBy(array('key' => $customerGroupKey)); $customerGroup = array_pop($customerGroups); // foreach ($this->getInvalidData($start, $offset) as $data) { PyLog()->message('Fix:Item:Price', 'Start of fixing corrupt prices of the item id ' . $data['itemId']); // Search foreach (explode(',', $data['detailIds']) as $detailId) { try { /** @var \Shopware\Models\Article\Detail $Detail */ $Detail = Shopware()->Models()->find('\\Shopware\\Models\\Article\\Detail', $detailId); $price = new Shopware\Models\Article\Price(); $price->setFrom(1); $price->setPrice(1); $price->setPercent(0); $price->setArticle($Detail->getArticle()); $price->setDetail($Detail); $price->setCustomerGroup($customerGroup); Shopware()->Models()->persist($price); } catch (Exception $E) { PyLog()->debug($E->getMessage()); } } Shopware()->Models()->flush(); PyLog()->message('Fix:Item:Price', 'Finished with the fixing corrupt prices of the item id »' . $data['itemId'] . '«'); try { foreach ($stores as $store) { // Update the complete item from plenty $controller->importItem(PlentymarketsMappingController::getItemByShopwareID($data['itemId']), $store['plentyID']); } } catch (Exception $e) { PyLog()->error('Fix:Item:Price', $e->getMessage()); } // Stop after the first break; } }
/** * imports the item for the given shop * * @param integer $itemId * @param integer $storeId * @throws PlentymarketsImportException */ public function importItem($itemId, $storeId) { // Check whether the item has already been imported $full = !isset($this->itemIdsDone[$itemId]); // Build the request $Request_GetItemsBase = new PlentySoapRequest_GetItemsBase(); $Request_GetItemsBase->GetAttributeValueSets = $full; $Request_GetItemsBase->GetCategories = true; $Request_GetItemsBase->GetCategoryNames = true; $Request_GetItemsBase->GetItemAttributeMarkup = $full; $Request_GetItemsBase->GetItemOthers = $full; //$Request_GetItemsBase->GetItemProperties = $full; $Request_GetItemsBase->GetItemProperties = true; $Request_GetItemsBase->GetItemSuppliers = false; $Request_GetItemsBase->GetItemURL = 0; $Request_GetItemsBase->GetLongDescription = $full; $Request_GetItemsBase->GetMetaDescription = false; $Request_GetItemsBase->GetShortDescription = $full; $Request_GetItemsBase->GetTechnicalData = false; $Request_GetItemsBase->StoreID = $storeId; $Request_GetItemsBase->ItemID = $itemId; // get the main language of the shop //$mainLang = array_values(PlentymarketsTranslation::getInstance()->getShopMainLanguage(PlentymarketsMappingController::getShopByPlentyID($storeId))); // set the main language of the shop in soap request //$Request_GetItemsBase->Lang = PlentymarketsTranslation::getInstance()->getPlentyLocaleFormat($mainLang[0]['locale']); $Request_GetItemsBase->Lang = 'de'; // Do the request $Response_GetItemsBase = PlentymarketsSoapClient::getInstance()->GetItemsBase($Request_GetItemsBase); // On error if ($Response_GetItemsBase->Success == false) { // Re-add the item to the stack and quit PlentymarketsImportStackItem::getInstance()->addItem($itemId, $storeId); return; } // Item not found if (!isset($Response_GetItemsBase->ItemsBase->item[0])) { return; } // $ItemBase = $Response_GetItemsBase->ItemsBase->item[0]; // Skip bundles if ($ItemBase->BundleType == 'bundle' && PlentymarketsConfig::getInstance()->getItemBundleHeadActionID(IMPORT_ITEM_BUNDLE_HEAD_NO) == IMPORT_ITEM_BUNDLE_HEAD_NO) { PlentymarketsLogger::getInstance()->message('Sync:Item', 'The item »' . $ItemBase->Texts->Name . '« will be skipped (bundle)'); return; } // get the item texts in all active languages $itemTexts = array(); $shopId = PlentymarketsMappingController::getShopByPlentyID($storeId); //if this is a main shop , get the item texts translation for its main language and its shop languages if (PlentymarketsTranslation::isMainShop($shopId)) { // get all active languages of the shop (from shopware) $activeLanguages = PlentymarketsTranslation::getShopActiveLanguages($shopId); foreach ($activeLanguages as $localeId => $language) { $Request_GetItemsTexts = new PlentySoapRequest_GetItemsTexts(); $Request_GetItemsTexts->ItemsList = array(); $Object_RequestItems = new PlentySoapObject_RequestItems(); $Object_RequestItems->ExternalItemNumer = null; // string $Object_RequestItems->ItemId = $itemId; // string $Object_RequestItems->ItemNumber = null; // string $Object_RequestItems->Lang = PlentymarketsTranslation::getPlentyLocaleFormat($language['locale']); // string $Request_GetItemsTexts->ItemsList[] = $Object_RequestItems; $Response_GetItemsTexts = PlentymarketsSoapClient::getInstance()->GetItemsTexts($Request_GetItemsTexts); if (isset($Response_GetItemsTexts->ItemTexts->item[0])) { $itemText = array(); // save the language infos for the item texts $itemText['locale'] = $language['locale']; // if mainShopId == null, then it is the main shop and no language shop // each language shop has a mainShopId if (!is_null($language['mainShopId'])) { $itemText['languageShopId'] = PlentymarketsTranslation::getLanguageShopID($localeId, $language['mainShopId']); } elseif (PlentymarketsTranslation::getPlentyLocaleFormat($language['locale']) != 'de') { // set the language for the main shop if the main language is not German $itemText['languageShopId'] = $shopId; } $itemText['texts'] = $Response_GetItemsTexts->ItemTexts->item[0]; $itemTexts[] = $itemText; } } } try { $shopId = PlentymarketsMappingController::getShopByPlentyID($storeId); $Shop = Shopware()->Models()->find('Shopware\\Models\\Shop\\Shop', $shopId); $Importuer = new PlentymarketsImportEntityItem($ItemBase, $Shop); // The item has already been updated if (!$full) { // so we just need to do the categories $Importuer->importCategories(); //if this is a main shop , import the translation for its main language and its shop languages if (PlentymarketsTranslation::isMainShop($shopId)) { if (!empty($itemTexts)) { // Do the import for item texts translation $Importuer->saveItemTextsTranslation($itemTexts); } // Do the import for the property value translations $Importuer->importItemPropertyValueTranslations(); } } else { // Do a full import $Importuer->import(); //if this is a main shop , import the translation for its main language and its shop languages if (PlentymarketsTranslation::isMainShop($shopId)) { if (!empty($itemTexts)) { // Do the import for item texts translation $Importuer->saveItemTextsTranslation($itemTexts); } // Do the import for the property value translations $Importuer->importItemPropertyValueTranslations(); } // Add it to the link controller PlentymarketsImportControllerItemLinked::getInstance()->addItem($ItemBase->ItemID); // Mark this item as done $this->itemIdsDone[$ItemBase->ItemID] = true; } // Log the usage data PyLog()->usage(); } catch (Shopware\Components\Api\Exception\ValidationException $E) { PlentymarketsLogger::getInstance()->error('Sync:Item:Validation', 'The item »' . $ItemBase->Texts->Name . '« with the id »' . $ItemBase->ItemID . '« could not be imported', 3010); foreach ($E->getViolations() as $ConstraintViolation) { PlentymarketsLogger::getInstance()->error('Sync:Item:Validation', $ConstraintViolation->getMessage()); PlentymarketsLogger::getInstance()->error('Sync:Item:Validation', $ConstraintViolation->getPropertyPath() . ': ' . $ConstraintViolation->getInvalidValue()); } } catch (Shopware\Components\Api\Exception\OrmException $E) { PlentymarketsLogger::getInstance()->error('Sync:Item:Orm', 'The item »' . $ItemBase->Texts->Name . '« with the id »' . $ItemBase->ItemID . '« could not be imported (' . $E->getMessage() . ')', 3020); PlentymarketsLogger::getInstance()->error('Sync:Item:Orm', $E->getTraceAsString(), 1000); throw new PlentymarketsImportException('The item import will be stopped (internal database error)', 3021); } catch (PlentymarketsImportItemNumberException $E) { PlentymarketsLogger::getInstance()->error('Sync:Item:Number', $E->getMessage(), $E->getCode()); } catch (PlentymarketsImportItemException $E) { PlentymarketsLogger::getInstance()->error('Sync:Item:Number', $E->getMessage(), $E->getCode()); } catch (Exception $E) { PlentymarketsLogger::getInstance()->error('Sync:Item', 'The item »' . $ItemBase->Texts->Name . '« with the id »' . $ItemBase->ItemID . '« could not be imported', 3000); PlentymarketsLogger::getInstance()->error('Sync:Item', $E->getTraceAsString(), 1000); PlentymarketsLogger::getInstance()->error('Sync:Item', get_class($E)); PlentymarketsLogger::getInstance()->error('Sync:Item', $E->getMessage()); } }
/** * Returns the klarna transaction id. * * @return string */ protected function getKlarnaTransactionId() { $orderNumber = $this->order['number']; try { if ($this->pluginExists('PigmbhKlarnaPayment')) { // eid / shop_id $sql = 'SELECT shop_id FROM Pi_klarna_payment_multistore WHERE order_number = ?'; $multistore = Shopware()->Db()->query($sql, array($orderNumber))->fetchObject(); // pclass $sql = 'SELECT pclassid FROM Pi_klarna_payment_pclass where ordernumber = ?'; $pclass = Shopware()->Db()->query($sql, array($orderNumber))->fetchObject(); // Transaction ID $sql = 'SELECT transactionid FROM Pi_klarna_payment_order_data WHERE order_number = ?'; $order = Shopware()->Db()->query($sql, array($orderNumber))->fetchObject(); return sprintf('%s_%s_%s', $order->transactionid, $pclass->pclassid, $multistore->shop_id); } elseif ($this->pluginExists('SwagPaymentKlarna') || $this->pluginExists('SwagPaymentKlarnaKpm')) { /* * @var Klarna $klarna */ $this->klarnaService = Shopware()->Container()->get('KlarnaService'); if (!empty($this->order['languageIso'])) { $this->klarnaService->setLanguage($this->order['languageIso']); } else { throw new Exception('order language missing'); } if (!empty($this->order['billing']['country']['iso'])) { $this->klarnaService->setCountry($this->order['billing']['country']['iso']); } else { throw new Exception('order country missing'); } if (!empty($this->order['currency'])) { $this->klarnaService->setCurrency($this->order['currency']); } else { throw new Exception('order currency missing'); } /** * @var KlarnaPClass */ $pclass = $this->getKlarnaPClass(); if (!empty($pclass)) { if (isset($this->order['payment']['name']) && $this->order['payment']['name'] == 'klarna_invoice') { $classId = KlarnaPClass::INVOICE; } else { $classId = $pclass->getId(); } return sprintf('%s_%s_%s', $this->order['transactionId'], $classId, $pclass->getEid()); } else { throw new Exception('No compatible pclass found'); } } else { throw new Exception('No compatible Klarna payment plugin found'); } } catch (Exception $e) { PyLog()->error('Sync:Order:PaymentKlarna', $e->getMessage()); } return ''; }
/** * Prunes the item bundles */ protected function pruneItemBundles() { // Register the modules PlentymarketsUtils::registerBundleModules(); // Create a temporary table Shopware()->Db()->exec(' CREATE TEMPORARY TABLE IF NOT EXISTS plenty_cleanup_item_bundle (bundleId INT UNSIGNED, INDEX (bundleId)) ENGINE = MEMORY; '); // Get all bundles - regardless of store ids $Request_GetItemBundles = new PlentySoapRequest_GetItemBundles(); $Request_GetItemBundles->LastUpdate = 0; $Request_GetItemBundles->Page = 0; do { /** @var PlentySoapResponse_GetItemBundles $Response_GetItemsBase */ $Response_GetItemBundles = PlentymarketsSoapClient::getInstance()->GetItemBundles($Request_GetItemBundles); // Call failed if (is_null($Response_GetItemBundles) || !property_exists($Response_GetItemBundles, 'ItemBundles')) { // Log PlentymarketsLogger::getInstance()->error('Cleanup:Item:Bundle', 'Aborting. GetItemBundles apparently failed'); // Delete the temporary table Shopware()->Db()->exec(' DROP TEMPORARY TABLE plenty_cleanup_item_bundle '); return; } $bundleIds = array(); // Collect the bundle head ids foreach ($Response_GetItemBundles->ItemBundles->item as $bundle) { /** @var PlentySoapObject_Bundle $bundle */ $plentyBundleHeadSku = explode('-', $bundle->SKU); $plentyBundleHeadId = (int) $plentyBundleHeadSku[0]; $bundleIds[] = $plentyBundleHeadId; } if (empty($bundleIds)) { break; } // Build the sql statement $bundleIdsSql = implode(', ', array_map(function ($itemId) { return sprintf('(%u)', $itemId); }, $bundleIds)); // Fill the table Shopware()->Db()->exec(' INSERT IGNORE INTO plenty_cleanup_item_bundle VALUES ' . $bundleIdsSql . ' '); } while (++$Request_GetItemBundles->Page < $Response_GetItemBundles->Pages); // Get all shopware bundles which are no longer in plentymarkets $bundles = Shopware()->Db()->fetchAll(' SELECT id FROM s_articles_bundles WHERE id NOT IN ( SELECT pmi.shopwareID FROM plenty_cleanup_item_bundle pci LEFT JOIN plenty_mapping_item_bundle pmi ON pmi.plentyID = pci.bundleId WHERE pmi.shopwareID IS NOT NULL ) '); // And delete them foreach ($bundles as $bundle) { /** @var Shopware\CustomModels\Bundle\Bundle $bundle */ $bundle = Shopware()->Models()->find('Shopware\\CustomModels\\Bundle\\Bundle', $bundle['id']); Shopware()->Models()->remove($bundle); // Log PyLog()->message('Cleanup:Item:Bundle', 'The item bundle »' . $bundle->getName() . '« with the number »' . $bundle->getNumber() . '« has been deleted'); } Shopware()->Models()->flush(); Shopware()->Db()->delete('plenty_mapping_item_bundle', 'shopwareID NOT IN (SELECT id FROM s_articles_bundles)'); }
/** * Performes a SOAP call * * @see SoapClient::__call() */ public function __call($call, $args) { $retries = 0; do { try { $headers = $this->__getLastResponseHeaders(); if ($headers) { preg_match('/X-Plenty-Soap-Calls-Left: (-?\\d+)/', $headers, $matches); $callsLeft = isset($matches[1]) ? (int) $matches[1] : -1; preg_match('/X-Plenty-Soap-Seconds-Left: (-?\\d+)/', $headers, $matches); $secondsLeft = isset($matches[1]) ? (int) $matches[1] : -1; if (!($callsLeft % 50)) { PyLog()->message('Soap:CallLimit', sprintf('Soap-Calls-Left: %d – Soap-Seconds-Left: %d', $callsLeft, $secondsLeft)); } // check if the limit of the soap calls is already reached if ($callsLeft != -1 && $callsLeft <= 10) { $sleep = $secondsLeft + 5; PyLog()->message('Soap:CallLimit', sprintf('Soap call limit reached. Waiting %d seconds.', $sleep)); sleep($sleep); PyLog()->message('Soap:CallLimit', sprintf('Waited %d seconds.', $sleep)); } } // Call $Response = $this->doCall($call, $args); // Quit the loop on success break; } catch (Exception $E) { ++$retries; // Calculate seconds based on the number of retries $seconds = self::NUMBER_OF_SECONDS_SLEEP * $retries; // Try to get a new token if ($E->getMessage() == 'Unauthorized Request - Invalid Token') { // Log the error PlentymarketsLogger::getInstance()->error('Soap:Call', $call . ' failed: Unauthorized Request - Invalid Token', 1110); // Refresh the token $this->getToken(); $this->setSoapHeaders(); } else { PlentymarketsLogger::getInstance()->message('Soap:Call', $call . ' will wait ' . $seconds . ' seconds and then try again (' . $retries . '/' . self::NUMBER_OF_RETRIES_MAX . ')'); sleep($seconds); } } } while ($retries < self::NUMBER_OF_RETRIES_MAX); // Log the call's success state if (isset($Response->Success) && $Response->Success == true) { if ($call == 'GetServerTime') { if (!$this->Config->getApiIgnoreGetServerTime()) { PlentymarketsLogger::getInstance()->message('Soap:Call', 'GetServerTime success'); } } else { PlentymarketsLogger::getInstance()->message('Soap:Call', $call . ' success'); } // Remember the timestamp if (!empty($this->timestampConfigKey)) { $this->Config->set($this->timestampConfigKey, time()); } } else { PlentymarketsLogger::getInstance()->error('Soap:Call', $call . ' failed', 1100); if (isset($Response) && $this->Config->getApiLogHttpHeaders(false)) { PlentymarketsLogger::getInstance()->error('Soap:Call', var_export($Response, true)); } if (isset($E) && $E instanceof Exception) { PlentymarketsLogger::getInstance()->error('Soap:Call:Request', htmlspecialchars($this->__getLastRequest())); PlentymarketsLogger::getInstance()->error('Soap:Call', $E->getMessage()); } } // Log the HTTP headers? if ($this->Config->getApiLogHttpHeaders(false)) { PlentymarketsLogger::getInstance()->message('Soap:Call:Header:Request', $this->__getLastRequestHeaders()); PlentymarketsLogger::getInstance()->message('Soap:Call:Header:Response', $this->__getLastResponseHeaders()); } // Remember the timestamp for soap calls number of any kind if (!empty($this->soapCallsTimestampConfigKey)) { $this->Config->set($this->soapCallsTimestampConfigKey, time()); } ++$this->numberOfCalls; return $Response; }
/** * Runs the import of an expicit entity */ protected function runEntity($entity) { $timestamp = time(); PyConf()->set(sprintf('ImportItem%sLastRunTimestamp', $entity), time()); PyConf()->set(sprintf('ImportItem%sNextRunTimestamp', $entity), time() + $this->cronJobInterval); if (PyStatus()->maySynchronize()) { PyLog()->message('Sync:Item:' . $entity, 'Starting'); try { $controller = sprintf('PlentymarketsImportControllerItem%s', $entity); $Controller = new $controller(); $Controller->run((int) PyConf()->get(sprintf('ImportItem%sLastUpdateTimestamp', $entity))); PyConf()->set(sprintf('ImportItem%sStatus', $entity), 1); PyConf()->set(sprintf('ImportItem%sLastUpdateTimestamp', $entity), $timestamp); PyConf()->erase(sprintf('ImportItem%sError', $entity)); } catch (PlentymarketsImportException $E) { PyConf()->set(sprintf('ImportItem%sStatus', $entity), 2); PyConf()->set(sprintf('ImportItem%sError', $entity), $E->getMessage()); } PyLog()->message('Sync:Item:' . $entity, 'Finished'); } else { PyConf()->set(sprintf('ImportItem%sStatus', $entity), 0); } PyConf()->setImportItemAssociateLastEnity($entity); }
/** * Returns the customer class id * * @return integer|null */ protected function getCustomerClassId() { try { return PlentymarketsMappingController::getCustomerClassByShopwareID($this->Customer->getGroup()->getId()); } catch (Exception $E) { PyLog()->debug($E->getMessage()); return null; } }
/** * Imports the attribtue */ protected function importAttribute() { try { $SHOPWARE_attributeId = PlentymarketsMappingController::getAttributeGroupByPlentyID($this->Attribute->Id); PyLog()->message('Sync:Item:Attribute', 'Updating the attribute »' . $this->Attribute->FrontendName . '«'); } catch (PlentymarketsMappingExceptionNotExistant $E) { PyLog()->message('Sync:Item:Attribute', 'Skipping the attribute »' . $this->Attribute->FrontendName . '«'); return; } /** @var Shopware\Models\Article\Configurator\Group $Group */ $Group = Shopware()->Models()->find('Shopware\\Models\\Article\\Configurator\\Group', $SHOPWARE_attributeId); // Set the new data if (!is_null($this->Attribute->FrontendName)) { $Group->setName($this->Attribute->FrontendName); } elseif (!is_null($this->Attribute->BackendName)) { // use backend-name if frontend-name doesn't exists $Group->setName($this->Attribute->BackendName); } else { PyLog()->message('Sync:Item:Attribute', 'No valid name for the attribute with id »' . $this->Attribute->Id . '«'); return; } $Group->setPosition($this->Attribute->Position); $this->Group = $Group; }