private:koding:hostcms:modules:shop:useful:import_market_opinions:controller.php
<?php
 
defined('HOSTCMS') || exit('HostCMS: access denied.');
 
/**
 * Класс для взаимодействия с Контентным API Яндекса.
 *
 * @author KAD Systems (©) 2017
 */
class Kad_MarketContent_Controller extends Core_Servant_Properties
{
	/**
	 * Публичные свойства.
	 *
	 * @var array
	 */
	protected $_allowedProperties = array(
		'geoId',
		'cache',
		'cachePath',
		'cacheDays',
		'log',
	);
 
	/**
	 * Адрес для API-запросов.
	 *
	 * @var string
	 */
	protected $_apiUrl;
 
	/**
	 * Ключ для доступа к API.
	 *
	 * @var string
	 */
	protected $_apiKey;
 
	/**
	 * Количество выполненных запросов.
	 *
	 * @var integer
	 */
	protected $_countRequests;
 
	/**
	 * Обрабатывает ссылки в отзывах.
	 *
	 * @param  string  $text
	 * @return string
	 */
	static public function processLinks($text)
	{
		return str_replace('href=', 'target="_blank" href=', $text);
	}
 
	/**
	 * Конструктор.
	 * 
	 * @param  string  $apiKey
	 * @param  string  $apiUrl
	 * @return void
	 */
	public function __construct($apiKey, $apiUrl = 'https://api.content.market.yandex.ru/v1')
	{
		parent::__construct();
 
		$this->_apiUrl = $apiUrl;
		$this->_apiKey = $apiKey;
		$this->_countRequests = 0;
 
		$this->geoId = '10645';
		$this->cache = FALSE;
		$this->cachePath = TMP_DIR . 'marketcontent/';
		$this->cacheDays = 7;
		$this->log = FALSE;
	}
 
	/**
	 * Возвращает количество выполненных запросов.
	 *
	 * @return integer
	 */
	public function getCountRequests()
	{
		return $this->_countRequests;
	}
 
	/**
	 * Возвращает отзывы о модели.
	 *
	 * @param  integer  $modelId
 	 * @return array
	 */
	public function getModelOpinions($modelId)
	{
		$page = 1;
		$count = 30;
 
		// 
		$oOpinionsJson = $this->_getResource("/model/{$modelId}/opinion", 
			array(
				'count' => $count
			)
		);
		$oModelOpinions = $oOpinionsJson->modelOpinions;
 
		$aOpinions = $oModelOpinions->opinion;
 
		while ($page * $count < $oModelOpinions->total)
		{
			$page = $oModelOpinions->page + 1;
 
			$oOpinionsJson = $this->_getResource("/model/{$modelId}/opinion",
				array(
					'page' => $page,
					'count' => $count
				)
			);
			$oModelOpinions = $oOpinionsJson->modelOpinions;
 
			$aOpinions = array_merge($aOpinions, $oModelOpinions->opinion);
		}
 
		return $aOpinions;
	}
 
	/**
	 * Возвращает отзывы об интернет-магазине.
	 *
	 * @param  integer  $shopId
	 * @return array
	 */
	public function getShopOpinions($shopId)
 	{
 		$page = 1;
		$count = 30;
 
		// 
		$oOpinionsJson = $this->_getResource("/shop/{$shopId}/opinion", 
			array(
				'count' => $count
			)
		);
		$oShopOpinions = $oOpinionsJson->shopOpinions;
 
		$aOpinions = $oShopOpinions->opinion;
 
		while ($page * $count < $oShopOpinions->total)
		{
			$page = $oShopOpinions->page + 1;
 
			$oOpinionsJson = $this->_getResource("/shop/{$shopId}/opinion",
				array(
					'page' => $page,
					'count' => $count
				)
			);
			$oShopOpinions = $oOpinionsJson->shopOpinions;
 
			$aOpinions = array_merge($aOpinions, $oShopOpinions->opinion);
		}
 
		return $aOpinions;
 	}
 
	/**
	 * Возвращает информацию о регионе.
	 *
	 * @param  string  $geoId
	 * @return object
	 */
	public function getRegionInfo($geoId)
	{
		$oRegionJson = $this->_getResource("/georegion/{$geoId}");
 
		return isset($oRegionJson->georegion)
			? $oRegionJson->georegion
			: NULL;
	}
 
	/**
	 * Возвращает данные ресурса.
	 *
	 * @param  string  $resource
	 * @param  array  $resourceParams
	 * @param  string  $type
	 * @return SimpleXmlElement
	 */
	protected function _getResource($resource, $resourceParams = array())
	{
		$query = array('geo_id' => $this->geoId) + $resourceParams;
 
		$requestUrl = $this->_apiUrl
			. $resource
			. '.json'
			. '?' . http_build_query($query, '', '&');
 
		$oData = NULL;
		$bFromRequest = FALSE;
		$dailyRemining = '(none)';
 
		// Запрашиваем данные из кэша
		if ($this->cache)
		{
			$oData = @json_decode($this->_readCache($requestUrl));
		}
 
		// Запрашиваем данные из API
		if (!$this->cache || !$oData)
		{
			usleep(0.1 * 1000000);
 
			$oCoreHttp = Core_Http::instance()
				->clear()
				->additionalHeader('Authorization', $this->_apiKey)
				->additionalHeader('Accept', '*/*')
				->url($requestUrl)
				->execute();
 
			if (preg_match('/X-RateLimit-Daily-Remaining: (\d+)\s/', $oCoreHttp->getHeaders(), $aMatches))
			{
				$dailyRemining = intval($aMatches[1]);
			}
 
			$oData = @json_decode(strval($oCoreHttp->getBody()));
			$bFromRequest = TRUE;
 
			$this->_countRequests++;
 
			$this->_log("data from request '{$requestUrl}'");
		}
		else
		{
			$this->_log("data from cache '{$requestUrl}'");
		}
 
		if (!$oData)
		{
			throw new Core_Exception('Content Api returns invalid response.');
		}
		elseif (isset($oData->errors))
		{
			throw new Core_Exception("Content Api returns error: «{$oData->errors[0]}», daily limit remainig: {$dailyRemining}");
		}
 
		$this->_log("daily limit remainig = {$dailyRemining}");
 
		// Сохраняем запрос в кэш
		if ($this->cache && $bFromRequest)
		{
			$this->_writeCache($requestUrl, json_encode($oData));
		}
 
		return $oData;
	}
 
	/**
	 * Возвращает данные запроса из кэша.
	 *
	 * @param  string  $request
	 * @return string
	 */
	protected function _readCache($request)
	{
		$cacheFile = $this->_getCacheFile($request);
 
		$bCacheTimeout = filemtime($cacheFile) > time() - $this->cacheDays * 24 * 60 * 60
			// Запрос на получение информации о регионе никогда не устаривает
			|| strpos($request, '/georegion/') !== FALSE
		;
 
		if (file_exists($cacheFile) && $bCacheTimeout)
		{
			return file_get_contents($cacheFile);
		}
 
		return NULL;
	}
 
	/**
	 * Записывает данные запроса в кэш.
	 *
	 * @param  string  $data
	 * @param  string  $data
	 * @return void
	 */
	protected function _writeCache($request, $data)
	{
		$cacheFile = $this->_getCacheFile($request);
		$cacheDir = substr($cacheFile, 0, strrpos($cacheFile, '/'));
 
		if (!is_dir($cacheDir))
		{
			mkdir($cacheDir, 0777, TRUE);			
		}
 
		file_put_contents($this->_getCacheFile($request), $data);
	}
 
	/**
	 * Возвращает путь к кэш-файлу запроса.
	 *
	 * @param  string  $request
	 * @return string
	 */
	protected function _getCacheFile($request)
	{
		return CMS_FOLDER . $this->cachePath . hash('sha256', $request);
	}
 
	/**
	 * Логирует строку.
	 *
	 * @param  string  $string
	 * @return void
	 */
	protected function _log($string)
	{
		if (!$this->log)
		{
			return;
		}
 
		print $string . "\n";
	}
}
private/koding/hostcms/modules/shop/useful/import_market_opinions/controller.php.txt · Last modified: 30.06.17 в 16:32 by maximzasorin_gmail.com