Your IP : 18.223.213.234


Current Path : /home/bitrix/ext_www/crm.klimatlend.ua/bitrix/modules/crm/lib/rest/
Upload File :
Current File : /home/bitrix/ext_www/crm.klimatlend.ua/bitrix/modules/crm/lib/rest/externalchannel.php

<?php

namespace Bitrix\Crm\Rest;
use Bitrix\Crm;
use Bitrix\Crm\Activity\Provider;
use Bitrix\Disk\File;
use Bitrix\Faceid\FaceTable;
use Bitrix\Main\ArgumentException;
use Bitrix\Main\Error;
use Bitrix\Main\Localization\Loc;
use Bitrix\Crm\Integration\Channel\ExternalTracker;
use Bitrix\Crm\Integration\Channel\ChannelType;
use Bitrix\Main\Result;

Loc::loadMessages(__FILE__);

class CCrmExternalChannelImportActivity extends \CCrmExternalChannelRestProxy
{
	private static $ENTITY = null;
	protected $class = null;
	protected $ownerId = -1;
	public $import = null;
	protected $activityType = CCrmExternalChannelActivityType::Undefined;

	public static function getEntity()
	{
		if(!self::$ENTITY)
		{
			self::$ENTITY = new \CCrmActivityRestProxy();
		}

		return self::$ENTITY;
	}

	public function setOwnerEntity($class)
	{
		$this->class = $class;
	}

	/**
	 * @return \CCrmCompanyRestProxy|\CCrmContactRestProxy
	 */
	protected function getOwnerEntity()
	{
		return $this->class;
	}

	public function setOwnerEntityId($id)
	{
		$this->ownerId = (int)$id;
	}

	protected function getOwnerEntityId()
	{
		return $this->ownerId;
	}

	public function setTypeActivity($type)
	{
		$this->activityType = $type;
	}

	protected function getTypeActivity()
	{
		return $this->activityType;
	}

	/**
	 * @param $fields
	 * @return Result
	 */
	protected function checkFields(&$fields)
	{
		$result = new Result();

		if(!is_set($fields, 'SUBJECT') || !is_string($fields['SUBJECT']))
		{
			$result->addError(new Error("SUBJECT is not defined or is invalid", 7001));
		}

		if(!is_set($fields, 'DESCRIPTION') || !is_string($fields['DESCRIPTION']))
		{
			$result->addError(new Error("DESCRIPTION is not defined or is invalid",7002));
		}

		if(!is_set($fields, 'RESULT_VALUE') || !is_numeric($fields['RESULT_VALUE']))
		{
			$result->addError(new Error("RESULT_VALUE is not defined or is invalid",7003));
		}

		if(!is_set($fields, 'RESULT_SUM') || $fields['RESULT_SUM']=='')
		{
			$result->addError(new Error("RESULT_SUM is not defined",7004));
		}

		if(!is_set($fields, 'RESULT_CURRENCY_ID') || $fields['RESULT_CURRENCY_ID']=='' || !\CCrmCurrency::IsExists($fields['RESULT_CURRENCY_ID']))
		{
			$result->addError(new Error("RESULT_CURRENCY_ID not defined or is invalid",7005));
		}

		if(!is_set($fields, 'START_TIME') || !is_string(\CRestUtil::unConvertDateTime($fields['START_TIME'])))
		{
			$result->addError(new Error("START_TIME is not defined or is invalid",7006));
		}

		if(!is_set($fields, 'ORIGIN_ID') || $fields['ORIGIN_ID']=='')
		{
			$result->addError(new Error("ORIGIN_ID is not defined",7007));
		}

		return $result;
	}

	public function fillEmptyFields(&$fields, $params=array())
	{
		$ownerEntity = $this->getOwnerEntity();

		if($ownerEntity->getOwnerTypeID() ===  \CCrmOwnerType::Company)
		{
			$title = is_set($params[CCrmExternalChannelImport::FIELDS], 'TITLE')? $params[CCrmExternalChannelImport::FIELDS]['TITLE']:'';

			$fields['SUBJECT'] =  Loc::getMessage('CRM_REST_EXTERNAL_CHANNEL_IMPORT_COMPANY_ACTIVITY_SUBJECT')." ".$title;
		}
		elseif($ownerEntity->getOwnerTypeID() ===  \CCrmOwnerType::Contact)
		{
			$name[] = is_set($params[CCrmExternalChannelImport::FIELDS], 'LAST_NAME')? $params[CCrmExternalChannelImport::FIELDS]['LAST_NAME']:'';
			$name[] = is_set($params[CCrmExternalChannelImport::FIELDS], 'NAME')? $params[CCrmExternalChannelImport::FIELDS]['NAME']:'';
			$name[] = is_set($params[CCrmExternalChannelImport::FIELDS], 'SECOND_NAME')? $params[CCrmExternalChannelImport::FIELDS]['SECOND_NAME']:'';

			$fields['SUBJECT'] = Loc::getMessage('CRM_REST_EXTERNAL_CHANNEL_IMPORT_CONTACT_ACTIVITY_SUBJECT')." ".implode(' ', $name);
		}

		$fields['START_TIME'] = ConvertTimeStamp((time() + \CTimeZone::GetOffset()), 'FULL', SITE_ID);
	}

	/**
	 * @return array
	 */
	protected function prepareFieldsProviderParams()
	{
		/** @var CCrmExternalChannelImport $import */
		$import = $this->import;
		$fields = $import->getRawData();

		if(isset($fields[CCrmExternalChannelImport::ACTIVITY][CCrmExternalChannelImport::EXTERNAL_FIELDS]) &&
			isset($fields[CCrmExternalChannelImport::ACTIVITY][CCrmExternalChannelImport::EXTERNAL_FIELDS]['FACE_SNAPSHOT']))
		{
			unset($fields[CCrmExternalChannelImport::ACTIVITY][CCrmExternalChannelImport::EXTERNAL_FIELDS]['FACE_SNAPSHOT']);
		}

		return $fields;
	}

	/**
	 * @return string
	 */
	protected function getShapshotName()
	{
		return Loc::getMessage('CRM_REST_EXTERNAL_CHANNEL_IMPORT_ACTIVITI_SNAPSHOT_NAME', array('#POSTFIX#'=>ConvertTimeStamp((time() + \CTimeZone::GetOffset()), 'FULL', SITE_ID))).'.jpg';
	}

	/**
	 * @return array
	 */
	protected function internalizeFileFaceSnapshot()
	{
		/** @var CCrmExternalChannelImport $import */
		$import = $this->import;
		$fields = $import->getRawData();
		$files['FILES'] = array();

		if(isset($fields[CCrmExternalChannelImport::ACTIVITY][CCrmExternalChannelImport::EXTERNAL_FIELDS]) &&
			isset($fields[CCrmExternalChannelImport::ACTIVITY][CCrmExternalChannelImport::EXTERNAL_FIELDS]['FACE_SNAPSHOT']))
		{
			$binaryImageContent = $fields[CCrmExternalChannelImport::ACTIVITY][CCrmExternalChannelImport::EXTERNAL_FIELDS]['FACE_SNAPSHOT'];

			$files['FILES'] = array('fileData'=>array($this->getShapshotName(), $binaryImageContent));

			$this->tryInternalizeDiskFileField($files, 'FILES');
		}

		return count($files['FILES'])>0 ? $files['FILES']:array();
	}

	public function fillFields(&$fields, $params=array())
	{
		$ownerEntity = $this->getOwnerEntity();

		/** @var CCrmExternalChannelImport $import */
		$import = $this->import;

		/** @var CCrmExternalChannelConnector $connector */
		$connector = $import->getConnector();

		$curUserId = \CCrmSecurityHelper::GetCurrentUserID();

		$fields['DIRECTION'] = \CCrmActivityDirection::Incoming;
		$fields['COMPLETED'] = 'Y';
		$fields['START_TIME'] = \CRestUtil::unConvertDateTime($fields['START_TIME']);
		$fields['RESPONSIBLE_ID'] = $curUserId;
		$fields['AUTHOR_ID'] = $curUserId;
		$fields['PROVIDER_ID'] = Provider\ExternalChannel::PROVIDER_ID;
		$fields['PROVIDER_TYPE_ID'] = $this->getTypeActivity();
		$fields['PROVIDER_GROUP_ID'] = $connector->getTypeId();
		$fields['OWNER_ID'] = $this->getOwnerEntityId();
		$fields['OWNER_TYPE_ID'] = $ownerEntity->getOwnerTypeID();
		$fields['PROVIDER_PARAMS'] = $this->prepareFieldsProviderParams();
		$fields['ORIGINATOR_ID'] = $connector->getOriginatorId();

		if($this->getTypeActivity() == CCrmExternalChannelActivityType::ActivityFaceCardName)
		{
			$activityType = CCrmExternalChannelActivityType::getAllDescriptions();

			$fields['SUBJECT'] = $activityType[CCrmExternalChannelActivityType::ActivityFaceCard];
			$fields['FILES'][] = $this->internalizeFileFaceSnapshot();
		}

		$this->fields = $fields;
	}

	protected function innerAdd($activity, &$resultList)
	{
		$error = array();
		$resultList = array(
			'id'=> -1,
			'process' => array(
				'add' => false,
				'error' => array()
			)
		);

		if(($fields = $activity[self::FIELDS]) && count($fields)>0)
		{
			$errors = array();
			$this->checkFields($fields, $errors);
			if(count($errors)>0)
				$error[] = implode('; ', $errors);

			if(count($error)<=0)
			{
				$errors = array();

				$this->getEntity()->internalizeFields($fields, $this->getEntity()->getFieldsInfo());

				$this->fillFields($fields, $activity);

				$id = $this->getEntity()->innerAdd($fields, $errors);
				if($this->isValidID($id))
				{
					$resultList['id'] = $id;
					$resultList['process']['add'] = true;
				}

				if(count($errors)>0)
					$error[] = implode('; ', $errors);
			}
		}
		else
			$error[] = "Activity fields is not defined.";

		if(count($error)>0)
			$resultList['process']['error'] = $error;
	}

	/**
	 * @param $entityFields
	 * @param array $errors
	 * @return bool
	 * @internal
	 */
	public function onAfterEntityModify($entityFields, &$errors=array())
	{
		$ownerEntity = $this->getOwnerEntity();

		if($ownerEntity->getOwnerTypeID() <> \CCrmOwnerType::Contact)
		{
			return false;
		}

		if(is_array($entityFields['FILES'][0]) && intval($entityFields['FILES'][0]['FILE_ID'])>0)
		{
			$file = File::getById($entityFields['FILES'][0]['FILE_ID']);
			$fileId = $file->getFileId();

			$dbRes = \CCrmContact::GetListEx(
				array(),
				array('=ID' => $this->getOwnerEntityId()),
				false,
				false,
				array(),
				array()
			);

			$result = $dbRes ? $dbRes->Fetch() : null;
			if(is_array($result))
			{
				if(empty($result['PHOTO']))
				{
					$fields = array();
					$agent = new CCrmExternalChannelImportAgent();
					$agent->internalizeFileFieldPhoto($fields, $fileId);

					$errors = array();
					if(count($fields)>0)
					{
						$ownerEntity->innerUpdate($this->getOwnerEntityId(), $fields, $errors);
					}
				}
			}
		}

		return true;
	}

	public function import($activity, &$resultList, &$fields)
	{
		$result = new Result();

		$resultList = array(
			'id'=> -1,
			'process' => array(
				'add' => false,
				'upd' => false,
				'error' => array()
			)
		);

		/** @var CCrmExternalChannelImport $import */
		$import = $this->import;

		/** @var CCrmExternalChannelConnector $connector */
		$connector = $import->getConnector();

		if(($fields = $activity[CCrmExternalChannelImport::FIELDS]) && count($fields)>0)
		{
			$r = $this->checkFields($fields);

			if($r->getErrors())
				$result->addErrors($r->getErrors());
			else
			{
				$res = $this->getEntity()->innerGetList(
					array(),
					array(
						'ORIGIN_ID'=>$fields['ORIGIN_ID'],
						'ORIGINATOR_ID' => $connector->getOriginatorId()
					),
					array('*'),
					false,
					$errors
				);
				if(!$res)
				{
					if(count($errors)>0)
						$result->addError(new Error(implode('; ', $errors), 7008));
				}
				else
				{
					$errors = array();

					$this->getEntity()->internalizeFields($fields, $this->getEntity()->getFieldsInfo());

					$this->fillFields($fields, $activity);

					if($r = $res->Fetch())
					{
						$resultUpdate = $this->getEntity()->innerUpdate($r['ID'], $fields, $errors);
						if($resultUpdate !== false)
						{
							$resultList['id'] = (int)$r['ID'];
							$resultList['process']['upd'] = true;
						}

						if(count($errors)>0)
							$result->addError(new Error(implode('; ', $errors), 7009));
					}
					else
					{
						$id = $this->getEntity()->innerAdd($fields, $errors);
						if($this->isValidID($id))
						{
							$this->registerActivityInChannel($id, $connector);

							$resultList['id'] = $id;
							$resultList['process']['add'] = true;
						}

						if(count($errors)>0)
							$result->addError(new Error(implode('; ', $errors), 7010));
					}
				}
			}
		}
		else
			$result->addError(new Error("Activity fields is not defined.", 7011)) ;

		return $result;
	}

	/**
	 * @param $id
	 * @param CCrmExternalChannelConnector $connector
	 */
	public function registerActivityInChannel($id, CCrmExternalChannelConnector $connector)
	{
		$instanceExternalTracker = '';
		switch($connector->getTypeId())
		{
			case CCrmExternalChannelType::CustomName:
				$instanceExternalTracker = ExternalTracker::getInstance(ChannelType::EXTERNAL_CUSTOM);
				break;
			case CCrmExternalChannelType::BitrixName:
				$instanceExternalTracker = ExternalTracker::getInstance(ChannelType::EXTERNAL_BITRIX);
				break;
			case CCrmExternalChannelType::OneCName:
				$instanceExternalTracker = ExternalTracker::getInstance(ChannelType::EXTERNAL_ONE_C);
				break;
			case CCrmExternalChannelType::WordpressName:
				$instanceExternalTracker = ExternalTracker::getInstance(ChannelType::EXTERNAL_WORDPRESS);
				break;
			case CCrmExternalChannelType::DrupalName:
				$instanceExternalTracker = ExternalTracker::getInstance(ChannelType::EXTERNAL_DRUPAL);
				break;
			case CCrmExternalChannelType::JoomlaName:
				$instanceExternalTracker = ExternalTracker::getInstance(ChannelType::EXTERNAL_JOOMLA);
				break;
			case CCrmExternalChannelType::MagentoName:
				$instanceExternalTracker = ExternalTracker::getInstance(ChannelType::EXTERNAL_MAGENTO);
				break;
		}

		if($instanceExternalTracker instanceof Crm\Integration\Channel\ExternalTracker)
		{
			$typeId = $this->getTypeActivity();
			$originatorId = $connector->getOriginatorId();
			$instanceExternalTracker->registerActivity($id, array('ORIGIN_ID' => $originatorId, 'COMPONENT_ID' => $typeId));
		}
	}
}

class CCrmExternalChannelImportAgent extends \CCrmExternalChannelRestProxy
{
	const UPDATE_MODE_NONE = 0;
	const UPDATE_MODE_MERGE = 1;
	const CUSTOM_FIELDS = 'CUSTOM';

	public $import = null;
	protected $entityId = -1;
	protected $updateEntityMode = self::UPDATE_MODE_NONE;
	private static $ENTITY = null;

	/**
	 * @return int
	 */
	public function getUpdateEntityMode()
	{
		return $this->updateEntityMode;
	}

	/**
	 * @param $mode
	 * @throws ArgumentException
	 */
	public function setUpdateEntityMode($mode)
	{
		if (!in_array($mode, array(self::UPDATE_MODE_NONE, self::UPDATE_MODE_MERGE)))
		{
			throw new ArgumentException("Mode {$mode} not implemented.");
		}

		$this->updateEntityMode = $mode;
	}

	protected static function getEntity()
	{
		return self::$ENTITY;
	}

	public static function setEntity($class)
	{
		self::$ENTITY = $class;
	}

	private function getCustomFieldsFieldName()
	{
		return self::CUSTOM_FIELDS;
	}

	protected function sanitizeFields(&$fields)
	{
		/** @var \CCrmCompanyRestProxy|\CCrmContactRestProxy $entity */
		$entity = $this->getEntity();

		$originFields = $fields;
		$fieldsInfo = $entity->getFieldsInfo();
		if(is_array($fieldsInfo) && count($fieldsInfo)>0)
		{
			$sanitize = array();
			foreach($fieldsInfo as $fieldName => $fieldEntity)
			{
				$sanitize[$fieldName] = is_set($fields, $fieldName) ? $fields[$fieldName]:'';
			}

			$custom =  array_diff_assoc($originFields, $sanitize);
			if(!empty($custom))
			{
				$sanitize[$this->getCustomFieldsFieldName()] = $custom;
			}

			$fields[$this->getCustomFieldsFieldName()] = $sanitize[$this->getCustomFieldsFieldName()];
		}
	}

	protected static function getNameUserFieldExternalUrl()
	{
		return 'UF_CRM_EXTERNAL_URL';
	}

	/**
	 * @param $agent
	 * @return Result
	 */
	protected function convertExternalFieldsToFields(&$agent)
	{
		$result = new Result();

		/** @var \CCrmCompanyRestProxy|\CCrmContactRestProxy $entity */
		$entity = $this->getEntity();

		/** @var CCrmExternalChannelImport $import */
		$import = $this->import;

		/** @var CCrmExternalChannelConnector $connector */
		$connector = $import->getConnector();

		$company = new \CCrmCompanyRestProxy();

		if(is_set($agent, CCrmExternalChannelImport::EXTERNAL_FIELDS))
		{
			$externalFields = $agent[CCrmExternalChannelImport::EXTERNAL_FIELDS];

			if($entity->getOwnerTypeID() ===  \CCrmOwnerType::Contact && is_set($externalFields, 'COMPANY_ORIGIN_ID'))
			{
				if($this->isValidOriginId($externalFields['COMPANY_ORIGIN_ID']))
				{
					$res = $company->innerGetList(
						array(),
						array(
							'ORIGIN_ID' => $externalFields['COMPANY_ORIGIN_ID'],
							'ORIGINATOR_ID' => $connector->getOriginatorId()
						),
						array('ID'),
						false,
						$error
					);

					if(!$res)
					{
						$result->addError(new Error(implode("\n", $error), 34004));
					}
					else
					{
						if ($r = $res->Fetch())
							$agent[CCrmExternalChannelImport::FIELDS]['COMPANY_ID'] = $r['ID'];
						else
							$result->addError(new Error("Company not found. Field COMPANY_ORIGIN_ID - '".$externalFields['COMPANY_ORIGIN_ID']."' is invalid", 34005));
					}
				}
				else
					$result->addError(new Error("Field COMPANY_ORIGIN_ID is empty", 34006));
			}
			if(is_set($externalFields, 'EXTERNAL_URL') && $externalFields['EXTERNAL_URL'] <> '')
			{
				$r = $this->prepareUserField(self::getNameUserFieldExternalUrl());
				$resUF = $r->getData();
				$userFieldsFieldName = $resUF['RESULT'];
				if($r->getErrors())
					$result->addErrors($r->getErrors());
				else
				{
					$agent[CCrmExternalChannelImport::FIELDS][$userFieldsFieldName] = $externalFields['EXTERNAL_URL'];
				}
			}
		}

		return $result;
	}

	/**
	 * @param $ufName
	 * @return Result
	 */
	protected function prepareUserField($ufName)
	{
		$result = new Result();

		/** @var \CCrmCompanyRestProxy|\CCrmContactRestProxy $entity */
		$entity = $this->getEntity();

		$ownerTypeID = $entity->getOwnerTypeID();
		$ufProxy = new \CCrmUserFieldRestProxy($ownerTypeID);
		$res = $ufProxy->getList(array(), array('FIELD_NAME'=>$ufName));
		if($res['total']>0)
		{
			$ufFields = $res[0];
			$id = $ufFields['ID'];
		}
		else
		{
			$ufFields['USER_TYPE_ID'] = 'url';
			$ufFields['FIELD_NAME'] = $ufName;

			$langDbResult = \CLanguage::GetList($by = '', $order = '');
			while($lang = $langDbResult->Fetch())
			{
				$lid = $lang['LID'];
				$ufFields['EDIT_FORM_LABEL'][$lid] = $ufFields['LIST_COLUMN_LABEL'][$lid] = $ufFields['LIST_FILTER_LABEL'][$lid] = Loc::getMessage('CRM_REST_EXTERNAL_CHANNEL_IMPORT_UF_EXTERNAL_URL');
			}

			$id = $ufProxy->add($ufFields);
		}

		$fieldName = '';
		if($this->isValidID((int)$id))
		{
			$fieldName = $ufFields['FIELD_NAME'];
		}
		else
		{
			$result->addError(new Error($ufName.' not created ', 34007));
		}

		$result->setData(array('RESULT'=>$fieldName)) ;

		return $result;
	}

	protected function prepareMultiFields($entityId, &$fields, $option = array())
	{
		$fmDeleteListFieldId = array();

		$fmResult = $this->innerGetListFieldsMulti($entityId);

		while($fm = $fmResult->Fetch())
		{
			$fmTypeID = $fm['TYPE_ID'];

			$fmDeleteListFieldId[$fmTypeID][] = $fm['ID'];

			if(is_set($fields, $fmTypeID))
			{
				foreach($fields[$fmTypeID] as &$fieldsType)
				{
					$valueType = isset($fieldsType['VALUE_TYPE']) ? trim($fieldsType['VALUE_TYPE']) : '';
					if($valueType === '')
						$fieldsType['VALUE_TYPE'] = \CCrmFieldMulti::GetDefaultValueType($fmTypeID);

					if($fieldsType['VALUE_TYPE'] ==  $fm['VALUE_TYPE']
						&& $fieldsType['VALUE'] == $fm['VALUE']
						&& !is_set($fieldsType, 'ID')
					)
					{
						$fieldsType['ID'] = $fm['ID'];

						$key = array_search($fm['ID'], $fmDeleteListFieldId[$fmTypeID]);
						if($key!==false && $key!==null)
						{
							unset($fmDeleteListFieldId[$fmTypeID][$key]);
						}
					}
				}
				unset($fieldsType);
			}
		}

		if($this->getUpdateEntityMode() == self::UPDATE_MODE_NONE)
		{
			if(count($fmDeleteListFieldId)>0)
			{
				foreach($fmDeleteListFieldId as $typeId => $listId)
				{
					if(count($listId) > 0)
					{
						foreach($listId as $id)
							$fields[$typeId][] = array('ID'=>$id, 'DELETE'=>'Y');
					}
				}
			}
		}
	}

	protected function innerGetListFieldsMulti($entityId)
	{
		/** @var \CCrmCompanyRestProxy|\CCrmContactRestProxy $entity */

		$entity = $this->getEntity();

		return \CCrmFieldMulti::GetList(
			array('ID' => 'asc'),
			array(
				'ENTITY_ID' => \CCrmOwnerType::ResolveName($entity->getOwnerTypeID()),
				'ELEMENT_ID' => $entityId
			)
		);
	}

	protected function isValidOriginId($OriginId)
	{
		return $OriginId !== '';
	}

	/**
	 * @param $fields
	 * @return \Bitrix\Main\Result
	 */
	public function checkFields(&$fields)
	{
		$result = new \Bitrix\Main\Result();

		if(!is_set($fields,'ORIGIN_ID') || $fields['ORIGIN_ID']=='')
		{
			$result->addError(new Error("ORIGIN_ID is not defined", 34001));
		}

		if(!is_set($fields,'ORIGIN_VERSION') || $fields['ORIGIN_VERSION']=='')
		{
			$result->addError(new Error("VERSION is not defined", 34002));
		}

		return $result;
	}

	public function checkExternalFields(&$fields, &$errors) {}

	/**
	 * @param $fields
	 * @param array $entityFields
	 */
	protected function fillFields(&$fields, $entityFields=array())
	{
		/** @var \CCrmCompanyRestProxy|\CCrmContactRestProxy $entity */
		$entity = $this->getEntity();

		/** @var CCrmExternalChannelImport $import */
		$import = $this->import;

		/** @var CCrmExternalChannelConnector $connector */
		$connector = $import->getConnector();

		$fields['ORIGINATOR_ID'] = $connector->getOriginatorId();

		if($entity->getOwnerTypeID() == \CCrmOwnerType::Contact)
		{
			if($this->getUpdateEntityMode() == self::UPDATE_MODE_MERGE)
			{
				$entityObject = new \CCrmContact(false);

				if(intval($entityFields['ID'])>0)
				{
					$merger = new Crm\Merger\ContactMerger(0, false);

					$entityFieldsDb = $entityObject->getListEx(
						array(),
						array(
							'=ID' => $entityFields['ID'],
							'CHECK_PERMISSIONS' => 'N'
						),
						false,
						false,
						array('*', 'UF_*')
					);
					$originFields = $entityFieldsDb->fetch();
					if ($originFields)
					{
						$merger->mergeFields($originFields, $fields);
					}
				}

				unset($fields['ORIGINATOR_ID']);
				unset($fields['ORIGIN_ID']);
				unset($fields['ORIGIN_VERSION']);
			}
		}
	}

	/**
	 * @param $fields
	 * @return int|0
	 * @internal
	 */
	protected function getFileIdByFaceId($fields)
	{
		$id = 0;

		if(!\Bitrix\Main\Loader::includeModule("faceid"))
			return $id;

		if(isset($fields[CCrmExternalChannelImport::AGENT][CCrmExternalChannelImport::FIELDS]) &&
			isset($fields[CCrmExternalChannelImport::AGENT][CCrmExternalChannelImport::FIELDS]['FACE_ID']))
		{
			$faceId = $fields[CCrmExternalChannelImport::AGENT][CCrmExternalChannelImport::FIELDS]['FACE_ID'];

			if(intval($faceId)>0)
			{
				$r = FaceTable::getList(array('filter' => array('ID' => $faceId)));
				if($fieldsFace = $r->fetch())
				{
					$id = $fieldsFace['FILE_ID'];
				}
			}
		}

		return $id;
	}

	/**
	 * @param $photoId
	 * @internal
	 */
	public function internalizeFileFieldPhoto(&$fieldsAgent, $photoId)
	{
		if(intval($photoId) > 0)
		{
			$fieldsAgent['PHOTO'] = \CFile::MakeFileArray($photoId);
		}
	}

	/**
	 * @param $fieldsAgent
	 * @return \Bitrix\Main\Result
	 * @internal
	 */
	public function tryGetOwnerInfos($fieldsAgent)
	{
		$result = new \Bitrix\Main\Result();

		/** @var \CCrmCompanyRestProxy|\CCrmContactRestProxy $entity */
		$entity = $this->getEntity();

		/** @var CCrmExternalChannelImport $import */
		$import = $this->import;

		/** @var CCrmExternalChannelConnector $connector */
		$connector = $import->getConnector();

		$res = array(
			'ID' => 0,
			'ORIGIN_VERSION' => ''
		);

		$entityList = $entity->innerGetList(
			array(),
			array(
				'ORIGIN_ID' => $fieldsAgent['ORIGIN_ID'],
				'ORIGINATOR_ID' => $connector->getOriginatorId()
			),
			array('*'),
			false,
			$errors
		);
		if(!$entityList)
		{
			if(count($errors)>0)
			{
				$result->addError(new Error(implode('; ', $errors), 34003));
			}

		}
		elseif($entityEntity = $entityList->Fetch())
		{
			$res = $entityEntity;
		}
		else
		{
			if($entity->getOwnerTypeID()== \CCrmOwnerType::Contact)
			{
				$personFields = $this->prepareFieldsPerson($fieldsAgent);

				$personId = $this->getActualPersonId($personFields);

				if(intval($personId)>0)
				{
					$this->setUpdateEntityMode(self::UPDATE_MODE_MERGE);

					$res['ID'] = $personId;
				}
			}
		}

		$result->setData(array('RESULT'=>$res));

		return $result;
	}


	/**
	 * @return int|null
	 */
	protected function getActualPersonId($fields)
	{
		$duplicateCriteria = \Bitrix\Crm\Integrity\ActualEntitySelector::createDuplicateCriteria($fields, array(
			Crm\Integrity\ActualEntitySelector::SEARCH_PARAM_PERSON));

		$list = array();
		foreach ($duplicateCriteria as $criterion)
		{
			/** @var Crm\Integrity\Duplicate $duplicate */
			$duplicate = $criterion->find();
			if($duplicate !== null)
			{
				$list = array_merge(
					$list,
					$duplicate->getEntityIDsByType(\CCrmOwnerType::Contact)
				);
			}
		}

		$list = array_unique($list);
		$ranking = new \Bitrix\Crm\Integrity\ActualRanking;
		$ranking->rank(\CCrmOwnerType::Contact, $list);

		return $ranking->getEntityId();
	}

	/**
	 * @param $fieldsAgent
	 * @return array
	 * @internal
	 */
	protected function prepareFieldsPerson($fieldsAgent)
	{
		$result = array();

		$fieldsInfo = array(
			'NAME',
			'LAST_NAME',
			'SECOND_NAME',
			'PHONE',
			'EMAIL'
		);

		foreach ($fieldsInfo as $value)
		{
			if(isset($fieldsAgent[$value]))
			{
				if($value == 'PHONE' || $value == 'EMAIL')
				{
					$result['FM'][$value] = $fieldsAgent[$value];
				}
				else
				{
					$result[$value] = $fieldsAgent[$value];
				}
			}
		}

		return $result;
	}

	/**
	 * @param array $entityField
	 * @param $agent
	 * @param $resultList
	 * @internal
	 */
	public function modify($entityFields, $agent, &$resultList)
	{
		$result = new \Bitrix\Main\Result();

		$entityId = $entityFields['ID'];
		/** @var \CCrmCompanyRestProxy|\CCrmContactRestProxy $entity */
		$entity = $this->getEntity();
		/** @var CCrmExternalChannelImport $import */
		$import = $this->import;

		$bContact = $entity->getOwnerTypeID()== \CCrmOwnerType::Contact ? true:false;

		$resultList = array(
			'id'=> -1,
			'process' => array(
				'add' => false,
				'upd' => false,
				'error' => array()
			)
		);

		$r = $this->convertExternalFieldsToFields($agent);

		$this->sanitizeFields($agent[CCrmExternalChannelImport::FIELDS]);

		if($r->getErrors())
			$result->addErrors($r->getErrors());
		else
		{
			$requisite = new CCrmExternalChannelImportRequisite();
			$requisite->setOwnerEntity($entity);
			$requisite->import = $this->import;

			$fieldsAgent = $agent[CCrmExternalChannelImport::FIELDS];

			$this->fillFields($fieldsAgent, $entityFields);

			$photoId = 0;
			if($bContact)
			{
				$photoId = $this->getFileIdByFaceId($import->getRawData());
			}

			$id = 0;
			if(intval($entityId)>0)
			{
				$this->prepareMultiFields($entityId, $fieldsAgent, $entityFields);

				$entity->internalizeFields($fieldsAgent, $entity->getFieldsInfo());

				if($bContact && empty($entityFields['PHOTO']))
				{
					$this->internalizeFileFieldPhoto($fieldsAgent, $photoId);
				}

				$res = $entity->innerUpdate($entityId, $fieldsAgent, $errors);
				if($res !== false)
				{
					$id = (int)$entityId;
					$resultList['process']['upd'] = true;
				}

				if(count($errors)>0)
					$result->addError(new Error(implode('; ', $errors), 34008));
			}
			else
			{
				$entity->internalizeFields($fieldsAgent, $entity->getFieldsInfo());

				if($bContact)
				{
					$this->internalizeFileFieldPhoto($fieldsAgent, $photoId);
				}

				$resultId = $entity->innerAdd($fieldsAgent, $errors);
				if($entity->isValidID($resultId))
				{
					$id = (int)$resultId;
					$resultList['process']['add'] = true;
				}

				if(count($errors)>0)
					$result->addError(new Error(implode('; ', $errors), 34009));
			}

			if($id>0)
			{
				$resultList['id'] = $id;
				$requisite->setOwnerEntityId($id);
				$r = $requisite->import($agent);
				if($r->getErrors())
				{
					$result->addError(new Error('Import error', 34010));
					$result->setData(array('requisites'=>$r->getData()));

				}
			}
		}

		return $result;
	}
}

class CCrmExternalChannelImportRequisite extends CCrmExternalChannelImportAgent
{
	private static $ENTITY = null;

	protected $ownerId = -1;
	protected $class = null;

	public function setOwnerEntity($class)
	{
		$this->class = $class;
	}

	protected function getOwnerEntity()
	{
		return $this->class;
	}

	public function setOwnerEntityId($id)
	{
		$this->ownerId = (int)$id;
	}

	protected function getOwnerEntityId()
	{
		return $this->ownerId;
	}

	public function getOwnerTypeID()
	{
		return \CCrmOwnerType::Requisite;
	}

	protected static function getEntity()
	{
		if(!self::$ENTITY)
		{
			self::$ENTITY = new \Bitrix\Crm\EntityRequisite();
		}

		return self::$ENTITY;
	}

	protected function innerList($filter=array())
	{
		/** @var \CCrmCompanyRestProxy|\CCrmContactRestProxy $ownerEntity */
		$ownerEntity = $this->getOwnerEntity();

		/** @var CCrmExternalChannelImport $import */
		$import = $this->import;

		/** @var CCrmExternalChannelConnector $connector */
		$connector = $import->getConnector();


		return $this->getEntity()->getList(
			array(
				'order' => array('ID'),
				'filter' => array_merge(
					$filter,
					array(
						'ENTITY_TYPE_ID' => $ownerEntity->getOwnerTypeID(),
						'ORIGINATOR_ID' => $connector->getOriginatorId()
					)
				),
				'select' => array('*')
			)
		);
	}

	/**
	 * @param $id
	 * @param $fields
	 * @return Result
	 */
	protected function innerUpdate($id, $fields)
	{
		$result = new Result();
		$entity = $this->getEntity();

		if(!$this->isValidID((int)$id))
		{
			$result->addError(new Error("ID is not defined or invalid", 8007));
		}

		if($result->isSuccess())
		{
			$r = $entity->update($id, $fields);
			if(!$r->isSuccess())
			{
				$error = '';
				foreach($r->getErrorMessages() as $message)
					$error .= $message."\n";

				$result->addError(new Error($error, 8004));
			}
		}

		return $result;
	}

	/**
	 * @param $fields
	 * @return Result
	 */
	protected function innerAdd($fields)
	{
		$result = new Result();
		$entity = $this->getEntity();

		$r = $entity->add($fields);
		if($r->isSuccess())
		{
			$result->setData(array('RESULT'=>$r->getId()));
		}
		else
		{
			$error = "";
			foreach($r->getErrorMessages() as $message)
				$error .= $message."\n";

			$result->addError(new Error($error, 8005));
		}

		return $result;
	}

	/**
	 * @param $id
	 * @return Result
	 */
	protected function innerDelete($id)
	{
		$result = new Result();
		$entity = $this->getEntity();

		$r = $entity->delete($id);
		if(!$r->isSuccess())
		{
			$error = "";
			foreach($r->getErrorMessages() as $message)
				$error .= $id.":".$message."\n";

			$result->addError(new Error($error, 8006));
		}

		return $result;
	}

	protected function getFieldsInfo()
	{
		$result = array();

		$fieldsInfo = array_flip(
			array_merge(
				array('NAME', 'XML_ID'),
				\Bitrix\Crm\EntityRequisite::getRqFields()
			)
		);

		foreach($fieldsInfo as $name=>$key)
		{
			$result[$name] = array('TYPE' => '', 'ATTRIBUTES'=>'');
		}

		return $result;
	}

	protected function fillFields(&$requisite, $entityFields=array())
	{
		/** @var \CCrmCompanyRestProxy|\CCrmContactRestProxy $ownerEntity */
		$ownerEntity = $this->getOwnerEntity();

		/** @var CCrmExternalChannelImport $import */
		$import = $this->import;

		/** @var CCrmExternalChannelConnector $connector */
		$connector = $import->getConnector();

		$curDateTime = new \Bitrix\Main\Type\DateTime();
		$curUserId = \CCrmSecurityHelper::GetCurrentUserID();

		$requisite['DATE_CREATE'] = $curDateTime;
		$requisite['DATE_MODIFY'] = $curDateTime;
		$requisite['CREATED_BY_ID'] = $curUserId;
		$requisite['MODIFY_BY_ID'] = $curUserId;
		$requisite['NAME'] = !is_set($requisite, 'NAME') || $requisite['NAME']=='' ? Loc::getMessage('CRM_REST_EXTERNAL_CHANNEL_IMPORT_REQUISITE_NAME'):$requisite['NAME'];
		$requisite['PRESET_ID'] = Crm\EntityRequisite::getDefaultPresetId($ownerEntity->getOwnerTypeID());
		$requisite['ENTITY_TYPE_ID'] = $ownerEntity->getOwnerTypeID();
		$requisite['ENTITY_ID'] = $this->getOwnerEntityId();
		$requisite['ACTIVE'] = 'Y';
		$requisite['ORIGINATOR_ID'] = $connector->getOriginatorId();

	}

	/**
	 * @param $requisite
	 * @return Result
	 */
	protected function sanitizeFields(&$requisite)
	{
		$result = new Result();

		$addres = new CCrmExternalChannelImportAddress();

		if(is_array($requisite) && count($requisite)>0)
		{
			$fieldsInfo = $addres->getFieldsInfo();

			if(is_set($requisite, CCrmExternalChannelImport::FIELDS_ADDRESS))
			{
				foreach($requisite[CCrmExternalChannelImport::FIELDS_ADDRESS] as $addresTypeId=>$addresFields)
				{
					unset($requisite[CCrmExternalChannelImport::FIELDS_ADDRESS][$addresTypeId]);

					if(!is_numeric($addresTypeId))
						$addresTypeId = \Bitrix\Crm\EntityAddressType::resolveID($addresTypeId);

					if(is_set($fieldsInfo, $addresTypeId))
						$requisite[CCrmExternalChannelImport::FIELDS_ADDRESS][$addresTypeId] = $addresFields;
				}
			}
		}

		return $result;
	}

	protected function prepareFieldsAddress(&$requisite)
	{
		$addres = new CCrmExternalChannelImportAddress();

		if($this->getUpdateEntityMode() == self::UPDATE_MODE_NONE)
		{
			foreach($addres->getFieldsInfo() as $typeId=>$typeInfo)
			{
				if(!is_set($requisite, CCrmExternalChannelImport::FIELDS_ADDRESS) ||
					!is_set($requisite[CCrmExternalChannelImport::FIELDS_ADDRESS], $typeId)
				)
					$requisite[CCrmExternalChannelImport::FIELDS_ADDRESS][$typeId]['DELETED'] = 'Y';
			}
		}
	}

	/**
	 * @param $fields
	 * @return Result
	 */
	public function checkFields(&$fields)
	{
		$result = new Result();

		$bank = new CCrmExternalChannelImportBank();

		if(is_set($fields, CCrmExternalChannelImport::FIELDS_REQUISITE) && count($fields[CCrmExternalChannelImport::FIELDS_REQUISITE])>0)
		{
			foreach($fields[CCrmExternalChannelImport::FIELDS_REQUISITE] as $requisiteKey=>$requisite)
			{
				if(is_array($requisite) && count($requisite)>0)
				{
					if(!is_set($requisite, 'XML_ID') || $requisite['XML_ID'] == '')
					{
						$result->addError(new Error(" requisite.$requisiteKey. xml_id is not defined", 8002));
					}

					if(is_set($requisite, CCrmExternalChannelImport::FIELDS_BANK))
					{
						$r = $bank->checkFields($requisite);
						if($r->getErrors())
							$result->addErrors($r->getErrors());
					}
				}
				else
				{
					$result->addError(new Error(" field requisite is invalid", 8003));
					unset($fields[CCrmExternalChannelImport::FIELDS_REQUISITE][$requisiteKey]);
					break;
				}
			}
		}
		return $result;
	}

	/**
	 * @param $fields
	 * @return Result
	 */
	public function import(&$fields)
	{
		$result = new Result();
		$import = new Result();
		$batch = array();

		if(!$this->isValidID($this->getOwnerEntityId()))
		{
			$import->addError(new Error("EntityId is not defined or invalid", 8001));
		}
		else
		{
			$proccessList = array();

			$r = $this->checkFields($fields);

			if($r->getErrors())
			{
				$import->addErrors($r->getErrors());
			}
			else
			{
				if(is_set($fields, CCrmExternalChannelImport::FIELDS_REQUISITE) && count($fields[CCrmExternalChannelImport::FIELDS_REQUISITE])>0)
				{
					$bank = new CCrmExternalChannelImportBank();
					$bank->setOwnerEntity($this);
					$bank->import = $this->import;

					foreach($fields[CCrmExternalChannelImport::FIELDS_REQUISITE] as $row=>$requisite)
					{
						$fields = $requisite;
						$this->sanitizeFields($requisite);
						$this->internalizeFields($requisite, $this->getFieldsInfo());
						$this->fillFields($requisite);

						$res = $this->innerList(array(
							'=ENTITY_ID' => $this->getOwnerEntityId(),
							'=XML_ID' => $requisite['XML_ID'],
						));

						if($r = $res->fetch())
						{
							$this->prepareFieldsAddress($requisite);
							$id = $r['ID'];
							$r = $this->innerUpdate($id, $requisite);
						}
						else
						{
							$r = $this->innerAdd($requisite);
							$data = $r->getData();
							$id = $data['RESULT'];
						}

						if($r->getErrors())
						{
							$batch[$row]['errors'] = $r->getErrors();
						}
						elseif($this->isValidID((int)$id))
						{
							$proccessList[] = $id;

							$bank->setOwnerEntityId($id);
							$r = $bank->import($fields);
							if($r->getErrors())
							{
								$batch[$row]['banks'] = $r->getData();
							}
						}
					}

					if(count($batch)<=0)
					{
						$r = $this->deleteEntities($proccessList);
						if($r->getErrors())
							$import->addErrors($r->getErrors());
					}
				}
				else
				{
					$r = $this->deleteEntities(array());
					if($r->getErrors())
						$import->addErrors($r->getErrors());
				}
			}
		}

		if($import->getErrors() || count($batch)>0)
		{
			$result->addError(new Error('','IMPORT_ERROR'));
			$result->setData(array(
				'IMPORT_ERROR'=>$import->getErrors(),
				'BATCH_ERROR'=>$batch
			));
		}

		return $result;
	}

	/**
	 * @param array $proccessList
	 * @return Result
	 */
	protected function deleteEntities($proccessList=array())
	{
		$result = new Result();

		if($this->getUpdateEntityMode() == self::UPDATE_MODE_NONE)
		{
			$resultList = $this->innerList(array('=ENTITY_ID' => $this->getOwnerEntityId()));
			while($list = $resultList->fetch())
			{
				if(!in_array($list['ID'], $proccessList))
				{
					$r = $this->innerDelete($list['ID']);
					if($r->getErrors())
						$result->addErrors($r->getErrors());
				}
			}
		}
		return $result;
	}
}

class CCrmExternalChannelImportBank extends CCrmExternalChannelImportRequisite
{
	private static $ENTITY = null;

	protected static function getEntity()
	{
		if(!self::$ENTITY)
		{
			self::$ENTITY = new \Bitrix\Crm\EntityBankDetail();
		}

		return self::$ENTITY;
	}

	protected function getFieldsInfo()
	{
		$result = array();

		$fieldsInfo = array_flip(
			array_merge(
				array('NAME', 'XML_ID'),
				\Bitrix\Crm\EntityBankDetail::getRqFields(),
				array('COMMENTS')
			)
		);

		foreach($fieldsInfo as $name=>$key)
		{
			$result[$name] = array('TYPE' => '', 'ATTRIBUTES'=>'');
		}

		return $result;
	}

	/**
	 * @param $fields
	 * @return Result
	 */
	public function checkFields(&$fields)
	{
		$result = new Result();

		if(is_set($fields, CCrmExternalChannelImport::FIELDS_BANK) && count($fields[CCrmExternalChannelImport::FIELDS_BANK])>0)
		{
			foreach($fields[CCrmExternalChannelImport::FIELDS_BANK] as $bankKey=>$bank)
			{
				if(is_array($bank) && count($bank)>0)
				{
					if(!is_set($bank, 'XML_ID') || $bank['XML_ID']=='')
					{
						$result->addError(new Error(" bank:$bankKey xml_id is not defined", 9001));
					}
				}
				else
				{
					$result->addError(new Error(" bank: is invalid", 9002));
					unset($fields[CCrmExternalChannelImport::FIELDS_BANK][$bankKey]);
					break;
				}
			}
		}
		return $result;
	}

	protected function fillFields(&$requisite, $entityFields=array())
	{
		/** @var \CCrmCompanyRestProxy|\CCrmContactRestProxy $ownerEntity */
		$ownerEntity = $this->getOwnerEntity();

		/** @var CCrmExternalChannelImport $import */
		$import = $this->import;

		/** @var CCrmExternalChannelConnector $connector */
		$connector = $import->getConnector();

		if(isset($requisite['COMMENTS']))
		{
			$requisite['COMMENTS'] = $this->sanitizeHtml($requisite['COMMENTS']);
		}

		$curUserId = \CCrmSecurityHelper::GetCurrentUserID();

		$requisite['ENTITY_ID'] = $this->getOwnerEntityId();
		$requisite['ENTITY_TYPE_ID'] = $ownerEntity->getOwnerTypeID();
		$requisite['NAME'] = !is_set($requisite, 'NAME') || $requisite['NAME']=='' ? Loc::getMessage('CRM_REST_EXTERNAL_CHANNEL_IMPORT_BANK_REQUISITE_NAME'):$requisite['NAME'];
		$requisite['CREATED_BY_ID'] = $curUserId;
		$requisite['MODIFY_BY_ID'] = $curUserId;
		$requisite['COUNTRY_ID'] = \Bitrix\Crm\EntityPreset::getCurrentCountryId();
		$requisite['ACTIVE'] = 'Y';
		$requisite['ORIGINATOR_ID'] = $connector->getOriginatorId();
	}

	/**
	 * @param $requisite
	 * @return Result
	 */
	public function import(&$requisite)
	{
		$result = new Result();
		$import = new Result();
		$batch = array();

		$proccessList = array();

		if(is_array($requisite[CCrmExternalChannelImport::FIELDS_BANK]) && !empty($requisite[CCrmExternalChannelImport::FIELDS_BANK]))
		{
			foreach($requisite[CCrmExternalChannelImport::FIELDS_BANK] as $row=>&$bank)
			{
				$this->internalizeFields($bank, $this->getFieldsInfo());
				$this->fillFields($bank);

				$res = $this->innerList(array(
					'=ENTITY_ID' => $this->getOwnerEntityId(),
					'=XML_ID' => $bank['XML_ID'],
				));

				if($r = $res->fetch())
				{
					$id = $r['ID'];
					$r = $this->innerUpdate($id, $bank);
				}
				else
				{
					$r = $this->innerAdd($bank);
					$data = $r->getData();
					$id = $data['RESULT'];
				}

				if($r->getErrors())
				{
					$batch[$row]['errors'] = $r->getErrors();
				}
				elseif($this->isValidID((int)$id))
				{
					$proccessList[] = $id;
				}
			}

			if(count($batch)<=0)
			{
				$r = $this->deleteEntities($proccessList);
				if($r->getErrors())
					$import->addErrors($r->getErrors());
			}
		}
		else
		{
			$r = $this->deleteEntities(array());
			if($r->getErrors())
				$import->addErrors($r->getErrors());
		}

		if($import->getErrors() || count($batch)>0)
		{
			$result->addError(new Error('','IMPORT_ERROR'));
			$result->setData(array(
				'IMPORT_ERROR'=>$import->getErrors(),
				'BATCH_ERROR'=>$batch
			));
		}

		return $result;
	}

	/**
	 * @param $id
	 * @param $fields
	 * @return Result
	 */
	protected function innerUpdate($id, $fields)
	{
		$result = new Result();
		$entity = $this->getEntity();

		if(!$this->isValidID((int)$id))
		{
			$result->addError(new Error("ID is not defined or invalid", 9007));
		}

		if($result->isSuccess())
		{
			$r = $entity->update($id, $fields);
			if(!$r->isSuccess())
			{
				$error = '';
				foreach($r->getErrorMessages() as $message)
					$error .= $message."\n";

				$result->addError(new Error($error, 9004));
			}
		}

		return $result;
	}

	/**
	 * @param $fields
	 * @return Result
	 */
	protected function innerAdd($fields)
	{
		$result = new Result();
		$entity = $this->getEntity();

		$r = $entity->add($fields);
		if($r->isSuccess())
		{
			$result->setData(array('RESULT'=>$r->getId()));
		}
		else
		{
			$error = "";
			foreach($r->getErrorMessages() as $message)
				$error .= $message."\n";

			$result->addError(new Error($error, 9005));
		}

		return $result;
	}

	/**
	 * @param $id
	 * @return Result
	 */
	protected function innerDelete($id)
	{
		$result = new Result();
		$entity = $this->getEntity();

		$r = $entity->delete($id);
		if(!$r->isSuccess())
		{
			$error = "";
			foreach($r->getErrorMessages() as $message)
				$error .= $id.":".$message."\n";

			$result->addError(new Error($error, 9006));
		}

		return $result;
	}
}

class CCrmExternalChannelImportAddress extends CCrmExternalChannelImportRequisite
{
	protected function getFieldsInfo()
	{
		$result = array();

		foreach(\Bitrix\Crm\RequisiteAddress::getClientTypeInfos() as $typeInfo)
		{
			$result[$typeInfo['id']] = $typeInfo;
		}

		return $result;
	}
}