* @link https://www.oxidmodule.com */ namespace D3\Importer\Application\Controller\Import; use D3\ModCfg\Application\Model\Exception\d3ShopCompatibilityAdapterException; use D3\ModCfg\Application\Model\Exception\d3_cfg_mod_exception; use Doctrine\DBAL\DBALException; use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException; use OxidEsales\Eshop\Core\Exception\DatabaseErrorException; use OxidEsales\Eshop\Core\Exception\StandardException; use OxidEsales\Eshop\Application\Component\Service\Element2ShopRelationsService; use stdClass; use Exception; use D3\Importer\Application\Models\Afterimport; use D3\Importer\Application\Models\Collector; use D3\Importer\Application\Models\Import\Accessories; use D3\Importer\Application\Models\Import\Article as ImportArticle; use D3\Importer\Application\Models\Csvconverter; use D3\Importer\Application\Models\Import\Attributes; use D3\Importer\Application\Models\Import\Category; use D3\Importer\Application\Models\Import\Crossselling; use D3\Importer\Application\Models\Import\Mall; use D3\Importer\Application\Models\Import\Manufacturer; use D3\Importer\Application\Models\Import\Price2Article; use D3\Importer\Application\Models\Import\Selectlist; use D3\Importer\Application\Models\Import\Vendor; use D3\Importer\Application\Models\ImportConfig; use D3\Importer\Application\Models\Service\ImportService; use D3\ModCfg\Application\Model\Configuration\d3_cfg_mod; use OxidEsales\Eshop\Application\Model\Article as OxidArticle; use OxidEsales\Eshop\Application\Model\ArticleList; use OxidEsales\Eshop\Application\Model\Shop; use OxidEsales\Eshop\Core\DatabaseProvider; use OxidEsales\Eshop\Core\Registry; use OxidEsales\Eshop\Core\UtilsCount; class Article { /** * @var int */ protected $importFailCode = 0; /** * @var int */ protected int|false $filePointerPosition = 0; protected int $actualLinePosition; protected bool $isEndOfFile = false; protected array $importProfile; /** * Article constructor. */ public function __construct(protected ImportConfig $importConfig) { $this->importProfile = $this->importConfig->getImportProfile(); } /** * @param int $actualLine * @param int $actualFilePointer * * @return bool * @throws d3ShopCompatibilityAdapterException * @throws d3_cfg_mod_exception * @throws DBALException * @throws DatabaseConnectionException * @throws DatabaseErrorException * @throws StandardException */ public function import(int $actualLine = 0, int|false $actualFilePointer = 0) { $this->actualLinePosition = $actualLine; $this->filePointerPosition = $actualFilePointer; $importFields = $this->getImportFields(); if ( ! $this->isStartProcedereSuccessful( $importFields ) ) { $this->isEndOfFile = true; return false; } if ( ! $this->filePointerPosition ) { // set flags $oDB = DatabaseProvider::getDb(); $oDB->execute("UPDATE `oxarticles` SET `d3importflag` = '' WHERE `d3importflag` NOT IN ('', 'manually')"); /* TODO: Hier muss spaeter nochmal die Importdatei geprueft werden! */ } // $csvConverter = oxNew(Csvconverter::class, $this->importConfig, $this->importProfile, $this->filePointerPosition); $csvLines = $csvConverter->convertCsvToArray(); $aConfigProfile = $this->importProfile['d3_importer_config']; $articleFieldIdentification = (string)$aConfigProfile['ASSIGNIDENT']; /** @var Collector $collector */ $collector = oxNew(Collector::class, $articleFieldIdentification); // jetzt aktualisieren wir noch die Uebergabeparameter fuer den naechsten Tick $this->filePointerPosition = ftell($this->importConfig->fpCsv); $this->actualLinePosition += count($csvLines); if (feof($this->importConfig->fpCsv)) { $this->isEndOfFile = true; } fclose($this->importConfig->fpCsv); /** @var ArticleList $articleList */ $articleList = oxNew(ArticleList::class); $articleList->renewPriceUpdateTime(); // /** @var Shop $shop */ $shop = Registry::getConfig()->getActiveShop(); $languageId = $shop->getLanguage(); $shopId = Registry::getConfig()->getShopId(); $isSuperShop = method_exists($shop, 'isSuperShop') ? $shop->isSuperShop() : false; // $importService = oxNew( ImportService::class, $collector, $this->importConfig, $importFields, $this->importProfile, $csvLines ); $importService->addProperty('isSuperShop', $isSuperShop); $importService->addProperty('shopId', $shopId); $importService->addProperty('languageId', $languageId); // $models = [ // oxNew(d3_importer_Application_Models_Models_Import_Article::class, $importService), // ]; // foreach ($csvLines as $index => $csvLine) { // $oxid = $collector->collectArticleIdent($csvLine[$columnIdentification]->import); // if(false == empty($oxid)) { // $csvLine['oxid'] = $oxid; // } // // foreach($models as $model) { // /** @var d3_importer_Application_Models_Models_Import_Article $model */ // $oxid = $model->importLine($csvLine); // // if(empty($oxid)) { // continue; // } // $csvLine['oxid'] = $oxid; // } // } // // die; /** @var ImportArticle $importer */ $importer = oxNew(ImportArticle::class, $importService); //TODO catch exception $importer->import(); /** @var Category $importCategories */ $importCategories = oxNew(Category::class, $importService); //TODO catch exception $importCategories->import(); /** @var Accessories $importAccessories */ $importAccessories = oxNew(Accessories::class, $importService); //TODO catch exception $importAccessories->import(); /** @var Crossselling $importCrossselling */ $importCrossselling = oxNew(Crossselling::class, $importService); //TODO catch exception $importCrossselling->import(); /** @var Attributes $importAttributes */ $importAttributes = oxNew(Attributes::class, $importService); //TODO catch exception $importAttributes->import(); /** @var Price2article $importPrice2Article */ $importPrice2Article = oxNew(Price2Article::class, $importService); //TODO catch exception $importPrice2Article->import(); /** @var Vendor $importVendor */ $importVendor = oxNew(Vendor::class, $importService); //TODO catch exception $importVendor->import(); /** @var Manufacturer $importManufacturer */ $importManufacturer = oxNew(Manufacturer::class, $importService); //TODO catch exception $importManufacturer->import(); /** @var Selectlist $importSelectlist */ $importSelectlist = oxNew(Selectlist::class, $importService); //TODO catch exception $importSelectlist->import(); if (class_exists(Element2ShopRelationsService::class) && $isSuperShop) { /** @var OxidArticle $article */ $article = oxNew(OxidArticle::class); $importService->addProperty('coreTable', $article->getCoreTableName()); $importService->addProperty('className', $article->getClassName()); /** @var Mall $mallImport */ $mallImport = oxNew(Mall::class, $importService); //TODO catch exception $mallImport->import(); } // /** * reset ArticleCountCache, as last action on ticker */ $this->resetArticleCount(); return true; } /** * @param $importFields * * @return boolean * @throws d3ShopCompatibilityAdapterException * @throws d3_cfg_mod_exception * @throws DBALException * @throws DatabaseConnectionException * @throws DatabaseErrorException * @throws StandardException */ protected function isStartProcedereSuccessful($importFields) { if (false == d3_cfg_mod::get('d3importer')->isActive()) { $this->importFailCode = 20;//TODO: use constant! $this->isEndOfFile = true; return false; } $profiles = $this->importConfig->getImportProfile(); if (empty($profiles)) { /** @var StandardException $exception */ $exception = oxNew( StandardException::class, 'import profiles are empty!' ); throw $exception; } $this->importConfig->validateImportFile(); if (false == isset($this->importConfig->fpCsv)) { $this->importFailCode = 10; //bedeutet "import-datei konnte nicht geoeffnet werden" return false; } $aConfigProfile = $profiles['d3_importer_config']; $sArticleAssignmentFieldname = (string)$aConfigProfile['ASSIGNIDENT']; // //pruefe, ob das Feld fuer die Artikelidentifikation auch zugeordnet ist if (empty($sArticleAssignmentFieldname) // || false == isset($importFields[$sArticleAssignmentFieldname]) // || false == strlen($importFields[$sArticleAssignmentFieldname]->import) ) { $this->importFailCode = 11; // bedeutet: Artikelidentifikation nicht zugeordnet return false; } // return true; } /** * @return array */ protected function getImportFields() { $importFields = []; /** @var OxidArticle $oArticle */ $oArticle = oxNew(OxidArticle::class); $oArticle->setEnableMultilang(false); $fieldNames = $oArticle->getFieldNames(); $fieldNames = $this->addLongdescFieldnames($fieldNames); $csvCells = $this->importProfile['d3_importer_fields']['fields']; $aUpdateFields = $this->importProfile['d3_importer_fields']['update']; $aVariantFields = $this->importProfile['d3_importer_variants']['FIELD']; foreach ($fieldNames as $fieldName) { foreach ($csvCells as $csvColumn => $csvCell) { $csvColumn = trim((string)$csvColumn); if ($csvCell != $fieldName) { continue; } if (! strlen($csvColumn)) { continue; } $temporaryClass = new stdClass(); $temporaryClass->import = $csvColumn; if (isset($aUpdateFields[$csvColumn]) && (bool)$aUpdateFields[$csvColumn]) { $temporaryClass->update = $csvColumn; } $importFields[$csvCell] = $temporaryClass; } if (! empty($aVariantFields)) { foreach ($aVariantFields as $csvCell => $csvColumn) { $csvColumn = trim((string)$csvColumn); if ($csvCell != $fieldName) { continue; } if (! strlen($csvColumn)) { continue; } $temporaryClass = new stdClass(); $temporaryClass->import = $csvColumn; $temporaryClass->update = $csvColumn; $importFields[$csvCell] = $temporaryClass; } } } return $importFields; } /** * @return int */ public function getFilePointerPosition() { return $this->filePointerPosition; } /** * @return int */ public function getFailImport() { return $this->importFailCode; } /** * @return int */ public function getActualLinePosition() { return $this->actualLinePosition; } /** * @return bool */ public function isEndOfFile() { return $this->isEndOfFile; } /** * @param $action * @param int $tickerMaximum * * @throws d3ShopCompatibilityAdapterException * @throws d3_cfg_mod_exception * @throws DBALException * @throws DatabaseConnectionException * @throws DatabaseErrorException * @throws StandardException * @throws Exception */ public function afterImport($action, $tickerMaximum) { if (false == d3_cfg_mod::get('d3importer')->isActive()) { $this->importFailCode = 20; $this->isEndOfFile = true; return; } if ($action != 'delete' && $action != 'inactive') { $this->importFailCode = 12; $this->isEndOfFile = true; return; } if (false == $this->isStartProcedereSuccessful($this->getImportFields())) { $this->isEndOfFile = true; return; } $oDB = DatabaseProvider::getDb(DatabaseProvider::FETCH_MODE_ASSOC); $oxarticlesViewname = (oxNew(OxidArticle::class))->getViewName(); $sSelect = <<quote($this->importConfig->getId())} LIMIT 0, {$tickerMaximum} MySQL; $articleIds = $oDB->getAll($sSelect); if (empty($articleIds)) { $this->isEndOfFile = true; return; } $afterImport = oxNew(Afterimport::class); $afterImport->afterimport($action, $articleIds); $this->resetArticleCount(); } /** * reset ArticleCountCache, as last action on ticker * -on Category * -Manufactorer * -Vendor */ protected function resetArticleCount() { $oUtilsCount = Registry::get(UtilsCount::class); $oUtilsCount->resetCatArticleCount(); $oUtilsCount->resetVendorArticleCount(); $oUtilsCount->resetManufacturerArticleCount(); } /** * @return array */ protected function addLongdescFieldnames(array $fieldnames) { $fieldnames[] = 'oxlongdesc'; $language = Registry::getLang(); $languages = $language->getLanguageArray(null, false); foreach ($languages as $language) { if (0 < $language->id) { $fieldnames[] = 'oxlongdesc_' . $language->id; } } return $fieldnames; } }