/**
  * Run import of property groups and property translations
  * @param int $lastUpdateTimestamp
  */
 private function runImportTranslations($lastUpdateTimestamp)
 {
     $mainShops = PlentymarketsUtils::getShopwareMainShops();
     /** @var $mainShop Shopware\Models\Shop\Shop */
     foreach ($mainShops as $mainShop) {
         // get all active languages of the main shop
         $activeLanguages = PlentymarketsTranslation::getShopActiveLanguages($mainShop->getId());
         foreach ($activeLanguages as $key => $language) {
             // import tanslation for property group
             $Request_GetPropertyGroups = new PlentySoapRequest_GetPropertyGroups();
             $Request_GetPropertyGroups->Lang = PlentymarketsTranslation::getPlentyLocaleFormat($language['locale']);
             $Request_GetPropertyGroups->LastUpdateFrom = $lastUpdateTimestamp;
             $Request_GetPropertyGroups->Page = 0;
             do {
                 /** @var PlentySoapResponse_GetPropertyGroups $Response_GetPropertyGroups */
                 $Response_GetPropertyGroups = PlentymarketsSoapClient::getInstance()->GetPropertyGroups($Request_GetPropertyGroups);
                 foreach ($Response_GetPropertyGroups->PropertyGroups->item as $group) {
                     $PlentymarketsImportEntityItemPropertyGroup = new PlentymarketsImportEntityItemPropertyGroup($group);
                     // set the property group translations from plenty for the language shops
                     if (!is_null($language['mainShopId'])) {
                         $languageShopID = PlentymarketsTranslation::getLanguageShopID($key, $language['mainShopId']);
                         $PlentymarketsImportEntityItemPropertyGroup->importPropertyGroupTranslation($languageShopID);
                     } else {
                         $PlentymarketsImportEntityItemPropertyGroup->importPropertyGroupTranslation($mainShop->getId());
                     }
                 }
             } while (++$Request_GetPropertyGroups->Page < $Response_GetPropertyGroups->Pages);
             // import translation for properties
             $Request_GetProperties = new PlentySoapRequest_GetProperties();
             $Request_GetProperties->Lang = PlentymarketsTranslation::getPlentyLocaleFormat($language['locale']);
             $Request_GetProperties->LastUpdateFrom = $lastUpdateTimestamp;
             $Request_GetProperties->Page = 0;
             do {
                 /** @var PlentySoapResponse_GetProperties $Response_GetProperties */
                 $Response_GetProperties = PlentymarketsSoapClient::getInstance()->GetProperties($Request_GetProperties);
                 foreach ($Response_GetProperties->Properties->item as $Option) {
                     $PlentymarketsImportEntityItemPropertyOption = new PlentymarketsImportEntityItemPropertyOption($Option);
                     // set the property translations from plenty for the language shops
                     if (!is_null($language['mainShopId'])) {
                         $languageShopID = PlentymarketsTranslation::getLanguageShopID($key, $language['mainShopId']);
                         $PlentymarketsImportEntityItemPropertyOption->importPropertyTranslation($languageShopID);
                     } else {
                         // set the property translation for the main shop
                         $PlentymarketsImportEntityItemPropertyOption->importPropertyTranslation($mainShop->getId());
                     }
                 }
             } while (++$Request_GetProperties->Page < $Response_GetProperties->Pages);
         }
     }
 }
 /**
  * Performs the actual import
  *
  * @param integer $lastUpdateTimestamp
  */
 public function run($lastUpdateTimestamp)
 {
     $Request_GetItemAttributes = new PlentySoapRequest_GetItemAttributes();
     $Request_GetItemAttributes->GetValues = true;
     $Request_GetItemAttributes->LastUpdateFrom = $lastUpdateTimestamp;
     /** @var PlentySoapResponse_GetItemAttributes $Response_GetItemAttributes */
     $Response_GetItemAttributes = PlentymarketsSoapClient::getInstance()->GetItemAttributes($Request_GetItemAttributes);
     if (!$Response_GetItemAttributes->Success) {
         return;
     }
     foreach ($Response_GetItemAttributes->Attributes->item as $Attribute) {
         $PlentymarketsImportEntityItemAttribute = new PlentymarketsImportEntityItemAttribute($Attribute);
         $PlentymarketsImportEntityItemAttribute->import();
     }
     // run import of attributes and attributes value translations
     $mainShops = PlentymarketsUtils::getShopwareMainShops();
     /** @var $mainShop Shopware\Models\Shop\Shop */
     foreach ($mainShops as $mainShop) {
         // get all active languages of the main shop
         $activeLanguages = PlentymarketsTranslation::getShopActiveLanguages($mainShop->getId());
         foreach ($activeLanguages as $key => $language) {
             $Request_GetItemAttributes = new PlentySoapRequest_GetItemAttributes();
             $Request_GetItemAttributes->GetValues = true;
             $Request_GetItemAttributes->LastUpdateFrom = $lastUpdateTimestamp;
             $Request_GetItemAttributes->Lang = PlentymarketsTranslation::getPlentyLocaleFormat($language['locale']);
             /** @var PlentySoapResponse_GetItemAttributes $Response_GetItemAttributes */
             $Response_GetItemAttributes = PlentymarketsSoapClient::getInstance()->GetItemAttributes($Request_GetItemAttributes);
             if ($Response_GetItemAttributes->Success) {
                 foreach ($Response_GetItemAttributes->Attributes->item as $Attribute) {
                     $PlentymarketsImportEntityItemAttribute = new PlentymarketsImportEntityItemAttribute($Attribute);
                     // set the atrribute translations from plenty for the language shops
                     if (!is_null($language['mainShopId'])) {
                         $languageShopID = PlentymarketsTranslation::getLanguageShopID($key, $language['mainShopId']);
                         $PlentymarketsImportEntityItemAttribute->importTranslation($languageShopID);
                     } else {
                         // import translations for the main shop languages
                         $PlentymarketsImportEntityItemAttribute->importTranslation($mainShop->getId());
                     }
                 }
             }
         }
     }
 }
 /**
  * Sets the variant details
  */
 protected function setVariants()
 {
     // No variants
     if (is_null($this->ItemBase->AttributeValueSets)) {
         return;
     }
     // Internal number cache
     $numbersUsed = array();
     $detailBase = $this->details + $this->data;
     unset($detailBase['id']);
     unset($detailBase['attribute']);
     /** @var PlentySoapObject_ItemAttributeValueSet $AttributeValueSet */
     foreach ($this->ItemBase->AttributeValueSets->item as $AttributeValueSet) {
         // Copy the base details
         $details = $detailBase;
         // SKU
         $sku = sprintf('%s-%s-%s', $this->ItemBase->ItemID, $AttributeValueSet->PriceID, $AttributeValueSet->AttributeValueSetID);
         // Strip whitespaces
         $number = trim($AttributeValueSet->ColliNo);
         try {
             // Set the details id
             $details['id'] = PlentymarketsMappingController::getItemVariantByPlentyID($sku);
             if (PlentymarketsConfig::getInstance()->getItemNumberImportActionID(IMPORT_ITEM_NUMBER) == IMPORT_ITEM_NUMBER) {
                 // If this number does not belong to this item
                 if (!PlentymarketsImportItemHelper::isNumberExistantVariant($number, $details['id'])) {
                     // and check if the number is valid
                     if (!PlentymarketsImportItemHelper::isNumberValid($number)) {
                         throw new PlentymarketsImportItemNumberException('The item variation number »' . $number . '« of item »' . $this->data['name'] . '« with the id »' . $this->ItemBase->ItemID . '« is invalid', 3110);
                     }
                     // check if the number is available anyway
                     if (PlentymarketsImportItemHelper::isNumberExistant($number)) {
                         throw new PlentymarketsImportItemNumberException('The item variation number »' . $number . '« of item »' . $this->data['name'] . '« with the id »' . $this->ItemBase->ItemID . '« is already in use', 3111);
                     }
                     // check if the number is in the internal cache
                     if (isset($numbersUsed[$number])) {
                         throw new PlentymarketsImportItemNumberException('The item variation number »' . $number . '« of item »' . $this->data['name'] . '« with the id »' . $this->ItemBase->ItemID . '« would be assigned twice', 3112);
                     }
                     // Use this number
                     $details['number'] = $number;
                     // Cache the number
                     $numbersUsed[$number] = true;
                 }
             }
         } catch (PlentymarketsMappingExceptionNotExistant $e) {
             // Numbers should be synced
             if (PlentymarketsConfig::getInstance()->getItemNumberImportActionID(IMPORT_ITEM_NUMBER) == IMPORT_ITEM_NUMBER) {
                 // Nummer ist ungültig oder in Benutzung
                 if (!PlentymarketsImportItemHelper::isNumberValid($number)) {
                     throw new PlentymarketsImportItemNumberException('The item variation number »' . $number . '« of item »' . $this->data['name'] . '« with the id »' . $this->ItemBase->ItemID . '« is invalid', 3110);
                 }
                 // check if the number is available
                 if (PlentymarketsImportItemHelper::isNumberExistant($number)) {
                     throw new PlentymarketsImportItemNumberException('The item variation number »' . $number . '« of item »' . $this->data['name'] . '« with the id »' . $this->ItemBase->ItemID . '« is already in use', 3111);
                 }
                 // check if the number is in the internal cache
                 if (isset($numbersUsed[$number])) {
                     throw new PlentymarketsImportItemNumberException('The item variation number »' . $number . '« of item »' . $this->data['name'] . '« with the id »' . $this->ItemBase->ItemID . '« would be assigned twice', 3112);
                 }
                 // Use this number
                 $details['number'] = $number;
                 // Cache the number
                 $numbersUsed[$number] = true;
             } else {
                 // A new number is generated
                 $details['number'] = PlentymarketsImportItemHelper::getItemNumber();
             }
         }
         $shippingTime = PlentymarketsUtils::getShippingTimeByAvailabilityId($AttributeValueSet->Availability);
         if ($shippingTime) {
             $details['shippingtime'] = $shippingTime;
         }
         $details['additionaltext'] = $AttributeValueSet->AttributeValueSetName;
         $details['ean'] = $AttributeValueSet->EAN;
         $details['X_plentySku'] = $sku;
         $this->variants[$AttributeValueSet->AttributeValueSetID] = $details;
     }
 }
 /**
  * Registers the bundle modules
  */
 public function __construct()
 {
     PlentymarketsUtils::registerBundleModules();
 }
 /**
  * @param int $shopware_propertyID
  * @param int $plenty_propertyID
  */
 protected function exportPropertyGroupTranslations($shopware_propertyID, $plenty_propertyID)
 {
     $Request_SetPropertyGroups = new PlentySoapRequest_SetPropertyGroups();
     $Request_SetPropertyGroups->PropertyGroups = array();
     $mainShops = PlentymarketsUtils::getShopwareMainShops();
     /** @var $mainShop Shopware\Models\Shop\Shop */
     foreach ($mainShops as $mainShop) {
         // get all active languages of the main shop
         $activeLanguages = PlentymarketsTranslation::getShopActiveLanguages($mainShop->getId());
         foreach ($activeLanguages as $key => $language) {
             // export the property group translations of the language shops and main shops
             // try to get translation
             $propertyGroupTranslation = PlentymarketsTranslation::getShopwareTranslation($mainShop->getId(), 'propertygroup', $shopware_propertyID, $key);
             // if the translation was found, do export
             if (!is_null($propertyGroupTranslation) && isset($propertyGroupTranslation['groupName'])) {
                 $Object_SetPropertyGroup = new PlentySoapObject_SetPropertyGroup();
                 $Object_SetPropertyGroup->PropertyGroupID = $plenty_propertyID;
                 $Object_SetPropertyGroup->Lang = PlentymarketsTranslation::getPlentyLocaleFormat($language['locale']);
                 $Object_SetPropertyGroup->FrontendName = $propertyGroupTranslation['groupName'];
                 $Request_SetPropertyGroups->PropertyGroups[] = $Object_SetPropertyGroup;
             }
         }
     }
     if (!empty($Request_SetPropertyGroups->PropertyGroups)) {
         $Response = PlentymarketsSoapClient::getInstance()->SetPropertyGroups($Request_SetPropertyGroups);
         if (!$Response->Success) {
             // throw exception
         }
     }
 }
 /**
  * @description Export the translation of the attributes and attributes values that are set for the language shops in shopware
  * @param int $shopwareAttributeID
  * @param int $plentyAttributeID
  */
 private function exportAttributeTranslations($shopwareAttributeID, $plentyAttributeID)
 {
     $Request_SetItemAttributes = new PlentySoapRequest_SetItemAttributes();
     $mainShops = PlentymarketsUtils::getShopwareMainShops();
     /** @var $mainShop Shopware\Models\Shop\Shop */
     foreach ($mainShops as $mainShop) {
         $Request_SetItemAttributes = new PlentySoapRequest_SetItemAttributes();
         // get all active languages of the main shop
         $activeLanguages = PlentymarketsTranslation::getShopActiveLanguages($mainShop->getId());
         foreach ($activeLanguages as $key => $language) {
             // export the atrribute translations of the language shops and main shops
             // try to get translation
             $attrTranslation = PlentymarketsTranslation::getShopwareTranslation($mainShop->getId(), 'configuratorgroup', $shopwareAttributeID, $key);
             // if the translation was found, do export
             if (!is_null($attrTranslation) && isset($attrTranslation['name'])) {
                 $Object_SetItemAttribute = new PlentySoapObject_SetItemAttribute();
                 $Object_SetItemAttribute->Id = $plentyAttributeID;
                 $Object_SetItemAttribute->FrontendLang = PlentymarketsTranslation::getPlentyLocaleFormat($language['locale']);
                 $Object_SetItemAttribute->FrontendName = $attrTranslation['name'];
                 $Request_SetItemAttributes->Attributes[] = $Object_SetItemAttribute;
             }
         }
     }
     if (!empty($Request_SetItemAttributes->Attributes)) {
         $Response = PlentymarketsSoapClient::getInstance()->SetItemAttributes($Request_SetItemAttributes);
         if (!$Response->Success) {
             // throw exception
         }
     }
 }
 /**
  * Checks whether the connection to plentymarkets can be established
  *
  * @return boolean
  */
 public function isConnected()
 {
     // The connection is only checked every 10 seconds
     if ($this->isConnected && $this->connectionTimestamp > time() - 10) {
         return true;
     }
     $this->isConnected = false;
     if (!PlentymarketsConfig::getInstance()->getApiWsdl()) {
         PlentymarketsConfig::getInstance()->erasePlentymarketsVersion();
         PlentymarketsConfig::getInstance()->setApiLastStatusTimestamp(time());
         PlentymarketsConfig::getInstance()->setApiStatus(1);
         return false;
     }
     try {
         $Response = PlentymarketsSoapClient::getInstance()->GetServerTime();
         //
         PlentymarketsConfig::getInstance()->setApiTimestampDeviation(time() - $Response->Timestamp);
         PlentymarketsConfig::getInstance()->setApiLastStatusTimestamp(time());
         PlentymarketsConfig::getInstance()->setApiStatus(2);
         $this->isConnected = true;
         $this->connectionTimestamp = time();
         // plenty version
         PlentymarketsUtils::checkPlentymarketsVersion();
         return true;
     } catch (Exception $E) {
         PlentymarketsConfig::getInstance()->setApiTimestampDeviation(0);
         PlentymarketsConfig::getInstance()->setApiLastStatusTimestamp(time());
         PlentymarketsConfig::getInstance()->setApiStatus(1);
         return false;
     }
 }
 /**
  * Exports the item bundle head item
  *
  * @throws PlentymarketsExportException
  */
 protected function exportHead()
 {
     // The shopware item on which the bundle is based on
     $shopwareBundleHead = $this->SHOPWARE_bundle->getArticle();
     $shopwareBundleHeadIsVariant = !is_null($shopwareBundleHead->getConfiguratorSet());
     // If the bundle head is a variant, the bundle can't be exported
     // since that feature is not provided by plentymarkets
     if ($shopwareBundleHeadIsVariant) {
         throw new PlentymarketsExportException('The item bundle with the number »' . $this->SHOPWARE_bundle->getNumber() . '« can not be exported because the master item is a variant.', 2230);
     }
     if ($this->SHOPWARE_bundle->getDiscountType() != 'abs') {
         throw new PlentymarketsExportException('The item bundle with the number »' . $this->SHOPWARE_bundle->getNumber() . '« can not be exported because the discount type is not supported.', 2240);
     }
     if ($this->SHOPWARE_bundle->getType() != 1) {
         throw new PlentymarketsExportException('The item bundle with the number »' . $this->SHOPWARE_bundle->getNumber() . '« can not be exported because the bundle type is not supported.', 2250);
     }
     // The shopware bundle head needs to be added as a plenty-bundle-item
     // The bundle head in plentymarkets is a "special" item
     $bundleItemId = PlentymarketsMappingController::getItemByShopwareID($shopwareBundleHead->getId());
     $sku = sprintf('%d-0', $bundleItemId);
     // If this item is also a bundle item in shopware,
     // we need to increase the quantity of it
     if (isset($this->PLENTY_bundleSkuList[$sku])) {
         $this->PLENTY_bundleSkuList[$sku] += 1;
     } else {
         $this->PLENTY_bundleSkuList[$sku] = 1;
     }
     // Create the bundle head
     $Request_AddItemsBase = new PlentySoapRequest_AddItemsBase();
     $Request_AddItemsBase->BaseItems = array();
     $Object_AddItemsBaseItemBase = new PlentySoapObject_AddItemsBaseItemBase();
     $Object_ItemAvailability = new PlentySoapObject_ItemAvailability();
     $validTo = $this->SHOPWARE_bundle->getValidTo();
     if ($validTo instanceof DateTime) {
         $Object_ItemAvailability->AvailableUntil = $this->SHOPWARE_bundle->getValidTo()->getTimestamp();
     }
     $Object_ItemAvailability->WebAPI = 1;
     $Object_ItemAvailability->Inactive = (int) $this->SHOPWARE_bundle->getActive();
     $Object_ItemAvailability->Webshop = (int) $this->SHOPWARE_bundle->getActive();
     $Object_AddItemsBaseItemBase->Availability = $Object_ItemAvailability;
     $storeIds = array();
     $Object_AddItemsBaseItemBase->Categories = array();
     $Object_AddItemsBaseItemBase->StoreIDs = array();
     foreach ($shopwareBundleHead->getCategories() as $category) {
         /** @var Shopware\Models\Category\Category $category */
         try {
             $categoryPath = PlentymarketsMappingController::getCategoryByShopwareID($category->getId());
         } catch (PlentymarketsMappingExceptionNotExistant $E) {
             continue;
         }
         $Object_ItemCategory = new PlentySoapObject_ItemCategory();
         $Object_ItemCategory->ItemCategoryPath = $categoryPath;
         // string
         $Object_AddItemsBaseItemBase->Categories[] = $Object_ItemCategory;
         // Get the store for this category
         $rootId = PlentymarketsUtils::getRootIdByCategory($category);
         $shops = PlentymarketsUtils::getShopIdByCategoryRootId($rootId);
         foreach ($shops as $shopId) {
             try {
                 $storeId = PlentymarketsMappingController::getShopByShopwareID($shopId);
             } catch (PlentymarketsMappingExceptionNotExistant $E) {
                 continue;
             }
             if (!isset($storeIds[$storeId])) {
                 // Activate the item for this store
                 $Object_Integer = new PlentySoapObject_Integer();
                 $Object_Integer->intValue = $storeId;
                 $Object_AddItemsBaseItemBase->StoreIDs[] = $Object_Integer;
                 // Cache
                 $storeIds[$storeId] = true;
             }
         }
     }
     $Object_AddItemsBaseItemBase->ExternalItemID = 'Swag/Bundle/' . $this->SHOPWARE_bundle->getId();
     // string
     $Object_AddItemsBaseItemBase->ItemNo = $this->SHOPWARE_bundle->getNumber();
     // string
     $Object_ItemPriceSet = new PlentySoapObject_ItemPriceSet();
     $defaultCustomerGroupKey = PlentymarketsConfig::getInstance()->get('DefaultCustomerGroupKey');
     $price = null;
     $isPriceFound = false;
     foreach ($this->SHOPWARE_bundle->getPrices() as $price) {
         /** @var Shopware\CustomModels\Bundle\Price $price */
         if ($price->getCustomerGroup()->getKey() == $defaultCustomerGroupKey) {
             $isPriceFound = true;
             break;
         }
     }
     if ($isPriceFound && $price instanceof Shopware\CustomModels\Bundle\Price) {
         $tax = $this->SHOPWARE_bundle->getArticle()->getTax()->getTax();
         $priceNet = $price->getPrice();
         $price = $priceNet + $priceNet / 100 * $tax;
         $Object_ItemPriceSet->Price = $price;
         $Object_ItemPriceSet->VAT = $tax;
     } else {
         // If there is no price, we have to set one anyway.
         // Otherwise the re-import will crash
         $Object_ItemPriceSet->Price = 1;
     }
     $Object_AddItemsBaseItemBase->PriceSet = $Object_ItemPriceSet;
     $Object_AddItemsBaseItemBase->VATInternalID = PlentymarketsMappingController::getVatByShopwareID($this->SHOPWARE_bundle->getArticle()->getTax()->getId());
     $Object_AddItemsBaseItemBase->ProducerID = PlentymarketsMappingController::getProducerByShopwareID($shopwareBundleHead->getSupplier()->getId());
     // int
     $Object_AddItemsBaseItemBase->Published = null;
     // int
     $Object_ItemTexts = new PlentySoapObject_ItemTexts();
     $Object_ItemTexts->Name = $this->SHOPWARE_bundle->getName();
     // string
     $Object_AddItemsBaseItemBase->Texts = $Object_ItemTexts;
     $Request_AddItemsBase->BaseItems[] = $Object_AddItemsBaseItemBase;
     $Response_AddItemsBase = PlentymarketsSoapClient::getInstance()->AddItemsBase($Request_AddItemsBase);
     $ResponseMessage = $Response_AddItemsBase->ResponseMessages->item[0];
     if (!$Response_AddItemsBase->Success || $ResponseMessage->Code != 100) {
         throw new PlentymarketsExportException('The item bundle with the number »' . $this->SHOPWARE_bundle->getNumber() . '« could not be exported', 2210);
     }
     $PLENTY_priceID = null;
     foreach ($ResponseMessage->SuccessMessages->item as $SubMessage) {
         if ($SubMessage->Key == 'ItemID') {
             $this->PLENTY_bundleHeadId = (int) $SubMessage->Value;
         } else {
             if ($SubMessage->Key == 'PriceID') {
                 $PLENTY_priceID = (int) $SubMessage->Value;
             }
         }
     }
     if ($this->PLENTY_bundleHeadId && $PLENTY_priceID) {
         PlentymarketsLogger::getInstance()->message('Export:Initial:Item:Bundle', 'The item bundle with the number »' . $this->SHOPWARE_bundle->getNumber() . '« has been created with the id »' . $this->PLENTY_bundleHeadId . '«.');
         PlentymarketsMappingController::addItemBundle($this->SHOPWARE_bundle->getId(), $this->PLENTY_bundleHeadId);
     } else {
         throw new PlentymarketsExportException('The item bundle with the number »' . $this->SHOPWARE_bundle->getNumber() . '« could not be exported', 2210);
     }
 }
 /**
  * Exports the item variants
  */
 protected function exportVariants()
 {
     // Verknüpfung mit den Attribut(-werten)
     $ConfiguratorSet = $this->SHOPWARE_Article->getConfiguratorSet();
     if (!$ConfiguratorSet instanceof Shopware\Models\Article\Configurator\Set) {
         return;
     }
     // Active the attribute values at the item --------------------------------------------------------------------
     $objectsActivateLinks = array();
     $Request_SetItemAttributeLinks = new PlentySoapRequest_SetItemAttributeLinks();
     $Request_SetItemAttributeLinks->ItemID = $this->PLENTY_itemID;
     // int
     $Request_SetItemAttributeLinks->AttributeLinks = array();
     /** @var Shopware\Models\Article\Configurator\Option $ConfiguratorOption */
     foreach ($ConfiguratorSet->getOptions() as $ConfiguratorOption) {
         $PLENTY_attributeID = PlentymarketsMappingController::getAttributeGroupByShopwareID($ConfiguratorOption->getGroup()->getId());
         $PLENTY_attributeValueID = PlentymarketsMappingController::getAttributeOptionByShopwareID($ConfiguratorOption->getId());
         $Object_AttributeLink = new PlentySoapObject_AttributeLink();
         $Object_AttributeLink->AttributeID = $PLENTY_attributeID;
         // int
         $Object_AttributeLink->AttributeValueID = $PLENTY_attributeValueID;
         // int
         $Object_AttributeLink->Activate = true;
         $objectsActivateLinks[] = $Object_AttributeLink;
     }
     // Run the calls
     foreach (array_chunk($objectsActivateLinks, 100) as $activateLinks) {
         $Request_SetItemAttributeLinks->AttributeLinks = $activateLinks;
         PlentymarketsSoapClient::getInstance()->SetItemAttributeLinks($Request_SetItemAttributeLinks);
     }
     // generate the attribute value sets --------------------------------------------------------------------------
     $objectsSetAttributeValueSets = array();
     $cacheAttributeValueSets = array();
     $Request_SetItemAttributeVariants = new PlentySoapRequest_SetItemAttributeVariants();
     $Request_SetItemAttributeVariants->ItemID = $this->PLENTY_itemID;
     // int
     $Request_SetItemAttributeVariants->SetAttributeValueSets = array();
     $Details = $this->SHOPWARE_Article->getDetails();
     /**
      * @var Shopware\Models\Article\Detail $ItemVariation
      * @var Shopware\Models\Article\Configurator\Option $ConfiguratorOption
      */
     foreach ($Details as $ItemVariation) {
         $cacheAttributeValueSets[$ItemVariation->getId()] = array();
         $Object_AttributeVariantList = new PlentySoapObject_AttributeVariantList();
         foreach ($ItemVariation->getConfiguratorOptions() as $ConfiguratorOption) {
             $PLENTY_attributeValueID = PlentymarketsMappingController::getAttributeOptionByShopwareID($ConfiguratorOption->getId());
             $cacheAttributeValueSets[$ItemVariation->getId()][] = $PLENTY_attributeValueID;
             $Object_Integer = new PlentySoapObject_Integer();
             $Object_Integer->intValue = $PLENTY_attributeValueID;
             $Object_AttributeVariantList->AttributeValueIDs[] = $Object_Integer;
         }
         $objectsSetAttributeValueSets[] = $Object_AttributeVariantList;
     }
     foreach (array_chunk($objectsSetAttributeValueSets, 100) as $setAttributeValueSets) {
         // Complete the request
         $Request_SetItemAttributeVariants->SetAttributeValueSets = $setAttributeValueSets;
         // and go for it
         $Response_SetItemAttributeVariants = PlentymarketsSoapClient::getInstance()->SetItemAttributeVariants($Request_SetItemAttributeVariants);
         // Matching der Varianten
         foreach ($Response_SetItemAttributeVariants->ResponseMessages->item as $ResponseMessage) {
             if ($ResponseMessage->IdentificationKey != 'AttributeValueIDs') {
                 continue;
             }
             // If there is an error message, go ahead
             if (!is_null($ResponseMessage->ErrorMessages)) {
                 continue;
             }
             $PLENTY_attributeValueIDs = array_map('intval', explode(';', $ResponseMessage->IdentificationValue));
             $PLENTY_variantID = (int) $ResponseMessage->SuccessMessages->item[0]->Value;
             foreach ($cacheAttributeValueSets as $SHOPWARE_variantID => $attributeValueIDs) {
                 if (PlentymarketsUtils::arraysAreEqual($attributeValueIDs, $PLENTY_attributeValueIDs)) {
                     PlentymarketsMappingController::addItemVariant($SHOPWARE_variantID, sprintf('%s-%s-%s', $this->PLENTY_itemID, $this->PLENTY_priceID, $PLENTY_variantID));
                     break;
                 }
             }
         }
     }
     // Set the variation details ----------------------------------------------------------------------------------
     $objectsAttributeValueSetsDetails = array();
     // start the request
     $Request_SetAttributeValueSetsDetails = new PlentySoapRequest_SetAttributeValueSetsDetails();
     $Request_SetAttributeValueSetsDetails->AttributeValueSetsDetails = array();
     /** @var Shopware\Models\Article\Detail $ItemVariation */
     foreach ($Details as $ItemVariation) {
         try {
             $sku = PlentymarketsMappingController::getItemVariantByShopwareID($ItemVariation->getId());
         } catch (PlentymarketsMappingExceptionNotExistant $E) {
             // Roll back the item
             $this->rollback();
             // and quit
             throw new PlentymarketsExportException('The item variation with the number »' . $ItemVariation->getNumber() . '« could not be created (corrupt data)', 2880);
         }
         $Object_SetAttributeValueSetsDetails = new PlentySoapObject_SetAttributeValueSetsDetails();
         $Object_SetAttributeValueSetsDetails->Availability = $ItemVariation->getActive();
         // int
         $Object_SetAttributeValueSetsDetails->EAN1 = $ItemVariation->getEan();
         // string
         $Object_SetAttributeValueSetsDetails->MaxStock = null;
         // float
         $Object_SetAttributeValueSetsDetails->PurchasePrice = null;
         // float
         $Object_SetAttributeValueSetsDetails->SKU = $sku;
         $Object_SetAttributeValueSetsDetails->Variantnumber = $ItemVariation->getNumber();
         // string
         $objectsAttributeValueSetsDetails[] = $Object_SetAttributeValueSetsDetails;
     }
     foreach (array_chunk($objectsAttributeValueSetsDetails, 50) as $attributeValueSetsDetails) {
         $Request_SetAttributeValueSetsDetails->AttributeValueSetsDetails = $attributeValueSetsDetails;
         PlentymarketsSoapClient::getInstance()->SetAttributeValueSetsDetails($Request_SetAttributeValueSetsDetails);
     }
 }
 /**
  * Public import handler method
  *
  */
 public function import()
 {
     $this->prepare();
     // Helper
     $numberOfOrdersUpdated = 0;
     do {
         // Force Update
         //$this->Request_SearchOrders->LastUpdateFrom = ($this->Request_SearchOrders->LastUpdateFrom - (3600*1));
         $Response_SearchOrders = PlentymarketsSoapClient::getInstance()->SearchOrders($this->Request_SearchOrders);
         $pages = max($Response_SearchOrders->Pages, 1);
         $this->log('Page: ' . ($this->Request_SearchOrders->Page + 1) . '/' . $pages);
         if ($Response_SearchOrders->Success == false) {
             $this->log('Failed', 'error');
             break;
         }
         $this->log('Received ' . count($Response_SearchOrders->Orders->item) . ' items');
         foreach ($Response_SearchOrders->Orders->item as $Order) {
             /** @var PlentySoapObject_OrderHead $Order */
             $Order = $Order->OrderHead;
             try {
                 $orderId = $Order->ExternalOrderID;
                 if (strstr($orderId, 'Swag/') === false) {
                     $this->log('The sales order with the external order id ' . $Order->ExternalOrderID . ' could not be updated because it isn\'t a shopware order.', 'error');
                     continue;
                 }
                 $SHOPWARE_orderId = PlentymarketsUtils::getShopwareIDFromExternalOrderID($orderId);
                 if ($SHOPWARE_orderId <= 0) {
                     $this->log('The sales order with the external order id ' . $Order->ExternalOrderID . ' could not be updated.', 'error');
                     continue;
                 }
                 $this->handle($SHOPWARE_orderId, $Order);
                 $this->log('The sales order with the id ' . $orderId . ' has been updated.');
                 $db = Shopware()->Db();
                 $r = $db->executeUpdate("UPDATE `s_order` SET trackingcode = '" . $Order->PackageNumber . "' WHERE `id` = " . $SHOPWARE_orderId);
                 $this->log('Setting the package number ' . $Order->PackageNumber . ' for the order ' . $SHOPWARE_orderId);
                 ++$numberOfOrdersUpdated;
             } catch (Exception $E) {
                 $this->log('The sales order with the external order id ' . $Order->ExternalOrderID . ' could not be updated.', 'error');
                 $this->log($E->getMessage(), 'error');
             }
         }
     } while (++$this->Request_SearchOrders->Page < $Response_SearchOrders->Pages);
     //
     $this->log($numberOfOrdersUpdated . ' sales orders have been updated.');
 }
    /**
     * 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)');
    }
 /**
  * Returns the shipping time
  *
  * @param $availabilityId
  * @return integer|null
  */
 public static function getShippingTimeByAvailabilityId($availabilityId)
 {
     if ((int) $availabilityId <= 0) {
         return null;
     }
     if (!is_array(self::$availability)) {
         self::$availability = PlentymarketsImportController::getItemAvailability();
     }
     return isset(self::$availability[$availabilityId]) ? self::$availability[$availabilityId] : null;
 }
 /**
  * Exports the delivery address
  */
 protected function exportDeliveryAddress()
 {
     if ($this->ShippingAddress === null) {
         return;
     }
     if ($this->PLENTY_customerID === null) {
         return;
     }
     $city = trim($this->ShippingAddress->getCity());
     $street_arr = PlentymarketsUtils::extractStreetAndHouseNo($this->ShippingAddress->getStreet());
     if (isset($street_arr['street']) && strlen($street_arr['street']) > 0) {
         $streetName = $street_arr['street'];
     } else {
         $streetName = trim($this->ShippingAddress->getStreet());
     }
     if (isset($street_arr['houseNo']) && strlen($street_arr['houseNo']) > 0) {
         $streetHouseNumber = $street_arr['houseNo'];
     } else {
         $streetHouseNumber = '';
     }
     $zip = trim($this->ShippingAddress->getZipCode());
     if (empty($city)) {
         $city = PlentymarketsConfig::getInstance()->get('CustomerDefaultCity');
     }
     if (!isset($streetHouseNumber) || $streetHouseNumber == '') {
         $streetHouseNumber = PlentymarketsConfig::getInstance()->get('CustomerDefaultHouseNumber');
     }
     if (!isset($streetName) || $streetName == '') {
         $streetName = PlentymarketsConfig::getInstance()->get('CustomerDefaultStreet');
     }
     if ($zip == '') {
         $zip = PlentymarketsConfig::getInstance()->get('CustomerDefaultZipcode');
     }
     $Request_SetCustomerDeliveryAddresses = new PlentySoapRequest_SetCustomerDeliveryAddresses();
     $Request_SetCustomerDeliveryAddresses->DeliveryAddresses = array();
     $Object_SetCustomerDeliveryAddressesCustomer = new PlentySoapRequest_ObjectSetCustomerDeliveryAddresses();
     $Object_SetCustomerDeliveryAddressesCustomer->AdditionalName = null;
     // string
     $Object_SetCustomerDeliveryAddressesCustomer->City = $city;
     $Object_SetCustomerDeliveryAddressesCustomer->Company = $this->ShippingAddress->getCompany();
     $Object_SetCustomerDeliveryAddressesCustomer->CountryID = $this->getDeliveryCountryID();
     // int
     $Object_SetCustomerDeliveryAddressesCustomer->CustomerID = $this->PLENTY_customerID;
     // int
     $Object_SetCustomerDeliveryAddressesCustomer->ExternalDeliveryAddressID = PlentymarketsUtils::getExternalCustomerID($this->ShippingAddress->getId());
     // string
     $Object_SetCustomerDeliveryAddressesCustomer->FirstName = $this->ShippingAddress->getFirstName();
     $Object_SetCustomerDeliveryAddressesCustomer->FormOfAddress = $this->getDeliveryFormOfAddress();
     // int
     $Object_SetCustomerDeliveryAddressesCustomer->HouseNumber = $streetHouseNumber;
     $Object_SetCustomerDeliveryAddressesCustomer->Street = $streetName;
     $Object_SetCustomerDeliveryAddressesCustomer->Surname = $this->ShippingAddress->getLastName();
     $Object_SetCustomerDeliveryAddressesCustomer->ZIP = $zip;
     $Request_SetCustomerDeliveryAddresses->DeliveryAddresses[] = $Object_SetCustomerDeliveryAddressesCustomer;
     $Response_SetCustomerDeliveryAddresses = PlentymarketsSoapClient::getInstance()->SetCustomerDeliveryAddresses($Request_SetCustomerDeliveryAddresses);
     if (!$Response_SetCustomerDeliveryAddresses->Success) {
         throw new PlentymarketsExportEntityException('The delivery address of the customer with the number »' . $this->getCustomerNumber() . '« could not be exported', 2120);
     }
     $this->PLENTY_addressDispatchID = (int) $Response_SetCustomerDeliveryAddresses->ResponseMessages->item[0]->SuccessMessages->item[0]->Value;
 }
 /**
  * Logs the usage data
  */
 public function usage()
 {
     // Quit if the usage may not be logged
     if (!PlentymarketsConfig::getInstance()->getMayLogUsageData(false)) {
         return;
     }
     // Collect data
     $memoryUsage = PlentymarketsUtils::convertBytes(memory_get_usage());
     $memoryUsageReal = PlentymarketsUtils::convertBytes(memory_get_usage(true));
     $memoryLimit = ini_get('memory_limit');
     $numberOfCalls = PlentymarketsSoapClient::getInstance()->getNumberOfCalls();
     // Generate message
     $message = sprintf('Memory: %s (%s) / (%s) – Calls: %s', $memoryUsageReal, $memoryUsage, $memoryLimit, $numberOfCalls);
     // And save to the log
     $this->message('Usage data', $message);
 }
 /**
  * Export the missing categories from shopware to plenty
  */
 protected function main()
 {
     $shopwareCategories = Shopware()->Models()->getRepository('Shopware\\Models\\Category\\Category')->findBy(array('path' => null));
     /** @var Shopware\Models\Category\Category $shopwareCategory */
     foreach ($shopwareCategories as $shopwareCategory) {
         // Skip "Root"
         if ((int) $shopwareCategory->getParentId() == 0) {
             continue;
         }
         if ($shopwareCategory->getBlog()) {
             continue;
         }
         // Get the store for this category
         $rootId = PlentymarketsUtils::getRootIdByCategory($shopwareCategory);
         $shops = PlentymarketsUtils::getShopIdByCategoryRootId($rootId);
         if (!$shops) {
             $shops = array(0);
         }
         foreach ($shops as $shopId) {
             try {
                 $storeId = PlentymarketsMappingController::getShopByShopwareID($shopId);
             } catch (PlentymarketsMappingExceptionNotExistant $E) {
                 $storeId = 0;
             }
             $this->export($shopwareCategory->getChildren(), $this->PLENTY_CategoryTree2ShopID, $storeId);
         }
     }
 }