Your IP : 18.216.187.74


Current Path : /home/bitrix/ext_www/royal-thermo.com.ua/bitrix/modules/seo/lib/engine/
Upload File :
Current File : /home/bitrix/ext_www/royal-thermo.com.ua/bitrix/modules/seo/lib/engine/yandex.php

<?
/**
 * Bitrix Framework
 * @package bitrix
 * @subpackage seo
 * @copyright 2001-2013 Bitrix
 */
namespace Bitrix\Seo\Engine;

use Bitrix\Main\Context;
use Bitrix\Seo\Engine;
use Bitrix\Seo\IEngine;
use Bitrix\Main\Text;
use Bitrix\Main\Text\Converter;

class Yandex extends Engine\YandexBase implements IEngine
{
	const ENGINE_ID = 'yandex';

	const SERVICE_URL = "https://webmaster.yandex.ru/api/v2";

	const HOSTS_SERVICE = "host-list";
	const HOST_VERIFY = "verify-host";
	const HOST_INFO = "host-information";
	const HOST_TOP_QUERIES = "top-queries";
	const HOST_ORIGINAL_TEXTS = "original-texts";
	const HOST_INDEXED = "indexed-urls";
	const HOST_EXCLUDED = "excluded-urls";

	const ORIGINAL_TEXT_MIN_LENGTH = 500;
	const ORIGINAL_TEXT_MAX_LENGTH = 32000;

	const QUERY_USER = 'https://login.yandex.ru/info';

	const VERIFIED_STATE_VERIFIED = "VERIFIED";
	const VERIFIED_STATE_WAITING = "WAITING";
	const VERIFIED_STATE_FAILED = "VERIFICATION_FAILED";
	const VERIFIED_STATE_NEVER_VERIFIED = "NEVER_VERIFIED";
	const VERIFIED_STATE_IN_PROGRESS = "IN_PROGRESS";

	protected $engineId = 'yandex';
	protected $arServiceList = array();

	// temporary hack
	public function getAuthSettings()
	{
		return $this->engineSettings['AUTH'];
	}

	public function getFeeds()
	{
		if(!isset($this->arServiceList[self::HOSTS_SERVICE]))
		{
			$this->getServiceDocument();
		}

		if(isset($this->arServiceList[self::HOSTS_SERVICE]))
		{
			$queryResult = $this->queryOld($this->arServiceList[self::HOSTS_SERVICE]);

			if($queryResult->status == self::HTTP_STATUS_OK && strlen($queryResult->result) > 0)
			{
				return $this->processResult($queryResult->result);
			}
			else
			{
				throw new Engine\YandexException($queryResult);
			}
		}
	}

	public function getSiteFeeds($domain)
	{
		$domain = ToLower($domain);

		if(!isset($this->engineSettings['SITES'][$domain]))
		{
			$this->getFeeds();
		}

		if(isset($this->engineSettings['SITES'][$domain]))
		{
			$queryResult = $this->queryOld($this->engineSettings['SITES'][$domain]['href']);

			if($queryResult->status == self::HTTP_STATUS_OK && strlen($queryResult->result) > 0)
			{
				return $this->processSiteResult($queryResult->result);
			}
			else
			{
				throw new Engine\YandexException($queryResult);
			}
		}
		else
		{
			throw new \Exception('Site not binded! '.$domain);
		}
	}

	public function getSiteInfo($domain)
	{
		$domain = ToLower($domain);

		if(!isset($this->engineSettings['SITES'][$domain]['SERVICES']))
		{
			$this->getSiteFeeds($domain);
		}

		if(isset($this->engineSettings['SITES'][$domain]['SERVICES']))
		{
			$queryResult = $this->queryOld($this->engineSettings['SITES'][$domain]['SERVICES'][self::HOST_INFO]);
			if($queryResult->status == self::HTTP_STATUS_OK && strlen($queryResult->result) > 0)
			{
				return $this->processResult($queryResult->result);
			}
			else
			{
				throw new Engine\YandexException($queryResult);
			}
		}
		else
		{
			throw new \Exception('Site not binded! '.$domain);
		}
	}

	public function getQueriesFeed($domain)
	{
		$domain = ToLower($domain);

		if(!isset($this->engineSettings['SITES'][$domain]['SERVICES']))
		{
			$this->getSiteFeeds($domain);
		}

		if(isset($this->engineSettings['SITES'][$domain]['SERVICES']))
		{
			$queryResult = $this->queryOld($this->engineSettings['SITES'][$domain]['SERVICES'][self::HOST_TOP_QUERIES]);
			if($queryResult->status == self::HTTP_STATUS_OK && strlen($queryResult->result) > 0)
			{
				$obXml = new \CDataXML();
				if($obXml->loadString($queryResult->result))
				{
					$root = $obXml->getTree()->elementsByName('top-queries');
					if(count($root) > 0)
					{
						$root = $root[0];

						$arQueriesData = array(
							'top-shows' => array(),
							'top-clicks' => array()
						);

						foreach ($root->children as $child)
						{
							switch($child->name())
							{
								case 'top-shows':
								case 'top-clicks':
									$arQueries = $child->elementsByName('top-info');
									foreach($arQueries as $query)
									{
										$arData = array();
										foreach($query->children() as $subChild)
										{
											$arData[$subChild->name()] = $subChild->textContent();
										}
										$arQueriesData[$child->name()][] = $arData;
									}

								break;
								default:
									$arQueriesData[$child->name()] = $child->textContent();
								break;
							}
						}

						return $arQueriesData;
					}

				}
				throw new \Exception('Unexpected query result! '.$queryResult->result);
			}
			else
			{
				throw new Engine\YandexException($queryResult);
			}
		}
		else
		{
			throw new \Exception('Site not binded! '.$domain);
		}
	}

	public function getOriginalTexts($domain, $dir = "/")
	{
		$domain = ToLower($domain);

		if(!isset($this->engineSettings['SITES'][$domain]['SERVICES']))
		{
			$this->getSiteFeeds($domain);
		}

		if(isset($this->engineSettings['SITES'][$domain]['SERVICES']))
		{
			$queryResult = $this->queryOld($this->engineSettings['SITES'][$domain]['SERVICES'][self::HOST_ORIGINAL_TEXTS]);
			if($queryResult->status == self::HTTP_STATUS_OK)
			{
				$obXml = new \CDataXML();
				if($obXml->loadString($queryResult->result))
				{
					$arOriginalTexts = array();
					$arEntries = $obXml->getTree()->elementsByName('original-text');
					foreach($arEntries as $entry)
					{
						$arText = array();
						$arChildren = $entry->children();
						foreach($arChildren as $child)
						{
							$arText[$child->name] = $child->textContent();
						}
						$arOriginalTexts[] = $arText;
					}

					return array(
						"total" => $obXml->getTree()->root[0]->getAttribute("total"),
						"can-add" => $obXml->getTree()->root[0]->getAttribute("can-add"),
						"text" => $arOriginalTexts,
					);
				}

				throw new \Exception('Unexpected query result! '.$queryResult->result);
			}
			else
			{
				throw new Engine\YandexException($queryResult);
			}
		}
	}

	public function addOriginalText($text, $domain, $dir = '/')
	{
		$domain = ToLower($domain);

		if(!isset($this->engineSettings['SITES'][$domain]['SERVICES']))
		{
			$this->getSiteFeeds($domain);
		}

		if(isset($this->engineSettings['SITES'][$domain]['SERVICES']))
		{
$str = <<<EOT
<original-text><content>%s</content></original-text>
EOT;

			$queryResult = $this->queryOld(
				$this->engineSettings['SITES'][$domain]['SERVICES'][self::HOST_ORIGINAL_TEXTS],
				'POST',
				urlencode(sprintf(
					$str,
					Converter::getXmlConverter()->encode(
						Text\Encoding::convertEncoding(
							$text,
							LANG_CHARSET,
							'utf-8'
						)
					)
				))
			);

			if($queryResult->status == self::HTTP_STATUS_OK || $queryResult->status == self::HTTP_STATUS_CREATED)
			{

				return true;
			}
			else
			{
				throw new Engine\YandexException($queryResult);
			}
		}
	}

	public function getIndexed($domain, $dir = "/")
	{
		$domain = ToLower($domain);

		if(!isset($this->engineSettings['SITES'][$domain]['SERVICES']))
		{
			$this->getSiteFeeds($domain);
		}

		if(isset($this->engineSettings['SITES'][$domain]['SERVICES']))
		{
			$queryResult = $this->queryOld($this->engineSettings['SITES'][$domain]['SERVICES'][self::HOST_INDEXED]);
			if($queryResult->status == self::HTTP_STATUS_OK)
			{
				$obXml = new \CDataXML();
				if($obXml->loadString($queryResult->result))
				{
					$arIndexed = array(
						'last-week-index-urls' => array(),
					);
					$root = $obXml->getTree()->root[0];
					foreach($root->children as $tag)
					{
						switch($tag->name())
						{
							case 'last-week-index-urls':
								if(count($tag->children()) > 0)
								{
									foreach($tag->children() as $child)
									{
										$arIndexed[$tag->name()][] = $child->textContent();
									}
								}
							break;
							default:
								$arIndexed[$tag->name()] = $tag->textContent();
							break;
						}
					}

					return $arIndexed;
				}

				throw new \Exception('Unexpected query result! '.$queryResult->result);
			}
			else
			{
				throw new Engine\YandexException($queryResult);
			}
		}
	}

	public function getExcluded($domain, $dir = "/")
	{
		$domain = ToLower($domain);

		if(!isset($this->engineSettings['SITES'][$domain]['SERVICES']))
		{
			$this->getSiteFeeds($domain);
		}

		if(isset($this->engineSettings['SITES'][$domain]['SERVICES']))
		{
			$queryResult = $this->queryOld($this->engineSettings['SITES'][$domain]['SERVICES'][self::HOST_EXCLUDED]);
			if($queryResult->status == self::HTTP_STATUS_OK)
			{
				$obXml = new \CDataXML();
				if($obXml->loadString($queryResult->result))
				{
					$root = $obXml->getTree()->root[0]->children();
					$arExcluded = array(
						"count" => $root[0]->getAttribute('count'),
						"errors" => array(),
					);
					$arEntries = $obXml->getTree()->elementsByName('url-errors-with-code');
					foreach($arEntries as $entry)
					{
						$error = array(
							"code" => $entry->getAttribute('code')
						);
						foreach($entry->children() as $child)
						{
							$error[$child->name()] = $child->textContent();
						}
						$arExcluded['errors'][] = $error;
					}

					return $arExcluded;
				}

				throw new \Exception('Unexpected query result! '.$queryResult->result);
			}
			else
			{
				throw new Engine\YandexException($queryResult);
			}
		}
	}

	public function addSite($domain, $dir = '/')
	{
		$domain = ToLower($domain);
		$queryDomain = Context::getCurrent()->getRequest()->isHttps() ? 'https://'.$domain : $domain;

		if(!isset($this->arServiceList[self::HOSTS_SERVICE]))
		{
			$this->getServiceDocument();
		}

		if(isset($this->arServiceList[self::HOSTS_SERVICE]))
		{
			$str = <<<EOT
<host><name>%s</name></host>
EOT;
			$queryResult = $this->queryOld(
				$this->arServiceList[self::HOSTS_SERVICE],
				"POST",
				sprintf($str, Converter::getXmlConverter()->encode($queryDomain))
			);

			if($queryResult->status == self::HTTP_STATUS_CREATED && strlen($queryResult->result) > 0)
			{
				return array($domain => true);
			}
			else
			{
				throw new Engine\YandexException($queryResult);
			}
		}
	}

	public function verifySite($domain, $bCheck)
	{
		$domain = ToLower($domain);

		if(!isset($this->engineSettings['SITES'][$domain]['SERVICES']))
		{
			$this->getSiteFeeds($domain);
		}

		$queryDomain = Context::getCurrent()->getRequest()->isHttps() ? 'https://'.$domain : $domain;
		if(isset($this->engineSettings['SITES'][$domain]['SERVICES']))
		{
			if(!$bCheck)
			{
				$queryResult = $this->queryOld($this->engineSettings['SITES'][$domain]['SERVICES'][self::HOST_VERIFY]);
				if($queryResult->status == self::HTTP_STATUS_OK && strlen($queryResult->result) > 0)
				{
					$obXml = new \CDataXML();
					if($obXml->loadString($queryResult->result))
					{
						$ver = $obXml->getTree()->elementsByName('verification');
						$ver = $ver[0];

						$state = $ver->getAttribute('state');
						if($state != 'VERIFIED')
						{
							return $ver->children[0]->textContent();
						}
						else
						{
							return false;
						}
					}
				}
				else
				{
					throw new Engine\YandexException($queryResult);
				}
			}
			else
			{
				$queryResult = $this->queryOld(
					$this->engineSettings['SITES'][$domain]['SERVICES'][self::HOST_VERIFY],
					"PUT",
					"<host><type>HTML_FILE</type></host>"
				);

				if($queryResult->status == self::HTTP_STATUS_OK || $queryResult->status == self::HTTP_STATUS_NO_CONTENT)
				{
					return array($domain => array('verification' => 'VERIFIED'));
				}
				else
				{
					throw new Engine\YandexException($queryResult);
				}
			}
		}

		return;
	}

	protected function getServiceDocument()
	{
		$queryResult = $this->queryOld(self::SERVICE_URL);
		if($queryResult->status == self::HTTP_STATUS_OK && strlen($queryResult->result) > 0)
		{
			return $this->processServiceDocument($queryResult->result);
		}
		else
		{
			throw new Engine\YandexException($queryResult);
		}
	}

	protected function processServiceDocument($res)
	{
		$obXml = new \CDataXML();

		if($obXml->loadString($res))
		{
			$arEntries = $obXml->getTree()->elementsByName('link');
			foreach($arEntries as $entry)
			{
				$this->arServiceList[$entry->getAttribute('rel')] = $entry->getAttribute('href');
			}
		}
	}

	protected function processResult($res)
	{
		$obXml = new \CDataXML();

		if($obXml->loadString($res))
		{
			$arEntries = $obXml->getTree()->elementsByName('host');

			$arDomains = array();
			foreach($arEntries as $entry)
			{
				$entryChildren = $entry->children();
				$entryData = array();

				foreach ($entryChildren as $child)
				{
					$tag = $child->name();

					switch($tag)
					{
						case 'name':
							$value = \CBXPunycode::toASCII(ToLower($child->textContent()), $e = null);
							if(preg_match("/^https:\/\//", $value))
							{
								$value = substr($value, 8);
								$entryData['https'] = 1;
							}

							$entryData[$tag] = $value;

						break;

						case 'verification':
						case 'crawling':
							$entryData[$tag] = $child->getAttribute('state');
							$details = $child->children();
							if($details)
							{
								$entryData[$tag.'-details'] = $details[0]->textContent();
							}
						break;

						case 'virused':
							$entryData[$tag] = $child->textContent() == 'true';
						break;

						default: $entryData[$tag] = $child->textContent();
					}
				}

				// HOST_INFO query returns only host id instead of direct url so we should take it from the previous data
				$hostHref = $entry->getAttribute('href');
				if(!$hostHref)
				{
					$hostHref = $this->engineSettings['SITES'][$entryData['name']]['href'];
				}
				$entryData['href'] = $hostHref;

				$arDomains[$entryData['name']] = $entryData;
			}

			$arExistedDomains = \CSeoUtils::getDomainsList();
			foreach($arExistedDomains as $domain)
			{
				$domain['DOMAIN'] = ToLower($domain['DOMAIN']);

				if(isset($arDomains[$domain['DOMAIN']]))
				{
					if(!is_array($this->engineSettings['SITES']))
						$this->engineSettings['SITES'] = array();

					$this->engineSettings['SITES'][$domain['DOMAIN']] = $arDomains[$domain['DOMAIN']];
				}
			}

			$this->saveSettings();

			return $arDomains;
		}

		throw new \Exception('Unexpected query result! '.$res);
		return false;
	}

	protected function processSiteResult($res)
	{
		$obXml = new \CDataXML();

		if($obXml->loadString($res))
		{
			$hostName = $obXml->getTree()->elementsByName('name');
			$hostName = \CBXPunycode::toASCII(ToLower($hostName[0]->textContent()), $e = null);

			if(preg_match("/^https:\/\//", $hostName))
			{
				$hostName = substr($hostName, 8);
			}

			$this->engineSettings['SITES'][$hostName]['SERVICES'] = array();

			$arLinks = $obXml->getTree()->elementsByName('link');
			foreach ($arLinks as $link)
			{
				$this->engineSettings['SITES'][$hostName]['SERVICES'][$link->getAttribute('rel')] = $link->getAttribute('href');
			}

			$this->saveSettings();

			return true;
		}

		return false;
	}

	// TODO: rewrite the whole upper code to use \Bitrix\Main\Web\HttpClient and than kill that implementation
	protected function queryOld($scope, $method = "GET", $data = null, $skipRefreshAuth = false)
	{
		if($this->engineSettings['AUTH'])
		{
			$http = new \CHTTP();
			$http->setAdditionalHeaders(
				array(
					'Authorization' => 'OAuth '.$this->engineSettings['AUTH']['access_token']
				)
			);
			$http->setFollowRedirect(false);

			switch($method)
			{
				case 'GET':
					$result = $http->get($scope);
				break;
				case 'POST':
					$result = $http->post($scope, $data);
				break;
				case 'PUT':
					$result = $http->httpQuery($method, $scope, $http->prepareData($data));
				break;
				case 'DELETE':

				break;
			}

			if($http->status == 401 && !$skipRefreshAuth)
			{
				if($this->checkAuthExpired())
				{
					$this->queryOld($scope, $method, $data, true);
				}
			}

			$http->result = Text\Encoding::convertEncoding($http->result, 'utf-8', LANG_CHARSET);

			return $http;
		}
	}
}
?>