private:koding:hostcms:modules:shop:import_export:import_tovarov_iz_jandeks.marketa:market_parser
<?php
  	//
	class MarketParser {
		protected $_Shop;
		protected $_apiKey;
		protected $_cacheDir;
		protected $_onlyCache;
 
		protected $_geoId = 10645;
		protected $_apiUrl = 'http://market.apisystem.ru/v1';
 
		protected $_categoryFiltersXml = null;
 
		protected $_importedItems = 0;
		protected $_importedProperties = 0;
		protected $_importedListItems = 0;
		protected $_page = 0;
 
		protected $_parserOutput = '';
 
		/**
		 * Создает экземпляр класса
		 * 
		 * @param integer $shopId Идентификатор интернет-магазина
		 * @param string $apiKey Ключ для доступа к сервису
		 */
		public function __construct($shopId, $apiKey, $onlyCache = false)
		{
			$this->_Shop = Core_Entity::factory('Shop', $shopId);
			$this->_apiKey = $apiKey;
			$this->_cacheDir = CMS_FOLDER . 'upload/parser/cache/';
			$this->_onlyCache = $onlyCache;
		}
 
		/**
		 * Выполняет парсинг и импорт товаров из категории
		 *
		 * @param integer $categoryId
		 * @param integer $page
		 * @param $count
		 * @return boolean
		 */
		public function parseCategoryPage($categoryId, $page = 1, $count = 30)
		{
			$this->_importedItems = 0;
			$this->_importedProperties = 0;
			$this->_importedListItems = 0;
			$this->_page = $page;
			$this->_parserOutput = '';
 
			if ($page < 1 && $page > 50)
			{
				return false;
			}
 
			$oCategoryXml = $this->_getResource('/category/' . $categoryId);
			$categoryName = strval($oCategoryXml['name']);
 
			$oCategoryModelsXml = $this->_getResource('/category/' . $categoryId . '/models', array('page' => $page, 'count' => $count));
			$aoModelsXml = $oCategoryModelsXml->xpath('model');			
 
			if (count($aoModelsXml) == 0)
			{
				return false;
			}
 
			$oShop_Group = $this->_getShopGroup($categoryName, $categoryId);
 
			foreach ($aoModelsXml as $oModelXml)
			{
				// Товар
				$this->parseModel($oShop_Group, $categoryId, intval($oModelXml['id']));
			}
 
			$this->_printOutput();
 
			return true;
		}
 
		public function parseProducerPage($categoryId, $producerId, $page = 1, $count = 30)
		{
			$this->_importedItems = 0;
			$this->_importedProperties = 0;
			$this->_importedListItems = 0;
			$this->_page = $page;
			$this->_parserOutput = '';
 
			if ($page < 1 && $page > 50)
			{
				return false;
			}
 
			// Категория
			$oCategoryXml = $this->_getResource('/category/' . $categoryId);
			$categoryName = strval($oCategoryXml['name']);
 
			$oShop_Group = $this->_getShopGroup($categoryName, $categoryId);
 
			// Производитель
			$oProducerFilter = $this->_getDetailsParamFilter('Производитель', $categoryId);
			$filterId = strval($oProducerFilter['id']);
 
			// Поиск
			$oSearchResultXml = $this->_getResource('/filter/' . $categoryId, array(
				$filterId => $producerId,
				'page' => $page,
				'count' => $count
			));
			$aoSearchItems = $oSearchResultXml->xpath('search-item');
 
			if (count($aoSearchItems) == 0)
			{
				return false;
			}
 
			foreach ($aoSearchItems as $oSearchItem)
			{
				$aoModelsXml = $oSearchItem->xpath('model');
				$oModelXml = $aoModelsXml[0];
 
				$this->parseModel($oShop_Group, $categoryId, intval($oModelXml['id']));
			}
 
			$this->_printOutput();
 
			return true;
		}
 
		public function getNextProducerId($categoryId, $producerId = 0)
		{
			$oProducerFilter = $this->_getDetailsParamFilter('Производитель', $categoryId);
 
			if (!$producerId)
			{
				$aoProducers = $oProducerFilter->xpath('option');
				$oProducer = $aoProducers[0];
 
				return intval($oProducer['id']);
			}
			else
			{
				$aoNextProducer = $oProducerFilter->xpath('option[@id="' . $producerId . '"]/following-sibling::option[1]');
 
				if (count($aoNextProducer))
				{
					return intval($aoNextProducer[0]['id']);
				}
				else
				{
					return 0;
				}
			}
		}
 
		/**
		 * Выполняет парсинг и импорт товара
		 *
		 * @param Shop_Group_Model $oShop_Group
		 * @param integer $categoryId
		 * @param integer $modelId
		 */
		public function parseModel(Shop_Group_Model $oShop_Group, $categoryId, $modelId)
		{
			$oModelXml = $this->_getResource('/model/' . $modelId);
 
			$aoNameXml = $oModelXml->xpath('name');
			$aoVendorXml = $oModelXml->xpath('vendor');
 
			$sModelName = strval($aoNameXml[0]);
			$sProducerName = strval($aoVendorXml[0]);
			$sShopItemName = $sProducerName . ' ' . $sModelName;
 
			// Товар
			$oShop_Item = $oShop_Group->Shop_Items->getByName($sShopItemName, false);
 
			if (!$oShop_Item)
			{
				$oShop_Item = Core_Entity::factory('Shop_Item');
				$oShop_Item->name = $sShopItemName;
				$oShop_Item->save();
 
				$oShop_Group->add($oShop_Item);
				$this->_Shop->add($oShop_Item);
 
				$oShop_Item->makePath();
				$oShop_Item->save();
 
				// Производитель
				$this->_saveProducer($oShop_Item, $sProducerName);
 
				// Изображения
				$this->_savePhotos($oShop_Item, $oModelXml);
 
				// Характеристики
				$this->_parseDetails($oShop_Item, $categoryId, $modelId);
 
				// Сохраняет информацию о товаре
				$this->_saveModelInfo($oShop_Item, $oModelXml);
 
				$this->_importedItems++;
				$this->_parserOutput .= $sShopItemName . '<br />';
			}
		}
 
		/**
		 * Сохраняет производителя товара
		 *
		 * @param Shop_Item_Model $oShop_Item
		 * @param string $sProducerName
		 */
		protected function _saveProducer(Shop_Item_Model $oShop_Item, $sProducerName)
		{
			$oShop = $this->_Shop;
			$oShop_Producer = $oShop->Shop_Producers->getByName($sProducerName, false);
 
			if (!$oShop_Producer)
			{
				$oShop_Producer = Core_Entity::factory('Shop_Producer');
				$oShop_Producer->name = $sProducerName;
				$oShop_Producer->save();
 
				$oShop->add($oShop_Producer);
				$oShop_Producer_Dir->add($oShop_Producer);
 
				$oShop_Producer->makePath();
				$oShop_Producer->save();
			}
 
			$oShop_Item->add($oShop_Producer);
		}
 
				/**
		 * Сохраняет фотографии товара
		 *
		 * @param Shop_Item_Model $oShop_Item
		 * @param SimpleXmlElement $oModelXml
		 */
		protected function _savePhotos(Shop_Item_Model $oShop_Item, SimpleXmlElement $oModelXml)
		{
			$oMainPhotoXml = $oModelXml->xpath('main-photo');
 
			if (count($oMainPhotoXml) > 0)
			{
				$this->_savePhoto($oShop_Item, strval($oMainPhotoXml[0]));
			}
 
			$aoPhotosXml = $oModelXml->xpath('photos/photo');
 
			foreach ($aoPhotosXml as $oPhotoXml)
			{
				$this->_savePhoto($oShop_Item, strval($oPhotoXml), false);
			}
		}
 
		/**
		 * Сохраняет одну фотографию товара
		 *
		 * @param Shop_Item_Model $oShop_Item
		 * @param string $sRemoteFile
		 * @param boolean $bFirstPhoto
		 */
		protected function _savePhoto(Shop_Item_Model $oShop_Item, $sRemoteFile, $bFirstPhoto = true)
		{
			$oShop = $this->_Shop;
 
			if (Core_File::isValidExtension($sRemoteFile, Core::$mainConfig['availableExtension']))
			{
				// Папка назначения
				$sDestinationFolder = $oShop_Item->getItemPath();
 
				if (!$bFirstPhoto)
				{
					$sFileName = basename($sRemoteFile);
 
					$oShop_Item_Property_List = Core_Entity::factory('Shop_Item_Property_List', $oShop->id);
 
					$oProperties = $oShop_Item_Property_List->Properties;
					$oProperties->queryBuilder()
						->where('tag_name', '=', 'image')
						->where('deleted', '=', 0);
					$aoProperties = $oProperties->findAll(false);
 
					if (count($aoProperties) > 0)
					{
						$oProperty = $aoProperties[0];
					}
					else
					{
						$oProperty = Core_Entity::factory('Property');
						$oProperty->name = 'Изображение';
						$oProperty->type = 2;
						$oProperty->tag_name = 'image';
 
						// Для вновь создаваемого допсвойства размеры берем из магазина
						$oProperty->image_large_max_width = $oShop->image_large_max_width;
						$oProperty->image_large_max_height = $oShop->image_large_max_height;
						$oProperty->image_small_max_width = $oShop->image_small_max_width;
						$oProperty->image_small_max_height = $oShop->image_small_max_height;
 
						$oProperty->save();
 
						$oShop_Item_Property_List->add($oProperty);
					}
 
					$oShop->Shop_Item_Property_For_Groups->allowAccess($oProperty->Shop_Item_Property->id, ($oShop_Item->modification_id == 0
						? intval($oShop_Item->Shop_Group->id)
						: intval($oShop_Item->Modification->Shop_Group->id)
					));
 
					$aPropertyValues = $oProperty->getValues($oShop_Item->id, false);
 
					$oProperty_Value = null;
					foreach ($aPropertyValues as $oTmpPropertyValue)
					{
						// Ранее загруженное значение ищим по имени файла
						if ($oTmpPropertyValue->file_name == $sFileName)
						{
							$oProperty_Value = $oTmpPropertyValue;
							break;
						}
					}
 
					if (is_null($oProperty_Value))
					{
						$oProperty_Value = $oProperty->createNewValue($oShop_Item->id);
					}
 
					$oProperty_Value->save();
 
					if ($oProperty_Value->file != '')
					{
						try
						{
							Core_File::delete($sDestinationFolder . $oProperty_Value->file);
						} catch (Exception $e) {}
					}
 
					// Удаляем старое малое изображение
					if ($oProperty_Value->file_small != '')
					{
						try
						{
							Core_File::delete($sDestinationFolder . $oProperty_Value->file_small);
						} catch (Exception $e) {}
					}
				}
				else
				{
					if ($oShop_Item->image_large != '' && is_file($sDestinationFolder . $oShop_Item->image_large))
					{
						try
						{
							Core_File::delete($sDestinationFolder . $oShop_Item->image_large);
						} catch (Exception $e) {}
					}
 
					// Удаляем старое малое изображение
					if ($oShop_Item->image_small != '' && is_file($sDestinationFolder . $oShop_Item->image_small))
					{
						try
						{
							Core_File::delete($sDestinationFolder . $oShop_Item->image_small);
						} catch (Exception $e) {}
					}
				}
 
				clearstatcache();
 
				// Создаем папку назначения
				$oShop_Item->createDir();
 
				// Файл-источник
				$sSourceFile = $this->_downloadPhoto($sRemoteFile);
				$sSourceFileBaseName = basename($sRemoteFile);
 
				if (!$oShop->change_filename)
				{
					$sTargetFileName = $sSourceFileBaseName;
				}
				else
				{
					$sTargetFileExtension = Core_File::getExtension($sRemoteFile);
 
					if ($sTargetFileExtension != '')
					{
						$sTargetFileExtension = ".{$sTargetFileExtension}";
					}
 
					if (!$bFirstPhoto)
					{
						$sTargetFileName = "shop_property_file_{$oShop_Item->id}_{$oProperty_Value->id}{$sTargetFileExtension}";
					}
					else
					{
						$sTargetFileName = "shop_items_catalog_image{$oShop_Item->id}{$sTargetFileExtension}";
					}
				}
 
				$aPicturesParam = array();
				$aPicturesParam['large_image_isset'] = TRUE;
				$aPicturesParam['large_image_source'] = $sSourceFile;
				$aPicturesParam['large_image_name'] = $sSourceFileBaseName;
				$aPicturesParam['large_image_target'] = $sDestinationFolder . $sTargetFileName;
				$aPicturesParam['watermark_file_path'] = $oShop->getWatermarkFilePath();
				$aPicturesParam['watermark_position_x'] = $oShop->watermark_default_position_x;
				$aPicturesParam['watermark_position_y'] = $oShop->watermark_default_position_y;
				$aPicturesParam['large_image_preserve_aspect_ratio'] = $oShop->preserve_aspect_ratio;
				$aPicturesParam['small_image_source'] = $aPicturesParam['large_image_source'];
				$aPicturesParam['small_image_name'] = $aPicturesParam['large_image_name'];
				$aPicturesParam['small_image_target'] = $sDestinationFolder . "small_{$sTargetFileName}";
				$aPicturesParam['create_small_image_from_large'] = TRUE;
 
				if (!$bFirstPhoto)
				{
					$aPicturesParam['large_image_max_width'] = $oProperty->image_large_max_width;
					$aPicturesParam['large_image_max_height'] = $oProperty->image_large_max_height;
					$aPicturesParam['small_image_max_width'] = $oProperty->image_small_max_width;
					$aPicturesParam['small_image_max_height'] = $oProperty->image_small_max_height;
				}
				else
				{
					$aPicturesParam['large_image_max_width'] = $oShop->image_large_max_width;
					$aPicturesParam['large_image_max_height'] = $oShop->image_large_max_height;
					$aPicturesParam['small_image_max_width'] = $oShop->image_small_max_width;
					$aPicturesParam['small_image_max_height'] = $oShop->image_small_max_height;
				}
 
				$aPicturesParam['small_image_watermark'] = $oShop->watermark_default_use_small_image;
				$aPicturesParam['small_image_preserve_aspect_ratio'] = $oShop->preserve_aspect_ratio_small;
 
				$aPicturesParam['large_image_watermark'] = $oShop->watermark_default_use_large_image;
 
				try
				{
					$result = Core_File::adminUpload($aPicturesParam);
				}
				catch (Exception $exc)
				{
					$result = array('large_image' => FALSE, 'small_image' => FALSE);
				}
 
				if ($result['large_image'])
				{
					if (!$bFirstPhoto)
					{
						$oProperty_Value->file = $sTargetFileName;
						$oProperty_Value->file_name = $sFileName;
						$oProperty_Value->save();
					}
					else
					{
						$oShop_Item->image_large = $sTargetFileName;
						$oShop_Item->setLargeImageSizes();
					}
				}
 
				if ($result['small_image'])
				{
					if (!$bFirstPhoto)
					{
						$oProperty_Value->file_small = "small_{$sTargetFileName}";
						$oProperty_Value->file_small_name = '';
						$oProperty_Value->save();
					}
					else
					{
						$oShop_Item->image_small = "small_{$sTargetFileName}";
						$oShop_Item->setSmallImageSizes();
					}
				}
 
				$oShop_Item->save();
			}
		}
 
		/**
		 * Выполняет парсинг и импорт характеристик
		 * 
		 * @param Shop_Item_Model $oShop_Item
		 * @param integer $categoryId
		 * @param integer $	 modelId
		 */
		protected function _parseDetails(Shop_Item_Model $oShop_Item, $categoryId, $modelId)
		{
			$oDetailsXml = $this->_getResource('/model/' . $modelId . '/details');
			$aoDetailsBlocks = $oDetailsXml->xpath('block');
 
			foreach ($aoDetailsBlocks as $oDetailsBlock)
			{
				$this->_saveDetailsBlock($oShop_Item, $oDetailsBlock, $categoryId);
			}
		}
 
		/**
		 * Сохраняет информацию о товаре
		 * 
		 * @param Shop_Item_Model $oShop_Item
		 * @param SimpleXmlElement $oModelXml
		 */
		protected function _saveModelInfo(Shop_Item_Model $oShop_Item, SimpleXmlElement $oModelXml)
		{
			$oNameXml = $oModelXml->xpath('name');
 
			$sModelName = strval($oNameXml[0]);
			$iModelId = intval($oModelXml['id']);
 
			$this->_createPropertyAndSetValue(
				'Идентификатор модели в Яндекс.Маркете',
				'market_model_id',
				0,
				$oShop_Item,
				$iModelId
			);
 
			$this->_createPropertyAndSetValue(
				'Модель',
				'model_name',
				1,
				$oShop_Item,
				$sModelName
			);
		}
 
		// Сохраняет блок характеристик товара
		protected function _saveDetailsBlock(Shop_Item_Model $oShop_Item, $oDetailsBlock, $categoryId)
		{
			$sBlockName = strval($oDetailsBlock['name']);
 
			if ($sBlockName == 'Габариты и вес')
			{
				$this->_saveDimensionsAndWeight($oShop_Item, $oDetailsBlock);
				return;
			}
 
			$sCategoryName = $oShop_Item->Shop_Group->name;
 
			$aoDetailsParams = $oDetailsBlock->xpath('param');
			foreach ($aoDetailsParams as $oDetailsParam)
			{
				$sParamName = strval($oDetailsParam['name']);
 
				if (strpos($sParamName, 'Габариты') !== false || strpos($sParamName, 'Размеры') !== false)
				{
					$this->_saveDimensions($oShop_Item, strval($oDetailsParam['value']));
					continue;
				}
 
				if ($sParamName == 'Вес')
				{
					$this->_saveWeight($oShop_Item, strval($oDetailsParam['value']));
					continue;
				}
 
				$sParamValue = strval($oDetailsParam['value']);
 
				$oProperty = $this->_getProperty($sCategoryName, $sBlockName, $sParamName, $categoryId);
 
				$sParamValue = str_replace($oProperty->Shop_Item_Property->Shop_Measure->name, '', $sParamValue);
				$sParamValue = trim($sParamValue);
 
				// Удаляем кавычки в начале и в конце значения
				$sParamValue = preg_replace('/^\"/', '', $sParamValue);
				$sParamValue = preg_replace('/\"$/', '', $sParamValue);
 
				// Разрешаем свойство группе
				$this->_Shop->Shop_Item_Property_For_Groups->allowAccess($oProperty->Shop_Item_Property->id, intval($oShop_Item->Shop_Group->id));
 
				switch ($oProperty->type)
				{
					case 3: // Список
						$aParamValue = explode(', ', $sParamValue);
 
						foreach ($aParamValue as $sParamValue)
						{
							$oProperty_Value = $oProperty->createNewValue($oShop_Item->id);
 
							$oList_Item = $this->_getListItem($sCategoryName, $sBlockName, $sParamName, trim($sParamValue));
							$oProperty_Value->value = $oList_Item->id;
 
							$oProperty_Value->save();
						}
					break;
 
					case 7:  // Флажок
						$oProperty_Value = $oProperty->createNewValue($oShop_Item->id);
						$oProperty_Value->value = (strpos($sParamValue, 'есть') !== null) ? 1 : 0;
						$oProperty_Value->save();
					break;
 
					default:
						$oProperty_Value = $oProperty->createNewValue($oShop_Item->id);
						$oProperty_Value->value = $sParamValue;
						$oProperty_Value->save();
					break;
				}
			}
		}
 
		// Сохраняет габариты и вес товара
		protected function _saveDimensionsAndWeight(Shop_Item_Model $oShop_Item, $oDimensionsAndWeightBlock)
		{
			$aoDimensions = $oDimensionsAndWeightBlock->xpath('param[contains(@name, "Габариты") or contains(@name, "Размеры")]');
			$aoWeight = $oDimensionsAndWeightBlock->xpath('param[contains(@name, "Вес")]');
 
			if (count($aoDimensions) > 0)
			{
				$this->_saveDimensions($oShop_Item, strval($aoDimensions[0]['value']));
			}
 
			if (count($aoWeight) > 0)
			{
				$this->_saveWeight($oShop_Item, strval($aoWeight[0]['value']));
			}
		}
 
		// Сохраняет габариты товара
		protected function _saveDimensions(Shop_Item_Model $oShop_Item, $sDimensionsValue)
		{
			$aDimensionsWithUnit = explode(' ', $sDimensionsValue);
			$sDimensions = $aDimensionsWithUnit[0];
 
			$sUnit = $aDimensionsWithUnit[1];
			switch ($sUnit)
			{
				case 'см': $coefficient = 10; break;
				case 'м': $coefficient = 1000; break;
				default: $coefficient = 1; break;
			}
 
			$aDimensions = explode('x', $sDimensions);
 
			$oShop_Item->length = $aDimensions[0] * $coefficient;
 
			if (count($aDimensions) > 1)
			{
				$oShop_Item->width = $aDimensions[1] * $coefficient;
			}
 
			if (count($aDimensions) > 2)
			{
				$oShop_Item->height = $aDimensions[2] * $coefficient;
			}
 
			$oShop_Item->save();
		}
 
		// Сохраняет вес товара
		protected function _saveWeight(Shop_Item_Model $oShop_Item, $sWeightValue)
		{
			$iWeight = $sWeightValue;
			$oShop_Item->weight = $iWeight;
 
			$oShop_Item->save();
		}
 
		/**
		 * Возвращает XML-данные ресурса
		 *
		 * Например, получим фильтры категории:
		 * $aFiltersXml = $this->_getResource('category/85674362/filters', array('filter_set' => 'all');
		 *
		 * @param string $resource
		 * @param array $resourceParams
		 * @param string $type
		 * @return SimpleXmlElement
		 */
		protected function _getResource($resource, $resourceParams = array(), $type = 'xml')
		{
			$authParams = array('api_key' => $this->_apiKey, 'geo_id' => $this->_geoId);
			$query = $authParams + $resourceParams;
 
			$resourceUrl = $this->_apiUrl . $resource . '.' . $type;
			$resourceUrl .= '?' . http_build_query($query, '', '&');
 
			// Кэширование запросов
			$cacheFile = $this->_cacheDir . md5($resourceUrl);
			$bFromCache = false;
 
			if (is_file($cacheFile) || $this->_onlyCache)
			{
				$content = file_get_contents($cacheFile);
 
				try
				{
					$contentXml = new SimpleXmlElement($content);
					$bFromCache = true;
				}
				catch (Exception $e)
				{
					// Кэш файл сломался
					$content = $this->_getRemoteContent($resourceUrl);
				}
			}
			else
			{
				$content = $this->_getRemoteContent($resourceUrl);
				$contentXml = new SimpleXmlElement($content);
			}
 
			if ($content && !$bFromCache)
			{
				file_put_contents($cacheFile, $content);
			}
 
			if (!$contentXml || count($contentXml->xpath('error')) > 0)
			{
				throw new Core_Exception('Ошибка в запросе.');
			}
 
			return $contentXml;
		}
 
		/**
		 * Возвращает тело ответа по URL
		 * 
		 * @param string $url
		 * @return string
		*/
		protected function _getRemoteContent($url)
		{
			$statusCode = false;
			$i = 0;
 
			while ($statusCode != 200 && $i < 10)
			{
				$content = file_get_contents($url);
 
				if (isset($http_response_header))
				{
					$aResponseHeader = explode(' ', $http_response_header[0]);
					$statusCode = $aResponseHeader[1];
				}
				else
				{
					$statusCode = false;
				}
 
				if ($statusCode != 200)
				{
					usleep(100 * $i * $i);
				}
 
				$i++;
			}
 
			return $content;
		}
 
		// 
		protected function _createPropertyAndSetValue($sName, $sTagName, $type, Shop_Item_Model $oShop_Item, $value)
		{
			$oShop = $this->_Shop;
			$oShop_Item_Property_List = Core_Entity::factory('Shop_Item_Property_List', $oShop->id);
			$oProperties = $oShop_Item_Property_List->Properties;
			$oProperties->queryBuilder()
				->where('tag_name', '=', $sTagName)
				->where('deleted', '=', 0);
			$aoProperties = $oProperties->findAll(false);
 
			if (count($aoProperties) > 0)
			{
				$oProperty = $aoProperties[0];
			}
			else
			{
				$oProperty = Core_Entity::factory('Property');
				$oProperty->name = $sName;
				$oProperty->tag_name = $sTagName;
				$oProperty->type = $type;
 
				$oProperty->save();
 
				$oShop_Item_Property_List->add($oProperty);
			}
 
			$aoProperty_Values = $oProperty->getValues($oShop_Item->id);
 
			$oProperty_Value = count($aoProperty_Values) > 0
				? $aoProperty_Values[0]
				: $oProperty->createNewValue($oShop_Item->id);
 
			$oProperty_Value->value = $value;
			$oProperty_Value->save();
 
			$oShop->Shop_Item_Property_For_Groups->allowAccess($oProperty->Shop_Item_Property->id, ($oShop_Item->modification_id == 0
				? intval($oShop_Item->Shop_Group->id)
				: intval($oShop_Item->Modification->Shop_Group->id)
			));
		}
 
		// Возвращает группу по имени, если такой нет, то создает
		protected function _getShopGroup($sGroupName)
		{
			$oShop_Group = $this->_Shop->Shop_Groups->getByName($sGroupName, false);
 
			if (!$oShop_Group)
			{
				$oShop_Group = Core_Entity::factory('Shop_Group');
				$oShop_Group->name = $sGroupName;
				$oShop_Group->save();
 
				$this->_Shop->add($oShop_Group);
 
				$oShop_Group->makePath();
				$oShop_Group->save();
			}
 
			return $oShop_Group;
		}
 
 
		/**
		 * Возвращает фильтр характеристики
		 *
		 * @param string $sParamName
		 * @param integer $categoryId
		 * @param boolean $bStrict
		 * @return SimpleXmlElement
		 */
		protected function _getDetailsParamFilter($sParamName, $categoryId, $bStrict = true)
		{
			if (!$this->_categoryFiltersXml)
			{
				$this->_categoryFiltersXml = $this->_getResource('/category/' . $categoryId . '/filters', array('filter_set' => 'all'));
			}
 
			if ($bStrict)
			{
				$oFiltersXml = $this->_categoryFiltersXml->xpath('filter[@name = "' . $sParamName . '"]');
			}
			else
			{
				$oFiltersXml = $this->_categoryFiltersXml->xpath('filter[contains(@name, "' . $sParamName . '")]');
			}
 
			if (count($oFiltersXml) > 0)
			{
				return $oFiltersXml[0];
			}
 
			return null;
		}
 
		// Возвращает единицу измерения по имени
		protected function _getMeasure($sMeasureName)
		{
			$oShop_Measure = Core_Entity::factory('Shop_Measure')->getByName($sMeasureName, false);
 
			if (!$oShop_Measure)
			{
				$oShop_Measure = Core_Entity::factory('Shop_Measure');
				$oShop_Measure->name = $sMeasureName;
				$oShop_Measure->description = $sMeasureName;
				$oShop_Measure->save();
			}
 
			return $oShop_Measure;
		}
 
		// Возвращает директорию свойства, если такой нет, то создает
		protected function _getDetailsPropertyDir($sCategoryName, $sBlockName)
		{
			$oShop_Item_Property_List = Core_Entity::factory('Shop_Item_Property_List', $this->_Shop->id);
			$oCategoryPropertyDir = $oShop_Item_Property_List->Property_Dirs->getByName($sCategoryName, false);
 
			if (!$oCategoryPropertyDir)
			{
				$oCategoryPropertyDir = Core_Entity::factory('Property_Dir');
				$oCategoryPropertyDir->name = $sCategoryName;
				$oCategoryPropertyDir->save();
 
				$oShop_Item_Property_List->add($oCategoryPropertyDir);
			}
 
			$oProperty_Dir = $oCategoryPropertyDir->Property_Dirs->getByName($sBlockName, false);
 
			if (!$oProperty_Dir)
			{
				$oProperty_Dir = Core_Entity::factory('Property_Dir');
				$oProperty_Dir->name = $sBlockName;
				$oProperty_Dir->parent_id = $oCategoryPropertyDir->id;
				$oProperty_Dir->save();
 
				$oShop_Item_Property_List->add($oProperty_Dir);
			}
 
			return $oProperty_Dir;
		}
 
		// Возвращает свойство, если такого нет, то создает
		protected function _getProperty($sCategoryName, $sBlockName, $sParamName, $categoryId)
		{
			$oShop_Item_Property_List = Core_Entity::factory('Shop_Item_Property_List', $this->_Shop->id);
 
			// Определяем название свойства
			$oFilterXml = $this->_getDetailsParamFilter($sParamName, $categoryId);
 
			$sParamType = strval($oFilterXml['type']);
			$sParamMeasure = strval($oFilterXml['unit']);
			$sParamShortname = strval($oFilterXml['shortname']);
 
			$oProperty_Dir = $this->_getDetailsPropertyDir($sCategoryName, $sBlockName);
			$oProperties = $oProperty_Dir->Properties;
			$oProperties->queryBuilder()
				->where('name', 'LIKE', $sParamName . '%')
				->where('deleted', '=', 0);
			$aoProperties = $oProperties->findAll(false);
 
			if (count($aoProperties) > 0)
			{
				$oProperty = $aoProperties[0];
			}
			else
			{
				$oProperty = Core_Entity::factory('Property');
				$oProperty->name = $sParamName . ($sParamMeasure ? ', ' . $sParamMeasure : '');
				$oProperty->multiple = 0;
 
				if ($sParamShortname)
				{
					$oProperty->tag_name = strtolower(preg_replace('/(?<=\\w)(?=[A-Z])/','_$1', $sParamShortname));
				}
				else
				{
					$sTranslated = Core_Str::translate($sParamName);
					$oProperty->tag_name = $sTranslated
						? $sTranslated
						: $sParamName;
					$oProperty->tag_name = Core_Str::transliteration($oProperty->tag_name);
				}
 
				switch ($sParamType)
				{
					case 'enum':
						$oProperty->type = 3; // Список
						$oProperty->save();
 
						$oList = $this->_getList($sCategoryName, $sBlockName, $sParamName);
 
						$oProperty->add($oList);
					break;
 
					case 'numeric':
						$oProperty->type = 11; // Число с плавающей запятой
						$oProperty->save();
					break;
 
					case 'bool': 
						$oProperty->type = 7; // Флажок
						$oProperty->save();
					break;
 
					default:
						if ($sParamName == 'Дополнительная информация')
						{
							$oProperty->type = 4; // Большое текстовое поле
						}
						else
						{
							$oProperty->type = 3; // Список
							$oProperty->save();
 
							$oList = $this->_getList($sCategoryName, $sBlockName, $sParamName);
 
							$oProperty->add($oList);
						}
 
						$oProperty->save();
					break;
				}
 
				$oShop_Item_Property_List->add($oProperty);
				$oProperty_Dir->add($oProperty);
 
				// Единица измерения
				$oShop_Measure = $this->_getMeasure($sParamMeasure);
				$oProperty->Shop_Item_Property->add($oShop_Measure);
 
				$this->_importedProperties++;
			}
 
			return $oProperty;
		}
 
		// Возвращает список свойства, если такого нет, то создает
		protected function _getList($sCategoryName, $sBlockName, $sParamName)
		{
			$oCategoryList_Dirs = Core_Entity::factory('List_Dir');
			$oCategoryList_Dirs->queryBuilder()
				->where('name', '=', $sCategoryName)
				->where('deleted', '=', 0)
				->where('parent_id', '=', 0);
			$aoCategoryList_Dirs = $oCategoryList_Dirs->findAll(false);
 
			if (count($aoCategoryList_Dirs) > 0)
			{
				$oCategoryListDir = $aoCategoryList_Dirs[0];
			}
			else
			{
				$oCategoryListDir = Core_Entity::factory('List_Dir');
				$oCategoryListDir->name = $sCategoryName;
				$oCategoryListDir->save();
			}
 
			$oList_Dir = $oCategoryListDir->List_Dirs->getByName($sBlockName, false);
 
			if (!$oList_Dir)
			{
				$oList_Dir = Core_Entity::factory('List_Dir');
				$oList_Dir->name($sBlockName);
				$oList_Dir->parent_id = $oCategoryListDir->id;
				$oList_Dir->save();
			}
 
			$oList = $oList_Dir->Lists->getByName($sParamName, false);
 
			if (!$oList)
			{
				$oList = Core_Entity::factory('List');
				$oList->name = $sParamName;
				$oList->save();
 
				$oList_Dir->add($oList);
			}
 
			return $oList;
		}
 
		// Возвращает элемент списка, если такого нет, то создает
		protected function _getListItem($sCategoryName, $sBlockName, $sParamName, $value)
		{
			$oList = $this->_getList($sCategoryName, $sBlockName, $sParamName);
			$oList_Item = $oList->List_Items->getByValue($value, false);
 
			if (!$oList_Item)
			{
				$oList_Item = Core_Entity::factory('List_Item');
				$oList_Item->value = $value;
 
				$sTranslated = Core_Str::translate($value);
				$oList_Item->tag = $sTranslated
					? $sTranslated
					: $value;
				$oList_Item->tag = Core_Str::transliteration($oList_Item->tag);
 
				$oList_Item->save();
 
				$oList->add($oList_Item);
 
				$this->_importedListItems++;
			}
 
			return $oList_Item;
		}
 
		/**
		 * Скачивает удаленный файл, возвращает путь к временному файлу
		 *
		 * @param string $sRemoteFile
		 * @return string
		 */
		protected function _downloadPhoto($sRemoteFile)
		{
			$sTempFileName = tempnam(CMS_FOLDER . TMP_DIR, 'CMS');
 
			// Копируем содержимое WEB-файла в локальный временный файл
			file_put_contents($sTempFileName, file_get_contents($sRemoteFile));
 
			return $sTempFileName;
		}
 
		protected function _printOutput()
		{
			?>
				<strong>Импортирована страница <?=$this->_page?>:</strong><br />
				Создано товаров: <?=$this->_importedItems?><br />
				Создано свойств: <?=$this->_importedProperties?><br />
				Создано элементов списков: <?=$this->_importedListItems?><br /><br />
			<?php
 
			print $this->_parserOutput;
		}
	}
 
	$iPage = Core_Array::getGet('page') !== null
		? Core_Array::getGet('page')
		: (
			isset($_SESSION['parser_page'])
				? $_SESSION['parser_page']
				: 1
		);
 
	$iCategoryId = Core_Array::getGet('category_id') !== null
		? Core_Array::getGet('category_id')
		: (
			isset($_SESSION['parser_category_id'])
				? $_SESSION['parser_category_id']
				: 0
		);
 
	$iProducerId = Core_Array::getGet('producer_id') !== null
		? Core_Array::getGet('producer_id')
		: (
			isset($_SESSION['parser_producer_id'])
				? $_SESSION['parser_producer_id']
				: 0
		);
 
	$bMakeParsing = Core_Array::getGet('parse') && $iCategoryId;
 
	if ($bMakeParsing)
	{
		ob_start();
 
		$marketParser = new MarketParser(
			Core_Array::get(Core_Page::instance()->libParams, 'shopId'),
			Core_Array::get(Core_Page::instance()->libParams, 'key'),
			false
		);
 
		if (!$iProducerId)
		{
			$iProducerId = $marketParser->getNextProducerId($iCategoryId, 0);
		}
 
		// if ($iProducerId)
		// {
			$hasItems = $marketParser->parseProducerPage($iCategoryId, $iProducerId, $iPage);
		// }
		// else
		// {
		// 	$hasItems = $marketParser->parseCategoryPage($iCategoryId, $iPage);
		// }
 
		$iPage++;
 
		if (!$hasItems)
		{
			$iProducerId = $marketParser->getNextProducerId($iCategoryId, $iProducerId);
 
			$iPage = 1;
 
			if ($iProducerId)
			{
				$hasItems = true;
			}
		}
 
		$_SESSION['parser_page'] = $iPage;
		$_SESSION['parser_category_id'] = $iCategoryId;
		$_SESSION['parser_producer_id'] = $iProducerId;
 
		$sParserOutput = ob_get_clean();
	}
 
	?>
	<form name="parsing_form" method="GET">
		<table>
			<tr>
				<td>Категория:</td>
				<td><input name="category_id" type="text" size="50" value="<?=$iCategoryId?>" style="margin: 5px 0" /><!-- Водяные насосы --></td>
			</tr>
			<tr>
				<td>Производитель:</td>
				<td><input name="producer_id" type="text" size="50" value="<?=$iProducerId?>" style="margin: 5px 0" /></td>
			</tr>
			<tr>
				<td>Страница:</td>
				<td><input name="page" value="<?=$iPage <= 50 ? $iPage : 1?>" style="margin: 5px 0" /></td>
			</tr>
		</table>
 
		<input type="hidden" name="parse" value="1" />
		<button type="submit" style="margin: 5px 0">Парсить</button><br/><br/>
	</form>
 
	<div>
		<?php
			if (isset($sParserOutput))
			{
				print $sParserOutput;
			}
		?>
	</div>
 
	<?php
		if ($bMakeParsing)
		{
			if ($hasItems && $iPage >= 1 && $iPage <= 50)
			{
				?>
					<script>
						setTimeout(
							function() {
								document.parsing_form.submit();
							},
							2000
						);
					</script>
				<?
			}
			else
			{
				?>Парсинг завершен!<?
			}
		}
private/koding/hostcms/modules/shop/import_export/import_tovarov_iz_jandeks.marketa/market_parser.txt · Last modified: 27.12.17 в 10:01 by maximzasorin_gmail.com