/**
  * Deletes a page of invalid data
  *
  * @param integer $start
  * @param integer $offset
  */
 public function deleteInvalidData($start, $offset)
 {
     // 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) {
         try {
             /** @var \Shopware\Models\Article\Article $Item */
             $Item = Shopware()->Models()->find('\\Shopware\\Models\\Article\\Article', $data['itemId']);
             $detail = new \Shopware\Models\Article\Detail();
             $detail->setArticle($Item);
             // The number will be changed by the sync process
             $detail->setNumber(PlentymarketsImportItemHelper::getItemNumber());
             $price = new Shopware\Models\Article\Price();
             $price->setFrom(1);
             $price->setPrice(1);
             $price->setPercent(0);
             $price->setArticle($Item);
             $price->setDetail($detail);
             $price->setCustomerGroup($customerGroup);
             $Item->setMainDetail($detail);
             Shopware()->Models()->persist($Item);
             Shopware()->Models()->remove($Item);
         } catch (Exception $E) {
         }
     }
     Shopware()->Models()->flush();
 }
    /**
     * Runs the export of the incoming payments
     */
    public function run()
    {
        // Start
        PlentymarketsConfig::getInstance()->setItemIncomingPaymentExportStart(time());
        $now = time();
        $lastUpdateTimestamp = date('Y-m-d H:i:s', PlentymarketsConfig::getInstance()->getItemIncomingPaymentExportLastUpdate(time()));
        $status = explode('|', PlentymarketsConfig::getInstance()->getOrderPaidStatusID(12));
        $status = array_map('intval', $status);
        if (!count($status)) {
            $status = array(12);
        }
        $Result = Shopware()->Db()->query('
			SELECT
					DISTINCT orderID
				FROM s_order_history
					JOIN plenty_order ON shopwareId = orderID
				WHERE
					change_date > \'' . $lastUpdateTimestamp . '\' AND
					payment_status_id IN (' . implode(', ', $status) . ') AND
					IFNULL(plentyOrderPaidStatus, 0) != 1
		');
        while (($order = $Result->fetchObject()) && is_object($order)) {
            try {
                $ExportEntityIncomingPayment = new PlentymarketsExportEntityOrderIncomingPayment($order->orderID);
                $ExportEntityIncomingPayment->book();
            } catch (PlentymarketsExportEntityException $E) {
                PlentymarketsLogger::getInstance()->error('Sync:Order:IncomingPayment', $E->getMessage(), $E->getCode());
            }
        }
        // Set timestamps
        PlentymarketsConfig::getInstance()->setItemIncomingPaymentExportTimestampFinished(time());
        PlentymarketsConfig::getInstance()->setItemIncomingPaymentExportLastUpdate($now);
    }
 /**
  * I am the constructor
  */
 protected function __construct()
 {
     $itemWarehousePercentage = PlentymarketsConfig::getInstance()->getItemWarehousePercentage(100);
     if ($itemWarehousePercentage > 100 || $itemWarehousePercentage <= 0) {
         $itemWarehousePercentage = 100;
     }
     $this->itemWarehousePercentage = $itemWarehousePercentage;
 }
 /**
  * Prepares the soap orders SOAP object
  *
  * @see PlentymarketsImportEntityOrderAbstract::prepare()
  */
 public function prepare()
 {
     $timestamp = (int) PlentymarketsConfig::getInstance()->getImportOrderStatusChangeLastUpdateTimestamp(0);
     if (!$timestamp) {
         $timestamp = time();
     }
     $this->log('LastUpdate: ' . date('r', $timestamp));
     $this->Request_SearchOrders->LastUpdateFrom = $timestamp;
 }
 /**
  * Prepares the soap orders SOAP object
  * 
  * @see PlentymarketsImportEntityOrderAbstract::prepare()
  */
 public function prepare()
 {
     $timestamp = PlentymarketsConfig::getInstance()->getImportOrderIncomingPaymentsLastUpdateTimestamp(0);
     if ($timestamp > 0) {
         $this->log('LastUpdate: ' . date('r', $timestamp));
     }
     $this->Request_SearchOrders->OrderPaidFrom = $timestamp;
     if (is_null(self::$paymentStatusFull)) {
         self::$paymentStatusFull = PlentymarketsConfig::getInstance()->getIncomingPaymentShopwarePaymentFullStatusID();
     }
     if (is_null(self::$paymentStatusPartial)) {
         self::$paymentStatusPartial = PlentymarketsConfig::getInstance()->getIncomingPaymentShopwarePaymentPartialStatusID();
     }
 }
 /**
  * Prepares the search orders SOAP object
  * 
  * @see PlentymarketsImportEntityOrderAbstract::prepare()
  */
 public function prepare()
 {
     if (is_null(self::$orderStatus)) {
         self::$orderStatus = PlentymarketsConfig::getInstance()->getOutgoingItemsShopwareOrderStatusID(7);
     }
     $timestamp = PlentymarketsConfig::getInstance()->getImportOrderOutgoingItemsLastUpdateTimestamp(0);
     $this->log('LastUpdate: ' . date('r', $timestamp));
     if (PlentymarketsConfig::getInstance()->getOutgoingItemsOrderStatus(0)) {
         $this->Request_SearchOrders->LastUpdateFrom = $timestamp;
         $this->Request_SearchOrders->OrderStatus = (double) PlentymarketsConfig::getInstance()->getOutgoingItemsOrderStatus();
         $this->log('Mode: Status (' . $this->Request_SearchOrders->OrderStatus . ')');
     } else {
         $this->Request_SearchOrders->OrderCompletedFrom = $timestamp;
         $this->log('Mode: Outgoing items booked');
     }
 }
 /**
  * Returns a price array for the shopware REST api
  *
  * @return array
  */
 public function getPrices()
 {
     $prices = array();
     $customerGroupKey = PlentymarketsConfig::getInstance()->getDefaultCustomerGroupKey();
     // Prices
     if ($this->PLENTY_PriceSet->RebateLevelPrice6 > 0) {
         $price = array('from' => 1, 'to' => $this->PLENTY_PriceSet->RebateLevelPrice6 - 1, 'customerGroupKey' => $customerGroupKey, 'price' => $this->PLENTY_PriceSet->Price, 'percent' => 0);
         $prices[] = $price;
         for ($n = 6; $n < 12; ++$n) {
             $price = sprintf('Price%u', $n);
             $rebateLevel = sprintf('RebateLevelPrice%u', $n);
             $rebateLevelNext = sprintf('RebateLevelPrice%u', $n + 1);
             if ($this->PLENTY_PriceSet->{$rebateLevel} > 0) {
                 if (isset($this->PLENTY_PriceSet->{$rebateLevelNext})) {
                     $to = $this->PLENTY_PriceSet->{$rebateLevelNext} - 1;
                 } else {
                     $to = 'beliebig';
                 }
                 $price = array('customerGroupKey' => $customerGroupKey, 'from' => $this->PLENTY_PriceSet->{$rebateLevel}, 'to' => $to, 'price' => $this->PLENTY_PriceSet->{$price}, 'percent' => ($this->PLENTY_PriceSet->Price - $this->PLENTY_PriceSet->{$price}) / $this->PLENTY_PriceSet->Price * 100);
                 $prices[] = $price;
             } else {
                 break;
             }
         }
     } else {
         $price = array('customerGroupKey' => $customerGroupKey);
         // Reliably available starting in SOAP 111
         if (isset($this->PLENTY_PriceSet->Price) && !is_null($this->PLENTY_PriceSet->Price)) {
             $price['price'] = $this->PLENTY_PriceSet->Price;
         }
         if (isset($this->PLENTY_PriceSet->PurchasePriceNet) && !is_null($this->PLENTY_PriceSet->PurchasePriceNet)) {
             $price['basePrice'] = $this->PLENTY_PriceSet->PurchasePriceNet;
         }
         // Reliably available starting in SOAP 111
         // check whether the RRP is higher than price to prevent ugly display
         if (isset($this->PLENTY_PriceSet->RRP) && !is_null($this->PLENTY_PriceSet->RRP) && isset($price['price']) && $this->PLENTY_PriceSet->RRP > $price['price']) {
             $price['pseudoPrice'] = $this->PLENTY_PriceSet->RRP;
         }
         $prices[] = $price;
     }
     foreach ($prices as &$price) {
         $price['price'] += $this->PLENTY_markup;
     }
     // Allow plugins to change the data
     $prices = Shopware()->Events()->filter('PlentyConnector_ImportEntityItemPrice_AfterGetPrice', $prices, array('subject' => $this, 'priceset' => $this->PLENTY_PriceSet, 'markup' => $this->PLENTY_markup));
     return $prices;
 }
 /**
  * Exports images, variants, properties item data and items base to make sure, that the corresponding items data exist.
  */
 protected function export()
 {
     // Query builder
     $QueryBuilder = Shopware()->Models()->createQueryBuilder();
     $QueryBuilder->select('item.id')->from('Shopware\\Models\\Article\\Article', 'item');
     do {
         // Log the chunk
         PlentymarketsLogger::getInstance()->message('Export:Initial:Item', 'Chunk: ' . ($this->currentChunk + 1));
         // Set Limit and Offset
         $QueryBuilder->setFirstResult($this->currentChunk * $this->sizeOfChunk)->setMaxResults($this->sizeOfChunk);
         // Get the items
         $items = $QueryBuilder->getQuery()->getArrayResult();
         //
         $itemsAlreadyExported = 0;
         foreach ($items as $item) {
             try {
                 // If there is a plenty id for this shopware id,
                 // the item has already been exported to plentymarkets
                 PlentymarketsMappingController::getItemByShopwareID($item['id']);
                 //
                 ++$itemsAlreadyExported;
                 // already done
                 continue;
             } catch (PlentymarketsMappingExceptionNotExistant $E) {
             }
             $PlentymarketsExportEntityItem = new PlentymarketsExportEntityItem(Shopware()->Models()->find('Shopware\\Models\\Article\\Article', $item['id']));
             $PlentymarketsExportEntityItem->export();
         }
         // Remember the chunk
         $this->Config->setItemExportLastChunk($this->currentChunk);
         if ($this->maxChunks > 0) {
             // Increase number of chunks if every item has already been exported
             if ($itemsAlreadyExported == $this->sizeOfChunk) {
                 ++$this->maxChunks;
                 PlentymarketsLogger::getInstance()->message('Export:Initial:Item', 'Increasing number of chunks per run to ' . $this->maxChunks . ' since every item of chunk ' . ($this->currentChunk + 1) . ' has already been exported');
             }
             // Quit when the maximum number of chunks is reached
             if (++$this->chunksDone >= $this->maxChunks) {
                 $this->toBeContinued = true;
                 break;
             }
         }
         // Next chunk
         ++$this->currentChunk;
     } while (!empty($items) && count($items) == $this->sizeOfChunk);
 }
 /**
  * Retrieves the stocks for the stack
  */
 public function import()
 {
     // Unify
     $this->stack = array_unique($this->stack);
     if (empty($this->stack)) {
         return;
     }
     // Chunkify
     $stacks = array_chunk($this->stack, 100);
     // Reset
     $this->stack = array();
     // Warehouse
     $warehouseId = PlentymarketsConfig::getInstance()->getItemWarehouseID(0);
     // Build the request
     $Request_GetCurrentStocks = new PlentySoapRequest_GetCurrentStocks();
     $Request_GetCurrentStocks->Page = 0;
     //
     $ImportEntityItemStock = PlentymarketsImportEntityItemStock::getInstance();
     foreach ($stacks as $stack) {
         // Reset
         $Request_GetCurrentStocks->Items = array();
         // Add the SKUs
         foreach ($stack as $sku) {
             $RequestObject_GetCurrentStocks = new PlentySoapRequestObject_GetCurrentStocks();
             $RequestObject_GetCurrentStocks->SKU = $sku;
             $Request_GetCurrentStocks->Items[] = $RequestObject_GetCurrentStocks;
         }
         // Log
         PlentymarketsLogger::getInstance()->message('Sync:Item:Stock', 'Fetching ' . count($Request_GetCurrentStocks->Items) . ' stocks');
         // Do the request
         $Response_GetCurrentStocks = PlentymarketsSoapClient::getInstance()->GetCurrentStocks($Request_GetCurrentStocks);
         // Process
         /** @var PlentySoapObject_GetCurrentStocks $CurrentStock */
         foreach ($Response_GetCurrentStocks->CurrentStocks->item as $CurrentStock) {
             // Skip wrong warehouses
             if ($CurrentStock->WarehouseID != $warehouseId) {
                 continue;
             }
             $ImportEntityItemStock->update($CurrentStock);
         }
     }
 }
 /**
  * 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.');
         }
     }
 }
    /**
     * Retrieves the images from plentymarkets and adds them to the item.
     *
     * @return number
     */
    public function image()
    {
        $plentyId2ShopwareId = array();
        $shopwareId2PlentyPosition = array();
        $Request_GetItemsImages = new PlentySoapRequest_GetItemsImages();
        $Request_GetItemsImages->Page = 0;
        $Request_GetItemsImages->SKU = $this->PLENTY_itemId;
        // Cleanup
        $this->purge();
        /**
         * @var Media $mediaResource
         */
        $mediaResource = \Shopware\Components\Api\Manager::getResource('Media');
        do {
            /**
             * @var PlentySoapResponse_GetItemsImages $Response_GetItemsImages
             */
            $Response_GetItemsImages = PlentymarketsSoapClient::getInstance()->GetItemsImages($Request_GetItemsImages);
            if ($Response_GetItemsImages->Success == false) {
                PlentymarketsLogger::getInstance()->error('Sync:Item:Image', 'The images for the plentymarkets item id »' . $this->PLENTY_itemId . '« could not be retrieved', 3200);
                continue;
            }
            /**
             * @var $Image PlentySoapResponse_ObjectItemImage
             */
            foreach ($Response_GetItemsImages->ItemsImages->item as $Image) {
                $shopwareStoreIds = array();
                /**
                 * @var $reference PlentySoapResponse_ObjectGetItemImageReference
                 */
                foreach ($Image->References->item as $reference) {
                    if ($reference->ReferenceType == 'Mandant') {
                        try {
                            if (PlentymarketsMappingController::getShopByPlentyID($reference->ReferenceValue) > 0) {
                                $shopwareStoreId = PlentymarketsMappingController::getShopByPlentyID($reference->ReferenceValue);
                            }
                        } catch (PlentymarketsMappingExceptionNotExistant $E) {
                            continue;
                        }
                        if (isset($shopwareStoreId)) {
                            $shopwareStoreIds[] = $shopwareStoreId;
                        }
                    }
                }
                // Skip the image if it should not be shown
                if (empty($shopwareStoreIds)) {
                    continue;
                } else {
                    try {
                        $media = $this->updateMedia($Image, $mediaResource);
                    } catch (PlentymarketsMappingExceptionNotExistant $e) {
                        $media = $this->createMedia($Image, $mediaResource);
                    } catch (NotFoundException $e) {
                        $media = $this->createMedia($Image, $mediaResource);
                    } catch (Exception $e) {
                        PlentymarketsLogger::getInstance()->error('Sync:Item:Image', $e->getMessage(), 3200);
                        continue;
                    }
                    $image = new Image();
                    $image->setMain(2);
                    $image->setMedia($media);
                    $image->setPath($media->getName());
                    $image->setExtension($media->getExtension());
                    // get the main language of the shop
                    //$mainLangData = array_values(PlentymarketsTranslation::getInstance()->getShopMainLanguage($shopwareStoreId));
                    //$mainLang = PlentymarketsTranslation::getInstance()->getPlentyLocaleFormat($mainLangData[0]['locale']);
                    foreach ($Image->Names->item as $imageName) {
                        if ($imageName->Lang == 'de') {
                            // set the image title in German
                            $image->setDescription($imageName->Name);
                        }
                    }
                    if (!is_null(PlentymarketsConfig::getInstance()->getItemImageAltAttributeID()) && PlentymarketsConfig::getInstance()->getItemImageAltAttributeID() > 0 && PlentymarketsConfig::getInstance()->getItemImageAltAttributeID() <= 3) {
                        // get the attribute number for alternative text from connector's settings
                        $plenty_attributeID = PlentymarketsConfig::getInstance()->getItemImageAltAttributeID();
                        // set the value for the attribute number
                        $attribute = new \Shopware\Models\Attribute\ArticleImage();
                        call_user_func(array($attribute, 'setAttribute' . $plenty_attributeID), $Image->Names->item[0]->AlternativeText);
                        $image->setAttribute($attribute);
                    }
                    $image->setPosition($Image->Position);
                    // Generate the thumbnails
                    if (version_compare(Shopware::VERSION, '4.2') != 1) {
                        PlentymarketsImportItemImageThumbnailController::getInstance()->addMediaResource($media);
                    }
                    Shopware()->Models()->persist($image);
                    Shopware()->Models()->flush();
                    $imageId = $image->getId();
                    foreach ($shopwareStoreIds as $shopwareStoreId) {
                        // import the image title translations for all active shops of the image
                        $this->importImageTitleTranslation($imageId, $Image->Names->item, $shopwareStoreId);
                    }
                    $plentyId2ShopwareId[$Image->ImageID] = $imageId;
                    $shopwareId2PlentyPosition[$Image->Position] = $imageId;
                    Shopware()->DB()->query('
											UPDATE s_articles_img
												SET articleID = ?
												WHERE id = ?
										', array($this->SHOPWARE_itemId, $imageId));
                }
            }
        } while (++$Request_GetItemsImages->Page < $Response_GetItemsImages->Pages);
        if (empty($shopwareId2PlentyPosition)) {
            return;
        }
        ksort($shopwareId2PlentyPosition);
        $mainImageId = reset($shopwareId2PlentyPosition);
        if (empty($mainImageId)) {
            return;
        }
        /**
         * @var Shopware\Models\Article\Image $mainImage
         */
        $mainImage = Shopware()->Models()->find('Shopware\\Models\\Article\\Image', $mainImageId);
        $mainImage->setMain(1);
        Shopware()->Models()->persist($mainImage);
        Shopware()->Models()->flush();
        // Get the variant images
        $Request_GetItemsVariantImages = new PlentySoapRequest_GetItemsVariantImages();
        $Request_GetItemsVariantImages->Items = array();
        $RequestObject_GetItemsVariantImages = new PlentySoapRequestObject_GetItemsVariantImages();
        $RequestObject_GetItemsVariantImages->ItemID = $this->PLENTY_itemId;
        $Request_GetItemsVariantImages->Items[] = $RequestObject_GetItemsVariantImages;
        /**
         * @var PlentySoapResponse_GetItemsVariantImages $Response_GetItemsVariantImages
         */
        $Response_GetItemsVariantImages = PlentymarketsSoapClient::getInstance()->GetItemsVariantImages($Request_GetItemsVariantImages);
        foreach ($Response_GetItemsVariantImages->Images->item as $GetItemsVariantImagesImage) {
            try {
                $shopwareOptionId = PlentymarketsMappingController::getAttributeOptionByPlentyID($GetItemsVariantImagesImage->AttributeValueID);
                /**
                 * @var \Shopware\Models\Article\Configurator\Option $shopwareOption
                 */
                $shopwareOption = Shopware()->Models()->find('Shopware\\Models\\Article\\Configurator\\Option', $shopwareOptionId);
            } catch (PlentymarketsMappingExceptionNotExistant $e) {
                continue;
            }
            if (!isset($plentyId2ShopwareId[$GetItemsVariantImagesImage->ImageID])) {
                continue;
            }
            /** @var Shopware\Models\Article\Image $shopwareImage */
            $shopwareImageId = $plentyId2ShopwareId[$GetItemsVariantImagesImage->ImageID];
            /**
             * @var Image $shopwareImage
             */
            $shopwareImage = Shopware()->Models()->find('Shopware\\Models\\Article\\Image', $shopwareImageId);
            $mapping = new Shopware\Models\Article\Image\Mapping();
            $mapping->setImage($shopwareImage);
            $rule = new Shopware\Models\Article\Image\Rule();
            $rule->setMapping($mapping);
            $rule->setOption($shopwareOption);
            $mapping->getRules()->add($rule);
            $shopwareImage->setMappings($mapping);
            Shopware()->Models()->persist($mapping);
            $details = Shopware()->Db()->fetchCol('
				SELECT
						d.id
					FROM s_articles_details d
						INNER JOIN s_article_configurator_option_relations alias16 ON alias16.option_id = ' . $shopwareOptionId . ' AND alias16.article_id = d.id
					WHERE d.articleID = ' . $this->SHOPWARE_itemId . '
			');
            foreach ($details as $detailId) {
                /**
                 * Get the detail object
                 *
                 * @var Shopware\Models\Article\Detail $detail
                 */
                $detail = Shopware()->Models()->getReference('Shopware\\Models\\Article\\Detail', $detailId);
                // Create the variant image
                $variantImage = new Shopware\Models\Article\Image();
                $variantImage->setExtension($shopwareImage->getExtension());
                $variantImage->setMain($shopwareImage->getMain());
                $variantImage->setParent($shopwareImage);
                $variantImage->setArticleDetail($detail);
                // And persist it
                Shopware()->Models()->persist($variantImage);
            }
        }
        Shopware()->Db()->update('s_articles', array('changetime' => date('c', time())), 'id=' . $this->SHOPWARE_itemId);
        Shopware()->Models()->flush();
    }
 /**
  * Update plugin method
  *
  * @see Shopware_Components_Plugin_Bootstrap::update()
  */
 public function update($version)
 {
     $Logger = PlentymarketsLogger::getInstance();
     $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, $version . ' →  ' . $this->getVersion());
     if (version_compare($version, '1.6') !== 1) {
         try {
             PlentymarketsExportController::getInstance()->erase('ItemCategory');
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'PlentymarketsExportController::getInstance()->erase(\'ItemCategory\') done');
         } catch (Exception $E) {
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'PlentymarketsExportController::getInstance()->erase(\'ItemCategory\') failed');
         }
         try {
             Shopware()->Db()->exec("\n\t\t\t\t\tALTER TABLE `plenty_mapping_category` CHANGE `shopwareID` `shopwareID` VARCHAR(255) NOT NULL DEFAULT '';\n\t\t\t\t");
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'ALTER TABLE `plenty_mapping_category` done');
         } catch (Exception $E) {
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'ALTER TABLE `plenty_mapping_category` failed');
         }
         PyConf()->erase('PlentymarketsVersionTimestamp');
     }
     if (version_compare($version, '1.7') !== 1) {
         $this->subscribeEvent('Shopware_Models_Order_Order::postPersist', 'onOrderModelPostPersist');
         $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'Shopware_Models_Order_Order::postPersist');
         try {
             Shopware()->Db()->exec("\n\t\t\t\t\tALTER TABLE `plenty_mapping_referrer` CHANGE `plentyID` `plentyID` FLOAT(11)  UNSIGNED  NOT NULL;\n\t\t\t\t");
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'ALTER TABLE `plenty_mapping_referrer` done');
         } catch (Exception $E) {
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'ALTER TABLE `plenty_mapping_referrer` failed');
         }
     }
     if (version_compare($version, '1.7.4') !== 1) {
         PyConf()->setCheckIncomingPayment(1);
         PyConf()->setCheckOutgoingItems(1);
         PyConf()->setItemNumberSourceKey('ItemNo');
         PyConf()->setItemVariationNumberSourceKey('ColliNo');
         PlentymarketsConfig::getInstance()->setImportOrderStatusChangeLastUpdateTimestamp(time());
         $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'setCheckIncomingPayment(1)');
         $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'setCheckOutgoingItems(1)');
         $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'setImportOrderStatusChangeLastUpdateTimestamp(time())');
         $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, "setItemNumberSourceKey('ItemNo')");
         $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, "setItemVariationNumberSourceKey('ColliNo')");
         try {
             Shopware()->Db()->exec("\n\t\t\t\t\tCREATE TABLE `plenty_mapping_order_status` (\n\t\t\t\t\t  `shopwareID` int(11) NOT NULL,\n\t\t\t\t\t  `plentyID` decimal(3,1) unsigned NOT NULL,\n\t\t\t\t\t  PRIMARY KEY (`shopwareID`,`plentyID`),\n\t\t\t\t\t  UNIQUE KEY `plentyID` (`plentyID`)\n\t\t\t\t\t) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\t\t\t\t");
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'CREATE TABLE `plenty_mapping_order_status` done');
         } catch (Exception $E) {
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'CREATE TABLE `plenty_mapping_order_status` failed');
         }
         try {
             Shopware()->Db()->exec("\n\t\t\t\t\tCREATE TABLE `plenty_mapping_payment_status` (\n\t\t\t\t\t  `shopwareID` int(11) NOT NULL,\n\t\t\t\t\t  `plentyID` decimal(3,1) unsigned NOT NULL,\n\t\t\t\t\t  PRIMARY KEY (`shopwareID`,`plentyID`),\n\t\t\t\t\t  UNIQUE KEY `plentyID` (`plentyID`)\n\t\t\t\t\t) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\t\t\t\t");
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'CREATE TABLE `plenty_mapping_payment_status` done');
         } catch (Exception $E) {
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'CREATE TABLE `plenty_mapping_payment_status` failed');
         }
     }
     if (version_compare($version, '1.8.1', '<')) {
         try {
             $this->subscribeEvent('Shopware_Models_Order_Order::postPersist', 'onOrderModelPostPersist');
         } catch (Exception $e) {
             return array('success' => false, 'message' => $e->getMessage());
         }
     }
     PlentymarketsConfig::getInstance()->setConnectorVersion($this->getVersion());
     return true;
 }
 /**
  * Returns the customer group
  * @return Shopware\Models\Customer\Group
  */
 public function getCustomerGroup()
 {
     $key = PlentymarketsConfig::getInstance()->get('DefaultCustomerGroupKey');
     return Shopware()->Models()->getRepository('Shopware\\Models\\Customer\\Group')->findOneBy(array('key' => $key));
 }
 /**
  * Checks whether data may be synchronized
  *
  * @param boolean $checkExtended Perform the extended checks (memory and runtime)
  * @return boolean
  */
 public function maySynchronize($checkExtended = true)
 {
     // Export has basically the same needs
     $mayExport = $this->mayExport();
     // Export is okay
     $isExportFinished = $this->isExportFinished();
     // May Synchronize
     $maySynchronize = $mayExport && $isExportFinished;
     // User settings
     $mayDatexActual = PlentymarketsConfig::getInstance()->getMayDatexUser(0);
     //
     if (!$maySynchronize) {
         // Deactivate the sync and remember the setting
         PlentymarketsConfig::getInstance()->setMayDatex(0);
         PlentymarketsConfig::getInstance()->setMayDatexActual(0);
     } else {
         // Remember the setting and activate or deactivate the sync
         // depending on the user's choice
         PlentymarketsConfig::getInstance()->setMayDatex(1);
         PlentymarketsConfig::getInstance()->setMayDatexActual($mayDatexActual);
     }
     // status vars
     $isCli = true;
     $mayRunUnlimited = true;
     // do some extended checks whether the sync may be started
     if ($checkExtended) {
         // Check the cli
         $sapi = php_sapi_name();
         if ($sapi != 'cli') {
             $isCli = false;
             if (!$this->isCliWarningLogged) {
                 PlentymarketsLogger::getInstance()->error('System:PHP', 'The synchronizing processes have to be started with the PHP-CLI (command line interface). You are using »' . $sapi . '«.', 1001);
                 if (isset($_ENV['_'])) {
                     PlentymarketsLogger::getInstance()->error('System:PHP', 'The process is handled through »' . $_ENV['_'] . '«.', 1001);
                 }
                 if (isset($_SERVER['HTTP_REFERER'])) {
                     PlentymarketsLogger::getInstance()->error('System:PHP', 'The process is called through »' . $_SERVER['HTTP_REFERER'] . '«.', 1001);
                 }
                 $this->isCliWarningLogged = true;
             }
         }
         // Check the runtime
         $runtime = ini_get('max_execution_time');
         if ($runtime > 0) {
             $mayRunUnlimited = false;
             if (!$this->isRuntimeWarningLogged) {
                 PlentymarketsLogger::getInstance()->error('System:PHP', 'The synchronizing processes have to be started with unlimited runtime. Your runtime is limited to »' . $runtime . '« seconds.', 1002);
                 $this->isRuntimeWarningLogged = true;
             }
         }
     }
     return $maySynchronize && $mayDatexActual && $isCli && $mayRunUnlimited;
 }
 /**
  * Export the missing attribtues to plentymarkets and save the mapping
  */
 protected function doExport()
 {
     // Repository
     $Repository = Shopware()->Models()->getRepository('Shopware\\Models\\Article\\Configurator\\Group');
     // Chunk configuration
     $chunk = 0;
     $size = PlentymarketsConfig::getInstance()->getInitialExportChunkSize(PlentymarketsExportController::DEFAULT_CHUNK_SIZE);
     do {
         PlentymarketsLogger::getInstance()->message('Export:Initial:Attribute', 'Chunk: ' . ($chunk + 1));
         $Groups = $Repository->findBy(array(), null, $size, $chunk * $size);
         /** @var Shopware\Models\Article\Configurator\Group $Attribute */
         foreach ($Groups as $Attribute) {
             $Request_SetItemAttributes = new PlentySoapRequest_SetItemAttributes();
             $Object_SetItemAttribute = new PlentySoapObject_SetItemAttribute();
             $Object_SetItemAttribute->BackendName = sprintf('%s (Sw %d)', $Attribute->getName(), $Attribute->getId());
             $Object_SetItemAttribute->FrontendLang = 'de';
             $Object_SetItemAttribute->FrontendName = $Attribute->getName();
             $Object_SetItemAttribute->Position = $Attribute->getPosition();
             try {
                 $attributeIdAdded = PlentymarketsMappingController::getAttributeGroupByShopwareID($Attribute->getId());
             } catch (PlentymarketsMappingExceptionNotExistant $E) {
                 if (isset($this->PLENTY_name2ID[strtolower($Object_SetItemAttribute->BackendName)])) {
                     $attributeIdAdded = $this->PLENTY_name2ID[strtolower($Object_SetItemAttribute->BackendName)];
                 } else {
                     $Request_SetItemAttributes->Attributes[] = $Object_SetItemAttribute;
                     $Response = PlentymarketsSoapClient::getInstance()->SetItemAttributes($Request_SetItemAttributes);
                     if (!$Response->Success) {
                         throw new PlentymarketsExportException('The item attribute »' . $Object_SetItemAttribute->BackendName . '« could not be created', 2911);
                     }
                     $attributeIdAdded = (int) $Response->ResponseMessages->item[0]->SuccessMessages->item[0]->Value;
                 }
                 // Add the mapping
                 PlentymarketsMappingController::addAttributeGroup($Attribute->getId(), $attributeIdAdded);
                 $this->exportAttributeTranslations($Attribute->getId(), $attributeIdAdded);
             }
             // Values
             /** @var Shopware\Models\Article\Configurator\Option $AttributeValue */
             foreach ($Attribute->getOptions() as $AttributeValue) {
                 $Request_SetItemAttributes = new PlentySoapRequest_SetItemAttributes();
                 $Object_SetItemAttribute = new PlentySoapObject_SetItemAttribute();
                 $Object_SetItemAttribute->Id = $attributeIdAdded;
                 $Object_SetItemAttributeValue = new PlentySoapObject_SetItemAttributeValue();
                 $Object_SetItemAttributeValue->BackendName = sprintf('%s (Sw %d)', $AttributeValue->getName(), $AttributeValue->getId());
                 $Object_SetItemAttributeValue->FrontendName = $AttributeValue->getName();
                 $Object_SetItemAttributeValue->Position = $AttributeValue->getPosition();
                 $Object_SetItemAttribute->Values[] = $Object_SetItemAttributeValue;
                 $Request_SetItemAttributes->Attributes[] = $Object_SetItemAttribute;
                 try {
                     PlentymarketsMappingController::getAttributeOptionByShopwareID($AttributeValue->getId());
                 } catch (PlentymarketsMappingExceptionNotExistant $E) {
                     // Workaround
                     $checknameValue = strtolower(str_replace(',', '.', $Object_SetItemAttributeValue->BackendName));
                     if (isset($this->PLENTY_idAndValueName2ID[$attributeIdAdded][$checknameValue])) {
                         PlentymarketsMappingController::addAttributeOption($AttributeValue->getId(), $this->PLENTY_idAndValueName2ID[$attributeIdAdded][$checknameValue]);
                     } else {
                         $Response = PlentymarketsSoapClient::getInstance()->SetItemAttributes($Request_SetItemAttributes);
                         if (!$Response->Success) {
                             throw new PlentymarketsExportException('The item attribute option »' . $Object_SetItemAttributeValue->BackendName . '« could not be created', 2912);
                         }
                         foreach ($Response->ResponseMessages->item[0]->SuccessMessages->item as $MessageItem) {
                             if ($MessageItem->Key == 'AttributeValueID') {
                                 PlentymarketsMappingController::addAttributeOption($AttributeValue->getId(), $MessageItem->Value);
                                 $this->exportAttributeValuesTranslations($attributeIdAdded, $AttributeValue->getId(), $MessageItem->Value);
                             }
                         }
                     }
                 }
             }
         }
         ++$chunk;
     } while (!empty($Groups) && count($Groups) == $size);
 }
 /**
  * Returns the order referrer id
  *
  * @return integer
  */
 protected function getReferrerId()
 {
     // Sub-objects
     $Partner = $this->Order->getPartner();
     // Referrer
     if ($Partner) {
         try {
             $referrerId = PlentymarketsMappingController::getReferrerByShopwareID($Partner->getId());
         } catch (PlentymarketsMappingExceptionNotExistant $E) {
         }
     }
     return isset($referrerId) ? $referrerId : PlentymarketsConfig::getInstance()->getOrderReferrerID();
 }
    /**
     * Get the mapping data: measure units
     *
     * @return array
     */
    public function getMeasureUnit()
    {
        $rows = Shopware()->Db()->query('
					SELECT
							C.id, CONCAT(C.description, " (", C.unit, ")") name,
							C.description, C.unit,
							IFNULL(PMC.plentyID, 0) plentyID
						FROM s_core_units C
						LEFT JOIN plenty_mapping_measure_unit PMC
							ON PMC.shopwareID = C.id
						ORDER BY C.description
				')->fetchAll();
        $plentyMU = PlentymarketsConfig::getInstance()->getItemMeasureUnits();
        foreach ($rows as &$row) {
            if ($row['plentyID']) {
                $row['plentyName'] = $plentyMU[$row['plentyID']]['name'];
            } else {
                if ($this->auto) {
                    $plentyUnits = PlentymarketsConfig::getInstance()->getItemMeasureUnits();
                    foreach ($plentyUnits as $plentyData) {
                        preg_match('/(.*?) \\((.*?)\\)/', $plentyData['name'], $matches);
                        if (!is_array($matches)) {
                            $name = $plentyData['name'];
                            $unit = '';
                        } else {
                            list($match, $name, $unit) = $matches;
                        }
                        $distance = levenshtein($row['description'], $name);
                        if ($row['unit'] == $unit || $distance <= 2) {
                            $row['plentyName'] = $plentyData['name'];
                            $row['plentyID'] = $plentyData['id'];
                            PlentymarketsMappingController::addMeasureUnit($row['id'], $plentyData['id']);
                            break;
                        }
                    }
                } else {
                    $row['plentyName'] = '';
                }
            }
        }
        return $rows;
    }
    /**
     * Either deletes or deactivates all shopware item that
     * are not associated with the store id configured.
     */
    protected function pruneItems()
    {
        // Create a temporary table
        Shopware()->Db()->exec('
			CREATE TEMPORARY TABLE IF NOT EXISTS plenty_cleanup_item
				(itemId INT UNSIGNED, INDEX (itemId))
				ENGINE = MEMORY;
		');
        // Get the data from plentymarkets (for every mapped shop)
        $shopIds = Shopware()->Db()->fetchAll('
			SELECT plentyID FROM plenty_mapping_shop
		');
        foreach ($shopIds as $shopId) {
            $Request_GetItemsByStoreID = new PlentySoapRequest_GetItemsByStoreID();
            $Request_GetItemsByStoreID->Page = 0;
            $Request_GetItemsByStoreID->StoreID = $shopId['plentyID'];
            do {
                // Do the request
                $Response_GetItemsByStoreID = PlentymarketsSoapClient::getInstance()->GetItemsByStoreID($Request_GetItemsByStoreID);
                // Call failed
                if (is_null($Response_GetItemsByStoreID) || !property_exists($Response_GetItemsByStoreID, 'Items')) {
                    // Log
                    PlentymarketsLogger::getInstance()->error('Cleanup:Item', 'Aborting. GetItemsByStoreID apparently failed');
                    // Delete the temporary table
                    Shopware()->Db()->exec('
						DROP TEMPORARY TABLE plenty_cleanup_item
					');
                    return;
                }
                $itemIds = array();
                foreach ($Response_GetItemsByStoreID->Items->item as $ItemByStoreID) {
                    $itemIds[] = $ItemByStoreID->intValue;
                }
                if (empty($itemIds)) {
                    break;
                }
                // Build the sql statement
                $itemsIdsSql = implode(', ', array_map(function ($itemId) {
                    return sprintf('(%u)', $itemId);
                }, $itemIds));
                // Fill the table
                Shopware()->Db()->exec('
					INSERT IGNORE INTO plenty_cleanup_item VALUES ' . $itemsIdsSql . '
				');
            } while (++$Request_GetItemsByStoreID->Page < $Response_GetItemsByStoreID->Pages);
        }
        // Get the action
        $actionId = PlentymarketsConfig::getInstance()->getItemCleanupActionID(self::ITEM_ACTION_DEACTIVATE);
        $where = '';
        if ($actionId == self::ITEM_ACTION_DEACTIVATE) {
            $where = ' AND s_articles.active = 1';
        }
        // Get all items, that are neither in the cleanup nor the mapping table
        $Result = Shopware()->Db()->fetchAll('
			SELECT
					id
				FROM s_articles
				WHERE
					id NOT IN (
						SELECT pmi.shopwareID
							FROM plenty_cleanup_item pci
							LEFT JOIN plenty_mapping_item pmi ON pmi.plentyID = pci.itemId
							WHERE pmi.shopwareID IS NOT NULL

					) ' . $where . '
		');
        // Handle the items
        foreach ($Result as $item) {
            /** @var Shopware\Models\Article\Article $Item */
            $Item = Shopware()->Models()->find('Shopware\\Models\\Article\\Article', $item['id']);
            if (!$Item) {
                continue;
            }
            if ($actionId == self::ITEM_ACTION_DEACTIVATE) {
                if ($Item->getActive()) {
                    $Item->setActive(false);
                }
                foreach ($Item->getDetails() as $Detail) {
                    /** @var Shopware\Models\Article\Detail $Detail */
                    if ($Detail->getActive()) {
                        $Detail->setActive(false);
                        if ($Detail->getAdditionalText()) {
                            PlentymarketsLogger::getInstance()->message('Cleanup:Item', 'The item variant »' . $Item->getName() . ' (' . $Detail->getAdditionalText() . ')« with the number »' . $Detail->getNumber() . '« will be deactivated');
                        } else {
                            PlentymarketsLogger::getInstance()->message('Cleanup:Item', 'The item »' . $Item->getName() . ' with the number »' . $Detail->getNumber() . '« will be deactivated');
                        }
                    }
                }
                try {
                    Shopware()->Models()->persist($Item);
                    Shopware()->Models()->flush();
                } catch (Exception $E) {
                    PlentymarketsLogger::getInstance()->error('Cleanup:Item', 'The item »' . $Item->getName() . '« could not be completely deactivated (' . $E->getMessage() . ')', 1420);
                }
            } else {
                if ($actionId == self::ITEM_ACTION_DELETE) {
                    try {
                        $Resource = Shopware\Components\Api\Manager::getResource('Article');
                        $Resource->delete($Item->getId());
                        PlentymarketsLogger::getInstance()->message('Cleanup:Item', 'The item »' . $Item->getName() . '« with the number »' . $Item->getMainDetail()->getNumber() . '« has been deleted');
                    } catch (Exception $E) {
                        PlentymarketsLogger::getInstance()->error('Cleanup:Item', 'The item »' . $Item->getName() . '« with the number »' . $Item->getMainDetail()->getNumber() . '« could not be deleted (' . $E->getMessage() . ')', 1420);
                    }
                }
            }
        }
        // Delete the temporary table
        Shopware()->Db()->exec('
			DROP TEMPORARY TABLE plenty_cleanup_item
		');
    }
 /**
  * Deactivates the wizard
  */
 public function deactivate()
 {
     PlentymarketsConfig::getInstance()->setIsExportWizardActive(0);
 }
 /**
  * Resets the status of the export
  */
 public function reset()
 {
     $this->setStatus(self::STATUS_OPEN);
     $this->setStart(0);
     $this->setFinished(0);
     $this->setError();
     // Last chunk
     $key = sprintf('%sExportLastChunk', $this->getName());
     PlentymarketsConfig::getInstance()->erase($key);
 }
    /**
     * 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;
        }
    }
 /**
  * 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);
     }
 }
 /**
  * Update plugin method
  *
  * @see Shopware_Components_Plugin_Bootstrap::update()
  */
 public function update($version)
 {
     $Logger = PlentymarketsLogger::getInstance();
     $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, $version . ' →  ' . $this->getVersion());
     if ($version == '1.4.3') {
         try {
             // Drop unused columns from the log
             Shopware()->Db()->exec("\n\t\t\t\t\tALTER TABLE `plenty_log`\n\t\t\t\t\t\tDROP `request`,\n\t\t\t\t\t\tDROP `response`;\n\t\t\t\t");
         } catch (Exception $E) {
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'ALTER TABLE `plenty_log` (drop unused columns from the log) already carried out');
         }
     }
     if (version_compare($version, '1.4.4') !== 1) {
         try {
             Shopware()->Db()->exec("\n\t\t\t\t\tCREATE TABLE `plenty_mapping_customer_billing_address` (\n\t\t\t\t\t  `shopwareID` int(11) unsigned NOT NULL,\n\t\t\t\t\t  `plentyID` int(11) unsigned NOT NULL,\n\t\t\t\t\t  PRIMARY KEY (`shopwareID`,`plentyID`)\n\t\t\t\t\t) ENGINE=InnoDB DEFAULT CHARSET=utf8\n\t\t\t\t");
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'CREATE TABLE `plenty_mapping_customer_billing_address` done');
         } catch (Exception $E) {
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'CREATE TABLE `plenty_mapping_customer_billing_address` already carried out');
         }
         Shopware()->Db()->exec("\n\t\t\t\tTRUNCATE TABLE `plenty_mapping_customer`\n\t\t\t");
         $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'TRUNCATE TABLE `plenty_mapping_customer` done');
         Shopware()->Db()->exec("\n\t\t\t\tDELETE FROM `plenty_config` WHERE `key` LIKE 'CustomerExport%'\n\t\t\t");
         $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'DELETE FROM `plenty_config` done');
     }
     if (version_compare($version, '1.4.5') !== 1) {
         try {
             $this->addMappingCleanupCronEvent();
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'addMappingCleanupCronEvent done');
         } catch (Exception $E) {
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'addMappingCleanupCronEvent already carried out');
         }
     }
     if (version_compare($version, '1.4.7') !== 1) {
         if (PlentymarketsConfig::getInstance()->getItemExportStatus() == 'success') {
             PlentymarketsConfig::getInstance()->setItemCrossSellingExportStatus('success');
             PlentymarketsConfig::getInstance()->setItemCrossSellingExportTimestampStart(time());
             PlentymarketsConfig::getInstance()->setItemCrossSellingExportTimestampFinished(time());
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'Item cross selling export marked as done');
         }
     }
     if (version_compare($version, '1.4.8') !== 1) {
         $this->addItemImportStackCronEvent();
         $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'addItemImportStackCronEvent done');
         try {
             Shopware()->Db()->exec("\n\t\t\t\t\tCREATE TABLE `plenty_stack_item` (\n\t\t\t\t\t  `itemId` int(11) unsigned NOT NULL,\n\t\t\t\t\t  `timestamp` int(10) unsigned NOT NULL,\n\t\t\t\t\t  `storeIds` text NOT NULL,\n\t\t\t\t\t  PRIMARY KEY (`itemId`),\n\t\t\t\t\t  KEY `timestamp` (`timestamp`)\n\t\t\t\t\t) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\t\t\t\t");
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'CREATE TABLE `plenty_stack_item` done');
         } catch (Exception $E) {
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'CREATE TABLE `plenty_stack_item` already carried out');
         }
         try {
             Shopware()->Db()->exec("\n\t\t\t\t\tUPDATE plenty_config\n\t\t\t\t\t\tSET `key` = 'ImportItemStackLastUpdateTimestamp'\n\t\t\t\t\t\tWHERE `key` = 'ImportItemLastUpdateTimestamp'\n\t\t\t\t");
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'UPDATE plenty_config (ImportItemStackLastUpdateTimestamp) done');
         } catch (Exception $E) {
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'UPDATE plenty_config (ImportItemStackLastUpdateTimestamp) failed');
         }
     }
     if (version_compare($version, '1.4.12') !== 1) {
         try {
             Shopware()->Db()->exec("\n\t\t\t\t\tALTER TABLE `plenty_log` ADD `code` INT  UNSIGNED  NULL  DEFAULT NULL  AFTER `message`;\n\t\t\t\t");
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'ALTER TABLE `plenty_log` ADD `code` done');
         } catch (Exception $E) {
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'ALTER TABLE `plenty_log` ADD `code` already carried out');
         }
     }
     if (version_compare($version, '1.4.14') !== 1) {
         $this->addLogCleanupCronEvent();
     }
     if (version_compare($version, '1.4.18') !== 1) {
         $this->addItemAssociateUpdateCronEvent();
     }
     if (version_compare($version, '1.4.22') !== 1) {
         try {
             Shopware()->Db()->exec("\n\t\t\t\t\tCREATE TABLE `plenty_mapping_item_bundle` (\n\t\t\t\t\t  `shopwareID` int(11) unsigned NOT NULL,\n\t\t\t\t\t  `plentyID` int(11) unsigned NOT NULL,\n\t\t\t\t\t  PRIMARY KEY (`shopwareID`,`plentyID`),\n\t\t\t\t\t  UNIQUE KEY `plentyID` (`plentyID`)\n\t\t\t\t\t) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\t\t\t\t");
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'CREATE TABLE `plenty_mapping_item_bundle` done');
         } catch (Exception $E) {
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'CREATE TABLE `plenty_mapping_item_bundle` failed');
         }
         $this->addItemBundleCronEvents();
     }
     if (version_compare($version, '1.6') !== 1) {
         try {
             PlentymarketsExportController::getInstance()->erase('ItemCategory');
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'PlentymarketsExportController::getInstance()->erase(\'ItemCategory\') done');
         } catch (Exception $E) {
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'PlentymarketsExportController::getInstance()->erase(\'ItemCategory\') failed');
         }
         try {
             Shopware()->Db()->exec("\n\t\t\t\t\tALTER TABLE `plenty_mapping_category` CHANGE `shopwareID` `shopwareID` VARCHAR(255) NOT NULL DEFAULT '';\n\t\t\t\t");
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'ALTER TABLE `plenty_mapping_category` done');
         } catch (Exception $E) {
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'ALTER TABLE `plenty_mapping_category` failed');
         }
         PyConf()->erase('PlentymarketsVersionTimestamp');
     }
     if (version_compare($version, '1.7') !== 1) {
         $this->subscribeEvent('Shopware_Models_Order_Order::postPersist', 'onOrderModelPostPersist');
         $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'Shopware_Models_Order_Order::postPersist');
         try {
             Shopware()->Db()->exec("\n\t\t\t\t\tALTER TABLE `plenty_mapping_referrer` CHANGE `plentyID` `plentyID` FLOAT(11)  UNSIGNED  NOT NULL;\n\t\t\t\t");
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'ALTER TABLE `plenty_mapping_referrer` done');
         } catch (Exception $E) {
             $Logger->message(PlentymarketsLogger::PREFIX_UPDATE, 'ALTER TABLE `plenty_mapping_referrer` failed');
         }
     }
     //
     PlentymarketsConfig::getInstance()->setConnectorVersion($this->getVersion());
     return true;
 }
 /**
  * Generates the item price SOAP object
  *
  * @return PlentySoapObject_ItemPriceSet
  */
 protected function getObjectPriceSet()
 {
     //
     $MainDetail = $this->SHOPWARE_Article->getMainDetail();
     $Unit = $MainDetail->getUnit();
     $Tax = $this->SHOPWARE_Article->getTax();
     //
     $Object_ItemPriceSet = new PlentySoapObject_ItemPriceSet();
     $Object_ItemPriceSet->HeightInMM = $MainDetail->getHeight() * 100;
     // int
     $Object_ItemPriceSet->LengthInMM = $MainDetail->getLen() * 100;
     $Object_ItemPriceSet->Lot = $MainDetail->getPurchaseUnit();
     // float
     $Object_ItemPriceSet->PackagingUnit = $MainDetail->getReferenceUnit();
     $Object_ItemPriceSet->PurchasePriceNet = null;
     // float
     $Object_ItemPriceSet->TypeOfPackage = null;
     // int
     $Object_ItemPriceSet->Unit1 = $MainDetail->getPackUnit();
     $Object_ItemPriceSet->WeightInGramm = $MainDetail->getWeight() * 1000;
     $Object_ItemPriceSet->WidthInMM = $MainDetail->getWidth() * 100;
     // int
     if ($Unit instanceof \Shopware\Models\Article\Unit && $Unit->getId() > 0) {
         $Object_ItemPriceSet->Unit = PlentymarketsMappingController::getMeasureUnitByShopwareID($Unit->getId());
         // string
     }
     $prices = array();
     $ItemPrice = Shopware()->Models()->getRepository('Shopware\\Models\\Article\\Price');
     /** @var Shopware\Models\Article\Price $ItemPrice */
     foreach ($ItemPrice->findBy(array('customerGroupKey' => PlentymarketsConfig::getInstance()->getDefaultCustomerGroupKey(), 'articleDetailsId' => $MainDetail->getId())) as $ItemPrice) {
         $price = array();
         $price['to'] = $ItemPrice->getTo();
         $price['price'] = $ItemPrice->getPrice() * ($Tax->getTax() + 100) / 100;
         $price['rrp'] = $ItemPrice->getPseudoPrice() * ($Tax->getTax() + 100) / 100;
         $price['pp'] = $MainDetail->getPurchasePrice();
         $prices[$ItemPrice->getFrom()] = $price;
     }
     //
     ksort($prices);
     //
     $n = 0;
     foreach ($prices as $from => $p) {
         // The base price
         if ($from == 1) {
             $Object_ItemPriceSet->RRP = $p['rrp'];
             $Object_ItemPriceSet->Price = $p['price'];
             $Object_ItemPriceSet->PurchasePriceNet = $p['pp'];
         } else {
             $priceIndex = 'Price' . ($n + 5);
             $Object_ItemPriceSet->{$priceIndex} = $p['price'];
             $rebateLevel = 'RebateLevelPrice' . ($n + 5);
             $Object_ItemPriceSet->{$rebateLevel} = $from;
         }
         ++$n;
     }
     return $Object_ItemPriceSet;
 }
 /**
  * Configures the chunk settings
  */
 protected function configure()
 {
     // Items per chunk
     $this->sizeOfChunk = (int) PlentymarketsConfig::getInstance()->getInitialExportChunkSize(PlentymarketsExportController::DEFAULT_CHUNK_SIZE);
 }
 /**
  * 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);
     }
 }
 /**
  * Retrieves the plentymarkets version
  */
 public static function checkPlentymarketsVersion()
 {
     $timestamp = PlentymarketsConfig::getInstance()->getPlentymarketsVersionTimestamp(0);
     if ($timestamp < strtotime('- 12 hours')) {
         $Response = PlentymarketsSoapClient::getInstance()->GetPlentymarketsVersion();
         PlentymarketsConfig::getInstance()->setPlentymarketsVersion($Response->PlentyVersion);
         PlentymarketsConfig::getInstance()->setPlentymarketsVersionTimestamp(time());
     }
 }
 /**
  * If an instance of PlentymarketsConfig exists, it returns this instance.
  * Else it creates a new instance of PlentymarketsConfig.
  *
  * @return PlentymarketsConfig
  */
 public static function getInstance()
 {
     if (!self::$Instance instanceof self) {
         self::$Instance = new self();
     }
     return self::$Instance;
 }
 /**
  * Loads the plenty mapping data
  */
 public function getPlentyMappingDataAction()
 {
     $forceReload = $this->Request()->get('force', false);
     switch ($this->Request()->map) {
         case 'Country':
             $data = PlentymarketsConfig::getInstance()->getMiscCountriesSorted();
             break;
         case 'Currency':
             $data = PlentymarketsConfig::getInstance()->getMiscCurrenciesSorted();
             break;
         case 'MeasureUnit':
             $data = PlentymarketsConfig::getInstance()->getItemMeasureUnits();
             break;
         case 'Vat':
             if ($forceReload) {
                 PlentymarketsConfig::getInstance()->setMiscVatLastImport(0);
             }
             $data = PlentymarketsImportController::getVatList();
             break;
         case 'Referrer':
             if ($forceReload) {
                 PlentymarketsConfig::getInstance()->setMiscSalesOrderReferrerLastImport(0);
             }
             $data = PlentymarketsImportController::getOrderReferrerList();
             break;
         case 'ShippingProfile':
             if ($forceReload) {
                 PlentymarketsConfig::getInstance()->setMiscShippingProfilesLastImport(0);
             }
             $data = PlentymarketsImportController::getShippingProfileList();
             break;
         case 'MethodOfPayment':
             if ($forceReload) {
                 PlentymarketsConfig::getInstance()->setMiscMethodsOfPaymentLastImport(0);
             }
             $data = PlentymarketsImportController::getMethodOfPaymentList();
             break;
         case 'CustomerClass':
             if ($forceReload) {
                 PlentymarketsConfig::getInstance()->setMiscCustomerClassLastImport(0);
             }
             $data = PlentymarketsImportController::getCustomerClassList();
             break;
         case 'Shop':
             if ($forceReload) {
                 PlentymarketsConfig::getInstance()->setMiscMultishopsLastImport(0);
             }
             $data = PlentymarketsImportController::getStoreList();
             break;
         case 'OrderStatus':
         case 'PaymentStatus':
             if ($forceReload) {
                 PlentymarketsConfig::getInstance()->setMiscOrderStatusLastImport(0);
             }
             $data = PlentymarketsImportController::getOrderStatusList();
             foreach ($data as &$d) {
                 $d['id'] = $d['status'];
             }
             break;
     }
     $this->View()->assign(array('success' => true, 'data' => array_values($data)));
 }
 /**
  * Reads the items of plentymarkets that have changed
  */
 public function run()
 {
     // Number of items
     $chunkSize = PlentymarketsConfig::getInstance()->getImportItemChunkSize(self::DEFAULT_CHUNK_SIZE);
     // get the chunk out of the stack
     $chunk = PlentymarketsImportStackItem::getInstance()->getChunk($chunkSize);
     // Import each item
     try {
         while (($item = array_shift($chunk)) && is_array($item)) {
             // for each assigned store
             $storeIds = explode('|', $item['storeIds']);
             foreach ($storeIds as $storeId) {
                 // Import the item
                 $this->importItem($item['itemId'], $storeId);
             }
         }
     } catch (PlentymarketsImportException $E) {
         PlentymarketsLogger::getInstance()->error('Sync:Item', $E->getMessage(), $E->getCode());
         // return to the stack
         foreach ($chunk as $item) {
             // for each assigned store
             $storeIds = explode('|', $item['storeIds']);
             foreach ($storeIds as $storeId) {
                 // Import the item
                 PlentymarketsImportStackItem::getInstance()->addItem($item['itemId'], $storeId);
             }
         }
         PlentymarketsLogger::getInstance()->message('Sync:Stack:Item', 'Returned ' . count($chunk) . ' items to the stack');
     }
     $numberOfItems = count($this->itemIdsDone);
     // Log
     if ($numberOfItems == 0) {
         PlentymarketsLogger::getInstance()->message('Sync:Item', 'No item has been updated or created.');
     } else {
         if ($numberOfItems == 1) {
             PlentymarketsLogger::getInstance()->message('Sync:Item', '1 item has been updated or created.');
         } else {
             PlentymarketsLogger::getInstance()->message('Sync:Item', $numberOfItems . ' items have been updated or created.');
         }
     }
     // Log stack information
     $stackSize = count(PlentymarketsImportStackItem::getInstance());
     if ($stackSize == 1) {
         PlentymarketsLogger::getInstance()->message('Sync:Stack:Item', '1 item left in the stack');
     } else {
         if ($stackSize > 1) {
             PlentymarketsLogger::getInstance()->message('Sync:Stack:Item', $stackSize . ' items left in the stack');
         } else {
             PlentymarketsLogger::getInstance()->message('Sync:Stack:Item', 'The stack is empty');
         }
     }
     // Post processed
     $this->finish();
 }