1 <?php
2
3
4 class ImportCatalog1C_Importer extends Base1CExchanger {
5
6 protected $categoryCount = 0;
7 protected $productCount = 0;
8 protected $offersCount = 0;
9
10 static $startTime;
11
12 private $CATEGORIES = array();
13
14 private static $max_version_count = 1;
15
16 function init() {
17
18 Versioned::$versions_ttl = self::$max_version_count;
19
20
21 AssociatedFolderDecorator::$createFolders = false;
22
23
24 if (class_exists('LogItem')) {
25 LogItem::enable(false);
26 }
27 }
28
29 function importCatalog($importFile, $log) {
30
31 $startTime = self::$startTime;
32 $this->init();
33
34 $log->addStatus('process', _t('ProductCatalogImport.CatalogImportStarted', 'Catalog Import started'));
35 $log->addLog(_t('ProductCatalogImport.CatalogImportStarted', 'Catalog Import started'));
36
37
38
39 $xml = simplexml_load_file($importFile);
40 $data = array();
41
42
43 $sc = SiteConfig::current_site_config();
44
45 $startPage = DataObject::get_by_id('SiteTree', (int)$sc->StartPage);
46
47
48 if (!$startPage) {
49 $log->addLog(_t('ProductCatalogImport.NoRoot', 'No Root'), 'warning');
50 return false;
51 }
52
53 if($xml->Классификатор->Группы) $this->insertCategory($xml->Классификатор->Группы->Группа, $startPage->ID);
54 $msg = sprintf(_t('ProductCatalogImport.ImportedCatalogsCount', 'Imported Catalogs Count: %d'), $this->categoryCount);
55 $log->addStatus('process', $msg);
56 $log->addLog($msg);
57
58
59 if ($xml->Каталог->attributes()->{'СодержитТолькоИзменения'} == "false") {
60 $importType = 'full';
61 } else {
62 $importType = 'incremental';
63 }
64
65
66 if ($xml->Каталог->Товары->Товар) {
67 $log->addStatus('process', _t('ProductCatalogImport.ProductImportStarted', 'Product import started'));
68 $log->addLog(_t('ProductCatalogImport.ProductImportStarted', 'Product import started'));
69 $log->addLog(_t('ProductCatalogImport.ImportType', 'Import mode: ') . _t('ProductCatalogImport.ImportType_' . $importType, $importType));
70
71 foreach ($xml->Каталог->Товары->Товар as $product) {
72 $importID = (string)$product->Ид;
73 $newProduct = DataObject::get_one('Product', "ImportID = '{$importID}'");
74 if (!$newProduct) {
75 $newProduct = new Product();
76 $newProduct->ImportID = $importID;
77 }
78 $newProduct->ShowInSearch = 1;
79 $newProduct->Title = (string)$product->Наименование;
80
81
82
83
84
85
86 if((string)$product->Описание){
87 $content = "";
88 $splitted = explode("\n",(string)$product->Описание);
89 foreach ($splitted as $line) {
90 $content .= "<p>$line</p>";
91 }
92 $newProduct->Content = $content;
93 }
94
95 $newProduct->SKU = (string)$product->Артикул;
96 $newProduct->VendorCountry = (string)$product->СтранаПроисхождения;
97
98
99 if (isset($this->CATEGORIES[(string)$product->Группы->Ид])) {
100 $newProduct->ParentID = $this->CATEGORIES[(string)$product->Группы->Ид];
101 } else {
102
103 $newProduct->ParentID = 0;
104 }
105
106 $newProduct->writeToStage('Stage');
107 $newProduct->publish('Stage', 'Live');
108
109
110 if ($product->ЗначенияРеквизитов) {
111 foreach ($product->ЗначенияРеквизитов->ЗначениеРеквизита as $prop) {
112 $newProp = DataObject::get_one('ImportCatalog1C_ProductProp', "Title = '{$prop->Наименование}'");
113 if (!$newProp) {
114 $newProp = new ImportCatalog1C_ProductProp();
115 $newProp->Title = (string)$prop->Наименование;
116 $newProp->write();
117 }
118 if ($newProp->ProductField && trim((string)$prop->Значение)) {
119 $newProduct->{$newProp->ProductField} = trim((string)$prop->Значение);
120 }
121 }
122 }
123
124
125 if ($product->Картинка) {
126 $first = true;
127 $oldPhotos = $newProduct->Photos();
128 $oldPhotosIDs = $oldPhotos->getIdList();
129 $newProduct->Photos()->removeAll();
130
131 foreach ($product->Картинка as $photo) {
132 if ($first) {
133 if ($mainPhoto = self::import_photo($newProduct->PhotoID, (string)$photo)) {
134 $newProduct->PhotoID = ($mainPhoto) ? $mainPhoto->ID : 0;
135 $first = false;
136 }
137 } else {
138 $galleryPhoto = self::import_photo(0, (string)$photo);
139 if ($galleryPhoto) {
140 if ($mwPhoto = $oldPhotos->find('PhotoID', $galleryPhoto->ID)) {
141 unset($oldPhotosIDs[$mwPhoto->ID]);
142 } else {
143 $mwPhoto = new MediawebPage_Photo();
144 $mwPhoto->PhotoID = $galleryPhoto->ID;
145 }
146 $mwPhoto->MediawebPageID = $newProduct->ID;
147 $mwPhoto->Caption = $galleryPhoto->Title;
148 $mwPhoto->write();
149 }
150 }
151 }
152 if (count($oldPhotosIDs) > 0) {
153 foreach($oldPhotosIDs as $oldPhotosID) {
154 if ($oldPhoto = $oldPhotos->find('ID', $oldPhotosID)) {
155 $oldPhoto->delete();
156 }
157 }
158 }
159 }
160 $newProduct->writeToStage('Stage');
161 $newProduct->publish('Stage', 'Live');
162
163 $this->productCount++;
164 if ($this->productCount % 100 == 0) {
165 $log->addStatus('process', sprintf(_t('ProductCatalogImport.ImportedProductsCount', 'Imported %d Products'), $this->productCount));
166 }
167 if (is_file(self::absolute_import_path('stop_import'))) {
168 $log->addLog(_t('ProductCatalogImport.InterruptByUser', 'Пользователь отправил запрос на прерывание импорта'));
169 return;
170 }
171 }
172 $msg = sprintf(_t('ProductCatalogImport.ImportedProductsCount', 'Imported %d Products'), $this->productCount);
173 $log->addStatus('process', $msg);
174 $log->addLog($msg);
175 }
176
177 if ($importType == 'full') {
178 $this->unpublishNotUpdated($startTime, $log);
179 }
180 }
181
182 function ImportOffers($importFile, $log) {
183
184 $startTime = self::$startTime;
185 $this->init();
186
187 $msg = _t('ProductCatalogImport.OffersImportStarted', 'Offers Import Started');
188 $log->addStatus('process', $msg);
189 $log->addLog($msg);
190
191
192 $xml = simplexml_load_file($importFile);
193 $data = array();
194
195
196
197 if ($xml->ПакетПредложений->attributes()->{'СодержитТолькоИзменения'} == "false") {
198 $importType = 'full';
199 } else {
200 $importType = 'incremental';
201 }
202 $log->addLog(_t('ProductCatalogImport.ImportType', 'Import mode: ') . _t('ProductCatalogImport.ImportType_' . $importType, $importType));
203
204
205
206 if ($xml->ПакетПредложений->ТипыЦен) {
207 foreach ($xml->ПакетПредложений->ТипыЦен->ТипЦены as $priceType) {
208 $priceID = Convert::raw2sql((string)$priceType->Ид);
209 $newPriceType = DataObject::get_one('ImportCatalog1C_PriceType', "PriceID = '{$priceID}'");
210 if (!$newPriceType) {
211 $newPriceType = new ImportCatalog1C_PriceType();
212 $newPriceType->PriceID = $priceID;
213 }
214 $newPriceType->Title = Convert::raw2sql((string)$priceType->Наименование);
215 $newPriceType->Currency = Convert::raw2sql((string)$priceType->Валюта);
216 $newPriceType->write();
217 }
218 }
219
220 $sc = SiteConfig::current_site_config();
221 if (!$sc->BasePriceTypeID || !$sc->BasePriceType()->PriceID) {
222 $log->addLog(_t('ProductCatalogImport.BadPriceType', 'Bad Price Type'), 'error');
223 $log->addStatus('error', _t('ProductCatalogImport.BadPriceType', 'Bad Price Type'));
224 return false;
225 }
226
227
228 if ($xml->ПакетПредложений->Предложения) {
229 foreach ($xml->ПакетПредложений->Предложения->Предложение as $offer) {
230 $importID = (string)$offer->Ид;
231
232 if (strpos($importID, '#') !== false) {
233 echo $importID ."\n";
234 $importID = substr($importID, 0, strpos($importID, '#'));
235 }
236 $newProduct = DataObject::get_one('Product', "ImportID = '{$importID}'");
237 if (!$newProduct) {
238
239 continue;
240 }
241
242
243 $newProduct->Available = 0;
244 $newProduct->AllowPurchase = 0;
245 if ($offer->Цены) {
246 foreach ($offer->Цены->Цена as $price) {
247 if ($price->ИдТипаЦены == $sc->BasePriceType()->PriceID) {
248 $newProduct->BasePrice = (float)$price->ЦенаЗаЕдиницу;
249 }
250 if ($price->ИдТипаЦены == $sc->CostPriceType()->PriceID) {
251 $newProduct->CostPrice = (float)$price->ЦенаЗаЕдиницу;
252 }
253 }
254 $newProduct->Available = 1;
255 $newProduct->AllowPurchase = 1;
256 }
257
258
259
260 $newProduct->Quantity = (int)$offer->Количество;
261 $newProduct->writeToStage('Stage');
262
263
264
265
266 $newProduct->publish('Stage', 'Live');
267
268
269 $this->offersCount++;
270 if ($this->offersCount % 100 == 0) {
271 $log->addStatus('process', sprintf(_t('ProductCatalogImport.ImportedOffersCount', 'Imported %d Offers'), $this->offersCount));
272 }
273
274 if (is_file(self::absolute_import_path('stop_import'))) {
275 $log->addLog(_t('ProductCatalogImport.InterruptByUser', 'Пользователь отправил запрос на прерывание импорта'));
276 return;
277 }
278 }
279 $log->addStatus('process', sprintf(_t('ProductCatalogImport.ImportedOffersCount', 'Imported %d Offers'), $this->offersCount));
280 $log->addLog(sprintf(_t('ProductCatalogImport.ImportedOffersCount', 'Imported %d Offers'), $this->offersCount));
281
282 if ($importType == 'full') {
283 $this->unpublishNotUpdated($startTime, $log, true);
284 }
285
286 $msg = sprintf(_t('ProductCatalogImport.ImportDone', 'Import done. Updated: %d catalogs, %d products, %d offers'), $this->categoryCount, $this->productCount, $this->offersCount);
287 $log->addLog($msg);
288 $log->addStatus('ok', $msg);
289 return true;
290 }
291 }
292
293 function unpublishNotUpdated($importStartTime, $log, $offersOnly=false) {
294 $importStartTime = strtotime($importStartTime);
295 $log->addLog(_t('ProductCatalogImport.HideProductsStarted', 'Find & hide old products'));
296 $log->addStatus('process', _t('ProductCatalogImport.HideProductsStarted', 'Find & hide old products'));
297
298 $hideCatalogCount = 0;
299 $hideProductCount = 0;
300 $sc = SiteConfig::current_site_config();
301
302 $needUnpublish = DataObject::get('Product', 'ImportID IS NOT NULL AND LastEdited < \'' . date("Y-m-d H:i:s", strtotime($importStartTime)) . '\'');
303 if ($needUnpublish) {
304 foreach ($needUnpublish as $product) {
305 switch ($sc->OldItemAction) {
306 case 'hide':
307 $product->AllowPurchase = 0;
308 $product->writeToStage('Stage');
309 if ($product->isPublished()) {
310 $product->publish('Stage', 'Live');
311 }
312 break;
313 case 'unpublish':
314 $product->doUnpublish();
315 break;
316 case 'delete':
317 $product->doUnpublish();
318 $product->delete();
319 break;
320 default:
321 $product->doUnpublish();
322 $product->delete();
323 break;
324 }
325 $log->addLog("Скрыт товар {$product->Title} ({$product->ID})");
326 $hideProductCount++;
327 if ($hideProductCount % 100 == 0) {
328 $log->addStatus('process', sprintf(_t('ProductCatalogImport.HiddenProductsCount', 'Hide %d products'), $hideProductCount));
329 }
330
331 }
332 $log->addStatus('process', sprintf(_t('ProductCatalogImport.HiddenProductsCount', 'Hide %d products'), $hideProductCount));
333 $log->addLog(sprintf(_t('ProductCatalogImport.HiddenProductsCount', 'Hide %d products'), $hideProductCount));
334 }
335
336 if (!$offersOnly) {
337
338 $log->addLog(_t('ProductCatalogImport.HideCatalogsStarted', 'Find & hide old catalogs'));
339 $log->addStatus('process', _t('ProductCatalogImport.HideCatalogsStarted', 'Find & hide old catalogs'));
340
341 $needUnpublish = DataObject::get('Catalog', 'ImportID IS NOT NULL AND ClassName = \'Catalog\' AND LastEdited < \'' . date("Y-m-d H:i:s", $importStartTime) . '\'');
342 if ($needUnpublish) {
343 foreach ($needUnpublish as $catalog) {
344 switch ($sc->OldItemAction) {
345 case 'hide':
346 $catalog->ShowInMenus = 0;
347 $catalog->writeToStage('Stage');
348 if ($catalog->isPublished()) {
349 $catalog->publish('Stage', 'Live');
350 }
351 break;
352 case 'unpublish':
353 $catalog->doUnpublish();
354 break;
355 case 'delete':
356 $catalog->doUnpublish();
357 $catalog->delete();
358 break;
359 default:
360 $catalog->doUnpublish();
361 $catalog->delete();
362 break;
363 }
364 $hideCatalogCount++;
365 if ($hideCatalogCount % 100 == 0) {
366 $log->addStatus('process', sprintf(_t('ProductCatalogImport.HiddenCatalogsCount', 'Hide %d catalogs'), $hideCatalogCount));
367 }
368 }
369 }
370 $log->addStatus('process', sprintf(_t('ProductCatalogImport.HiddenCatalogsCount', 'Hide %d catalogs'), $hideCatalogCount));
371 $log->addLog(sprintf(_t('ProductCatalogImport.HiddenCatalogsCount', 'Hide %d catalogs'), $hideCatalogCount));
372
373 }
374 return true;
375 }
376
377 378 379 380 381 382
383 private function insertCategory($xml, $parent = 0) {
384 foreach ($xml as $category){
385 if (isset($category->Ид) && isset($category->Наименование) ){
386 $id = (string)$category->Ид;
387 $data = array();
388
389 $newCat = DataObject::get_one('Catalog', "ImportID = '{$id}'");
390 if (!$newCat) {
391 $newCat = new Catalog();
392 $newCat->ImportID = $id;
393 }
394 $newCat->Title = (string)$category->Наименование;
395 $newCat->ParentID = $parent;
396
397 $newCat->writeToStage('Stage');
398 $newCat->publish('Stage', 'Live');
399 $this->CATEGORIES[$id] = $newCat->ID;
400
401 $this->categoryCount++;
402 }
403 if ($category->Группы) $this->insertCategory($category->Группы->Группа, $newCat->ID);
404 }
405 unset($xml);
406 }
407
408 409 410 411 412 413 414 415
416 private static function import_photo($photoID, $imagePath) {
417 $imagePath = trim(str_replace("\\", "/", $imagePath));
418 if ($imagePath) {
419 $fullImagePath = self::absolute_import_path($imagePath);
420 $imagePath = self::import_path($imagePath);
421
422
423 $file = false;
424
425 if ($photoID != 0) {
426 $file = DataObject::get_by_id('Image', $photoID);
427 }
428
429
430 if (!$file || $file->ID == 0) {
431 $file = DataObject::get_one('Image', "\"Filename\"='".Convert::raw2sql($imagePath)."'", true, 'ID DESC');
432 }
433
434
435 if (is_file($fullImagePath)) {
436
437 if (!$file || $file->ID == 0) {
438 $file = new Image();
439 $file->setFilename($imagePath);
440 $file->Title = $file->Name;
441 $file->write();
442 }
443
444 if ($file->Filename != $imagePath) {
445
446 $file = DataObject::get_one('Image', "\"Filename\"='".Convert::raw2sql($imagePath)."'", true, 'ID DESC');
447
448 if (!$file) {
449 $file = new Image();
450 $file->setFilename($imagePath);
451 $file->Title = $file->Name;
452 $file->write();
453 }
454 }
455
456
457 if (($photoID != $file->ID)) {
458 if (!$file->Name) {
459 $file->Name = basename($imagePath);
460 }
461 if ($file->Filename && $file->Filename != $imagePath) {
462 $file->deleteFormattedImages();
463 }
464 $file->setFilename($imagePath);
465 $file->deleteFormattedImages();
466 if (!$file->Title)
467 $file->Title = $file->Name;
468 $file->write();
469 }
470 elseif ($photoID != 0) {
471
472 if (filemtime($fullImagePath) > strtotime($file->LastEdited)) {
473
474
475 $file->deleteFormattedImages();
476
477 $file->forceChange();
478 if (!$file->Title)
479 $file->Title = $file->Name;
480 $file->write();
481 }
482 }
483 return $file;
484 }
485 else {
486
487 if ($file) {
488 $file->deleteFormattedImages();
489 $file->deleteDatabaseOnly();
490 }
491 }
492 }
493 return false;
494 }
495 }
496
[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the
Silverstripe Forums to ask development related questions.
-