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

Packages

  • 1c
    • exchange
      • catalog
  • auth
  • Booking
  • building
    • company
  • cart
    • shipping
    • steppedcheckout
  • Catalog
    • monument
  • 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
  • Base1CExchanger
  • BookingOrder_StatusLog
  • CalendarUtil
  • CalendarWidgetExtention
  • CatalogCatalogLinkedDecorator
  • CatalogOldFieldsDecorator
  • CatalogProductLinkedDecorator
  • CheckoutStep_ShippingMethod
  • ChequePayment
  • ClearHistoryTask
  • ClientEmailOrderNotification_SiteConfig
  • ClientVKOrderNotification_SiteConfig
  • CommentsSiteConfig
  • ContactsPage
  • CookieExtention
  • CostTableShippingRate
  • CustomMenu
  • CustomMenuAdmin
  • CustomMenuDecorator
  • CustomMenuHolder
  • CustomMenuItem
  • CustomPayment
  • DataObjectLoggerExtension
  • DataObjectSubsites
  • DefaultCMSActionDecorator
  • DocPage
  • DocumentDirection
  • DocumentHaving
  • DocumentSearchForm
  • DocumentSiteConfig
  • DocumentsPage
  • DocumentType
  • DOMUtil
  • ExtendPageAnnouncement
  • ExtendPagePoll
  • FavoriteExtention
  • FavoritePage
  • FavoriteProductMemberExtention
  • FavoriteProducts
  • FileOversizeDecorator
  • FindCyrillicSiteConfig
  • FolderRenameTask
  • GDMergeAlpha
  • HomePage
  • ImageAutoResize
  • ImageResizeTask
  • ImportCatalog1C_Importer
  • ImportCatalogSiteConfig
  • ImportSiteConfig
  • LoggerAdmin
  • LogItem
  • ManagerEmailOrderNotification_SiteConfig
  • MapObject
  • MapObjectGroup
  • MapPage
  • MediawebForm
  • MemberLoggerExtension
  • MonumentsSiteConfig
  • MultiUploadConfig
  • NearestEventExtention
  • NewDocumentsAdmin
  • NewsArchive
  • NewsEntry
  • NewsHolder
  • NewsSiteConfig
  • Order_StatusLog
  • Orders1CExchange_Exporter
  • 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
  • ProductCatalogImportTask
  • ProductOldFieldsDecorator
  • ProductParamValue_BoolValueField
  • ProductParamValue_MultiValueField
  • ProductParamValue_MultiValueSetField
  • ProductParamValue_ValueField
  • ProductProductLinkedDecorator
  • PublHolder
  • Publication
  • PublicationSiteTree
  • RatingDataObject
  • RatingExtension
  • RealtySiteConfigDecorator
  • RecentComments
  • RecentFiles
  • RecentPages
  • RelatedPageLink
  • RoomRate_PriceField
  • RussianUpLower
  • SberbankPayment
  • SberbankPayment_Handler
  • SetMainSiteHomePageTypeTask
  • ShippingEstimator
  • ShippingPackage
  • ShowUserFromExtension
  • ShowViewedProductExtention
  • SiteConfigDecorator
  • SiteConfigSubsites
  • SiteTreeSubsites
  • SMSCOrderNotification_SiteConfig
  • SMSOrderNotification_SiteConfig
  • Socle
  • SocleSize
  • SortCMSActionDecorator
  • SS_Report_FakeQuery
  • SSMorphy
  • SSNController
  • SteppedCheckout_PageMessages
  • SubpageListField
  • SubscribeFormAllPagesExtension
  • SubsiteDropdownField
  • SubsiteReportWrapper
  • TableShippingRate
  • UnitellerPayment
  • UnitellerPayment_Handler
  • UnmoderatedComments
  • VAT
  • VideoManager
  • VideoSiteConfig
  • ViewedProductExtention
  • WatermarkImage
  • WatermarkSiteConfig
  • WeightTableShippingRate
  • XMLValidate
  • YaMoneyPayment
  • YaMoneyPayment_Handler
  • YMLExporter
  • YMLSiteConfig

Interfaces

  • 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
  • validEmailAddr
  • wrapImagesInline
  • wrapImagesInline_rewriter
   1 <?php
   2 /**
   3  * Процесс импортирования каталога 0.9
   4  * sake /ProductCatalogImportTask
   5  *
   6  * @author menedem
   7  */
   8 class ProductCatalogImportTask extends ScheduledTask {
   9 
  10     private static $baseFileURL = 'offers/';
  11     private static $importFileName = 'catalog.xml';
  12 
  13     protected $importStatus;
  14     protected $importLog;
  15     private static $max_version_count = 1;
  16     private static $max_log_count = 30;
  17     
  18     // разрешен импорт параметров каталога
  19     protected static $allow_parameters = true;
  20     
  21     // разрешен импорт фильтров каталога
  22     protected static $allow_filters = true;
  23     
  24     // кешированный список параметров каталога
  25     protected $cachedCatalogParams = array();
  26             
  27     protected $categoryCount = 0;
  28     protected $productCount = 0;
  29     
  30     protected static $possibleStartPages = array('StartCatalog', 'Catalog', 'DocPage');
  31     
  32     // настройки импорта
  33     protected $importSettings = false;
  34     
  35     protected static $possibleSettings = array('ImportMode' => 'full', 'ClearProducts' => 0, 'ClearCategory'=>0, 'StartPage'=>'/', 'SubSite'=>0, 'OldItemAction'=>'delete');
  36     
  37     protected static $catalog_version = 3;
  38     
  39     static $catalog_saveable_fields = array('URLSegment', 'Description', 'Content', 'MenuTitle', 'MetaTitle', 'MetaKeywords', 'MetaDescription', 'GroupTitle', 'Sort');
  40     
  41     static $product_saveable_fields_v2 = array('URLSegment', 'Description', 'Content', 'Vendor', 'MenuTitle', 'MetaTitle', 'MetaKeywords', 'MetaDescription', 'Available', 'AllowPurchase', 'Sort');
  42     
  43     static $product_saveable_fields_v3 = array('URLSegment', 'Description', 'Content', 'Vendor', 'SKU', 'MenuTitle', 'MetaTitle', 'MetaKeywords', 'MetaDescription', 'Available', 'AllowPurchase','Quantity', 'Weight', 'GroupID', 'GroupTitle', 'Sort');
  44     
  45     /**
  46      * Задаем версию каталога для импорта (2 - для catalog-0.8, 3 - для catalog-0.9)
  47      * 
  48      * @param Int $version (2 или 3)
  49      *      
  50      */ 
  51     static function set_catalog_version($version) {
  52         if ($version == 2 || $version == 3) {
  53             self::$catalog_version = $version;
  54         }
  55         // для catalog-0.8 отключаем импорт параметров и фильтров (не реализованы в этой версии)
  56         if ($version == 2) {
  57             self::$allow_parameters = false;
  58             self::$allow_filters = false;
  59         }
  60     }
  61     
  62     // получаем список полей товара для сохранения
  63     protected static function get_product_saveable_fields() {
  64         if (self::$catalog_version == 3) {
  65             return self::$product_saveable_fields_v3;
  66         }
  67         return self::$product_saveable_fields_v2;
  68     }
  69     
  70     static function getImportFileName() {
  71         return self::$importFileName;
  72     }
  73     
  74     static function set_base_url($url) {
  75         self::$baseFileURL = $url;
  76     }
  77 
  78     static function get_base_url() {
  79         return preg_replace('!/+$!','', self::$baseFileURL) . '/';
  80     }
  81     
  82     /**
  83      * Путь к папке импорта относительно корня сайта
  84      *
  85      * @param string $filename
  86      *
  87      * @return string
  88      */
  89     static function import_path($filename) {
  90         return self::get_base_url() . preg_replace('!^/!', '', $filename);
  91     }
  92 
  93     /**
  94      * Полный путь к папке импорта (может быть указано имя файла в этой папке)
  95      *
  96      * @param string $filename
  97      *
  98      * @return string
  99      */
 100     static function absolute_import_path($filename) {
 101         return BASE_PATH . '/' . self::import_path($filename);
 102     }
 103     
 104     /**
 105      * Полный путь к корню модуля (может быть указано имя файла в этой папке) - например для получения catalog2.xsd
 106      *
 107      * @param string $filename
 108      *
 109      * @return string
 110      */
 111     static function module_path($filename) {
 112         return BASE_PATH . '/catalog_import/' . $filename;
 113     }
 114     
 115     /**
 116      * Установка количества хранимых логов импорта
 117      *
 118      * @param int $count
 119      */
 120     static function set_log_count($count) {
 121         self::$max_log_count = $count;
 122     }
 123     
 124     /**
 125      * Установка количества хранимых версий страниц (чтоб не плодить версии при импорте)
 126      *
 127      * @param int $count
 128      */
 129     static function set_version_count($count) {
 130         self::$max_version_count = $count;
 131     }
 132     
 133     /**
 134      * Получение допустимых типов корневых страниц для импорта
 135      *
 136      * @return Array
 137      */
 138     static function get_possible_start_pages() {
 139         return self::$possibleStartPages;
 140     }
 141     
 142     /**
 143      * Установка допустимых типов корневых страниц для импорта
 144      *
 145      * @param Array $pages
 146      */
 147     static function set_possible_start_pages($pages) {
 148         self::$possibleStartPages = $pages;
 149     }
 150 
 151     /**
 152      * Установка разрешения импорта параметров
 153      *
 154      * @param bool $val
 155      */
 156     static function set_allow_parameters($val) {
 157         self::$allow_parameters = $val;
 158     }
 159     
 160     /**
 161      * Установка разрешения импорта параметров
 162      *
 163      * @param bool $val
 164      */
 165     static function set_allow_filters($val) {
 166         self::$allow_filters = $val;
 167     }
 168     
 169     static function import_parse_bool_value($value) {       
 170         if (in_array($value, array('true', '1'))) {
 171             return 1;
 172         }
 173         if (in_array($value, array('false', '0'))) {
 174             return 0;
 175         }
 176         return null;
 177     }
 178     
 179     /**
 180      * Заполняем настройки импорта
 181      *
 182      * @param SimpleXMLElement $settings
 183      *
 184      */
 185     function fillImportSettings($settings, $srcName) {
 186         if (!$this->checkImportSettings($settings)) {
 187             $this->importLog->addLog(sprintf(_t('ProductCatalogImportTask.ErrorIn', 'Error In %s'), $srcName), 'warning');
 188             return false;
 189         }
 190         if (!$this->importSettings)
 191             $this->importSettings = new DataObject();
 192             foreach (array_keys(self::$possibleSettings) as $set) {
 193             if (!isset($this->importSettings->{$set}) && isset($settings->{$set})) {
 194                 // !!! для правильной интерпретации строк true и false в xml
 195                 $value = trim((string)$settings->{$set});
 196                 if ($value === 'true') $value = 1;
 197                 if ($value === 'false') $value = 0;
 198                 $this->importSettings->{$set} = $value;
 199                 
 200                 if ($value && $set == 'StartPage') {
 201                     if ($value == '/') {
 202                         $this->importSettings->StartPage = 0;
 203                     } else {
 204                         $this->importSettings->StartPage = DataObject::get_one('SiteTree', "URLSegment = '{$value}'")->ID;
 205                     }
 206                 }
 207                 // !!!! id или url подсайта/языковой версии !!!!
 208                 if ($value && $set == 'SubSite') {
 209                     $this->importSettings->SubSite = (int) $value;
 210                 }
 211             }
 212         }
 213         return true;
 214     }
 215 
 216     /**
 217      * Проверяем настройки импорта
 218      *
 219      * @return boolean
 220      */
 221     function checkImportSettings($settings) {
 222         if (!$settings) {
 223             $this->importLog->addLog(_t('ProductCatalogImportTask.WrongSettings', 'Wrong Settings'), 'warning');
 224             return false;
 225         }
 226         if ($settings->StartPage) {
 227             if ($settings->StartPage != '/') {
 228                 $startPage = DataObject::get_one('SiteTree', "URLSegment = '{$settings->StartPage}'");
 229                 if (!$startPage) {
 230                     $this->importLog->addLog(_t('ProductCatalogImportTask.NoRoot', 'No Root'), 'warning');
 231                     return false;
 232                 }
 233             }
 234         }
 235         if (class_exists('Subsite') && $settings->SubSite) {
 236             $subsite = DataObject::get_by_id('Subsite', (int) $settings->SubSite);
 237             if (!$subsite) {
 238                 $this->importLog->addLog(_t('ProductCatalogImportTask.NoSubsite', 'No Subsite'), 'warning');
 239                 return false;
 240             }
 241         }
 242         if ($settings->ImportMode && $settings->ImportMode != 'full' && $settings->ImportMode != 'incremental' ) {
 243             $this->importLog->addLog(
 244                 sprintf(_t('ProductCatalogImportTask.WrongImportParam', 'Wrong Import Param') . '  ImportMode: "%s"!', $settings->ImportMode),
 245                 'warning'
 246             );
 247             return false;
 248         }
 249         if ($settings->ClearCategory && !in_array($settings->ClearCategory, array('true', 'false'))) {
 250             $this->importLog->addLog(
 251                 sprintf(_t('ProductCatalogImportTask.WrongImportParam', 'Wrong Import Param') . ' ClearCategory: "%s"!', $settings->ClearCategory),
 252                 'warning'
 253             );
 254             return false;
 255         }
 256         if ($settings->ClearProducts && !in_array($settings->ClearProducts, array('true', 'false'))) {
 257             $this->importLog->addLog(
 258                 sprintf(_t('ProductCatalogImportTask.WrongImportParam', 'Wrong Import Param') . ' ClearProducts: "%s"!', $settings->ClearProducts),
 259                 'warning'
 260             );
 261             return false;
 262         }
 263         if ($settings->ClearCategory == 'true' && $settings->ClearProducts == 'false' ) {
 264             $this->importLog->addLog(
 265                 _t('ProductCatalogImportTask.WrongImportParamClearProducts', 'Wrong Import Param ClearProducts'),
 266                 'warning'
 267             );
 268             return false;
 269         }
 270         if ($settings->ImportMode == 'incremental' && ($settings->ClearCategory == 'true' || $settings->ClearProducts == 'true')) {
 271             $this->importLog->addLog(
 272                 _t('ProductCatalogImportTask.WrongImportParamImportMode', 'Wrong Import Param ImportMode'),
 273                 'warning'
 274             );
 275             return false;
 276         }
 277         if ($setting->OldItemAction && !in_array($settings->OldItemAction, array('hide', 'unpublish', 'delete', ''))) {
 278             $this->importLog->addLog(
 279                 sprintf(_t('ProductCatalogImportTask.WrongOldItemActionParam', 'Wrong Old Item Action') . ' OldItemAction: "%s"!', $settings->OldItemAction),
 280                 'warning'
 281             );
 282             return false;
 283         }
 284         return true;
 285     }
 286         
 287     /**
 288      *
 289      *
 290      * @param <type> $element
 291      *
 292      * @return <type>
 293      */
 294     function xml2log($element) {
 295         $result = '<' . $element->getName();
 296         foreach ($element->attributes() as $name => $val) {
 297             $result .= ' ' . $name . '="' . $val . '"';
 298         }
 299         $result .= '>';
 300         return $result;
 301     }
 302    
 303     function TotalMessage() {
 304         return sprintf('Импортировано категорий: %d, товаров: %d.', $this->categoryCount, $this->productCount);
 305     }
 306 
 307     /**
 308      * Процесс импорта
 309      *
 310      */
 311     function process() {
 312         $pidFile = TEMP_FOLDER . '/import.pid';
 313         if (is_file($pidFile)) {
 314             $pid = (int) file_get_contents($pidFile);
 315             if (posix_getsid($pid) !== false) {
 316                 // импорт уже работает
 317                 return;
 318             }
 319             else {
 320                 // предыдущий импорт сдох?
 321                 $log = ProductImportLog::get_last_log();
 322                 if ($log && $log->Status == 'process') {
 323                     $log->EndTime = $log->LastEdited;
 324                     $log->addStatus('error', 'Скрипт импорта неожиданно прекратил работу');
 325                 }
 326                 unlink($pidFile);
 327             }
 328         }
 329 
 330         if (!is_file(self::absolute_import_path('start_ok'))) return;
 331 
 332         file_put_contents($pidFile, getmypid());
 333         
 334         //Запускаем импорт
 335         unlink(self::absolute_import_path('start_ok'));
 336         
 337         // время начала импорта
 338         $startTime = time();
 339         
 340         // установить кол-во версий для товаров
 341         Versioned::$versions_ttl = self::$max_version_count;
 342         
 343         // отключаем автосоздание папок каталогов и товаров -  в импорте мы не копируем туда прикрепленный фото и файлы
 344         AssociatedFolderDecorator::$createFolders = false;
 345         
 346         // отключаем протоколирование
 347         if (class_exists('LogItem')) {
 348             LogItem::enable(false);
 349         }
 350         
 351         // почистим старые ProductImportLog
 352         ProductImportLog::optimize_log_tables(self::$max_log_count);
 353         
 354         //Лог импорта
 355         $this->importLog = new ProductImportLog();
 356         $this->importLog->write();
 357         $this->importLog->addLog( _t('ProductCatalogImportTask.StartAt', 'Start At') .  date("Y-m-d H:i:s", $startTime));
 358         if (!is_file(self::absolute_import_path(self::$importFileName))) {
 359             $this->importLog->addLog("Нет файла импорта товаров " . self::$importFileName, 'warning');
 360             return false;
 361         }
 362         
 363         $validator = new XMLValidate(self::absolute_import_path(self::$importFileName), self::module_path('catalog3.xsd'));
 364         $rs = $validator->validate();
 365         if ($rs != 'validated') {
 366             foreach ($rs as $error)
 367                 $this->importLog->addLog( _t('ProductCatalogImportTask.ValidationError', 'Validation Error') . ': '.$error, 'error');
 368             $this->importLog->addStatus('error', _t('ProductCatalogImportTask.ValidationError', 'Validation Error'));
 369             return false;
 370         }
 371         
 372         // config.xml генерируем из админки - максимальный приоритет
 373         if (is_file(self::absolute_import_path('config.xml'))) {
 374             $settings = simplexml_load_file(self::absolute_import_path('config.xml'));
 375             //удаляем файл настроек, сгенереный из админки, чтобы при след.импорте не воспользоваться случайно
 376             unlink(self::absolute_import_path('config.xml'));
 377             if (!$this->fillImportSettings($settings, 'config.xml'))
 378                 return false;
 379         }
 380         if ($this->importProductCatalog($startTime)) {
 381             $this->importLog->EndTime = date('Y-m-d H:i:s');
 382             $this->importLog->addStatus('ok', $this->TotalMessage());
 383             $this->importLog->addLog(sprintf(_t('ProductCatalogImportTask.ImportDoneAt', 'Import done at %s'), date("Y-m-d H:i:s")));
 384         } else {
 385             $this->importLog->EndTime = date('Y-m-d H:i:s');
 386             $this->importLog->addStatus('error', _t('ProductCatalogImportTask.ImportError', 'Import Error'));
 387         }
 388         unlink($pidFile);
 389     }
 390 
 391     function importProductCatalog($startTime) {
 392             
 393         $this->categoryCount = 0;
 394         $this->productCount = 0;
 395 
 396         $importData = simplexml_load_file(self::absolute_import_path(self::$importFileName));
 397         rename(self::absolute_import_path(self::$importFileName), self::absolute_import_path(self::$importFileName) . '.bak');
 398         
 399         // настройки из самого xml - вторые по приоритету
 400         if ($importData->Config && !$this->fillImportSettings($importData->Config, self::$importFileName)) {
 401             return false;
 402         }
 403         
 404         //Настройки из SiteConfig - самые последние
 405         $sc = SiteConfig::current_site_config();
 406         $this->fillImportSettings($sc, 'SiteConfig');
 407         if (!$this->fillImportSettings(self::$possibleSettings, 'Defaults')) {
 408             return false;
 409         }
 410                 
 411         $this->importLog->addLog(sprintf(
 412             _t('ProductCatalogImportTask.ImportSettings', 'Import Settings: ImportMode = %s; ClearCategory = %s; ClearProducts = %s; BaseFileURL = %s; StartPage = %s; SubsiteID = %s; OldItemAction = %s'), $this->importSettings->ImportMode, $this->importSettings->ClearCategory, $this->importSettings->ClearProducts, self::$baseFileURL, $this->importSettings->StartPage, (int)$this->importSettings->Subsite, $this->importSettings->OldItemAction
 413         ));
 414 
 415         $this->importLog->ProductCatalogDate = (string) $importData->attributes()->date; // !! ПРОВЕРИТЬ атрибуты - есть ли date
 416         $this->importLog->addStatus('process', _t('ProductCatalogImportTask.ImportInProgress', 'Import In Progress'));
 417         $this->importLog->addLog(_t('ProductCatalogImportTask.CatalogImport', 'CatalogImport'));
 418         
 419         // импорт параметров
 420         if (self::$allow_parameters) {
 421             $IDs = array();
 422             if ($params = DataObject::get('ProductParam', "ParentCatalogID = 0")) {
 423                 $IDs = $params->map('ID', 'ID');
 424             }
 425             $this->importParams($importData, 0, $IDs);
 426             
 427             $possibleFilterFields = Product::$possible_filter_fields;
 428             if ($rootParams = DataObject::get('ProductParam', "ParentCatalogID = 0 AND ShowDefault = 1")) {
 429                 $possibleFilterFields = array_merge($possibleFilterFields, $rootParams->map('TechTitle', 'TechTitle'));
 430             }
 431             $this->cachedCatalogParams[0] = $possibleFilterFields;
 432         }
 433         
 434         // импорт фильтров
 435         if (self::$allow_filters) {
 436             $IDs = array();
 437             if ($filters = DataObject::get('CatalogFilter', "ParentCatalogID = 0")) {
 438                 $IDs = $filters->map('ID', 'ID');
 439             }
 440             if ($importData->xpath('CatalogFilters')) {
 441                 $this->importFilters($importData, 0, $IDs);
 442             }
 443         }
 444         
 445         $categories = $importData->xpath('Category');
 446         
 447         // Очищаем категории если нужно
 448         if ($this->importSettings->ClearCategory) {
 449             singleton('Catalog')->importClearAll($this->importLog);
 450             singleton('Product')->importClearAll($this->importLog);
 451         }
 452         
 453         // очищаем продукты
 454         if ($this->importSettings->ClearProducts) {
 455             singleton('Product')->importClearAll($this->importLog);
 456         }
 457         
 458         $startPageID = $this->importSettings->StartPage;
 459         $this->importCategories($categories, $startPageID);
 460         if ($this->importSettings->ImportMode == 'full') {
 461             $this->importLog->addLog(_t('ProductCatalogImportTask.ClearUnupdated', 'Clear Unupdated...'));
 462             $this->unpublishNotUpdated($startTime);
 463         }
 464         
 465         // Чистим записи в БД - картинки, которые есть в БД, но нет на диске.
 466         $this->deleteEmptyDBFiles();
 467         
 468         return true;
 469     }
 470 
 471     /*
 472      * Импорт категорий
 473      * Рекурсивная функция
 474      *
 475      * @param  array
 476      */
 477     function importCategories($categories, $parentID) {
 478         foreach($categories as $category) {
 479             $newCategoryID = $this->importCategory($category, $parentID);
 480             if (($childs = $category->xpath('Childs/Category')) && $newCategoryID) {
 481                 $this->importCategories($childs, $newCategoryID);
 482             }
 483         }
 484     }
 485 
 486     /*
 487      * Импорт конкретной категории
 488      *
 489      * @param  array
 490      */
 491     function importCategory($category, $parentID) {
 492         if (!$category->attributes()->id)
 493             return false;
 494         $importID = (string)$category->attributes()->id;
 495         $newCategory = DataObject::get_one('Catalog', "ImportID = '{$importID}'");
 496         if (!$newCategory) {
 497             $newCategory = new Catalog();
 498             $newCategory->ImportID = $importID;
 499         } else {
 500             if (((string)$category->attributes()->unpublish == "true")) {
 501                 $newCategory->doUnpublish();
 502                 return false;
 503             }
 504             if (((string)$category->attributes()->delete == "true")) {
 505                 $newCategory->doUnpublish();
 506                 $newCategory->delete();
 507                 return false;
 508             }
 509         }
 510         $newCategory->ParentID = $parentID;
 511         $newCategory->Title = (string)$category->Title;
 512         
 513         // сохраняем все подходящие поля каталога, если они есть в выгрузке
 514         foreach(self::$catalog_saveable_fields as $field) {
 515             if ($category->{$field}) {
 516                 $newCategory->{$field} = (string)$category->{$field};
 517             }
 518         }       
 519         // прописываем подсайт
 520         if ($this->importSettings->SubSite) {
 521             $newCategory->SubsiteID = $this->importSettings->SubSite;
 522         }
 523         $img = $this->importFile($newCategory->PhotoID, $category->Photo);
 524         if ($img) {
 525             $newCategory->PhotoID = $img->ID;
 526         }
 527         // выставляем показ в меню из выгрузки - если не указано, то показывать
 528         if (isset($category->ShowInMenus)) {
 529             $newCategory->ShowInMenus = ($category->ShowInMenus == 'true') ? 1 : 0;
 530         } else {
 531             $newCategory->ShowInMenus = 1;
 532         }
 533         $newCategory->writeToStage('Stage');
 534         $newCategory->publish('Stage', 'Live');
 535         
 536         // импорт параметров рубрики
 537         
 538         // импорт фильтров
 539         if (self::$allow_parameters) {
 540             $IDs = array();
 541             if ($newCategory->Params() && $newCategory->Params()->Count()) {
 542                 $IDs = $newCategory->Params()->getIdList();
 543             }
 544             $this->importParams($category, $newCategory->ID, $IDs);
 545             
 546             // список параметров конкретной рубрики
 547             $newCategory->OwnParams = 0;
 548             if ($category->xpath('ShowParams')) {
 549                 $params = $category->xpath('ShowParams/ShowParam');
 550                 // сначала всо удалим
 551                 if ($newCategory->EnabledParams() && $newCategory->EnabledParams()->Count()) {
 552                     $newCategory->EnabledParams()->removeAll();
 553                 }
 554                 // потом добавим, если существуют
 555                 foreach($params as $paramID) {
 556                     $param = DataObject::get_one('ProductParam', "TechTitle = '". Convert::raw2sql((string)$paramID) . "'");
 557                     if ($param) {
 558                         $newCategory->EnabledParams()->add($param);
 559                     }
 560                 }
 561                 $newCategory->OwnParams = 1; // если фильтры заданы - то отмечаем, чтот у этой категории свои фильтры
 562             }           
 563             $newCategory->writeToStage('Stage');
 564             $newCategory->publish('Stage', 'Live');
 565         }
 566         
 567         if (self::$allow_filters) {
 568             $possibleFilterFields = Product::$possible_filter_fields;
 569             if ($activeCatalogParams = $newCategory->catalogParams()) {
 570                 $possibleFilterFields = array_merge($possibleFilterFields, $activeCatalogParams->map('TechTitle', 'TechTitle'));
 571             }
 572             $this->cachedCatalogParams[$newCategory->ID] = $possibleFilterFields;
 573         
 574             // импорт фильтров
 575             $IDs = array();
 576             if ($newCategory->CatalogFilters() && $newCategory->CatalogFilters()->Count()) {
 577                 $IDs = $newCategory->CatalogFilters()->getIdList();
 578             }
 579             
 580             if ($category->xpath('CatalogFilters')) {
 581                 $this->importFilters($category, $newCategory->ID, $IDs);                
 582             }
 583             
 584             // список фильтров конкретной рубрики
 585             $newCategory->OwnFilter = 0;
 586             if ($category->xpath('ShowFilters')) {
 587                 $filters = $category->xpath('ShowFilters/ShowFilter');
 588                 // сначала всо удалим
 589                 if ($newCategory->EnabledCatalogFilters() && $newCategory->EnabledCatalogFilters()->Count()) {
 590                     $newCategory->EnabledCatalogFilters()->removeAll();
 591                 }
 592                 // потом добавим, если существуют
 593                 foreach($filters as $filterID) {
 594                     $filter = DataObject::get_one('CatalogFilter', "TechTitle = '". Convert::raw2sql((string)$filterID) . "'");
 595                     if ($filter) {
 596                         $newCategory->EnabledCatalogFilters()->add($filter);
 597                     }
 598                 }
 599                 $newCategory->OwnFilter = 1; // если фильтры заданы - то отмечаем, чтот у этой категории свои фильтры
 600             }           
 601             $newCategory->writeToStage('Stage');
 602             $newCategory->publish('Stage', 'Live');
 603         }
 604 
 605         $this->categoryCount++;
 606 
 607 
 608         if ($category->xpath('Products')) {
 609             $products = $category->xpath('Products/Product');
 610             foreach($products as $product) {
 611                 $this->importProduct($product, $newCategory->ID);
 612             }
 613         } else {
 614 //          $this->importLog->addLog(sprintf('У категории %s отсутствуют товары!', $newCategory->Title), 'warning');
 615         }
 616         return $newCategory->ID;
 617     }
 618         
 619     function importParams($xml, $parentID, $oldIDs) {
 620         if ($xml->xpath('ProductParams')) {
 621             $params = $xml->xpath('ProductParams/ProductParam');
 622             foreach($params as $param) {
 623                 if (!$param->attributes()->id) {
 624                     $this->importLog->addLog('У элемента ProductParam отсутвует обязательный атрибут id!', 'warning');
 625                     continue;
 626                 }
 627                 $paramData = DataObject::get_one('ProductParam', "ParentCatalogID = {$parentID} AND TechTitle = '". Convert::raw2sql($param->attributes()->id) . "'");
 628                 if (!$paramData) {
 629                     $paramData = new ProductParam();
 630                     $paramData->TechTitle = Convert::raw2sql($param->attributes()->id);
 631                 }
 632                 $paramData->ParentCatalogID = $parentID;
 633                 $paramData->Title = (string)$param->Title;
 634                 $paramData->Type = (string)$param->Type;
 635                 $paramData->ShowInList = ($param->ShowInList == 'true') ? 1 : 0;
 636                 $paramData->ShowInView = ($param->ShowInView == 'true') ? 1 : 0;
 637                 $paramData->ShowDefault = ($param->ShowDefault == 'true') ? 1 : 0;
 638                 $paramData->Sort = (int)$param->Sort;
 639                 $paramData->write();
 640                 unset($oldIDs[$paramData->ID]);
 641             }
 642 
 643             // удалим отсутствующие в выгрузке параметры
 644             foreach($oldIDs as $ID) {
 645                 $param = DataObject::get_by_id('ProductParam', $ID);
 646                 if ($param) {
 647                     $param->delete();
 648                 }
 649             }
 650         }
 651     }
 652         
 653     function importFilters($xml, $parentID, $oldIDs) {
 654         // импорт фильтров
 655         $filters = $xml->xpath('CatalogFilters/CatalogFilter');
 656         foreach($filters as $filter) {
 657             if (!$filter->attributes()->id) {
 658                 $this->importLog->addLog('У элемента CatalogFilter отсутвует обязательный атрибут id!', 'warning');
 659                 continue;
 660             }
 661             $filterField = trim((string)$filter->Field);
 662             if (!isset($this->cachedCatalogParams[$parentID]) || (array_search($filterField, $this->cachedCatalogParams[$parentID]) === false)) {
 663                 $this->importLog->addLog("У каталога с ID {$parentID} отсутвствует параметр {$filterField} для фильтра!", 'warning');
 664                 continue;
 665             }
 666             $filterData = DataObject::get_one('CatalogFilter', "ParentCatalogID = {$parentID} AND TechTitle = '". Convert::raw2sql($filter->attributes()->id) . "'");
 667             if (!$filterData) {
 668                 $filterData = new CatalogFilter();
 669                 $filterData->TechTitle = Convert::raw2sql($filter->attributes()->id);
 670             }
 671             $filterData->ParentCatalogID = $parentID;
 672             $filterData->Title = (string)$filter->Title;
 673             $filterData->Type = (string)$filter->Type;
 674             $filterData->FilterField = $filterField;
 675             $filterData->Important = ($filter->Important == 'true') ? 1 : 0;
 676             $filterData->ShowDefault = ($filter->ShowDefault == 'true') ? 1 : 0;
 677             $filterData->Sort = (int)$filter->Sort;
 678             if ((string)$filter->GroupTitle && $filterData->Type == 'boolgroup') {
 679                 $filterData->GroupTitle = (string)$filter->GroupTitle;
 680             }
 681             if ((string)$filter->DefaultValue && $filterData->Type == 'list') {
 682                 $filterData->DefaultValue = (string)$filter->DefaultValue;
 683             }
 684             $filterData->write();
 685             unset($oldIDs[$filterData->ID]);
 686         }
 687 
 688         // удалим отсутствующие в выгрузке параметры
 689         foreach($oldIDs as $ID) {
 690             $filter = DataObject::get_by_id('CatalogFilter', $ID);
 691             if ($filter) {
 692                 $filter->delete();
 693             }
 694         }
 695     }
 696     
 697     function importProduct($product, $categoryID) {
 698         if (!$product->attributes()->id)
 699             return;
 700         $importID = (string)$product->attributes()->id;     
 701         $productID = DB::query("SELECT ID FROM Product WHERE \"ImportID\"  = '{$importID}' ORDER BY ID DESC")->value();
 702         if ($productID) {
 703             //$newProduct = DataObject::get_by_id('Product', $productID);
 704             $newProduct = Versioned::get_one_by_stage("Product", "Stage", "\"Product\".\"ID\" = {$productID}");
 705             if (!$newProduct) {
 706                 $newProduct = Versioned::get_one_by_stage("Product", "Live", "\"Product\".\"ID\" = {$productID}");
 707             }           
 708             if (!$newProduct) {
 709                 return; // кидать ошибку в лог
 710             }
 711             
 712             if (((string)$product->attributes()->unpublish == "true")) {
 713                 $newProduct->doUnpublish();
 714                 return false;
 715             }
 716             if (((string)$product->attributes()->delete == "true")) {
 717                 $newProduct->doUnpublish();
 718                 $newProduct->delete();
 719                 return false;
 720             }
 721         } else {
 722             $newProduct = new Product();
 723             $newProduct->ImportID = $importID;
 724         }
 725         
 726         $newProduct->ParentID = $categoryID;
 727         $newProduct->Title = (string)$product->Title;
 728                 
 729         // сохраняем все подходящие поля, если они есть в выгрузке
 730         foreach(self::get_product_saveable_fields() as $field) {
 731             // разбиваем текст по строкам
 732             // и оборачиваем их в <p>, тк 1С не умеет в форматирование
 733             if($field == 'Content' && $product->{$field}){
 734                 $content = "";
 735                 $splitted = explode("\n",(string)$product->{$field});
 736                 foreach ($splitted as $line) {
 737                     $content .= "<p>{$line}</p>";
 738                 }
 739                 $newProduct->Content = $content;
 740                 continue;
 741             }
 742             if ($product->{$field}) {
 743                 $newProduct->{$field} = (string)$product->{$field};
 744             }
 745         }
 746         
 747         if ($product->Available) {
 748             $value = self::import_parse_bool_value($product->Available);
 749             if ($value !== null) {
 750                 $newProduct->Available = $value;
 751             }
 752         }
 753         
 754         if ($product->AllowPurchase) {
 755             $value = self::import_parse_bool_value($product->AllowPurchase);
 756             if ($value !== null) {
 757                 $newProduct->AllowPurchase = $value;
 758             }
 759         }
 760         
 761         // прописываем подсайт
 762         if ($this->importSettings->SubSite) {
 763             $newProduct->SubsiteID = $this->importSettings->SubSite;
 764         }       
 765 
 766         /*  Оставим на всяк случий!
 767         $price = htmlentities((string)$product->attributes()->price, null, 'utf-8'); // в файле импорта в цене стоит неразрывный пробел, поэтому
 768         $price = preg_replace(array('/\s|&nbsp;/', '/,/'), array('', '.'), $price); //сначала преобразуем его в HTML сущность (&nbsp;), а потом заменяем
 769         $price = (float) $price;
 770         */
 771         if ($product->BasePrice) {
 772             $newProduct->BasePrice = (float)$product->BasePrice;
 773         }
 774         
 775         if ($product->CostPrice) {
 776             $newProduct->CostPrice = 0; // зануляем, на случай, если тега не указано
 777             if ((float)$product->CostPrice) {
 778                 $newProduct->CostPrice = (float)$product->CostPrice;
 779             }
 780         }
 781         
 782         // импорт основного фото
 783         $img = $this->importFile($newProduct->PhotoID, (string)$product->Photo);
 784         if ($img) {
 785             $newProduct->PhotoID = $img->ID;
 786         }
 787         
 788         $newProduct->writeToStage('Stage');
 789         $newProduct->publish('Stage', 'Live');
 790         
 791         // импорт списка фото
 792         if ($product->xpath('Images')) {
 793             $oldPhotos = $newProduct->Photos();
 794             $oldPhotosIDs = $oldPhotos->getIdList(); //сохраняем список ID прикрепленных фоток
 795             $newPhotos = $product->xpath('Images/Image');
 796             foreach($newPhotos as $newPhoto) {
 797                 $importedImage = $this->importFile(0, $newPhoto->attributes()->path);
 798                 if ($importedImage) {
 799                     if ($mwPhoto = $oldPhotos->find('PhotoID', $importedImage->ID)) {
 800                         unset($oldPhotosIDs[$mwPhoto->ID]); //если фотка осталась, то удаляем ее ID из списка
 801                     } else {
 802                         $mwPhoto = new MediawebPage_Photo();
 803                         $mwPhoto->PhotoID = $importedImage->ID;
 804                     }
 805                     $mwPhoto->MediawebPageID = $newProduct->ID; //Цепляем к Product
 806                     $mwPhoto->Caption = (string)$newPhoto;//$importedImage->Title;
 807                     $mwPhoto->write();
 808                 }
 809             }
 810             // все, что осталось в списке - чистим!
 811             if (count($oldPhotosIDs) > 0) {
 812                 foreach($oldPhotosIDs as $oldPhotosID) {
 813                     if ($oldPhoto = DataObject::get_by_id('MediawebPage_Photo', $oldPhotosID)) {
 814                         $oldPhoto->delete();
 815                     }
 816                 }
 817             }
 818         }
 819     
 820         // импорт списка файлов
 821         if ($product->xpath('Files')) {
 822             $oldFiles = $newProduct->Files();
 823             $oldFilesIDs = $oldFiles->getIdList(); //сохраняем список ID прикрепленных фоток
 824             $newFiles = $product->xpath('Files/File');
 825             foreach($newFiles as $newFile) {
 826                 $importedFile = $this->importFile(0, $newFile->attributes()->path, 'File'); //!!! TODO написать importFiles
 827                 if ($importedFile) {
 828                     if ($mwFile = $oldFiles->find('FileID', $importedFile->ID)) {
 829                         unset($oldFilesIDs[$mwFile->ID]); //если фотка осталась, то удаляем ее ID из списка
 830                     } else {
 831                         $mwFile = new MediawebPage_File();
 832                         $mwFile->AttachID = $importedFile->ID;
 833                     }
 834                     $mwFile->MediawebPageID = $newProduct->ID; //Цепляем к Product
 835                     $mwFile->Caption = $importedFile->Title;
 836                     $mwFile->write();
 837                 }
 838             }
 839             // все, что осталось в списке - чистим!
 840             if (count($oldFilesIDs) > 0) {
 841                 foreach($oldFilesIDs as $oldFilesID) {
 842                     if ($oldFile = DataObject::get_by_id('MediawebPage_File', $oldFilesID)) {
 843                         $oldFile->delete();
 844                     }
 845                 }
 846             }
 847         }
 848 
 849         // ИМпорт СпецКаталогов
 850         if (class_exists('SpecialCatalog') && $product->xpath('SpecialCatalogs')) {
 851             $specCatalogs = $this->importListedSpecCatalogs($product->xpath('SpecialCatalogs/SpecialCatalog'));
 852             $productSpecialCatalogs = array(); //список ID-шники спецкаталогов, в которых изначально был продукт
 853             //складываем в список ID всех спец.каталогов, в которых есть товар
 854             $allSpecialCatalogs = DataObject::get('SpecialCatalog');
 855             if ($allSpecialCatalogs) {
 856                 foreach($allSpecialCatalogs as $specialCatalog) {
 857                     $specialCatalogProducts = $specialCatalog->LinkedProducts()->getIdList();
 858                     if (isset($specialCatalogProducts[$newProduct->ID])) {
 859                         $productSpecialCatalogs[$specialCatalog->ID] = $specialCatalog->ID;
 860                     }
 861                 }
 862             }
 863             //Добавляем товар в указанные спец.каталоги
 864             foreach($specCatalogs as $specialCatalog) {
 865                 if (isset($productSpecialCatalogs[$specialCatalog->ID])) { //если товар уже есто в новом спец.каталоге
 866                     unset($productSpecialCatalogs[$specialCatalog->ID]); //то удаляем ID спец.каталога из списка
 867                 } else {
 868                     $specialCatalog->LinkedProducts()->add($newProduct); // иначе добавляем товар в спец.каталог
 869                 }
 870             }
 871 
 872             if (count($productSpecialCatalogs)) {
 873                 foreach($productSpecialCatalogs as $productSpecialCatalog) { //чистим все, что осталось в списке
 874                     if ($oldSpecialCatalog = $allSpecialCatalogs->find('ID', $productSpecialCatalog)) {
 875                         $oldSpecialCatalog->LinkedProducts()->remove($newProduct);
 876                     }
 877                 }
 878             }
 879         }
 880 
 881         //импорт значений параметров
 882         if ($product->xpath('Params')) {
 883             // сначала удаляем старые значения
 884             $oldParamValues = DataObject::get('ProductParamValue', "ProductID = {$newProduct->ID}");
 885             if ($oldParamValues) {
 886                 foreach($oldParamValues as $oldParamValue)
 887                     $oldParamValue->delete();
 888             }
 889         
 890             //добавляем новые
 891             $params = $product->xpath('Params/Param');
 892             foreach($params as $param) {
 893                 if (!$param->attributes()->name) {
 894                     $this->importLog->addLog('У элемента param отсутвует обязательный атрибут name!', 'warning');
 895                     continue;
 896                 }
 897                 
 898                 $paramData = DataObject::get_one('ProductParam', "TechTitle = '{$param->attributes()->name}'"); //ParentCatalogID = {$categoryID} AND
 899                 if ($paramData) {
 900                     $paramValueID = DB::query("SELECT \"ID\" FROM \"ProductParamValue\" WHERE \"ProductParamID\"  = {$paramData->ID} AND ProductID = {$newProduct->ID}")->value();
 901                     if ($paramValueID) {
 902                         $paramValue = DataObject::get_by_id('ProductParamValue', $paramValueID);
 903                     } else {
 904                         $paramValue = new ProductParamValue();
 905                         $paramValue->ProductParamID = $paramData->ID;
 906                         $paramValue->ProductID = $newProduct->ID;
 907                     }
 908                     
 909                     $value = (string)$param;
 910                     // для типа bool проверяем значения true/false
 911                     if ($paramData->Type == 'bool') {
 912                         if ($value == 'true') {
 913                             $value = 1;
 914                         }
 915                         if ($value == 'false') {
 916                             $value = 0;
 917                         }
 918                     }
 919                     $paramValue->Value = $value;
 920                     $paramValue->write();
 921                     
 922                 } else {
 923                     //$this->importLog->addLog('У категории отсутствует параметр: ');
 924                     $this->importLog->addLog(sprintf('У категории %s отсутствует параметр: %s', $newProduct->Parent()->Title, $param->attributes()->name), 'warning');
 925                 }
 926             }
 927             unset($params);
 928             unset($oldParamValues);
 929         }
 930         $this->productCount++;
 931         $this->importLog->addStatus('process', "Импортировано категорий: {$this->categoryCount}, товаров: {$this->productCount}");
 932 
 933         unset($product);
 934         unset($newProduct);
 935         unset($oldPhotos);
 936         unset($newPhotos);
 937     }
 938 
 939     function importListedSpecCatalogs($data) {
 940         //Обрабатываем списочные спец.каталоги (если есть)
 941         $catalogs = false;
 942         if (isset($data)) {
 943             $catalogs = new DataObjectSet();
 944             foreach ($data as $catalog) {
 945                 $specialCatalog = false;
 946                 $id = (int)($catalog->attributes()->id);
 947                 $url = Convert::raw2sql($catalog->attributes()->url);
 948                 if ($id > 0)
 949                     $specialCatalog = DataObject::get_by_id('SpecialCatalog', $id);
 950                 if (!$specialCatalog && $url) {
 951                     $specialCatalog = DataObject::get_one('SpecialCatalog', "URLSegment = '$url'");
 952                 }
 953                 if ($specialCatalog) {
 954                     $catalogs->push($specialCatalog);
 955                 }
 956                 else {
 957                     $this->importLog->addLog(sprintf(_t('ProductCatalogImportTask.NoSpecialCatalog', 'No specila catalog %s'), self::xml2log($catalog)));
 958                 }
 959             }
 960         }
 961         return $catalogs;
 962     }
 963 
 964     /**
 965      * Скрываем элементы, которых не нужно отображать после импорта
 966      *
 967      * @param string $importStartTime
 968      *
 969      * @return boolean
 970      */
 971     function unpublishNotUpdated($importStartTime) {
 972         $this->importLog->addStatus('process', _t('ProductCatalogImportTask.HidingUnavailable', 'Hiding Unavailable categories and products'));
 973         // Скрываем не обновленные товары
 974         $needUnpublish = DataObject::get('Product', 'LastEdited < \'' . date("Y-m-d H:i:s", $importStartTime) . '\'');
 975         if ($needUnpublish)
 976             foreach ($needUnpublish as $product) {
 977                 switch ($this->importSettings->OldItemAction) {
 978                     case 'hide':
 979                         $product->AllowPurchase = 0;
 980                         $product->writeToStage('Stage');
 981                         if ($product->isPublished()) {
 982                             $product->publish('Stage', 'Live');
 983                         }
 984                         break;
 985                     case 'unpublish':
 986                         $product->doUnpublish();
 987                         break;
 988                     case 'delete':
 989                         $product->doUnpublish();
 990                         $product->delete();
 991                         break;
 992                     default:
 993                         $product->doUnpublish();
 994                         $product->delete();
 995                         break;                  
 996                 }
 997             }
 998         // Скрываем не обновленные рубрики
 999         $needUnpublish = DataObject::get('Catalog', 'ClassName = \'Catalog\' AND LastEdited < \'' . date("Y-m-d H:i:s", $importStartTime) . '\'');
1000         if ($needUnpublish)
1001             foreach ($needUnpublish as $catalog) {
1002                 switch ($this->importSettings->OldItemAction) {
1003                     case 'hide':
1004                         $catalog->ShowInMenus = 0;
1005                         $catalog->writeToStage('Stage');
1006                         if ($catalog->isPublished()) {
1007                             $catalog->publish('Stage', 'Live');
1008                         }
1009                         break;
1010                     case 'unpublish':
1011                         $catalog->doUnpublish();
1012                         break;
1013                     case 'delete':
1014                         $catalog->doUnpublish();
1015                         $catalog->delete();
1016                         break;
1017                     default:
1018                         $catalog->doUnpublish();
1019                         $catalog->delete();
1020                         break;
1021                 }
1022             }
1023         $this->importLog->addStatus('process', _t('ProductCatalogImportTask.UnavailableIsHide', 'Unavailable categories and products hide'));
1024         return true;
1025     }
1026     
1027     /**
1028      * Чистим записи в БД - картинки, которые есть в БД, но нет на диске.
1029      *
1030      * @return boolean
1031      */
1032     function deleteEmptyDBFiles() {
1033         $importPath = self::get_base_url();
1034         $images = DataObject::get('Image', "`Filename` LIKE '{$importPath}%'");
1035         if ($images) {
1036             foreach($images as $image) {
1037                 if (!file_exists($image->getFullPath())) {
1038                     DB::Query('UPDATE Catalog SET PhotoID = 0 WHERE PhotoID = ' . $image->ID);
1039                     DB::Query('UPDATE Catalog_Live SET PhotoID = 0 WHERE PhotoID = ' . $image->ID);
1040                     DB::Query('UPDATE Product SET PhotoID = 0 WHERE PhotoID = ' . $image->ID);
1041                     DB::Query('UPDATE Product_Live SET PhotoID = 0 WHERE PhotoID = ' . $image->ID);
1042                     DB::Query('DELETE FROM MediawebPage_Photo WHERE PhotoID = ' . $image->ID);
1043                     $image->deleteFormattedImages();
1044                     $image->deleteDatabaseOnly();
1045                 }
1046             }
1047         }
1048         return true;
1049     }
1050 
1051     /**
1052      * Импорт файлов (Image или File)
1053         *
1054      * @param DataObject $object
1055      * @param string $path
1056         *
1057      * @return Image
1058      */
1059     function importFile($fileID, $filePath, $type='Image') {
1060         $filePath = trim(str_replace("\\", "/", $filePath));
1061         $filePath = preg_replace('!^/!','', $filePath); // срежем ведущий /
1062         if ($filePath) { // !!! $filePath всегда true
1063             // используем полный абсолютный путь до файлов - чтоб при необходимости можно было их сложить в другие папки
1064             $fullFilePath = BASE_PATH . '/' . $filePath;
1065             // получим объект для картинки
1066             $file = false;
1067             // сначала вытащим по ID
1068             if ($fileID != 0) {
1069                 $file = DataObject::get_by_id($type, $fileID);
1070             }
1071 
1072             // не нашли по ID - поищем по пути к файлу
1073             if (!$file || $file->ID == 0) {
1074                 $file = DataObject::get_one($type, "\"Filename\"='".Convert::raw2sql($filePath)."'", true, 'ID DESC');
1075             }
1076 
1077             // картинка физически есть на диске
1078             if (is_file($fullFilePath)) {
1079                 // не нашли по пути - создаем новую
1080                 if (!$file || $file->ID == 0) {
1081                     $file = new $type();
1082                     $file->setFilename($filePath);
1083                     $file->Title = $file->Name;
1084                     $file->write();
1085                 }
1086 
1087                 if ($file->Filename != $filePath) {
1088                     //если поменялось имя файла, то сначала пытаемся найти имеющийся
1089                     $file = DataObject::get_one($type, "\"Filename\"='".Convert::raw2sql($filePath)."'", true, 'ID DESC');
1090                     //a если не находим создаем новый (старый может быть привязан к другому объекту!)
1091                     if (!$file) {
1092                         $file = new $type();
1093                         $file->setFilename($filePath);
1094                         $file->Title = $file->Name;
1095                         $file->write();
1096                     }
1097                 }
1098 
1099                 // Если поменялось имя файла (или новый файл)
1100                 if (($fileID != $file->ID)) {
1101                     if (!$file->Name) {
1102                         $file->Name = basename($filePath);
1103                     }
1104                     if (($type == 'Image') && $file->Filename && $file->Filename != $filePath) { // для старого имени
1105                         $file->deleteFormattedImages();
1106                     }
1107                     $file->setFilename($filePath);
1108                     if ($type == 'Image') {
1109                         $file->deleteFormattedImages(); // для нового имени
1110                     }
1111                     if (!$file->Title)
1112                     $file->Title = $file->Name;
1113                     $file->write();
1114                 }
1115                 elseif ($fileID != 0) {
1116                     // Если файл обновлен по ftp, а путь к нему не поменялся
1117                     if (filemtime($fullFilePath) > strtotime($file->LastEdited)) {
1118                         if ($type == 'Image') {
1119                             $file->deleteFormattedImages();
1120                         }
1121                         //Чтобы LastEdited обновился )))))
1122                         $file->forceChange();
1123                         if (!$file->Title)
1124                         $file->Title = $file->Name;
1125                         $file->write();
1126                     }
1127                 }
1128                 if (!$file->Hidden) {
1129                     $file->Hidden = 1;
1130                     $file->write();
1131                 }
1132                 return $file;
1133             } else {
1134                 //Если физически файла нет, а запись в БД есть
1135                 if ($file) {
1136                     if ($type == 'Image') {
1137                         $file->deleteFormattedImages();
1138                     }
1139                     $file->deleteDatabaseOnly(); // то удаляем запись
1140                 }
1141                 $this->importLog->addLog(sprintf('Отсутствует изображение: %s', $filePath), 'warning');
1142             }
1143         }
1144         return false;
1145     }
1146 }
[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.2 API Docs API documentation generated by ApiGen 2.8.0