/** * Builds an index and checks if all items are present * * @throws Exception */ protected function index() { $bundleHeadSku = explode('-', $this->PLENTY_bundle->SKU); $this->PLENTY_bundleHeadId = (int) $bundleHeadSku[0]; // Check whether all bundle items are present in shopware foreach ($this->PLENTY_bundle->Items->item as $PlentySoapObject_BundleItem) { /** @var PlentySoapObject_BundleItem $PlentySoapObject_BundleItem */ $bundleItemSku = explode('-', $PlentySoapObject_BundleItem->SKU); $plentyBundleItemId = $bundleItemSku[0]; try { // Variant if (isset($bundleItemSku[2]) && $bundleItemSku[2] > 0) { $shopwareBundleItemDetailId = PlentymarketsMappingController::getItemVariantByPlentyID($PlentySoapObject_BundleItem->SKU); // The detail is needed $detail = Shopware()->Models()->find('Shopware\\Models\\Article\\Detail', $shopwareBundleItemDetailId); $isVariant = true; } else { $shopwareBundleItemId = PlentymarketsMappingController::getItemByPlentyID($plentyBundleItemId); /** @var Shopware\Models\Article\Article $shopwareItem */ $shopwareItem = Shopware()->Models()->find('Shopware\\Models\\Article\\Article', $shopwareBundleItemId); // The detail is needed $detail = $shopwareItem->getMainDetail(); $isVariant = false; } } catch (PlentymarketsMappingExceptionNotExistant $E) { throw new PlentymarketsImportException('The item bundle with SKU »' . $this->PLENTY_bundle->SKU . '« can not be imported. Not all of the items included in the bundle are available in shopware.', 3710); } $this->SHOPWARE_bundleItemDetailList[$detail->getId()] = array('detail' => $detail, 'quantity' => (int) $PlentySoapObject_BundleItem->Quantity, 'isVariant' => $isVariant); } }
/** * Constructor method. * * @param int $PLENTY_itemId * @param int $SHOPWARE_itemId */ public function __construct($PLENTY_itemId, $SHOPWARE_itemId = null) { $this->PLENTY_itemId = $PLENTY_itemId; if (is_null($SHOPWARE_itemId)) { $this->SHOPWARE_itemId = PlentymarketsMappingController::getItemByPlentyID($PLENTY_itemId); } else { $this->SHOPWARE_itemId = $SHOPWARE_itemId; } $this->SHOPWARE_Article = Shopware()->Models()->find('Shopware\\Models\\Article\\Article', $this->SHOPWARE_itemId); }
/** * Updates the item prices */ public static function importItemPrices() { $numberOfPricesUpdates = 0; PlentymarketsLogger::getInstance()->message('Sync:Item:Price', 'LastUpdate: ' . date('r', PlentymarketsConfig::getInstance()->getImportItemPriceLastUpdateTimestamp(time()))); $timestamp = PlentymarketsConfig::getInstance()->getImportItemPriceLastUpdateTimestamp(time()); $now = time(); $Request_GetItemsPriceUpdate = new PlentySoapRequest_GetItemsPriceUpdate(); $Request_GetItemsPriceUpdate->LastUpdateFrom = $timestamp; $Request_GetItemsPriceUpdate->Page = 0; do { $Response_GetItemsPriceUpdate = PlentymarketsSoapClient::getInstance()->GetItemsPriceUpdate($Request_GetItemsPriceUpdate); $pages = max($Response_GetItemsPriceUpdate->Pages, 1); PlentymarketsLogger::getInstance()->message('Sync:Item:Price', 'Page: ' . ($Request_GetItemsPriceUpdate->Page + 1) . '/' . $pages); /** @var PlentySoapResponseObject_GetItemsPriceUpdate $ItemsPriceUpdate */ foreach ($Response_GetItemsPriceUpdate->ItemsPriceUpdate->item as $ItemsPriceUpdate) { try { // Base item if (preg_match('/\\d+\\-\\d+\\-0/', $ItemsPriceUpdate->SKU)) { $sku = explode('-', $ItemsPriceUpdate->SKU); $itemID = PlentymarketsMappingController::getItemByPlentyID($sku[0]); $PlentymarketsImportEntityItemPrice = new PlentymarketsImportEntityItemPrice($ItemsPriceUpdate); $PlentymarketsImportEntityItemPrice->update($itemID); } else { $itemDetailID = PlentymarketsMappingController::getItemVariantByPlentyID($ItemsPriceUpdate->SKU); $PlentymarketsImportEntityItemPrice = new PlentymarketsImportEntityItemPrice($ItemsPriceUpdate, $ItemsPriceUpdate->Markup); $PlentymarketsImportEntityItemPrice->updateVariant($itemDetailID); } ++$numberOfPricesUpdates; } catch (PlentymarketsMappingExceptionNotExistant $E) { } } } while (++$Request_GetItemsPriceUpdate->Page < $Response_GetItemsPriceUpdate->Pages); PlentymarketsConfig::getInstance()->setImportItemPriceLastUpdateTimestamp($now); // Log if ($numberOfPricesUpdates == 0) { PlentymarketsLogger::getInstance()->message('Sync:Item:Price', 'No price has been updated.'); } else { if ($numberOfPricesUpdates == 1) { PlentymarketsLogger::getInstance()->message('Sync:Item:Price', '1 price has been updated.'); } else { PlentymarketsLogger::getInstance()->message('Sync:Item:Price', $numberOfPricesUpdates . ' prices have been updated.'); } } }
/** * Handles the whole import */ public function import() { $this->setData(); $this->setDetails(); $this->setVariants(); $this->setProperties(); $data = $this->data; $data['mainDetail'] = $this->details; $mainDetailId = -1; $ArticleResource = self::getArticleApi(); $VariantResource = self::getVariantApi(); try { // If a mappings exists, it's a regular item $SHOPWARE_itemID = PlentymarketsMappingController::getItemByPlentyID($this->ItemBase->ItemID); // Should the categories be synchronized? if (PlentymarketsConfig::getInstance()->getItemCategorySyncActionID(IMPORT_ITEM_CATEGORY_SYNC) == IMPORT_ITEM_CATEGORY_SYNC) { $this->setCategories(); $data['categories'] = $this->categories; } // Should the number be synchronized? // This does only matter if there are no variants if (PlentymarketsConfig::getInstance()->getItemNumberImportActionID(IMPORT_ITEM_NUMBER) == IMPORT_ITEM_NUMBER && !count($this->variants)) { // strip whitespaces $number = trim($this->ItemBase->ItemNo); // If this number does not belong to this item if (!PlentymarketsImportItemHelper::isNumberExistantItem($number, $SHOPWARE_itemID)) { // and check if the number is valid if (!PlentymarketsImportItemHelper::isNumberValid($number)) { throw new PlentymarketsImportItemNumberException('The item number »' . $number . '« of item »' . $this->data['name'] . '« with the id »' . $this->ItemBase->ItemID . '« is invalid', 3120); } // check if the number is available anyway if (PlentymarketsImportItemHelper::isNumberExistant($number)) { throw new PlentymarketsImportItemNumberException('The item number »' . $number . '« of item »' . $this->data['name'] . '« with the id »' . $this->ItemBase->ItemID . '« is already in use', 3121); } // then update it $data['mainDetail']['number'] = $number; } } // Update the item $Article = $ArticleResource->update($SHOPWARE_itemID, $data); // Log PlentymarketsLogger::getInstance()->message('Sync:Item', sprintf('The item »%s« with the number »%s« has been updated', $data['name'], $Article->getMainDetail()->getNumber())); // Remember the main detail's id (to set the prices) $mainDetailId = $Article->getMainDetail()->getId(); // Variants that will be commited to the API $variants = array(); $update = array(); $number2sku = array(); $keep = array('numbers' => array(), 'ids' => array()); // Es gibt varianten if (count($this->variants)) { // $VariantController = new PlentymarketsImportItemVariantController($this->ItemBase); // Counter $numberOfVariantsUpdated = 0; $numberOfVariantsCreated = 0; $numberOfVariantsDeleted = 0; foreach ($this->variants as $variantId => $variant) { // Directly add the prices $PlentymarketsImportEntityItemPrice = new PlentymarketsImportEntityItemPrice($this->ItemBase->PriceSet, $VariantController->getMarkupByVariantId($variantId)); $variant['prices'] = $PlentymarketsImportEntityItemPrice->getPrices(); // If the variant has an id, it is already created and mapped soo we just keep it if (array_key_exists('id', $variant)) { ++$numberOfVariantsUpdated; $keep['ids'][] = $variant['id']; } else { ++$numberOfVariantsCreated; $variant['configuratorOptions'] = $VariantController->getOptionsByVariantId($variantId); $keep['numbers'][] = $variant['number']; // Internal mapping of the variant number to some plenty information $number2sku[$variant['number']] = $variant['X_plentySku']; } $variants[] = $variant; } // The configurator set has to be adapted $update['configuratorSet'] = array('groups' => $VariantController->getGroups()); // Delete all variants if ($numberOfVariantsUpdated == 0) { $Article = $ArticleResource->update($SHOPWARE_itemID, array('configuratorSet' => array('groups' => array()), 'variations' => array())); } $update['variants'] = $variants; // Check if the main detail will be deleted if (!in_array($mainDetailId, $keep['ids'])) { // Promote the first variante to be the main detail $update['variants'][0]['isMain'] = true; $deleteMainVariant = true; } else { $deleteMainVariant = false; } $ArticleResource->update($SHOPWARE_itemID, $update); // Check if the main detail will be deleted if ($deleteMainVariant) { // If the main detail is not needed anymore, delete it right away // Otherwise it will be a dead data record. The main details are not // returned from the API->getOne call. Only the "real" main detail. Shopware()->Models()->remove(Shopware()->Models()->find('Shopware\\Models\\Article\\Detail', $mainDetailId)); Shopware()->Models()->flush(); PlentymarketsMappingController::deleteItemVariantByShopwareID($mainDetailId); ++$numberOfVariantsDeleted; } $article = $ArticleResource->getOne($SHOPWARE_itemID); // Add the main detail $article['details'][] = $article['mainDetail']; // Mapping for the variants foreach ($article['details'] as $detail) { // If the variant is not needed anymore - delete it if (!in_array($detail['number'], $keep['numbers']) && !in_array($detail['id'], $keep['ids'])) { ++$numberOfVariantsDeleted; $VariantResource->delete($detail['id']); PlentymarketsMappingController::deleteItemVariantByShopwareID($detail['id']); } else { if (isset($number2sku[$detail['number']])) { // Add the mapping PlentymarketsMappingController::addItemVariant($detail['id'], $number2sku[$detail['number']]); } } } $VariantController->map($article); $messages = array(); // Log if ($numberOfVariantsUpdated == 1) { $messages[] = '1 variant has been updated'; } else { if ($numberOfVariantsUpdated > 1) { $messages[] = $numberOfVariantsUpdated . ' variants have been updated'; } } if ($numberOfVariantsCreated == 1) { $messages[] = '1 variant has been created'; } else { if ($numberOfVariantsCreated > 1) { $messages[] = $numberOfVariantsCreated . ' variants have been created'; } } if ($numberOfVariantsDeleted == 1) { $messages[] = '1 variant has been deleted'; } else { if ($numberOfVariantsDeleted > 1) { $messages[] = $numberOfVariantsDeleted . ' variants have been deleted'; } } if ($messages) { PlentymarketsLogger::getInstance()->message('Sync:Item', implode(', ', $messages)); } } else { // Preise eines Normalen Artikels aktualisieren $PlentymarketsImportEntityItemPrice = new PlentymarketsImportEntityItemPrice($this->ItemBase->PriceSet); $PlentymarketsImportEntityItemPrice->update($SHOPWARE_itemID); } // Bilder if (PlentymarketsConfig::getInstance()->getItemImageSyncActionID(IMPORT_ITEM_IMAGE_SYNC) == IMPORT_ITEM_IMAGE_SYNC) { $PlentymarketsImportEntityItemImage = new PlentymarketsImportEntityItemImage($this->ItemBase->ItemID, $SHOPWARE_itemID); $PlentymarketsImportEntityItemImage->image(); } } catch (PlentymarketsMappingExceptionNotExistant $E) { // Set the categories no matter what $this->setCategories(); $data['categories'] = $this->categories; // Regular item if (!count($this->variants)) { // Numbers should be synced if (PlentymarketsConfig::getInstance()->getItemNumberImportActionID(IMPORT_ITEM_NUMBER) == IMPORT_ITEM_NUMBER) { // strip whitespaces $number = trim($this->ItemBase->ItemNo); // Nummer ist ungültig oder in Benutzung if (!PlentymarketsImportItemHelper::isNumberValid($number)) { throw new PlentymarketsImportItemNumberException('The item number »' . $number . '« of item »' . $this->data['name'] . '« with the id »' . $this->ItemBase->ItemID . '« is invalid', 3120); } if (PlentymarketsImportItemHelper::isNumberExistant($number)) { throw new PlentymarketsImportItemNumberException('The item number »' . $number . '« of item »' . $this->data['name'] . '« with the id »' . $this->ItemBase->ItemID . '« is already in use', 3121); } // Use this number $data['mainDetail']['number'] = $number; } else { // A new number is generated $data['mainDetail']['number'] = PlentymarketsImportItemHelper::getItemNumber(); } // Create $Article = $ArticleResource->create($data); // $SHOPWARE_itemID = $Article->getId(); // Log PlentymarketsLogger::getInstance()->message('Sync:Item', 'The item »' . $this->data['name'] . '« has been created with the number »' . $data['mainDetail']['number'] . '«'); // Mapping speichern PlentymarketsMappingController::addItem($Article->getId(), $this->ItemBase->ItemID); // Stock stack PlentymarketsImportItemStockStack::getInstance()->add($this->ItemBase->ItemID); // Media // Preise $PlentymarketsImportEntityItemPrice = new PlentymarketsImportEntityItemPrice($this->ItemBase->PriceSet); $PlentymarketsImportEntityItemPrice->update($Article->getId()); } else { // Set the id of the first variant $mainVariant = array_shift(array_values($this->variants)); $data['mainDetail']['number'] = $mainVariant['number']; // Anlegen $Article = $ArticleResource->create($data); PlentymarketsLogger::getInstance()->message('Sync:Item', 'The variant base item »' . $this->data['name'] . '« has been created created with the number »' . $data['mainDetail']['number'] . '«'); // $SHOPWARE_itemID = $Article->getId(); // Mapping speichern PlentymarketsMappingController::addItem($Article->getId(), $this->ItemBase->ItemID); $VariantController = new PlentymarketsImportItemVariantController($this->ItemBase); // $number2sku = array(); // foreach ($this->variants as $variantId => &$variant) { $variant['configuratorOptions'] = $VariantController->getOptionsByVariantId($variantId); // Prices $PlentymarketsImportEntityItemPrice = new PlentymarketsImportEntityItemPrice($this->ItemBase->PriceSet, $VariantController->getMarkupByVariantId($variantId)); $variant['prices'] = $PlentymarketsImportEntityItemPrice->getPrices(); $number2sku[$variant['number']] = $variant['X_plentySku']; } // Varianten $id = $Article->getId(); $updateArticle = array('configuratorSet' => array('groups' => $VariantController->getGroups()), 'variants' => array_values($this->variants)); PlentymarketsLogger::getInstance()->message('Sync:Item:Variant', 'Starting to create variants for the item »' . $this->data['name'] . '« with the number »' . $data['mainDetail']['number'] . '«'); $Article = $ArticleResource->update($id, $updateArticle); /**@var Shopware\Models\Article\Detail $detail */ foreach ($Article->getDetails() as $detail) { // Save mapping and add the variant to the stock stack $sku = $number2sku[$detail->getNumber()]; PlentymarketsMappingController::addItemVariant($detail->getId(), $sku); PlentymarketsImportItemStockStack::getInstance()->add($sku); } $VariantController->map($ArticleResource->getOne($id)); PlentymarketsLogger::getInstance()->message('Sync:Item:Variant', 'Variants created successfully'); } // Bilder $PlentymarketsImportEntityItemImage = new PlentymarketsImportEntityItemImage($this->ItemBase->ItemID, $SHOPWARE_itemID); $PlentymarketsImportEntityItemImage->image(); } // Rebuild category tree if (count($this->categories)) { /** @var \Shopware\Components\Model\CategoryDenormalization $component */ $component = Shopware()->CategoryDenormalization(); $component->removeArticleAssignmentments($SHOPWARE_itemID); foreach ($this->categories as $category) { $component->addAssignment($SHOPWARE_itemID, $category['id']); } } // Der Hersteller ist neu angelegt worden if ($Article instanceof Shopware\Models\Article\Article && array_key_exists('supplier', $this->data)) { PlentymarketsLogger::getInstance()->message('Sync:Item', 'The producer »' . $Article->getSupplier()->getName() . '« has been created'); PlentymarketsMappingController::addProducer($Article->getSupplier()->getId(), $this->ItemBase->ProducerID); } }
/** * Imports the linked items * */ public function run() { foreach (array_chunk($this->itemIds, 100) as $chunk) { $Request_GetLinkedItems = new PlentySoapRequest_GetLinkedItems(); $Request_GetLinkedItems->ItemsList = array(); // foreach ($chunk as $itemId) { $Object_GetLinkedItems = new PlentySoapObject_GetLinkedItems(); $Object_GetLinkedItems->ItemID = $itemId; $Request_GetLinkedItems->ItemsList[] = $Object_GetLinkedItems; } /** @var PlentySoapResponse_GetLinkedItems $Response_GetLinkedItems */ $Response_GetLinkedItems = PlentymarketsSoapClient::getInstance()->GetLinkedItems($Request_GetLinkedItems); /** @var PlentySoapResponseObject_GetLinkedItems $Item */ foreach ($Response_GetLinkedItems->Items->item as $Item) { try { $SHOPWARE_itemId = PlentymarketsMappingController::getItemByPlentyID($Item->ItemID); } catch (PlentymarketsMappingExceptionNotExistant $E) { continue; } $PlentymarketsImportEntityItemLinked = new PlentymarketsImportEntityItemLinked($SHOPWARE_itemId, $Item->LinkedItems); $PlentymarketsImportEntityItemLinked->link(); } } }
/** * Retrieves the linked items from plentymarkets and links them */ public function link() { // Cleanup $this->purge(); /** @var PlentySoapObject_GetLinkedItems $LinkedItem */ foreach ($this->LinkedItems->item as $LinkedItem) { // Get the id try { $SHOWWARE_linkedItemId = PlentymarketsMappingController::getItemByPlentyID($LinkedItem->ItemID); } catch (PlentymarketsMappingExceptionNotExistant $E) { continue; } if ($LinkedItem->Relationship == 'Accessory') { $table = 's_articles_relationships'; } else { if ($LinkedItem->Relationship == 'Similar') { $table = 's_articles_similar'; } else { continue; } } Shopware()->Db()->insert($table, array('articleID' => (int) $this->SHOPWARE_itemId, 'relatedarticle' => (int) $SHOWWARE_linkedItemId)); } $this->purgeViews(); }
/** * Retrieves the linked items from plentymarkets and links them */ public function link() { // Cleanup $this->purge(); /** @var PlentySoapObject_GetLinkedItems $LinkedItem */ foreach ($this->LinkedItems->item as $LinkedItem) { // Get the id try { $SHOWWARE_linkedItemId = PlentymarketsMappingController::getItemByPlentyID($LinkedItem->ItemID); } catch (PlentymarketsMappingExceptionNotExistant $E) { continue; } $table = ''; if ($LinkedItem->Relationship == 'Accessory') { $table = 's_articles_relationships'; } else { if ($LinkedItem->Relationship == 'Similar') { $table = 's_articles_similar'; } else { // Allow plugins to change the data $table = Shopware()->Events()->filter('PlentyConnector_ImportEntityItemLinked_GetTable', $table, array('subject' => $this, 'item' => $LinkedItem)); if (empty($table)) { continue; } } } Shopware()->Db()->insert($table, array('articleID' => (int) $this->SHOPWARE_itemId, 'relatedarticle' => (int) $SHOWWARE_linkedItemId)); } $this->purgeViews(); }
/** * Updates the stack */ public function update() { PlentymarketsLogger::getInstance()->message('Sync:Stack:Item', 'Starting update'); $ShopRepository = Shopware()->Models()->getRepository('Shopware\\Models\\Shop\\Shop'); $Shops = $ShopRepository->findBy(array('active' => 1), array('default' => 'DESC')); // Remember the time $timestamp = time(); // Is this the first run? $firstBlood = (int) PlentymarketsConfig::getInstance()->getImportItemStackFirstRunTimestamp() == 0; $Request_GetItemsUpdated = new PlentySoapRequest_GetItemsUpdated(); $Request_GetItemsUpdated->LastUpdateFrom = (int) PlentymarketsConfig::getInstance()->getImportItemStackLastUpdateTimestamp(); // Cache to avoid duplicate inserts of the same id with multiple shops $itemIdsStacked = array(); /** @var Shopware\Models\Shop\Shop $Shop */ foreach ($Shops as $Shop) { $Request_GetItemsUpdated->Page = 0; $Request_GetItemsUpdated->StoreID = PlentymarketsMappingController::getShopByShopwareID($Shop->getId()); do { // Do the request $Response_GetItemsUpdated = PlentymarketsSoapClient::getInstance()->GetItemsUpdated($Request_GetItemsUpdated); foreach ((array) $Response_GetItemsUpdated->Items->item as $Object_Integer) { $itemId = $Object_Integer->intValue; // Skip existing items on the first run if ($Request_GetItemsUpdated->LastUpdateFrom == 0 && $firstBlood) { try { PlentymarketsMappingController::getItemByPlentyID($itemId); continue; } catch (PlentymarketsMappingExceptionNotExistant $E) { } } $this->addItem($itemId, $Request_GetItemsUpdated->StoreID); $itemIdsStacked[$itemId] = true; } } while (++$Request_GetItemsUpdated->Page < $Response_GetItemsUpdated->Pages); } // Upcomming last update timestamp PlentymarketsConfig::getInstance()->setImportItemStackLastUpdateTimestamp($timestamp); if ($firstBlood) { // Remember your very first time :) PlentymarketsConfig::getInstance()->setImportItemStackFirstRunTimestamp(time()); } // Log $numberOfItemsStacked = count($itemIdsStacked); if (!$numberOfItemsStacked) { PlentymarketsLogger::getInstance()->message('Sync:Stack:Item', 'No item has been added to the stack'); } else { if ($numberOfItemsStacked == 1) { PlentymarketsLogger::getInstance()->message('Sync:Stack:Item', '1 item has been added to the stack'); } else { PlentymarketsLogger::getInstance()->message('Sync:Stack:Item', count($itemIdsStacked) . ' items have been added to the stack'); } } PlentymarketsLogger::getInstance()->message('Sync:Stack:Item', 'Update finished'); }
/** * Updates the stock for the given PlentySoapObject_GetCurrentStocks object * * @param PlentySoapObject_GetCurrentStocks $CurrentStock */ public function update($CurrentStock) { try { // Master item if (preg_match('/\\d+\\-\\d+\\-0/', $CurrentStock->SKU)) { $parts = explode('-', $CurrentStock->SKU); $itemId = PlentymarketsMappingController::getItemByPlentyID((int) $parts[0]); $Item = Shopware()->Models()->find('Shopware\\Models\\Article\\Article', $itemId); // Book $this->updateByDetail($Item->getMainDetail(), $CurrentStock->NetStock); } else { $itemDetailId = PlentymarketsMappingController::getItemVariantByPlentyID($CurrentStock->SKU); // Book $this->updateById($itemDetailId, $CurrentStock->NetStock); } } catch (PlentymarketsMappingExceptionNotExistant $E) { } catch (Exception $E) { PlentymarketsLogger::getInstance()->error('Sync:Item:Stock', 'The stock of the item detail with the id »' . $itemDetailId . '« could not be updated (' . $E->getMessage() . ')', 3510); } }