├── downloaded └── .gitkeep ├── etc ├── sql │ ├── sync.sample.sql │ ├── dump.sql │ └── sync.magento.sql └── mailtemplate.php ├── .gitignore ├── index.php ├── composer.json ├── local ├── bootstrap.php └── XmlImport │ ├── Config │ └── Config.php │ ├── Helpers │ ├── VarHelper.php │ ├── MailHelper.php │ └── CurlHelper.php │ ├── Runner │ └── Runner.php │ └── Adapters │ └── AdapterBase.php ├── LICENSE └── config.sample.php /downloaded/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /etc/sql/sync.sample.sql: -------------------------------------------------------------------------------- 1 | -- @adapter_id 2 | -- @adapter_name 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | /vendor/ 3 | /local/Zaimoglu/ 4 | /config.php 5 | /composer.lock 6 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | start(); 7 | 8 | exit($tRunner->exitCode); 9 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eser.ozvataf/xmlimport", 3 | "authors": [ 4 | { 5 | "name": "larukedi", 6 | "email": "eser@sent.com" 7 | } 8 | ], 9 | "require": { 10 | "php-objects/query-builder": "dev-master" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /local/bootstrap.php: -------------------------------------------------------------------------------- 1 | addPsr4("", __DIR__ . "/"); 15 | 16 | \XmlImport\Config\Config::set($tConfig); 17 | -------------------------------------------------------------------------------- /etc/mailtemplate.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | XmlImport Error 4 | 13 | 14 | 15 |

XmlImport Error

16 | 17 |

18 | 19 | getMessage(); ?> 20 |
21 | 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Copyright 2015 Eser 'Laroux' Ozvataf 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | -------------------------------------------------------------------------------- /local/XmlImport/Config/Config.php: -------------------------------------------------------------------------------- 1 | array( 3 | "conn" => "mysql:host=localhost;dbname=xmlimport", 4 | "username" => "root", 5 | "password" => "" 6 | ), 7 | "mail" => array( 8 | "from" => "xmlimport@github.com", 9 | "to" => "eser@sent.com", 10 | "headers" => array( 11 | "X-Mailer" => "PHP/" . phpversion() 12 | ) 13 | ), 14 | "adapters" => array( 15 | array( 16 | "class" => "Vendor\\XmlAdapters\\Sample", 17 | "config" => array( 18 | "id" => 1, 19 | "name" => "Sample", 20 | "url" => "http://www.domain.com/path/filename.xml", 21 | "sql.sync" => "etc/sql/sync.sample.sql", 22 | "downloads" => "downloaded/" 23 | ) 24 | ) 25 | ) 26 | ); 27 | -------------------------------------------------------------------------------- /local/XmlImport/Helpers/VarHelper.php: -------------------------------------------------------------------------------- 1 | Config::get("mail/from"), 14 | "Reply-To" => Config::get("mail/from"), 15 | "Content-Type" => "text/html; charset=utf-8" 16 | ); 17 | $tHeaders += Config::get("mail/headers"); 18 | 19 | $tHeadersRaw = ""; 20 | foreach ($tHeaders as $tHeaderKey => $tHeaderValue) { 21 | if (strlen($tHeadersRaw) > 0) { 22 | $tHeadersRaw .= PHP_EOL; 23 | } 24 | 25 | $tHeadersRaw .= "{$tHeaderKey}: {$tHeaderValue}"; 26 | } 27 | 28 | mail($uTo, $uSubject, $uMessage, $tHeadersRaw); 29 | } 30 | 31 | public static function sendLog($uSubject, $uMessage) 32 | { 33 | static::send(Config::get("mail/to"), $uSubject, $uMessage); 34 | } 35 | 36 | public static function sendException(Exception $uException) 37 | { 38 | // for templating 39 | $exception = $uException; 40 | 41 | ob_start(); 42 | require BASE_DIR . "etc/mailtemplate.php"; 43 | $tContent = ob_get_clean(); 44 | 45 | static::sendLog("XmlImport Error: " . get_class($uException), $tContent); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /local/XmlImport/Runner/Runner.php: -------------------------------------------------------------------------------- 1 | pdo = new PDO( 26 | Config::get("database/conn"), 27 | Config::get("database/username"), 28 | Config::get("database/password") 29 | ); 30 | 31 | $this->pdo->exec("SET NAMES 'utf8'"); 32 | } catch (PDOException $tEx) { 33 | MailHelper::sendException($tEx); 34 | throw $tEx; 35 | } 36 | 37 | // load adapters 38 | $tAdapterConfigs = Config::get("adapters"); 39 | 40 | foreach ($tAdapterConfigs as $tAdapterConfig) { 41 | $this->adapterInstances[] = new $tAdapterConfig["class"] ($this, $tAdapterConfig["config"]); 42 | } 43 | 44 | // download data 45 | foreach ($this->adapterInstances as $tAdapterInstance) { 46 | try { 47 | $tAdapterInstance->start(); 48 | } catch (Exception $tEx) { 49 | MailHelper::sendException($tEx); 50 | throw $tEx; 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /local/XmlImport/Helpers/CurlHelper.php: -------------------------------------------------------------------------------- 1 | $uUrl, 24 | CURLOPT_TIMEOUT => 50, 25 | CURLOPT_FILE => $tFilePointer, 26 | CURLOPT_FOLLOWLOCATION => true, 27 | CURLOPT_SSL_VERIFYPEER => false 28 | ) 29 | ); 30 | 31 | $tLoop = 0; 32 | $tFailed = false; 33 | 34 | while (true) { 35 | curl_exec($tCurl); 36 | $tLoop++; 37 | 38 | $tError = curl_errno($tCurl); 39 | if ($tError !== 0) { 40 | $tHttpStatus = curl_getinfo($tCurl, CURLINFO_HTTP_CODE); 41 | 42 | // HTTP 5xx 43 | if ($tLoop < 3 && ($tHttpStatus >= 500 && $tHttpStatus < 600)) { 44 | echo "* HTTP {$tHttpStatus}, trying again...", PHP_EOL; 45 | // try again after 1 second delay 46 | usleep(1000000); 47 | continue; 48 | } 49 | 50 | echo "* CURL Error No {$tError} w/ HTTP {$tHttpStatus}...", PHP_EOL; 51 | // echo "CURL Error Message: ", curl_error($tCurl), PHP_EOL; 52 | $tFailed = true; 53 | } 54 | 55 | break; 56 | } 57 | 58 | curl_close($tCurl); 59 | 60 | fclose($tFilePointer); 61 | 62 | if ($tFailed) { 63 | unlink($uFile); 64 | return false; 65 | } 66 | 67 | return $uFile; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /etc/sql/dump.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Navicat MariaDB Data Transfer 3 | 4 | Source Server : local-maria 5 | Source Server Version : 50542 6 | Source Host : localhost:3306 7 | Source Database : localhost 8 | 9 | Target Server Type : MariaDB 10 | Target Server Version : 50542 11 | File Encoding : 65001 12 | 13 | Date: 2015-04-22 01:32:36 14 | */ 15 | 16 | -- ---------------------------- 17 | -- Table structure for XmlImport 18 | -- ---------------------------- 19 | DROP TABLE IF EXISTS `XmlImport`; 20 | CREATE TABLE `XmlImport` ( 21 | `ItemId` int(10) UNSIGNED NOT NULL AUTO_INCREMENT , 22 | `AdapterId` int(10) UNSIGNED NOT NULL , 23 | `Checksum` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 24 | `Status` int(10) UNSIGNED NOT NULL , 25 | `LastUpdate` datetime NOT NULL , 26 | `RemoteId` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 27 | `RemoteUrl` varchar(2048) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 28 | `RemoteSKU` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 29 | `RemoteBarcode` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 30 | `Brand` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 31 | `Model` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 32 | `RemoteCategoryId1` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 33 | `RemoteCategoryName1` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 34 | `RemoteCategoryId2` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 35 | `RemoteCategoryName2` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 36 | `RemoteCategoryId3` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 37 | `RemoteCategoryName3` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 38 | `RemoteCategoryId4` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 39 | `RemoteCategoryName4` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 40 | `Name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 41 | `ShortDescription` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 42 | `LongDescription` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 43 | `Price` decimal(10,4) NOT NULL , 44 | `DiscountedPrice` decimal(10,4) NOT NULL , 45 | `VAT` int(10) UNSIGNED NOT NULL , 46 | `Currency` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 47 | `Quantity` int(10) UNSIGNED NOT NULL , 48 | `Minimum` int(10) UNSIGNED NOT NULL , 49 | `Images` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 50 | `Options` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 51 | `Attributes` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 52 | `Type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 53 | `AttributeSet` int(10) UNSIGNED NOT NULL , 54 | `VendorCode` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 55 | `VendorProfile` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 56 | PRIMARY KEY (`ItemId`) 57 | ) 58 | ENGINE=InnoDB 59 | DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci; 60 | 61 | 62 | -- ---------------------------- 63 | -- Table structure for XmlImportImages 64 | -- ---------------------------- 65 | DROP TABLE IF EXISTS `XmlImportImages`; 66 | CREATE TABLE `XmlImportImages` ( 67 | `ImageId` int(10) UNSIGNED NOT NULL AUTO_INCREMENT , 68 | `ItemId` int(10) UNSIGNED NOT NULL , 69 | `Url` varchar(2048) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 70 | PRIMARY KEY (`ImageId`) 71 | ) 72 | ENGINE=InnoDB 73 | DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci; 74 | -------------------------------------------------------------------------------- /local/XmlImport/Adapters/AdapterBase.php: -------------------------------------------------------------------------------- 1 | runner = $uRunner; 30 | 31 | $this->id = $uConfig["id"]; 32 | $this->name = $uConfig["name"]; 33 | $this->url = $uConfig["url"]; 34 | $this->sqlSyncFile = $uConfig["sql.sync"]; 35 | $this->downloadsPath = rtrim($uConfig["downloads"], "/") . "/"; 36 | 37 | $this->sqlParameters = array( 38 | ":adapter_id" => $this->id, 39 | ":adapter_name" => $this->name 40 | ); 41 | } 42 | 43 | public function start() 44 | { 45 | echo "Adapter {$this->name} is starting...", PHP_EOL; 46 | 47 | echo "- Downloading XML from {$this->url}", PHP_EOL; 48 | $tFile = $this->downloadSource(); 49 | if ($tFile === false) { 50 | // TODO throw error 51 | return false; 52 | } 53 | 54 | $this->recordsAdded = 0; 55 | $this->recordsUpdated = 0; 56 | $this->recordsSkipped = 0; 57 | $this->downloads = array(); 58 | 59 | echo "- Processing Data", PHP_EOL; 60 | $this->loadPreviousMaps(); 61 | $this->processFile($tFile); 62 | echo "-- Completed: {$this->recordsAdded} added. {$this->recordsUpdated} updated. {$this->recordsSkipped} skipped.", PHP_EOL; 63 | 64 | echo "- Syncing SQL", PHP_EOL; 65 | $this->setRedundantsPassive(); 66 | $this->syncSql(); 67 | 68 | echo "- Downloading Assets", PHP_EOL; 69 | $this->downloadAssets(); 70 | echo "-- Completed.", PHP_EOL, PHP_EOL; 71 | } 72 | 73 | public function downloadSource() 74 | { 75 | return CurlHelper::downloadFile($this->url); 76 | } 77 | 78 | public function downloadAssets() 79 | { 80 | foreach ($this->downloads as $tDownload) { 81 | $tLocalDirectory = $this->downloadsPath . $tDownload["directory"]; 82 | $tLocalFile = "{$tLocalDirectory}/{$tDownload["file"]}"; 83 | if (!is_dir($tLocalDirectory)) { 84 | mkdir($tLocalDirectory, 0777, true); 85 | } else { 86 | if (file_exists($tLocalFile)) { 87 | continue; 88 | } 89 | } 90 | 91 | echo "-- Downloading: {$tDownload["file"]}", PHP_EOL; 92 | CurlHelper::downloadFile($tDownload["url"], $tLocalFile); 93 | } 94 | } 95 | 96 | public function loadPreviousMaps() 97 | { 98 | $tSelectQuery = QueryBuilder::factorySelect() 99 | ->select("ItemId, Checksum, RemoteId") 100 | ->from("XmlImport") 101 | ->where("AdapterId", $this->id) 102 | ->toSql(); 103 | 104 | $this->previousRemoteIdMap = array(); 105 | $this->previousChecksumMap = array(); 106 | $this->recordCheckListMap = array(); 107 | 108 | $tRows = $this->runner->pdo->query($tSelectQuery); 109 | foreach ($tRows as $tRow) { 110 | $this->previousRemoteIdMap[$tRow["RemoteId"]] = $tRow["ItemId"]; 111 | $this->previousChecksumMap[$tRow["ItemId"]] = $tRow["Checksum"]; 112 | $this->recordCheckListMap[$tRow["ItemId"]] = true; 113 | } 114 | } 115 | 116 | public function setRedundantsPassive() 117 | { 118 | if (count($this->recordCheckListMap) > 0) { 119 | $tUpdateQuery = QueryBuilder::update() 120 | ->table("XmlImport") 121 | ->set(array( 122 | "Status" => 0 123 | )) 124 | ->where(array( 125 | "ItemID IN (" . implode(", ", array_keys($this->recordCheckListMap)) . ")", 126 | array("AdapterId", $this->id) 127 | )) 128 | ->toSql(); 129 | 130 | $this->runner->pdo->exec($tUpdateQuery); 131 | } 132 | } 133 | 134 | public function syncSql() 135 | { 136 | if (strlen($this->sqlSyncFile) === 0) { 137 | return; 138 | } 139 | 140 | $tPath = BASE_DIR . $this->sqlSyncFile; 141 | $tSql = file_get_contents($tPath); 142 | 143 | $tQuery = $this->runner->pdo->prepare($tSql); 144 | $tQuery->execute($this->sqlParameters); 145 | } 146 | 147 | public function processFile($uFile) 148 | { 149 | $tXml = simplexml_load_file($uFile); 150 | // TODO throw error if it is not loaded 151 | return $this->processXml($tXml); 152 | } 153 | 154 | public abstract function processXml(SimpleXMLElement $uXml); 155 | 156 | protected function addDownload($uAdapterId, $uCategory, $uUrl) 157 | { 158 | $tDownload = array( 159 | "url" => $uUrl, 160 | "directory" => "xmlimport/{$uAdapterId}/{$uCategory}", 161 | "file" => str_replace( 162 | "/", 163 | "_", 164 | parse_url($uUrl, PHP_URL_PATH) 165 | ) 166 | ); 167 | 168 | $this->downloads[] = $tDownload; 169 | 170 | return $tDownload; 171 | } 172 | 173 | protected function addRecord($uValues, $uImages = array()) 174 | { 175 | $tDownload = false; 176 | $tItemId = 0; 177 | 178 | if (isset($this->previousRemoteIdMap[$uValues["RemoteId"]])) { 179 | $tPreviousId = $this->previousRemoteIdMap[$uValues["RemoteId"]]; 180 | $tPreviousChecksum = $this->previousChecksumMap[$tPreviousId]; 181 | 182 | // update if the record has changed 183 | if ($tPreviousChecksum != $uValues["Checksum"]) { 184 | $tUpdateQuery = QueryBuilder::update() 185 | ->table("XmlImport") 186 | ->set($uValues) 187 | ->where("ItemId", $tPreviousId) 188 | ->limit(1) 189 | ->toSql(); 190 | 191 | $this->runner->pdo->exec($tUpdateQuery); 192 | 193 | $this->recordsUpdated++; 194 | } else { 195 | $this->recordsSkipped++; 196 | } 197 | 198 | unset($this->recordCheckListMap[$tPreviousId]); 199 | } else { 200 | $tInsertQuery = QueryBuilder::insert() 201 | ->into("XmlImport") 202 | ->values($uValues) 203 | ->toSql(); 204 | 205 | $this->runner->pdo->exec($tInsertQuery); 206 | $tItemId = $this->runner->pdo->lastInsertId(); 207 | 208 | $this->recordsAdded++; 209 | $tDownload = true; 210 | } 211 | 212 | if ($tDownload && $uValues["Status"] != 0) { 213 | foreach ($uImages as $tImage) { 214 | $tDownload = $this->addDownload($this->id, "images", $tImage); 215 | 216 | $tInsertImageQuery = QueryBuilder::insert() 217 | ->into("XmlImportImages") 218 | ->values(array( 219 | "ItemId" => $tItemId, 220 | "Url" => "{$tDownload["directory"]}/{$tDownload["file"]}" 221 | )) 222 | ->toSql(); 223 | 224 | $this->runner->pdo->exec($tInsertImageQuery); 225 | } 226 | } 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /etc/sql/sync.magento.sql: -------------------------------------------------------------------------------- 1 | -- :adapter_id 2 | -- :adapter_name 3 | -- :attribute_set_id 4 | 5 | SET @adapter_id = :adapter_id; 6 | SET @adapter_name = :adapter_name; 7 | SET @attribute_set_id = :attribute_set_id; 8 | 9 | -- create temp table 10 | DROP TABLE IF EXISTS `XmlImportEntities`; 11 | CREATE TEMPORARY TABLE `XmlImportEntities` ( 12 | `LocalId` INT NOT NULL, 13 | `SyncTag` VARCHAR(64) NOT NULL, 14 | `EntityId` INT 15 | -- `xmlsync` INT NOT NULL 16 | ); 17 | 18 | INSERT INTO `XmlImportEntities` 19 | SELECT 20 | xi.`ItemId` AS `LocalId`, 21 | COALESCE(p.`sku`, CONCAT(@adapter_name, '_', COALESCE(xi.`RemoteSKU`, xi.`RemoteId`))) AS `SyncTag`, 22 | vendor_product_id.`entity_id` 23 | -- (xml.`value` IS NULL OR xml.`value` IN (6222, 6223)) AS `xmlsync` 24 | FROM 25 | `XmlImport` xi 26 | LEFT JOIN `mwcatalog_product_entity_varchar` vendor_product_id ON xi.`RemoteId`=vendor_product_id.`value` AND vendor_product_id.`attribute_id` = 176 AND vendor_product_id.`store_id` = 0 27 | LEFT JOIN `mwcatalog_product_entity` p ON vendor_product_id.`entity_id`=p.`entity_id` AND p.`attribute_set_id`=@attribute_set_id 28 | LEFT JOIN `mwcatalog_product_entity_int` xml ON p.`entity_id`=xml.`entity_id` AND xml.`attribute_id` = 266 AND xml.`store_id` = 0 29 | WHERE 30 | xi.`Status` = 1 AND 31 | xi.`AdapterId` = @adapter_id AND 32 | (xml.`value` IS NULL OR xml.`value` IN (6222, 6223)); 33 | 34 | -- disable existing entities first 35 | UPDATE 36 | `mwcatalog_product_entity_int` ints 37 | INNER JOIN `mwcatalog_product_entity` p ON ints.`entity_id`=p.`entity_id` AND ints.`attribute_id` = 84 AND ints.`store_id` = 0 38 | LEFT JOIN `mwcatalog_product_entity_int` xml ON p.`entity_id`=xml.`entity_id` AND xml.`attribute_id` = 266 AND xml.`store_id` = 0 39 | SET 40 | ints.`value` = 0 41 | WHERE 42 | p.`attribute_set_id`=@attribute_set_id AND 43 | (xml.`value` IS NULL OR xml.`value` IN (6222, 6223)); 44 | 45 | -- update existing entities 46 | UPDATE `mwcatalog_product_entity` p 47 | INNER JOIN `XmlImportEntities` xie ON p.`entity_id`=xie.`EntityId` 48 | SET p.`updated_at`=NOW(); 49 | 50 | -- insert new entities 51 | INSERT INTO `mwcatalog_product_entity` 52 | SELECT 53 | NULL AS `entity_id`, 54 | 4 AS `entity_type_id`, 55 | @attribute_set_id AS `attribute_set_id`, 56 | 'simple' AS `type_id`, 57 | xie.`SyncTag` AS `sku`, 58 | 0 AS `has_options`, 59 | 0 AS `required_options`, 60 | NOW() AS `created_at`, 61 | NOW() AS `updated_at` 62 | FROM 63 | `XmlImportEntities` xie 64 | WHERE 65 | xie.`EntityId` IS NULL; 66 | 67 | -- set entity_id of inserted entities 68 | UPDATE 69 | `XmlImportEntities` xie 70 | LEFT JOIN `mwcatalog_product_entity` p ON xie.`SyncTag`=p.`sku` 71 | SET 72 | xie.`EntityId`=p.`entity_id` 73 | WHERE 74 | xie.`EntityId` IS NULL; 75 | 76 | -- update quantity 77 | UPDATE 78 | `mwcataloginventory_stock_item` qty 79 | INNER JOIN `XmlImportEntities` xie ON qty.`product_id`=xie.`EntityId` 80 | INNER JOIN `XmlImport` xi ON xie.`LocalId`=xi.`ItemId` AND xi.`AdapterId`=@adapter_id 81 | SET 82 | qty.`qty`=xi.Quantity, 83 | qty.`is_in_stock`=(xi.Quantity > 0); 84 | 85 | -- insert quantity 86 | INSERT INTO `mwcataloginventory_stock_item` 87 | SELECT 88 | NULL AS `item_id`, 89 | xie.`EntityId` AS `product_id`, 90 | 1 AS `stock_id`, 91 | xi.`Quantity` AS `qty`, 92 | 0 AS `min_qty`, 93 | 1 AS `use_config_min_qty`, 94 | 0 AS `is_qty_decimal`, 95 | 0 AS `backorders`, 96 | 1 AS `use_config_backorders`, 97 | 1 AS `min_sale_qty`, 98 | 0 AS `use_config_min_sale_qty`, 99 | 0 AS `max_sale_qty`, 100 | 1 AS `use_config_max_sale_qty`, 101 | 1 AS `is_in_stock`, 102 | NULL AS `low_stock_date`, 103 | NULL AS `notify_stock_qty`, 104 | 1 AS `use_config_notify_stock_qty`, 105 | 0 AS `manage_stock`, 106 | 1 AS `use_config_manage_stock`, 107 | 0 AS `stock_status_changed_automatically`, 108 | 1 AS `use_config_qty_increments`, 109 | 0 AS `qty_increments`, 110 | 1 AS `use_config_enable_qty_increments`, 111 | 0 AS `use_config_increments` 112 | FROM 113 | `XmlImportEntities` xie 114 | INNER JOIN `XmlImport` xi ON xie.`LocalId`=xi.`ItemId` AND xi.`AdapterId`=@adapter_id 115 | LEFT JOIN `mwcataloginventory_stock_item` qty ON xie.`EntityId`=qty.`product_id` 116 | WHERE 117 | qty.`product_id` IS NULL; 118 | 119 | -- update ints 120 | UPDATE 121 | `mwcatalog_product_entity_int` ints 122 | INNER JOIN `XmlImportEntities` xie ON ints.`entity_id`=xie.`EntityId` 123 | INNER JOIN `XmlImport` xi ON xie.`LocalId`=xi.`ItemId` AND xi.`AdapterId`=@adapter_id 124 | SET 125 | ints.`value`=CASE ints.`attribute_id` 126 | WHEN 84 THEN 1 127 | END 128 | WHERE 129 | ints.`attribute_id` IN (84) AND ints.`store_id` = 0; 130 | 131 | -- insert ints: status 132 | INSERT INTO `mwcatalog_product_entity_int` 133 | SELECT 134 | NULL AS `value_id`, 135 | 4 AS `entity_type_id`, 136 | 84 AS `attribute_id`, 137 | 0 AS `store_id`, 138 | xie.`EntityId` AS `entity_id`, 139 | 1 AS `value` 140 | FROM 141 | `XmlImportEntities` xie 142 | INNER JOIN `XmlImport` xi ON xie.`LocalId`=xi.`ItemId` AND xi.`AdapterId`=@adapter_id 143 | LEFT JOIN `mwcatalog_product_entity_int` ints ON xie.`EntityId`=ints.`entity_id` 144 | WHERE 145 | ints.`value_id` IS NULL; 146 | 147 | -- insert ints: tax class 148 | INSERT INTO `mwcatalog_product_entity_int` 149 | SELECT 150 | NULL AS `value_id`, 151 | 4 AS `entity_type_id`, 152 | 85 AS `attribute_id`, 153 | 0 AS `store_id`, 154 | xie.`EntityId` AS `entity_id`, 155 | 3810 AS `value` 156 | FROM 157 | `XmlImportEntities` xie 158 | INNER JOIN `XmlImport` xi ON xie.`LocalId`=xi.`ItemId` AND xi.`AdapterId`=@adapter_id 159 | LEFT JOIN `mwcatalog_product_entity_int` ints ON xie.`EntityId`=ints.`entity_id` 160 | WHERE 161 | ints.`value_id` IS NULL; 162 | 163 | -- insert ints: visibility 164 | INSERT INTO `mwcatalog_product_entity_int` 165 | SELECT 166 | NULL AS `value_id`, 167 | 4 AS `entity_type_id`, 168 | 91 AS `attribute_id`, 169 | 0 AS `store_id`, 170 | xie.`EntityId` AS `entity_id`, 171 | 3808 AS `value` 172 | FROM 173 | `XmlImportEntities` xie 174 | INNER JOIN `XmlImport` xi ON xie.`LocalId`=xi.`ItemId` AND xi.`AdapterId`=@adapter_id 175 | LEFT JOIN `mwcatalog_product_entity_int` ints ON xie.`EntityId`=ints.`entity_id` 176 | WHERE 177 | ints.`value_id` IS NULL; 178 | 179 | -- insert ints: brand 180 | INSERT INTO `mwcatalog_product_entity_int` 181 | SELECT 182 | NULL AS `value_id`, 183 | 4 AS `entity_type_id`, 184 | 159 AS `attribute_id`, 185 | 0 AS `store_id`, 186 | xie.`EntityId` AS `entity_id`, 187 | XmlImportUpsertValue(159, xi.`Brand`) AS `value` 188 | FROM 189 | `XmlImportEntities` xie 190 | INNER JOIN `XmlImport` xi ON xie.`LocalId`=xi.`ItemId` AND xi.`AdapterId`=@adapter_id 191 | LEFT JOIN `mwcatalog_product_entity_int` ints ON xie.`EntityId`=ints.`entity_id` 192 | WHERE 193 | ints.`value_id` IS NULL; 194 | 195 | -- insert ints: category 196 | INSERT INTO `mwcatalog_product_entity_int` 197 | SELECT 198 | NULL AS `value_id`, 199 | 4 AS `entity_type_id`, 200 | 195 AS `attribute_id`, 201 | 0 AS `store_id`, 202 | xie.`EntityId` AS `entity_id`, 203 | XmlImportUpsertValue(195, xi.`RemoteCategoryName1`) AS `value` 204 | FROM 205 | `XmlImportEntities` xie 206 | INNER JOIN `XmlImport` xi ON xie.`LocalId`=xi.`ItemId` AND xi.`AdapterId`=@adapter_id 207 | LEFT JOIN `mwcatalog_product_entity_int` ints ON xie.`EntityId`=ints.`entity_id` 208 | WHERE 209 | ints.`value_id` IS NULL; 210 | 211 | -- insert ints: xml_updated 212 | INSERT INTO `mwcatalog_product_entity_int` 213 | SELECT 214 | NULL AS `value_id`, 215 | 4 AS `entity_type_id`, 216 | 266 AS `attribute_id`, 217 | 0 AS `store_id`, 218 | xie.`EntityId` AS `entity_id`, 219 | 6223 AS `value` 220 | FROM 221 | `XmlImportEntities` xie 222 | INNER JOIN `XmlImport` xi ON xie.`LocalId`=xi.`ItemId` AND xi.`AdapterId`=@adapter_id 223 | LEFT JOIN `mwcatalog_product_entity_int` ints ON xie.`EntityId`=ints.`entity_id` 224 | WHERE 225 | ints.`value_id` IS NULL; 226 | 227 | -- update decimals 228 | UPDATE 229 | `mwcatalog_product_entity_decimal` decimals 230 | INNER JOIN `XmlImportEntities` xie ON decimals.`entity_id`=xie.`EntityId` 231 | INNER JOIN `XmlImport` xi ON xie.`LocalId`=xi.`ItemId` AND xi.`AdapterId`=@adapter_id 232 | SET 233 | decimals.`value`=CASE decimals.attribute_id 234 | WHEN 64 THEN xi.`Price` 235 | WHEN 65 THEN xi.`DiscountedPrice` 236 | END 237 | WHERE 238 | decimals.`attribute_id` IN (64, 65) AND decimals.`store_id` = 0; 239 | 240 | -- insert decimals: price 241 | INSERT INTO `mwcatalog_product_entity_decimal` 242 | SELECT 243 | NULL AS `value_id`, 244 | 4 AS `entity_type_id`, 245 | 64 AS `attribute_id`, 246 | 0 AS `store_id`, 247 | xie.`EntityId` AS `entity_id`, 248 | xi.`Price` AS `value` 249 | FROM 250 | `XmlImportEntities` xie 251 | INNER JOIN `XmlImport` xi ON xie.`LocalId`=xi.`ItemId` AND xi.`AdapterId`=@adapter_id 252 | LEFT JOIN `mwcatalog_product_entity_decimal` decimals ON xie.`EntityId`=decimals.`entity_id` 253 | WHERE 254 | decimals.`value_id` IS NULL; 255 | 256 | -- insert decimals: discounted price 257 | INSERT INTO `mwcatalog_product_entity_decimal` 258 | SELECT 259 | NULL AS `value_id`, 260 | 4 AS `entity_type_id`, 261 | 65 AS `attribute_id`, 262 | 0 AS `store_id`, 263 | xie.`EntityId` AS `entity_id`, 264 | xi.`DiscountedPrice` AS `value` 265 | FROM 266 | `XmlImportEntities` xie 267 | INNER JOIN `XmlImport` xi ON xie.`LocalId`=xi.`ItemId` AND xi.`AdapterId`=@adapter_id 268 | LEFT JOIN `mwcatalog_product_entity_decimal` decimals ON xie.`EntityId`=decimals.`entity_id` 269 | WHERE 270 | decimals.`value_id` IS NULL; 271 | 272 | -- delete decimals: discounted price 273 | DELETE FROM `mwcatalog_product_entity_decimal` 274 | WHERE `attribute_id` = 65 AND `value` = 0 AND `store_id` = 0; 275 | 276 | -- update varchars 277 | UPDATE 278 | `mwcatalog_product_entity_varchar` varchars 279 | INNER JOIN `XmlImportEntities` xie ON varchars.`entity_id`=xie.`EntityId` 280 | INNER JOIN `XmlImport` xi ON xie.`LocalId`=xi.`ItemId` AND xi.`AdapterId`=@adapter_id 281 | SET 282 | varchars.`value`=CASE varchars.attribute_id 283 | WHEN 181 THEN xi.`RemoteBarcode` 284 | END 285 | WHERE 286 | varchars.`attribute_id` IN (181) AND varchars.`store_id` = 0; 287 | 288 | -- insert varchars: barcode 289 | INSERT INTO `mwcatalog_product_entity_varchar` 290 | SELECT 291 | NULL AS `value_id`, 292 | 4 AS `entity_type_id`, 293 | 181 AS `attribute_id`, 294 | 0 AS `store_id`, 295 | xie.`EntityId` AS `entity_id`, 296 | xi.`RemoteBarcode` AS `value` 297 | FROM 298 | `XmlImportEntities` xie 299 | INNER JOIN `XmlImport` xi ON xie.`LocalId`=xi.`ItemId` AND xi.`AdapterId`=@adapter_id 300 | LEFT JOIN `mwcatalog_product_entity_varchar` varchars ON xie.`EntityId`=varchars.`entity_id` 301 | WHERE 302 | varchars.`value_id` IS NULL; 303 | 304 | -- insert varchars: images 305 | INSERT INTO `mwcatalog_product_entity_varchar` 306 | SELECT 307 | NULL AS `value_id`, 308 | 4 AS `entity_type_id`, 309 | 74 AS `attribute_id`, 310 | 0 AS `store_id`, 311 | xie.`EntityId` AS `entity_id`, 312 | (SELECT xii.`Url` FROM `XmlImportImages` xii WHERE xii.`ItemId`=xie.`LocalId` ORDER BY xii.`ImageId` ASC LIMIT 0, 1) AS `value` 313 | FROM 314 | `XmlImportEntities` xie 315 | INNER JOIN `XmlImport` xi ON xie.`LocalId`=xi.`ItemId` AND xi.`AdapterId`=@adapter_id 316 | LEFT JOIN `mwcatalog_product_entity_varchar` varchars ON xie.`EntityId`=varchars.`entity_id` 317 | WHERE 318 | varchars.`value_id` IS NULL; 319 | 320 | -- insert varchars: small images 321 | INSERT INTO `mwcatalog_product_entity_varchar` 322 | SELECT 323 | NULL AS `value_id`, 324 | 4 AS `entity_type_id`, 325 | 75 AS `attribute_id`, 326 | 0 AS `store_id`, 327 | xie.`EntityId` AS `entity_id`, 328 | (SELECT xii.`Url` FROM `XmlImportImages` xii WHERE xii.`ItemId`=xie.`LocalId` ORDER BY xii.`ImageId` ASC LIMIT 0, 1) AS `value` 329 | FROM 330 | `XmlImportEntities` xie 331 | INNER JOIN `XmlImport` xi ON xie.`LocalId`=xi.`ItemId` AND xi.`AdapterId`=@adapter_id 332 | LEFT JOIN `mwcatalog_product_entity_varchar` varchars ON xie.`EntityId`=varchars.`entity_id` 333 | WHERE 334 | varchars.`value_id` IS NULL; 335 | 336 | -- insert varchars: thumbnails 337 | INSERT INTO `mwcatalog_product_entity_varchar` 338 | SELECT 339 | NULL AS `value_id`, 340 | 4 AS `entity_type_id`, 341 | 76 AS `attribute_id`, 342 | 0 AS `store_id`, 343 | xie.`EntityId` AS `entity_id`, 344 | (SELECT xii.`Url` FROM `XmlImportImages` xii WHERE xii.`ItemId`=xie.`LocalId` ORDER BY xii.`ImageId` ASC LIMIT 0, 1) AS `value` 345 | FROM 346 | `XmlImportEntities` xie 347 | INNER JOIN `XmlImport` xi ON xie.`LocalId`=xi.`ItemId` AND xi.`AdapterId`=@adapter_id 348 | LEFT JOIN `mwcatalog_product_entity_varchar` varchars ON xie.`EntityId`=varchars.`entity_id` 349 | WHERE 350 | varchars.`value_id` IS NULL; 351 | 352 | -- insert varchars: image labels 353 | INSERT INTO `mwcatalog_product_entity_varchar` 354 | SELECT 355 | NULL AS `value_id`, 356 | 4 AS `entity_type_id`, 357 | 100 AS `attribute_id`, 358 | 0 AS `store_id`, 359 | xie.`EntityId` AS `entity_id`, 360 | xi.`Name` AS `value` 361 | FROM 362 | `XmlImportEntities` xie 363 | INNER JOIN `XmlImport` xi ON xie.`LocalId`=xi.`ItemId` AND xi.`AdapterId`=@adapter_id 364 | LEFT JOIN `mwcatalog_product_entity_varchar` varchars ON xie.`EntityId`=varchars.`entity_id` 365 | WHERE 366 | varchars.`value_id` IS NULL; 367 | 368 | -- insert varchars: small image labels 369 | INSERT INTO `mwcatalog_product_entity_varchar` 370 | SELECT 371 | NULL AS `value_id`, 372 | 4 AS `entity_type_id`, 373 | 101 AS `attribute_id`, 374 | 0 AS `store_id`, 375 | xie.`EntityId` AS `entity_id`, 376 | xi.`Name` AS `value` 377 | FROM 378 | `XmlImportEntities` xie 379 | INNER JOIN `XmlImport` xi ON xie.`LocalId`=xi.`ItemId` AND xi.`AdapterId`=@adapter_id 380 | LEFT JOIN `mwcatalog_product_entity_varchar` varchars ON xie.`EntityId`=varchars.`entity_id` 381 | WHERE 382 | varchars.`value_id` IS NULL; 383 | 384 | -- insert varchars: thumbnail labels 385 | INSERT INTO `mwcatalog_product_entity_varchar` 386 | SELECT 387 | NULL AS `value_id`, 388 | 4 AS `entity_type_id`, 389 | 102 AS `attribute_id`, 390 | 0 AS `store_id`, 391 | xie.`EntityId` AS `entity_id`, 392 | xi.`Name` AS `value` 393 | FROM 394 | `XmlImportEntities` xie 395 | INNER JOIN `XmlImport` xi ON xie.`LocalId`=xi.`ItemId` AND xi.`AdapterId`=@adapter_id 396 | LEFT JOIN `mwcatalog_product_entity_varchar` varchars ON xie.`EntityId`=varchars.`entity_id` 397 | WHERE 398 | varchars.`value_id` IS NULL; 399 | --------------------------------------------------------------------------------