Webylon 3.1 API Docs
  • Package
  • Class
  • Tree
  • Deprecated
  • Download
Version: current
  • 3.2
  • 3.1

Packages

  • auth
  • Booking
  • cart
    • shipping
    • steppedcheckout
  • Catalog
  • cms
    • assets
    • batchaction
    • batchactions
    • bulkloading
    • comments
    • content
    • core
    • export
    • newsletter
    • publishers
    • reports
    • security
    • tasks
  • Dashboard
  • DataObjectManager
  • event
  • faq
  • forms
    • actions
    • core
    • fields-basic
    • fields-dataless
    • fields-datetime
    • fields-files
    • fields-formatted
    • fields-formattedinput
    • fields-relational
    • fields-structural
    • transformations
    • validators
  • googlesitemaps
  • guestbook
  • installer
  • newsletter
  • None
  • photo
    • gallery
  • PHP
  • polls
  • recaptcha
  • sapphire
    • api
    • bulkloading
    • control
    • core
    • cron
    • dev
    • email
    • fields-formattedinput
    • filesystem
    • formatters
    • forms
    • i18n
    • integration
    • misc
    • model
    • parsers
    • search
    • security
    • tasks
    • testing
    • tools
    • validation
    • view
    • widgets
  • seo
    • open
      • graph
  • sfDateTimePlugin
  • spamprotection
  • stealth
    • captha
  • subsites
  • userform
    • pagetypes
  • userforms
  • webylon
  • widgets

Classes

  • Address
  • AddSubsiteTask
  • Announcement
  • AnnouncementDecorator
  • AnnouncementHolder
  • AssociatedFolderDecorator
  • AttachedFiles
  • AudioPhpCaptcha
  • AutoCompleteField
  • BaseMediawebImportParser
  • BookingOrder_StatusLog
  • CalendarUtil
  • CalendarWidgetExtention
  • CatalogCatalogLinkedDecorator
  • CatalogImportTask
  • CatalogOldFieldsDecorator
  • CatalogProductLinkedDecorator
  • CheckoutStep_ShippingMethod
  • ChequePayment
  • ClearHistoryTask
  • ClientEmailOrderNotification_SiteConfig
  • ClientVKOrderNotification_SiteConfig
  • CommentsSiteConfig
  • ContactsPage
  • CookieExtention
  • CostTableShippingRate
  • CustomMenu
  • CustomMenuAdmin
  • CustomMenuDecorator
  • CustomMenuHolder
  • CustomMenuItem
  • CustomPayment
  • DataObjectLoggerExtension
  • DataObjectSubsites
  • DefaultCMSActionDecorator
  • DeleteOldAssociatedFoldersTask
  • DocPage
  • DocumentDirection
  • DocumentHaving
  • DocumentSearchForm
  • DocumentSiteConfig
  • DocumentsPage
  • DocumentType
  • DOMUtil
  • ExtendPageAnnouncement
  • ExtendPageNews
  • ExtendPagePoll
  • FileOversizeDecorator
  • FindCyrillicSiteConfig
  • FolderRenameTask
  • GDMergeAlpha
  • HomePage
  • ImageAutoResize
  • ImageResizeTask
  • ImportAdmin
  • ImportAutoStartTask
  • ImportCatalogMessage
  • ImportConfig
  • ImportLog
  • ImportSiteConfig
  • ImportTask
  • LoggerAdmin
  • LogItem
  • ManagerEmailOrderNotification_SiteConfig
  • MapObject
  • MapObjectGroup
  • MapPage
  • MediawebForm
  • MediawebImportParser
  • MemberLoggerExtension
  • MultiUploadConfig
  • NearestEventExtention
  • NewDocumentsAdmin
  • News_Controller
  • NewsEntry
  • NewsEntry_Controller
  • NewsHolder
  • NewsHolder_Controller
  • NewsLiveCalendarWidget
  • NewsSiteConfig
  • Order_StatusLog
  • Orders1CExchange
  • PageHideFieldsExtension
  • PageInformerRates
  • PageInformerWeather
  • Payment_Failure
  • Payment_Processing
  • Payment_Result
  • Payment_Success
  • PaymentMethod
  • PaymentSiteConfig
  • PayPalPayment
  • PayPalPayment_Handler
  • PhoneField
  • PhotoAlbumExtentions
  • PhpCaptcha
  • PhpCaptchaColour
  • PhpCaptchaField
  • phpMorphy
  • phpMorphy_AncodesResolver_AsIs
  • phpMorphy_AncodesResolver_Proxy
  • phpMorphy_AncodesResolver_ToDialingAncodes
  • phpMorphy_AncodesResolver_ToText
  • phpMorphy_AnnotDecoder_Base
  • phpMorphy_AnnotDecoder_Common
  • phpMorphy_AnnotDecoder_Factory
  • phpMorphy_AnnotDecoder_Predict
  • phpMorphy_FilesBundle
  • phpMorphy_Fsa
  • phpMorphy_Fsa_Decorator
  • phpMorphy_Fsa_Proxy
  • phpMorphy_Fsa_Sparse_File
  • phpMorphy_Fsa_Sparse_Mem
  • phpMorphy_Fsa_Sparse_Shm
  • phpMorphy_Fsa_Tree_File
  • phpMorphy_Fsa_Tree_Mem
  • phpMorphy_Fsa_Tree_Shm
  • phpMorphy_Fsa_WordsCollector
  • phpMorphy_GramInfo
  • phpMorphy_GramInfo_AncodeCache
  • phpMorphy_GramInfo_Decorator
  • phpMorphy_Graminfo_File
  • phpMorphy_Graminfo_Mem
  • phpMorphy_GramInfo_Proxy
  • phpMorphy_GramInfo_Proxy_WithHeader
  • phpMorphy_GramInfo_RuntimeCaching
  • phpMorphy_Graminfo_Shm
  • phpMorphy_GrammemsProvider_Base
  • phpMorphy_GrammemsProvider_Decorator
  • phpMorphy_GrammemsProvider_Empty
  • phpMorphy_GrammemsProvider_Factory
  • phpMorphy_GrammemsProvider_ForFactory
  • phpMorphy_GrammemsProvider_ru_RU
  • phpMorphy_GramTab
  • phpMorphy_GramTab_Empty
  • phpMorphy_GramTab_Proxy
  • phpMorphy_Link
  • phpMorphy_Link_Annot
  • phpMorphy_Link_Base
  • phpMorphy_Morphier_Base
  • phpMorphy_Morphier_Bulk
  • phpMorphy_Morphier_Common
  • phpMorphy_Morphier_Empty
  • phpMorphy_Morphier_Finder_Base
  • phpMorphy_Morphier_Finder_Common
  • phpMorphy_Morphier_Finder_Predict_Databse
  • phpMorphy_Morphier_Finder_Predict_Suffix
  • phpMorphy_Morphier_Helper
  • phpMorphy_Morphier_Predict_Database
  • phpMorphy_Morphier_Predict_Suffix
  • phpMorphy_Morphier_PredictCollector
  • phpMorphy_Semaphore
  • phpMorphy_Semaphore_Empty
  • phpMorphy_Semaphore_Nix
  • phpMorphy_Semaphore_Win
  • phpMorphy_Shm_Cache
  • phpMorphy_Shm_Cache_FileDescriptor
  • phpMorphy_Shm_Header
  • phpMorphy_Source_Dba
  • phpMorphy_Source_Fsa
  • phpMorphy_State
  • phpMorphy_Storage
  • phpMorphy_Storage_Factory
  • phpMorphy_Storage_File
  • phpMorphy_Storage_Mem
  • phpMorphy_Storage_Proxy
  • phpMorphy_Storage_Shm
  • phpMorphy_UnicodeHelper
  • phpMorphy_UnicodeHelper_Base
  • phpMorphy_UnicodeHelper_MultiByteFixed
  • phpMorphy_UnicodeHelper_singlebyte
  • phpMorphy_UnicodeHelper_ucs_2be
  • phpMorphy_UnicodeHelper_ucs_2le
  • phpMorphy_UnicodeHelper_ucs_4be
  • phpMorphy_UnicodeHelper_ucs_4le
  • phpMorphy_UnicodeHelper_utf_16_Base
  • phpMorphy_UnicodeHelper_utf_16be
  • phpMorphy_UnicodeHelper_utf_16le
  • phpMorphy_UnicodeHelper_utf_32_Base
  • phpMorphy_UnicodeHelper_utf_32be
  • phpMorphy_UnicodeHelper_utf_32le
  • phpMorphy_UnicodeHelper_utf_8
  • phpMorphy_WordDescriptor
  • phpMorphy_WordDescriptor_Collection
  • phpMorphy_WordDescriptor_Collection_Serializer
  • phpMorphy_WordForm
  • ProductImportV1Decorator
  • ProductOldFieldsDecorator
  • ProductProductLinkedDecorator
  • PublHolder
  • Publication
  • PublicationSiteTree
  • RatingDataObject
  • RatingExtension
  • RealtySiteConfigDecorator
  • RecentComments
  • RecentFiles
  • RecentPages
  • RelatedPageLink
  • RepairImportTask
  • RoomRate_PriceField
  • RussianUpLower
  • SberbankPayment
  • SberbankPayment_Handler
  • SetMainSiteHomePageTypeTask
  • ShippingEstimator
  • ShippingPackage
  • ShowUserFromExtension
  • SiteConfigDecorator
  • SiteConfigSubsites
  • SiteTreeSubsites
  • SMSCOrderNotification_SiteConfig
  • SMSOrderNotification_SiteConfig
  • SortCMSActionDecorator
  • SS_Report_FakeQuery
  • SSMorphy
  • SSNController
  • SteppedCheckout_PageMessages
  • SubpageListField
  • SubscribeFormAllPagesExtension
  • SubsiteDropdownField
  • SubsiteReportWrapper
  • TableShippingRate
  • UnitellerPayment
  • UnitellerPayment_Handler
  • UnmoderatedComments
  • VideoManager
  • VideoSiteConfig
  • WatermarkImage
  • WatermarkSiteConfig
  • WebylonImportAdmin
  • WebylonImportCatalog
  • WeightTableShippingRate
  • XMLValidate
  • YaMoneyPayment
  • YaMoneyPayment_Handler
  • YMLExporter
  • YMLSiteConfig

Interfaces

  • ImportInterface
  • PaymentObjectInterface
  • phpMorphy_AncodesResolver_Interface
  • phpMorphy_AnnotDecoder_Interface
  • phpMorphy_Fsa_Interface
  • phpMorphy_GramInfo_Interace
  • phpMorphy_GrammemsProvider_Interface
  • phpMorphy_GramTab_Interface
  • phpMorphy_Morphier_Finder_Interface
  • phpMorphy_Morphier_Interface
  • phpMorphy_Shm_Cache_Interface
  • phpMorphy_Source_Interface

Exceptions

  • phpMorphy_Exception

Functions

  • column_sort
  • column_sort_callback_basic
  • encodeFileForEmail
  • encodeMultipart
  • getMimeType
  • htmlEmail
  • loadMimeTypes
  • phpmorphy_overload_mb_funcs
  • plaintextEmail
  • processHeaders
  • QuotedPrintable_encode
  • supressOutput
  • validateError
  • validEmailAddr
  • wrapImagesInline
  • wrapImagesInline_rewriter
  1 <?php
  2 
  3 /**
  4  * Осуществление импорта каталога через веб-интерфейс
  5  *
  6  * @author inxo
  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'; // delete|unpublish
 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 //      $f = Folder::findOrMake($this->imageRoot);
 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                 // Import -> ImportID
 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                 // Import -> ImportID
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      * @return <type>
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                     $config->setStatus('error');
179                     $config->setMessage("Ошибка сохранения товара ({$e->getMessage()}), id=" . $offer['id']);
180                     $config->write();
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         // Import -> ImportID
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         // Price -> BasePrice
232         $product->setField(self::$price_field, str_replace(',', '.', $price));
233         $product->Description = $offer['description'];
234         $product->Content = $offer['fulldesc'];
235         // vendor -> Vendor
236         $product->setField(self::$vendor_field,  $offer['vendor']); // Производитель
237         // * -> x
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         // Import -> ImportID
249         $product->setField(self::$import_field, $offer['id']);
250         
251         // обработка картинки
252         // TODO: сохранять дополнительные картинки
253         // TODO: отказ от импортирования картинок через тег <image>
254 
255         // некоторые пихают имя картинки в <image>
256         if ($offer['image'] && strlen($offer['image']) < 50) {
257             $offer['picture'] = $offer['image'];
258             unset($offer['image']);
259         }
260 
261         // в xml есть картинка
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             // картинка прямо в xml - сохраним в файл
273             if(isset($offer['image']) && $offer['image'] != ''){
274                 // Декодируем base64 в файл
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 //print "Image1: P:".$product->ID."\tnew:'$imageName'\told:'".$product->PhotoImport."'\tid:".$product->PhotoID."\n";
285                     // получим объект для картинки
286                     $file = false;
287                     // сначала вытащим по ID
288                     if ($product->PhotoID != 0) {
289                         $file = $product->Photo();
290                     }
291                     // не нашли по ID - поищем по пути к файлу
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                         // Если файл обновлен по ftp, а путь к нему не поменялся
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 //print "Image2: P:".$product->ID."\tnew:'$imageName'\told:'".$product->PhotoImport."'\tid:".$product->PhotoID."\n";
329             }
330             else {
331                 // параметр в xml есть, а файла нет - ошибка (сейчас ничего не делаем, возможно надо обнулять $product->PhotoID)
332             }
333         }
334         else {
335             // в xml картинки нет - проверить есть ли в товаре (но не делали для возможности ручной заливки картинок)
336         }
337 
338         // TODO: Обработка кода не одна категория для товара, нужно создавать виртуальные
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                     // Import -> ImportID
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 //              printf("доп. параметр: '%s'='%s' для товара '%s' (%d)\n", $name, $param['value'], $product->Title, $product->ID);
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     //        $product->writeWithoutVersion();
400             $product->write();
401             $product->publish('Stage', 'Live', false);
402         } else {
403             $product->Status = "Unpublished";
404             $product->write();
405         }
406     }
407 
408     /**
409      * Поиск родителя рубрики
410      * @param Int $parentId
411      * @return array
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. -
Webylon 3.1 API Docs API documentation generated by ApiGen 2.8.0