1 <?php
2
3 4 5 6 7
8 class WebylonImportCatalog extends MediawebImportParser {
9
10 private $updateCatalog = true;
11 private $updateProduct = true;
12 private $ghostRoot = false;
13 private $notFoundCatalogID = null;
14 private $imageRoot = 'images/';
15
16 static $catalog_version = 1;
17 static $old_item_action = 'delete';
18
19 private static $import_field = 'Import';
20 private static $vendor_field = 'vendor';
21 private static $price_field = 'Price';
22 private static $root_class = 'RootCatalog';
23
24 static function set_catalog_version($v) {
25 self::$catalog_version = $v;
26 if ($v == 1) {
27 self::$import_field = 'Import';
28 self::$vendor_field = 'vendor';
29 self::$price_field = 'Price';
30 self::$root_class = 'RootCatalog';
31 }
32 elseif ($v == 2) {
33 self::$import_field = 'ImportID';
34 self::$vendor_field = 'Vendor';
35 self::$price_field = 'BasePrice';
36 self::$root_class = 'StartCatalog';
37 }
38 else {
39 die("Unknown catalog version: '$v'");
40 }
41
42 }
43
44 function __construct($filename, $imagefolder = null, $encoding = 'UTF-8') {
45 parent::__construct($filename, $imagefolder, $encoding);
46
47
48 $config = new ImportConfig();
49 if ($config->clearDatabaseCatalog) {
50 $this->updateCatalog = false;
51 }
52 if ($config->clearDatabaseProducts) {
53 $this->updateProduct = false;
54 }
55 $sc = SiteConfig::current_site_config();
56 if ($sc->ImportRootGhost) {
57 $this->ghostRoot = $sc->ImportRootGhost;
58 }
59 if ($sc->ImportImagePath) {
60 $this->imageRoot = preg_replace('!//!', '/', $sc->ImportImagePath .'/');
61 }
62
63 }
64
65 function writeCatalogIntoDB() {
66 $start_catalog = DataObject::get_one(self::$root_class);
67 if (!$start_catalog) {
68 $this->setMessage('No RootCatalog');
69 return false;
70 }
71
72
73
74 if ($this->ghostRoot) {
75 foreach ($this->categories as $key => $category) {
76 if (!$category['parentid']) {
77 $ghost_id = $category['id'];
78 unset($this->categories[$key]);
79 }
80 if (isset($ghost_id) && $category['parentid'] == $ghost_id) {
81 $this->categories[$key]['parentid'] = null;
82 }
83 }
84 }
85
86 foreach ($this->categories as $key => $category) {
87
88 if ($category['id'] == $category['parentid']) {
89 $this->setMessage(sprintf('Parent point to itself for category (%s) (%s)', $category['id'], $category['parentid']));
90 return false;
91 }
92
93 if ($this->updateCatalog) {
94
95 $old = DataObject::get_one('Catalog', self::$import_field . " = '" . Convert::raw2sql($category['id']) . "'");
96 }
97
98
99 $parent = ($category['parentid']) ? $this->findParentCatalog($category['parentid']) : array('CatalogID' => $start_catalog->ID);
100
101 if (!$parent) {
102 $this->setMessage(sprintf('No parent (%s) for category (%s)', $category['parentid'], $category['id']));
103 return false;
104 }
105
106
107 if (isset($old) && $old) {
108 $this->categories[$key]['CatalogID'] = $old->ID;
109 $old->Title = $category['title'];
110 $old->ParentID = $parent['CatalogID'];
111 $old->write();
112 $old->doPublish();
113 } else {
114 $catalog = new Catalog();
115 $catalog->Title = $category['title'];
116 $catalog->ParentID = $parent['CatalogID'];
117
118 $catalog->setField(self::$import_field, $category['id']);
119 $catalog->write();
120 $this->categories[$key]['CatalogID'] = $catalog->ID;
121 $catalog->doPublish();
122 }
123 }
124
125 $this->convertCatalogInMemory();
126
127
128 $catalog = new Catalog();
129 $catalog->Title = 'Без рубрики ' . date('Y-m-d', time());
130 $catalog->ParentID = $start_catalog->ID;
131 $catalog->write();
132 $this->categories[-1]['CatalogID'] = $catalog->ID;
133
134
135 $f = fopen(ASSETS_PATH . '/_import/catalog', 'w+');
136 fwrite($f, serialize($this->categories));
137 fclose($f);
138
139 return true;
140 }
141
142 143 144 145
146 function writeIntoDb() {
147 return true;
148 }
149
150 function writeOffersIntoDB() {
151 $config = new ImportConfig();
152 if (!file_exists(ASSETS_PATH . '/_import/catalog')) {
153 $config->setStatus('error');
154 $config->setMessage('Ошибка перед началом импорта товаров. Не определена структура каталога');
155 $config->write();
156 return false;
157 }
158 $data = file_get_contents(ASSETS_PATH . '/_import/catalog');
159 $this->categories = unserialize($data);
160
161
162 if ($config->allOffers == 0) {
163 $config->allOffers = count($this->offers);
164 $config->write();
165 }
166
167 $i = 1;
168 foreach ($this->offers as $offer) {
169 if ($i < $config->getCursor()) {
170 $i++;
171 continue;
172 } else {
173 try {
174 $this->updateOrWriteProduct($offer);
175 } catch (Exception $e) {
176 $this->setMessage("Ошибка сохранения товара ({$e->getMessage()}), id=" . $offer['id']);
177 178 179 180 181
182
183 return false;
184 }
185
186
187
188 $config->incrementCursor();
189 $i++;
190 }
191 }
192
193
194
195
196 $images = DataObject::get('Image', "`Filename` LIKE '".self::$imageRoot."%'");
197 if ($images) {
198 foreach($images as $image) {
199 if (!file_exists($image->getFullPath())) {
200 DB::Query('UPDATE Product SET PhotoID = 0 WHERE PhotoID = ' . $image->ID);
201 DB::Query('UPDATE Product_Live SET PhotoID = 0 WHERE PhotoID = ' . $image->ID);
202 $image->deleteDatabaseOnly();
203
204 }
205 }
206 }
207
208
209 return true;
210 }
211
212 private function updateOrWriteProduct($offer) {
213 $importField = self::$import_field;
214 $priceField = self::$price_field;
215 $vendorField = self::$vendor_field;
216
217 if (isset($offer['price'])) {
218 $price = (float) (str_replace(',', '.', $offer['price']));
219 if (isset($offer['currencyId']) && isset($this->currency[$offer['currencyId']])) {
220 $currencyId = $offer['currencyId'];
221 $price = (float) $price * (float) ($this->currency[$currencyId]['rate']);
222 }
223 }
224
225
226 if (!$this->updateProduct || !$product = DataObject::get_one('Product', self::$import_field . " = '" . Convert::raw2sql($offer['id']) ."'")) {
227 $product = new Product();
228 }
229 $product->Title = $offer['title'];
230 $product->Available = $offer['available'];
231
232 $product->setField(self::$price_field, str_replace(',', '.', $price));
233 $product->Description = $offer['description'];
234 $product->Content = $offer['fulldesc'];
235
236 $product->setField(self::$vendor_field, $offer['vendor']);
237
238 if (self::$catalog_version == 1) {
239 $product->model = $offer['model'];
240 $product->url = $offer['url'];
241 $product->typePrefix = $offer['typePrefix'];
242 $product->vendorCode = $offer['vendorCode'];
243 }
244 else {
245 $product->AllowPurchase = 1;
246 }
247
248
249 $product->setField(self::$import_field, $offer['id']);
250
251
252
253
254
255
256 if ($offer['image'] && strlen($offer['image']) < 50) {
257 $offer['picture'] = $offer['image'];
258 unset($offer['image']);
259 }
260
261
262 if ($offer['picture'] && strlen($offer['picture']) > 0) {
263 $imageName = preg_replace('!^/!','', $offer['picture']);
264 $imageName = preg_replace('![^a-zA-Z0-9_/.-]+!','', $imageName);
265 if (!$imageName) {
266 if (!$product->ID) $product->write();
267 $imageName= 'p'.$product->ID . '.jpg';
268 }
269 if (strpos($imageName, '/') === false)
270 $imageName = $this->imageRoot . $imageName;
271
272
273 if(isset($offer['image']) && $offer['image'] != ''){
274
275 if (!file_exists(Director::baseFolder() . '/' . $imageName)) {
276 $decode = base64_decode($offer['image']);
277 file_put_contents(Director::baseFolder().'/'.$imageName, $decode);
278 }
279 }
280
281
282 if (is_file(Director::baseFolder() . '/' . $imageName)) {
283 try {
284
285
286 $file = false;
287
288 if ($product->PhotoID != 0) {
289 $file = $product->Photo();
290 }
291
292 if (!$file) {
293 $file = DataObject::get_one('Image',"\"Filename\"='".Convert::raw2sql($imageName)."'", true, 'ID DESC');
294 }
295
296 if (!$file) {
297 $file = new Image();
298 $file->setFilename($imageName);
299 $file->Name = basename($imageName);
300
301 $file->write();
302 }
303
304
305 if ($product->PhotoImport != $imageName || $product->PhotoID != $file->ID) {
306 if (!$file->Name) $file->Name = basename($imageName);
307 if ($file->Filename && $file->Filename != $imageName)
308 $file->deleteFormattedImages();
309
310 $file->setFilename($imageName);
311 $file->deleteFormattedImages();
312
313 $FileID = $file->write();
314 $product->PhotoImport = $imageName;
315 $product->PhotoID = $FileID;
316 }
317 elseif ($product->PhotoID != 0) {
318
319 if (filectime(Director::baseFolder().'/'.$imageName) > strtotime($product->Photo()->LastEdited)) {
320 $file->deleteFormattedImages();
321 $file->forceChange();
322 $file->write();
323 }
324 }
325 } catch (Exception $e) {
326 throw new Exception("Ошибка импорта файла {$imageName}. " . $e->getMessage());
327 }
328
329 }
330 else {
331
332 }
333 }
334 else {
335
336 }
337
338
339 foreach ($offer['categories'] as $category) {
340 if (isset($this->categories[$category['id']]) && is_numeric($this->categories[$category['id']]['CatalogID'])) {
341 $product->ParentID = $this->categories[$category['id']]['CatalogID'];
342 } else {
343 $product->ParentID = $this->categories[-1]['CatalogID'];
344 }
345 }
346
347 if (is_array($offer['special']) && count($offer['special']) > 0) {
348 if (!$product->ID)
349 $product->writeWithoutVersion();
350 $productSpecial = $product->SpecialCatalogs();
351
352 $productSpecial->removeAll();
353 foreach ($offer['special'] as $obj) {
354 $special = false;
355 if (isset($obj['id']) && $obj['id']) {
356
357 $special = DataObject::get_one('SpecialCatalog', "Import = '" . Convert::raw2sql($obj['id']) . "'");
358 }
359 elseif (isset($obj['url']) && $obj['url']) {
360 $special = DataObject::get_one('SpecialCatalog', "URLsegment = '" . Convert::raw2sql($obj['url']) . "'");
361 }
362 elseif (isset($obj['siteid']) && $obj['siteid']) {
363 $special = DataObject::get_by_id('SpecialCatalog', $obj['siteid']);
364 }
365 else {
366 continue;
367 }
368
369 if ($special) {
370
371 $productSpecial->add($special);
372 }
373 else {
374 printf("Неизвестный спецкаталог: %s для товара '%s' (%s)\n", var_dump($obj), $product->Title, $product->Import);
375 }
376 }
377 }
378
379
380 foreach ($offer['params'] as $param) {
381 $name = $param['name'];
382 if ($product->db($name)) {
383 $product->{$name} = Convert::raw2sql($param['value']);
384 } elseif ($product->has_one($name)) {
385 if (!$product->ID)
386 $product->writeWithoutVersion();
387 $product->$name()->setValue($param['value']);
388 $product->$name()->write();
389
390 }
391 else {
392 printf("Неизвестный доп. параметр: '%s' для товара '%s' (%s)\n", $name, $product->Title, $product->Import);
393 }
394
395 }
396
397 if ($product->ParentID != $this->categories[-1]['CatalogID']) {
398 $product->Status = 'Published';
399
400 $product->write();
401 $product->publish('Stage', 'Live', false);
402 } else {
403 $product->Status = "Unpublished";
404 $product->write();
405 }
406 }
407
408 409 410 411 412
413 private function findParentCatalog($parentId) {
414 foreach ($this->categories as $category) {
415 if ($category['id'] == $parentId) {
416 return $category;
417 }
418 }
419 return false;
420 }
421
422 423 424
425 private function convertCatalogInMemory() {
426 $memory = array();
427 foreach ($this->categories as $category) {
428 $id = $category['id'];
429 $memory[$id] = $category;
430 }
431 $this->categories = $memory;
432 }
433
434 function unpublishNotUpdated() {
435 $config = new ImportConfig();
436
437 $needUnpublish = DataObject::get('Product', 'LastEdited < \'' . date("Y-m-d H:i:s", $config->startTime) . '\'');
438 if ($needUnpublish)
439 foreach ($needUnpublish as $product) {
440 $product->doUnpublish();
441 if (self::$old_item_action == 'delete') {
442 $product->delete();
443 }
444
445 }
446
447 $needUnpublish = DataObject::get('Catalog', 'ClassName<>\'RootCatalog\' AND LastEdited < \'' . date("Y-m-d H:i:s", $config->startTime) . '\'');
448 if ($needUnpublish)
449 foreach ($needUnpublish as $product) {
450 $product->doUnpublish();
451 }
452 return true;
453 }
454
455
456 function deleteBadImages() {
457 $importFiles = DataObject::get('Image',"\"Filename\" LIKE '{$this->imageRoot}%'");
458 if ($importFiles) {
459 foreach($importFiles as $importFile) {
460 if(!file_exists($importFile->getFullPath())) {
461 $set = "PhotoID = 0, PhotoImport = NULL";
462 if (self::$catalog_version == 2) {
463 $set = "PhotoID = 0";
464 }
465 DB::Query("UPDATE Product SET {$set} WHERE PhotoID = {$importFile->ID}");
466 DB::Query("UPDATE Product_Live SET {$set} WHERE PhotoID = {$importFile->ID}");
467 $importFile->deleteDatabaseOnly();
468 }
469 }
470 }
471 return true;
472 }
473
474 }
475
[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.
-