/**
     * 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);
    }
 /**
  * Returns an instance
  *
  * @return PlentymarketsLogger
  */
 public static function getInstance()
 {
     if (!self::$Instance instanceof self) {
         self::$Instance = new self();
     }
     return self::$Instance;
 }
 /**
  * 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.');
         }
     }
 }
    /**
     * Runs the export of the orders
     */
    public function run()
    {
        // Get all the orders, that are not yet exported to plentymarkets
        $Result = Shopware()->Db()->query('
			SELECT
					shopwareId, numberOfTries, timestampLastTry
				FROM plenty_order
				WHERE plentyOrderId IS NULL
		');
        while (($Order = $Result->fetchObject()) && is_object($Order)) {
            if ($Order->numberOfTries > 1000) {
                continue;
            }
            if (!is_null($Order->timestampLastTry) && strtotime($Order->timestampLastTry) > time() - 60 * 15) {
                continue;
            }
            try {
                $PlentymarketsExportEntityOrder = new PlentymarketsExportEntityOrder($Order->shopwareId);
                $PlentymarketsExportEntityOrder->export();
            } catch (PlentymarketsExportEntityException $E) {
                PlentymarketsLogger::getInstance()->error('Export:Order', $E->getMessage(), $E->getCode());
            }
        }
    }
 /**
  * Performes a SOAP call
  *
  * @see SoapClient::__call()
  */
 public function __call($call, $args)
 {
     $retries = 0;
     do {
         try {
             // Call
             $Response = $this->doCall($call, $args);
             // Quit the loop on success
             break;
         } catch (Exception $E) {
             ++$retries;
             // Calculate seconds based on the number of retries
             $seconds = self::NUMBER_OF_SECONDS_SLEEP * $retries;
             // Try to get a new token
             if ($E->getMessage() == 'Unauthorized Request - Invalid Token') {
                 // Log the error
                 PlentymarketsLogger::getInstance()->error('Soap:Call', $call . ' failed: Unauthorized Request - Invalid Token', 1110);
                 // Refresh the token
                 $this->getToken();
                 $this->setSoapHeaders();
             } else {
                 PlentymarketsLogger::getInstance()->message('Soap:Call', $call . ' will wait ' . $seconds . ' seconds and then try again (' . $retries . '/' . self::NUMBER_OF_RETRIES_MAX . ')');
                 sleep($seconds);
             }
         }
     } while ($retries < self::NUMBER_OF_RETRIES_MAX);
     // Log the call's success state
     if (isset($Response->Success) && $Response->Success == true) {
         if ($call == 'GetServerTime') {
             if (!$this->Config->getApiIgnoreGetServerTime()) {
                 PlentymarketsLogger::getInstance()->message('Soap:Call', 'GetServerTime success');
             }
         } else {
             PlentymarketsLogger::getInstance()->message('Soap:Call', $call . ' success');
         }
         // Remember the timestamp
         if (!empty($this->timestampConfigKey)) {
             $this->Config->set($this->timestampConfigKey, time());
         }
     } else {
         PlentymarketsLogger::getInstance()->error('Soap:Call', $call . ' failed', 1100);
         if (isset($Response) && $this->Config->getApiLogHttpHeaders(false)) {
             PlentymarketsLogger::getInstance()->error('Soap:Call', var_export($Response, true));
         }
         if (isset($E) && $E instanceof Exception) {
             PlentymarketsLogger::getInstance()->error('Soap:Call:Request', htmlspecialchars($this->__getLastRequest()));
             PlentymarketsLogger::getInstance()->error('Soap:Call', $E->getMessage());
         }
     }
     // Log the HTTP headers?
     if ($this->Config->getApiLogHttpHeaders(false)) {
         PlentymarketsLogger::getInstance()->message('Soap:Call:Header:Request', $this->__getLastRequestHeaders());
         PlentymarketsLogger::getInstance()->message('Soap:Call:Header:Response', $this->__getLastResponseHeaders());
     }
     ++$this->numberOfCalls;
     return $Response;
 }
 /**
  * Loads the log identifiers
  */
 public function getLogIdentifierListAction()
 {
     $this->View()->assign(array('success' => true, 'data' => PlentymarketsLogger::getInstance()->getIdentifierList()));
 }
 /**
  * Exports images, variants, properties item data and items base to make sure, that the corresponding items data exist.
  */
 protected function export()
 {
     // Repository
     $Repository = Shopware()->Models()->getRepository('Shopware\\Models\\Customer\\Customer');
     // Chunk configuration
     $chunk = 0;
     do {
         PlentymarketsLogger::getInstance()->message('Export:Initial:Customer', 'Chunk: ' . ($chunk + 1));
         $Customers = $Repository->findBy(array(), null, $this->sizeOfChunk, $chunk * $this->sizeOfChunk);
         /** @var Shopware\Models\Customer\Customer $Customer */
         foreach ($Customers as $Customer) {
             try {
                 $PlentymarketsExportEntityItem = new PlentymarketsExportEntityCustomer($Customer);
                 $PlentymarketsExportEntityItem->export();
             } catch (PlentymarketsExportEntityException $E) {
                 PlentymarketsLogger::getInstance()->error('Export:Initial:Customer', $E->getMessage(), $E->getCode());
             }
         }
         ++$chunk;
     } while (!empty($Customers) && count($Customers) == $this->sizeOfChunk);
 }
 /**
  * Update the prices for a variant
  *
  * @param integer $detailId
  * @return bool
  */
 public function updateVariant($detailId)
 {
     $Detail = Shopware()->Models()->find('Shopware\\Models\\Article\\Detail', $detailId);
     if (!$Detail instanceof Shopware\Models\Article\Detail) {
         return PlentymarketsLogger::getInstance()->error('Sync:Item:Price', 'The price of the item detail with the id »' . $detailId . '« could not be updated (item corrupt)', 3610);
     }
     $currentPrice = $this->PLENTY_PriceSet->Price + $this->PLENTY_markup;
     $Article = $Detail->getArticle();
     $ArticleResource = \Shopware\Components\Api\Manager::getResource('Article');
     // Update
     $ArticleResource->update($Article->getId(), array('variants' => array(array('number' => $Detail->getNumber(), 'prices' => $this->getPrices()))));
     PyLog()->message('Sync:Item:Price', 'The price of the variant with the number »' . $Detail->getNumber() . '« has been set to »' . money_format('%.2n', $currentPrice) . '«.');
 }
 /**
  * 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);
 }
 /**
  * Exports the items of the bundle
  *
  * todo: max 50
  * todo: analyse response
  */
 protected function exportItems()
 {
     $Request_AddItemsToBundle = new PlentySoapRequest_AddItemsToBundle();
     $Request_AddItemsToBundle->Bundles = array();
     $Object_AddBundle = new PlentySoapObject_AddBundle();
     $Object_AddBundle->BundleItems = array();
     foreach ($this->PLENTY_bundleSkuList as $sku => $quantity) {
         $Object_AddBundleItem = new PlentySoapObject_AddBundleItem();
         $Object_AddBundleItem->ItemSKU = $sku;
         $Object_AddBundleItem->Quantity = $quantity;
         $Object_AddBundle->BundleItems[] = $Object_AddBundleItem;
     }
     $Object_AddBundle->BundleSKU = $this->PLENTY_bundleHeadId;
     // string
     $Request_AddItemsToBundle->Bundles[] = $Object_AddBundle;
     PlentymarketsSoapClient::getInstance()->AddItemsToBundle($Request_AddItemsToBundle);
     $numberAdded = count($Object_AddBundle->BundleItems);
     PlentymarketsLogger::getInstance()->message('Export:Initial:Item:Bundle', $numberAdded . ' items have been added to the item bundle with the number »' . $this->SHOPWARE_bundle->getNumber() . '«.');
 }
 /**
  * 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();
 }
    /**
     * Deletes a page of invalid data
     *
     * @param integer $start
     * @param integer $offset
     */
    public function deleteInvalidData($start, $offset)
    {
        foreach ($this->getInvalidData($start, $offset) as $data) {
            try {
                $Item = Shopware()->Models()->find('\\Shopware\\Models\\Article\\Detail', $data['detailsId']);
                Shopware()->Models()->remove($Item);
            } catch (Exception $E) {
                PlentymarketsLogger::getInstance()->error(__LINE__ . __METHOD__, $E->getMessage());
                foreach (explode('|', $data['optionIds']) as $optionId) {
                    Shopware()->Db()->query('
						DELETE FROM s_article_configurator_option_relations
							WHERE
								article_id = ? AND
								option_id = ?
							LIMIT 1
					', array($data['detailsId'], $optionId));
                }
            }
        }
        Shopware()->Models()->flush();
    }
 /**
  * Updates the stack
  */
 public function update()
 {
     PlentymarketsLogger::getInstance()->message('Sync:Stack:Item', 'Starting update');
     $ShopRepository = Shopware()->Models()->getRepository('Shopware\\Models\\Shop\\Shop');
     $Shops = $ShopRepository->findBy(array('active' => 1), array('default' => 'DESC'));
     // Remember the time
     $timestamp = time();
     // Is this the first run?
     $firstBlood = (int) PlentymarketsConfig::getInstance()->getImportItemStackFirstRunTimestamp() == 0;
     $Request_GetItemsUpdated = new PlentySoapRequest_GetItemsUpdated();
     $Request_GetItemsUpdated->LastUpdateFrom = (int) PlentymarketsConfig::getInstance()->getImportItemStackLastUpdateTimestamp();
     // Cache to avoid duplicate inserts of the same id with multiple shops
     $itemIdsStacked = array();
     /** @var Shopware\Models\Shop\Shop $Shop */
     foreach ($Shops as $Shop) {
         $Request_GetItemsUpdated->Page = 0;
         $Request_GetItemsUpdated->StoreID = PlentymarketsMappingController::getShopByShopwareID($Shop->getId());
         do {
             // Do the request
             $Response_GetItemsUpdated = PlentymarketsSoapClient::getInstance()->GetItemsUpdated($Request_GetItemsUpdated);
             foreach ((array) $Response_GetItemsUpdated->Items->item as $Object_Integer) {
                 $itemId = $Object_Integer->intValue;
                 // Skip existing items on the first run
                 if ($Request_GetItemsUpdated->LastUpdateFrom == 0 && $firstBlood) {
                     try {
                         PlentymarketsMappingController::getItemByPlentyID($itemId);
                         continue;
                     } catch (PlentymarketsMappingExceptionNotExistant $E) {
                     }
                 }
                 $this->addItem($itemId, $Request_GetItemsUpdated->StoreID);
                 $itemIdsStacked[$itemId] = true;
             }
         } while (++$Request_GetItemsUpdated->Page < $Response_GetItemsUpdated->Pages);
     }
     // Upcomming last update timestamp
     PlentymarketsConfig::getInstance()->setImportItemStackLastUpdateTimestamp($timestamp);
     if ($firstBlood) {
         // Remember your very first time :)
         PlentymarketsConfig::getInstance()->setImportItemStackFirstRunTimestamp(time());
     }
     // Log
     $numberOfItemsStacked = count($itemIdsStacked);
     if (!$numberOfItemsStacked) {
         PlentymarketsLogger::getInstance()->message('Sync:Stack:Item', 'No item has been added to the stack');
     } else {
         if ($numberOfItemsStacked == 1) {
             PlentymarketsLogger::getInstance()->message('Sync:Stack:Item', '1 item has been added to the stack');
         } else {
             PlentymarketsLogger::getInstance()->message('Sync:Stack:Item', count($itemIdsStacked) . ' items have been added to the stack');
         }
     }
     PlentymarketsLogger::getInstance()->message('Sync:Stack:Item', 'Update finished');
 }
 /**
  * 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();
     // Look on my works, ye Mighty, and despair!'
     $ozymandias = isset($_ENV['ozymandias']) || isset($_SERVER['QUERY_STRING']) && $_SERVER['QUERY_STRING'] == 'ozymandias';
     // Check the license
     if (true || $ozymandias) {
         $isLicenseValid = true;
     } else {
         if (Shopware()->Bootstrap()->issetResource('License')) {
             $License = Shopware()->License();
             $isLicenseValid = $License->checkCoreLicense(false);
             if (!$isLicenseValid && !$this->isLicenseWarningLogged) {
                 PlentymarketsLogger::getInstance()->error('System:License', 'The shopware license that is used is invalid or has expired. No synchronization will be performed.', 1010);
                 $this->isLicenseWarningLogged = true;
             }
         } else {
             $isLicenseValid = false;
             if (!$this->isLicenseWarningLogged) {
                 PlentymarketsLogger::getInstance()->error('System:License', 'The license mananger is not installed. Therefore, it is not possible to check the license. No synchronization will be performed.', 1011);
                 $this->isLicenseWarningLogged = true;
             }
         }
     }
     // May Synchronize
     $maySynchronize = $mayExport && $isExportFinished && $isLicenseValid;
     // 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 && !$ozymandias) {
         // 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;
 }
 /**
  * Starts the actual pending export.
  *
  * @throws PlentymarketsExportException
  */
 public function export()
 {
     if ($this->isRunning == true) {
         throw new PlentymarketsExportException('Another export is running at this very moment', 2510);
     }
     // Check whether settings and mapping is complete
     if ($this->mayRun == false) {
         throw new PlentymarketsExportException('Either the mapping or the settings is not finished or the data integrity is not valid', 2520);
     }
     // Get the pending entity
     $entity = $this->Config->getExportEntityPending(false);
     // No exception.. or the log will ne spammed
     if ($entity == false) {
         return;
     }
     // Set the running flag and delete the last call timestmap and the pending entity
     $this->Config->setIsExportRunning(1);
     $this->Config->eraseExportEntityPending();
     $this->Config->eraseInitialExportLastCallTimestamp();
     // Configure the SOAP client to log the timestamp of the calls from now on
     PlentymarketsSoapClient::getInstance()->setTimestampConfigKey('InitialExportLastCallTimestamp');
     // Log the start
     PlentymarketsLogger::getInstance()->message('Export:Initial:' . $entity, 'Starting');
     // Get the entity status object
     $Status = $this->StatusController->getEntity($entity);
     // Set running
     $Status->setStatus(PlentymarketsExportStatus::STATUS_RUNNING);
     // Set the start timestamp if that hasn't already been done
     if ((int) $Status->getStart() <= 0) {
         $Status->setStart(time());
     }
     try {
         // Get the controller
         $class = sprintf('PlentymarketsExportController%s', $entity);
         // and run it
         $Instance = new $class();
         $Instance->run();
         // Log that we are done
         PlentymarketsLogger::getInstance()->message('Export:Initial:' . $entity, 'Done!');
         // If the export is finished
         if ($Instance->isFinished()) {
             // set the success status and the finished timestamp
             $Status->setStatus(PlentymarketsExportStatus::STATUS_SUCCESS);
             $Status->setFinished(time());
         } else {
             // otherwise re-announce the entity for the next run
             $this->Config->setExportEntityPending($Status->getName());
             $Status->setStatus(PlentymarketsExportStatus::STATUS_PENDING);
         }
     } catch (PlentymarketsExportException $E) {
         // Log and save the error
         PlentymarketsLogger::getInstance()->error('Export:Initial:' . $entity, $E->getMessage(), $E->getCode());
         $Status->setError($E->getMessage());
     }
     // Reconfigure the soap client
     PlentymarketsSoapClient::getInstance()->setTimestampConfigKey(null);
     // Erase the timestamp of the latest export call
     $this->Config->eraseInitialExportLastCallTimestamp();
     // Reset the running flag
     $this->Config->setIsExportRunning(0);
 }
 /**
  * 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;
 }
 /**
  * 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 magic :)
  */
 public function conjure()
 {
     //
     if (!$this->isActive()) {
         return;
     }
     // If there is nothing to do for the wizzard
     if ($this->StatusController->isBroke()) {
         // Deactivate
         $this->deactivate();
         // Log
         PlentymarketsLogger::getInstance()->message('Export:Initial:Wizard', 'Automatically disabled because an entity is broke');
         return;
     }
     // If there is nothing to do for the wizzard
     if ($this->StatusController->isFinished()) {
         // Deactivate
         $this->deactivate();
         // Log
         PlentymarketsLogger::getInstance()->message('Export:Initial:Wizard', 'Automatically disabled because there is nothing more to do');
         return;
     }
     // Entity is already waiting (item chunks)
     if ($this->StatusController->isWaiting()) {
         // Log
         PlentymarketsLogger::getInstance()->message('Export:Initial:Wizard', 'An entity is already waiting');
         return;
     }
     try {
         // Get the next entity
         $EntityStatus = $this->StatusController->getNext();
         // and announce it
         PlentymarketsExportController::getInstance()->announce($EntityStatus->getName());
         // Log
         PlentymarketsLogger::getInstance()->message('Export:Initial:Wizard', 'Automatically announced ' . $EntityStatus->getName());
     } catch (PlentymarketsExportException $E) {
         PlentymarketsLogger::getInstance()->error('Export:Initial:Wizard', $E->getMessage(), $E->getCode());
         $this->deactivate();
     } catch (PlentymarketsExportStatusException $E) {
         PlentymarketsLogger::getInstance()->error('Export:Initial:Wizard', $E->getMessage(), $E->getCode());
         $this->deactivate();
     }
 }
    /**
     * @description Set the translation for the object for the language shops
     * @param string $type
     * @param int $objectId
     * @param int $languageShopId
     * @param array $data
     */
    public static function setShopwareTranslation($type, $objectId, $languageShopId, $data)
    {
        $sw4_sql = null;
        $sw5_sql = null;
        try {
            $sql = 'SHOW FULL COLUMNS FROM `s_core_translations`;';
            $Result = Shopware()->Db()->query($sql);
            $lastColumn = array_pop($Result->fetchAll());
            if ($lastColumn['Field'] == 'dirty') {
                // create sql query for saving the translation for shopware version 5
                // !!! objectlanguage = language shopId
                // !!! objectkey = object Id (e.g. article Id)
                $sw5_sql = 'INSERT INTO `s_core_translations` (
				`objecttype`, `objectdata`, `objectkey`, `objectlanguage`,  `dirty`
				) VALUES (
				?, ?, ?, ?,?
				) ON DUPLICATE KEY UPDATE `objectdata`=VALUES(`objectdata`);
				';
            } elseif ($lastColumn['Field'] == 'objectlanguage') {
                // create sql query for saving the translation for shopware version 4
                // !!! objectkey = object Id (e.g. article Id)
                $sw4_sql = 'INSERT INTO `s_core_translations` (
				`objecttype`, `objectdata`, `objectkey`, `objectlanguage`
				) VALUES (
				?, ?, ?, ?
				) ON DUPLICATE KEY UPDATE `objectdata`=VALUES(`objectdata`);
				';
            }
        } catch (Exception $e) {
            PlentymarketsLogger::getInstance()->error('Sync:Translation', 'The translation could not be imported » shopware version » (' . $e->getMessage() . ')', 3020);
        }
        try {
            if (isset($sw5_sql)) {
                // try saving the translation for shopware version 5
                Shopware()->Db()->query($sw5_sql, array($type, serialize($data), $objectId, $languageShopId, 1));
            } elseif (isset($sw4_sql)) {
                // try saving the translation for shopware version 4
                Shopware()->Db()->query($sw4_sql, array($type, serialize($data), $objectId, $languageShopId));
            } else {
                PlentymarketsLogger::getInstance()->error('Sync:Translation', 'The translation could not be imported » shopware version', 3020);
                return;
            }
            Shopware\Components\Api\Manager::getResource('Translation')->flush();
        } catch (Shopware\Components\Api\Exception\OrmException $E) {
            PlentymarketsLogger::getInstance()->error('Sync:Translation', 'The translation type » ' . $type . ' «  for shopId » ' . $languageShopId . '« has been imported with errors (' . $E->getMessage() . ')', 3020);
        }
    }
 /**
  * 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;
 }
 /**
  * Exports the customer
  */
 protected function exportCustomer()
 {
     if (is_null($this->BillingAddress)) {
         throw new PlentymarketsExportEntityException('The customer with the email address »' . $this->Customer->getEmail() . '« could not be exported (no billing address)', 2100);
     }
     try {
         if ($this->BillingAddress instanceof \Shopware\Models\Customer\Billing) {
             $this->PLENTY_customerID = PlentymarketsMappingController::getCustomerBillingAddressByShopwareID($this->BillingAddress->getId());
         } else {
             if ($this->BillingAddress instanceof \Shopware\Models\Order\Billing) {
                 $this->PLENTY_customerID = PlentymarketsMappingController::getCustomerByShopwareID($this->BillingAddress->getId());
             }
         }
         // Already exported
         return;
     } catch (PlentymarketsMappingExceptionNotExistant $E) {
     }
     // Logging
     PlentymarketsLogger::getInstance()->message('Export:Customer', 'Export of the customer with the number »' . $this->getCustomerNumber() . '«');
     $city = trim($this->BillingAddress->getCity());
     $street_arr = PlentymarketsUtils::extractStreetAndHouseNo($this->BillingAddress->getStreet());
     if (isset($street_arr['street']) && strlen($street_arr['street']) > 0) {
         $streetName = $street_arr['street'];
     } else {
         $streetName = trim($this->BillingAddress->getStreet());
     }
     if (isset($street_arr['houseNo']) && strlen($street_arr['houseNo']) > 0) {
         $streetHouseNumber = $street_arr['houseNo'];
     } else {
         //no house number was found in the street string
         $streetHouseNumber = '';
     }
     $zip = trim($this->BillingAddress->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_SetCustomers = new PlentySoapRequest_SetCustomers();
     $Request_SetCustomers->Customers = array();
     $Object_SetCustomersCustomer = new PlentySoapObject_Customer();
     $Object_SetCustomersCustomer->City = $city;
     $Object_SetCustomersCustomer->Company = $this->BillingAddress->getCompany();
     $Object_SetCustomersCustomer->CountryID = $this->getBillingCountryID();
     // int
     $Object_SetCustomersCustomer->CustomerClass = $this->getCustomerClassId();
     $Object_SetCustomersCustomer->CustomerNumber = $this->getCustomerNumber();
     // string
     $Object_SetCustomersCustomer->CustomerSince = $this->Customer->getFirstLogin()->getTimestamp();
     // int
     $Object_SetCustomersCustomer->Email = $this->Customer->getEmail();
     // string
     $Object_SetCustomersCustomer->ExternalCustomerID = PlentymarketsUtils::getExternalCustomerID($this->Customer->getId());
     // string
     $Object_SetCustomersCustomer->FormOfAddress = $this->getBillingFormOfAddress();
     // string
     $Object_SetCustomersCustomer->Fax = $this->BillingAddress->getFax();
     $Object_SetCustomersCustomer->FirstName = $this->BillingAddress->getFirstName();
     $Object_SetCustomersCustomer->HouseNo = $streetHouseNumber;
     $Object_SetCustomersCustomer->IsBlocked = !$this->Customer->getActive();
     $Object_SetCustomersCustomer->Newsletter = (int) $this->Customer->getNewsletter();
     $Object_SetCustomersCustomer->PayInvoice = true;
     // boolean
     $Object_SetCustomersCustomer->Street = $streetName;
     $Object_SetCustomersCustomer->Surname = $this->BillingAddress->getLastName();
     $Object_SetCustomersCustomer->Telephone = $this->BillingAddress->getPhone();
     $Object_SetCustomersCustomer->VAT_ID = $this->BillingAddress->getVatId();
     $Object_SetCustomersCustomer->ZIP = $zip;
     // Store id
     try {
         $Object_SetCustomersCustomer->StoreID = PlentymarketsMappingController::getShopByShopwareID($this->Customer->getShop()->getId());
         $Object_SetCustomersCustomer->Language = strtolower(substr($this->Customer->getShop()->getLocale()->getLocale(), 0, 2));
     } catch (PlentymarketsMappingExceptionNotExistant $E) {
     }
     // Customer class
     if ($this->Customer->getGroup()->getId() > 0) {
         try {
             $Object_SetCustomersCustomer->CustomerClass = PlentymarketsMappingController::getCustomerClassByShopwareID($this->Customer->getGroup()->getId());
         } catch (PlentymarketsMappingExceptionNotExistant $E) {
         }
     }
     $Request_SetCustomers->Customers[] = $Object_SetCustomersCustomer;
     $Response_SetCustomers = PlentymarketsSoapClient::getInstance()->SetCustomers($Request_SetCustomers);
     if (!$Response_SetCustomers->Success) {
         throw new PlentymarketsExportEntityException('The customer with the number »' . $this->getCustomerNumber() . '« could not be exported', 2110);
     }
     if ($Response_SetCustomers->ResponseMessages->item[0]->Code == 100 || $Response_SetCustomers->ResponseMessages->item[0]->Code == 200) {
         $this->PLENTY_customerID = (int) $Response_SetCustomers->ResponseMessages->item[0]->SuccessMessages->item[0]->Value;
         if ($this->BillingAddress instanceof \Shopware\Models\Customer\Billing) {
             PlentymarketsMappingController::addCustomerBillingAddress($this->BillingAddress->getId(), $this->PLENTY_customerID);
         } else {
             if ($this->BillingAddress instanceof \Shopware\Models\Order\Billing) {
                 PlentymarketsMappingController::addCustomer($this->BillingAddress->getId(), $this->PLENTY_customerID);
             }
         }
     }
 }
 /**
  * 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;
 }
    /**
     * 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)');
    }
    /**
     * 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();
    }
 /**
  * Internal logging method
  *
  * @param string $message
  * @param string $type
  */
 protected function log($message, $type = 'message')
 {
     PlentymarketsLogger::getInstance()->{$type}('Sync:Order:' . static::$action, $message);
 }
 /**
  * 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);
     }
 }
    /**
     * Writes the plenty order id and the status into the database
     *
     * @param integer $plentyOrderID
     * @param float $plentyOrderStatus
     */
    protected function setSuccess($plentyOrderID, $plentyOrderStatus)
    {
        PlentymarketsLogger::getInstance()->message('Export:Order', 'The sales order with the number  »' . $this->Order->getNumber() . '« has been created in plentymakets (id: ' . $plentyOrderID . ', status: ' . $plentyOrderStatus . ')');
        Shopware()->Db()->prepare('
			UPDATE plenty_order
				SET
					status = 2,
					timestampLastTry = NOW(),
					numberOfTries = numberOfTries + 1,
					plentyOrderTimestamp = NOW(),
					plentyOrderId = ?,
					plentyOrderStatus = ?
				WHERE shopwareId = ?
		')->execute(array($plentyOrderID, $plentyOrderStatus, $this->Order->getId()));
    }
 /**
  * Returns the plentymarkets customer id
  *
  * @throws PlentymarketsExportEntityException
  * @return integer
  */
 protected function getCustomerId()
 {
     try {
         return PlentymarketsMappingController::getCustomerByShopwareID($this->order['billing']['id']);
     } catch (PlentymarketsMappingExceptionNotExistant $E) {
         // Customer needs to be re-exported
         PlentymarketsLogger::getInstance()->message('Sync:Order:IncomingPayment', 'Re-exporting customer');
     }
     // Get the data
     $Customer = Shopware()->Models()->find('Shopware\\Models\\Customer\\Customer', $this->order['customerId']);
     $BillingAddress = Shopware()->Models()->find('Shopware\\Models\\Order\\Billing', $this->order['billing']['id']);
     try {
         $PlentymarketsExportEntityCustomer = new PlentymarketsExportEntityCustomer($Customer, $BillingAddress);
         $PlentymarketsExportEntityCustomer->export();
     } catch (PlentymarketsExportEntityException $E) {
         throw new PlentymarketsExportEntityException('The incoming payment of the order with the number »' . $this->order['number'] . '« could not be booked (' . $E->getMessage() . ')', 4150);
     }
     return PlentymarketsMappingController::getCustomerByShopwareID($this->order['billing']['id']);
 }
 /**
  * Rolls back the item (delete all mappings and the item in plentymarkets)
  */
 protected function rollback()
 {
     // Delete the item in plentymarktes
     $Request_DeleteItems = new PlentySoapRequest_DeleteItems();
     $Request_DeleteItems->DeleteItems = array();
     $Object_DeleteItems = new PlentySoapObject_DeleteItems();
     $Object_DeleteItems->ItemID = $this->PLENTY_itemID;
     $Request_DeleteItems->DeleteItems[] = $Object_DeleteItems;
     PlentymarketsSoapClient::getInstance()->DeleteItems($Request_DeleteItems);
     PlentymarketsLogger::getInstance()->message('Export:Initial:Item', 'The item with the id »' . $this->PLENTY_itemID . '« has been deleted in plentymarkets');
     // Delete the mapping for the main item
     PlentymarketsMappingController::deleteItemByShopwareID($this->SHOPWARE_Article->getId());
     // And for the details
     foreach ($this->SHOPWARE_Article->getDetails() as $ItemVariation) {
         PlentymarketsMappingController::deleteItemVariantByShopwareID($ItemVariation->getId());
     }
 }