Your IP : 18.118.26.128


Current Path : /var/www/www-root/data/www/www.monolith-realty.ru/bitrix/components/bitrix/main.mail.form/
Upload File :
Current File : /var/www/www-root/data/www/www.monolith-realty.ru/bitrix/components/bitrix/main.mail.form/class.php

<?php

use Bitrix\Main\Engine\Contract\Controllerable;
use Bitrix\Main\Localization\Loc;
use Bitrix\Main\Web\Uri;
use Bitrix\Main\Engine\CurrentUser;
use Bitrix\Main\Loader;
use Bitrix\Calendar;
use Bitrix\Crm;

if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) die();

Loc::loadMessages(__FILE__);

class MainMailFormComponent extends CBitrixComponent implements Controllerable
{
	/**
	 * Cache for compatibility
	 *
	 * @var array
	 */
	private array $signatures;

	/**
	 * @param array $params
	 * @return array
	 */
	public function onPrepareComponentParams($params)
	{
		$params = parent::onPrepareComponentParams($params);

		if(!isset($params['USE_SIGNATURES']) || $params['USE_SIGNATURES'] !== true)
		{
			$params['USE_SIGNATURES'] = false;
		}

		if(!isset($params['USE_CALENDAR_SHARING']) || $params['USE_CALENDAR_SHARING'] !== true)
		{
			$params['USE_CALENDAR_SHARING'] = false;
		}

		$params['VERSION'] = (isset($params['VERSION']) && intval($params['VERSION']) > 0 ? intval($params['VERSION']) : 1);
//		$params['VERSION'] = 1;

		if (
			!empty($params['FIELDS'])
			&& $params['VERSION'] < 2
		)
		{
			foreach($params['FIELDS'] as $fieldKey => $field)
			{
				if (!empty($field['selector']))
				{
					if (
						!empty($field['selector']['items'])
						&& !empty($field['selector']['items']['mailcontacts'])
					)
					{
						if (empty($field['selector']['items']['users']))
						{
							$field['selector']['items']['users'] = [];
							$field['selector']['items']['emails'] = [];
						}
						foreach($field['selector']['items']['mailcontacts'] as $itemKey => $item)
						{
							$newItemKey = preg_replace('/^MC(.*)/', '$1', $itemKey);
							$newItemKey = 'U'.md5($newItemKey);
							$item['id'] = $newItemKey;
							$field['selector']['items']['users'][$newItemKey] = $item;
							$field['selector']['items']['emails'][$newItemKey] = $item;
							unset($field['selector']['items']['emails'][$itemKey]);
						}
						unset($field['selector']['items']['mailcontacts']);
					}
					if (
						!empty($field['selector']['itemsLast'])
						&& !empty($field['selector']['itemsLast']['mailcontacts'])
					)
					{
						if (empty($field['selector']['itemsLast']['users']))
						{
							$field['selector']['itemsLast']['users'] = [];
							$field['selector']['itemsLast']['emails'] = [];
						}
						foreach($field['selector']['itemsLast']['mailcontacts'] as $itemKey => $value)
						{
							$newItemKey = preg_replace('/^MC(.*)/', '$1', $itemKey);
							$newItemKey = 'U'.md5($newItemKey);
							$field['selector']['itemsLast']['users'][$newItemKey] = $newItemKey;
							$field['selector']['itemsLast']['emails'][$newItemKey] = $newItemKey;
							unset($field['selector']['itemsLast']['mailcontacts'][$itemKey]);
							unset($field['selector']['itemsLast']['emails'][$itemKey]);
						}
						unset($field['selector']['itemsLast']['mailcontacts']);
					}
					if (!empty($field['selector']['itemsSelected']))
					{
						foreach($field['selector']['itemsSelected'] as $itemKey => $value)
						{
							if ($value == 'mailcontacts')
							{
								$newItemKey = preg_replace('/^MC(.*)/', '$1', $itemKey);
								$newItemKey = 'U'.md5($newItemKey);
								$field['selector']['itemsSelected'][$newItemKey] = 'users';
								unset($field['selector']['itemsSelected'][$itemKey]);
							}
						}
					}
				}
			}
		}

		$params['USER_CALENDAR_PATH'] = $this->getUserCalendarPath();
		$params['CALENDAR_SHARING_TOUR_ID'] = $this->getSharingCalendarTourId();

		$params['POST_FORM_BUTTONS'] = ['UploadImage', 'UploadFile', 'Copilot'];

		return $params;
	}

	public function executeComponent()
	{
		global $APPLICATION;

		\CModule::includeModule('socialnetwork');
		$extensionsList = [ 'admin_interface' ];
		if ($this->arParams['VERSION'] < 2)
		{
			$extensionsList[] = 'socnetlogdest';
		}
		\CJSCore::init($extensionsList);

		$this->arParams['FIELDS'] = $this->arParams['~FIELDS'];
		$this->arParams['FIELDS_EXT'] = $this->arParams['~FIELDS_EXT'] ?? '';
		$this->arParams['BUTTONS'] = $this->arParams['~BUTTONS'];

		if (empty($this->arParams['FORM_ID']) || !trim($this->arParams['FORM_ID']))
			$this->arParams['FORM_ID'] = sprintf('%s%04x', hash('crc32b', microtime()), rand(0, 0xffff));

		$this->prepareFields();
		$this->prepareEditor();
		$this->prepareButtons();
		$this->prepareCopilotParams($this->arParams['COPILOT_PARAMS'] ?? null);

		$this->includeComponentTemplate();
	}

	protected function prepareFields()
	{
		$this->arParams['EDITOR'] = array('type' => 'editor');
		$this->arParams['FILES']  = array('type' => 'files');

		foreach (array('FIELDS', 'FIELDS_EXT') as $set)
		{
			$fields = &$this->arParams[$set];
			$fields = !empty($fields) && is_array($fields) ? array_values($fields) : array();

			foreach ($fields as $k => $item)
			{
				$type = $item['type'] ?? null;
				if (in_array($type, array('editor', 'files')))
				{
					$this->arParams[mb_strtoupper($type)] = $item;
					unset($fields[$k]);
				}
			}
		}

		$this->arParams['FIELDS'][] = &$this->arParams['EDITOR'];
		$this->arParams['FIELDS'][] = &$this->arParams['FILES'];

		$presets = array(
			'from' => array(
				'type'        => 'from',
				'name'        => 'from',
				'title'       => Loc::getMessage('MAIN_MAIL_FORM_FROM_FIELD'),
				'placeholders' => array(
					'default' => Loc::getMessage('MAIN_MAIL_FORM_FROM_FIELD_HINT'),
					'required' => Loc::getMessage('MAIN_MAIL_FORM_FROM_FIELD_REQUIRED_HINT'),
				),
			),
			'rcpt' => array(
				'type'        => 'rcpt',
				'name'        => 'rcpt',
				'title'       => Loc::getMessage('MAIN_MAIL_FORM_TO_FIELD'),
				'placeholder' => Loc::getMessage('MAIN_MAIL_FORM_TO_FIELD_HINT'),
				'email'       => true,
				'multiple'    => true,
				'selector'    => array(
					'items' => array(
						'users'     => array(),
						'emails'    => array(),
						'companies' => array(),
						'contacts'  => array(),
						'deals'     => array(),
						'leads'     => array(),
					),
					'itemsLast' => array(
						'users'     => array(),
						'emails'    => array(),
						'crm'       => array(),
						'companies' => array(),
						'contacts'  => array(),
						'deals'     => array(),
						'leads'     => array(),
					),
					'itemsSelected' => array(),
					'destSort'      => array(),
				),
			),
		);

		if ($this->arParams['VERSION'] >= 2)
		{
			$presets['entity'] = array(
				'type'        => 'entity',
				'name'        => 'entity',
				'title'       => Loc::getMessage('MAIN_MAIL_FORM_TO_FIELD'),
				'placeholder' => Loc::getMessage('MAIN_MAIL_FORM_TO_FIELD_HINT'),
				'email'       => true,
				'multiple'    => true,
				'selector'    => array(
					'items' => array(
						'users'     => array(),
						'emails'    => array(),
						'companies' => array(),
						'contacts'  => array(),
						'deals'     => array(),
						'leads'     => array(),
					),
					'itemsLast' => array(
						'users'     => array(),
						'emails'    => array(),
						'crm'       => array(),
						'companies' => array(),
						'contacts'  => array(),
						'deals'     => array(),
						'leads'     => array(),
					),
					'itemsSelected' => array(),
					'destSort'      => array(),
				),
			);
		}

		foreach (array('FIELDS', 'FIELDS_EXT') as $set)
		{
			$fields = &$this->arParams[$set];
			$fields = !empty($fields) && is_array($fields) ? array_values($fields) : array();

			foreach ($fields as $k => $item)
			{
				if (!empty($item['type']) && array_key_exists($item['type'], $presets))
				{
					$params = $presets[$item['type']];

					$item = static::deepMerge($params, $item);
					$item['type'] = $params['type'];
				}

				$item['id'] = sprintf('%04x%02x', rand(0, 0xffff), $k+1);
				$this->prepareField($this->arParams['FORM_ID'], $item);

				$fields[$k] = $item;
			}
		}
	}

	protected function prepareField($formId, &$field)
	{
		if (!array_key_exists('placeholder', $field) && array_key_exists('placeholders', $field))
		{
			$field['placeholder'] = empty($field['required'])
				? $field['placeholders']['default']
				: $field['placeholders']['required'];
		}

		if (empty($field['type']) || !trim($field['type']))
			$field['type'] = 'text';

		if (empty($field['name']) || !trim($field['name']))
			$field['name'] = sprintf('main_mail_form[%s][]', $formId);

		if (empty($field['title']) || !trim($field['title']))
			$field['title'] = $field['name'];

		switch ($field['type'])
		{
			case 'list':
			{
				if (empty($field['list']) || !is_array($field['list']))
					$field['list'] = array();

				if (empty($field['value']) || !array_key_exists($field['value'], $field['list']))
					$field['value'] = null;

				if (empty($field['value']) && !empty($field['required']) && !empty($field['list']))
				{
					reset($field['list']);
					$field['value'] = key($field['list']);
				}
				break;
			}
			case 'from':
			{
				$field['mailboxes'] = \Bitrix\Main\Mail\Sender::prepareUserMailboxes();

				if($this->arParams['USE_SIGNATURES'])
				{
					$field = array_merge($field, $this->getSignaturesParams($field['mailboxes']));
				}

				if($this->arParams['USE_CALENDAR_SHARING'] && Loader::includeModule('calendar'))
				{
					$field['showCalendarSharingButton']  = true;
					$field['showCalendarSharingTour'] = $this->isSharingCalendarTourAvailable();
				}

				$defaultMailbox = reset($field['mailboxes']);
				$value = empty($field['required']) ? null : $defaultMailbox['formated'];

				if (check_email($field['value']))
				{
					$email = $field['value'];
					if (preg_match('/.*?[<\[\(](.+?)[>\]\)].*/i', $email, $matches))
						$email = mb_strtolower(trim($matches[1]));

					foreach ($field['mailboxes'] as $item)
					{
						if ($item['email'] == $email)
						{
							$value = (!empty($field['isFormatted']) && $item['formated'])
								? $item['formated'] : $field['value'];
							break;
						}
					}
				}

				$field['value'] = $value;

				break;
			}
		}
	}

	protected function prepareEditor()
	{
		$editor = &$this->arParams['EDITOR'];
		$files  = &$this->arParams['FILES'];

		if (!empty($editor['value']) && !empty($files['value']))
		{
			$itemsIds = array(
				'objects'  => array(),
				'attached' => array(),
			);
			foreach ($files['value'] as $item)
			{
				if (preg_match('/^(n?)(\d+)$/', trim($item), $matches))
				{
					$itemType = $matches[1] ? 'objects' : 'attached';
					$itemsIds[$itemType][$matches[2]] = $matches[0];
				}
			}

			$objects = array();

			if (!empty($itemsIds['objects']))
			{
				$filter = array('@ID' => array_keys($itemsIds['objects']));
				foreach (\Bitrix\Disk\File::getModelList(array('filter' => $filter)) as $object)
					$objects[$itemsIds['objects'][$object->getId()]] = $object;
			}

			if (!empty($itemsIds['attached']))
			{
				$diskUfManager = \Bitrix\Disk\Driver::getInstance()->getUserFieldManager();
				$diskUfManager->loadBatchAttachedObject($itemsIds['attached']);
				foreach ($itemsIds['attached'] as $objectId)
				{
					if ($attachedObject = $diskUfManager->getAttachedObjectById($objectId))
						$objects[$objectId] = $attachedObject->getFile();
				}
			}

			$diskUrlManager = \Bitrix\Disk\Driver::getInstance()->getUrlManager();
			foreach ($files['value'] as $fileId)
			{
				if (array_key_exists($fileId, $objects))
				{
					$uri = (new Uri($diskUrlManager->getUrlUfController(
						'show',
						['attachedId' => $fileId]
					)))
						->addParams(['__bxacid' => $fileId])
						->getUri();

					$editor['value'] = preg_replace(
						sprintf('/bxacid:%u/', $fileId),
						$uri,
						$editor['value']
					);
				}
			}
		}
	}

	protected function prepareButtons()
	{
		$presets = array(
			'submit' => array(
				'title' => Loc::getMessage('MAIN_MAIL_FORM_SAVE_BTN'),
			),
			'cancel' => array(
				'title' => Loc::getMessage('MAIN_MAIL_FORM_CANCEL_BTN'),
			),
		);

		$buttons = &$this->arParams['BUTTONS'];
		$buttons = !empty($buttons) && is_array($buttons) ? $buttons : array();

		$buttons = array_merge(array('submit' => array()), $buttons);

		foreach ($buttons as $type => $item)
		{
			if (array_key_exists($type, $presets))
				$item = static::deepMerge($presets[$type], $item);

			if (empty($item['title']) || !trim($item['title']))
				$item['title'] = $type;

			$buttons[$type] = $item;
		}
	}

	private static function deepMerge(array &$base, array &$ext)
	{
		$result = array();

		foreach ($base as $k => $v)
			is_numeric($k) ? ($result[] = $v) : ($result[$k] = $v);

		foreach ($ext as $k => $v)
		{
			if (is_numeric($k))
			{
				$result[] = $v;
			}
			else
			{
				if (array_key_exists($k, $result) && is_array($result[$k]) && is_array($v))
					$v = static::deepMerge($result[$k], $v);

				$result[$k] = $v;
			}
		}

		return $result;
	}

	/**
	 * @param array $mailboxes
	 * @return array
	 */
	protected function loadSignatures(array $mailboxes)
	{
		if (!empty($mailboxes))
		{
			$onlyFirst = [];
			foreach ($this->getSignaturesFromDb() as $sender => $signatureFields)
			{
				if (!isset($onlyFirst[$sender]))
				{
					$onlyFirst[$sender] = $signatureFields;
				}
			}
			return $onlyFirst;
		}

		return [];
	}

	/**
	 * Get signatures from database
	 *
	 * @return array [sender => [signature,...],...]
	 * @throws \Bitrix\Main\ArgumentException
	 * @throws \Bitrix\Main\LoaderException
	 * @throws \Bitrix\Main\ObjectPropertyException
	 * @throws \Bitrix\Main\SystemException
	 */
	private function getSignaturesFromDb(): array
	{
		if (!isset($this->signatures))
		{
			$signatures = [];
			if (
				\Bitrix\Main\Loader::includeModule('mail')
				&& class_exists('\\Bitrix\\Mail\\Internals\\UserSignatureTable')
			)
			{
				$signatureList = \Bitrix\Mail\Internals\UserSignatureTable::getList([
					'order' => ['ID' => 'desc'],
					'select' => ['SIGNATURE', 'SENDER'],
					'filter' => [
						'USER_ID' => \Bitrix\Main\Engine\CurrentUser::get()->getId(),
					],
				]);
				while ($signature = $signatureList->fetch())
				{
					$signatures[$signature['SENDER']][] = [
						"list" => $this->getPreparedForTitleSignature((string)$signature['SIGNATURE']),
						"full" => $signature['SIGNATURE'],
					];
				}
			}
			$this->signatures = $signatures;
		}
		return $this->signatures;
	}

	/**
	 * Prepare string for correct display in title tag
	 *
	 * @param string $signature User signature text with html
	 *
	 * @return string
	 */
	private function getPreparedForTitleSignature(string $signature): string
	{
		$signature = mb_substr(strip_tags($signature), 0, 500);
		$signature = preg_replace("#\t#u", " ", $signature);
		$signature = preg_replace("#\n+#u", "\n", $signature);
		$signature = preg_replace("# +#u", " ", $signature);
		$signature = trim($signature);
		$encoding = (defined("BX_UTF") ? "UTF-8" : "ISO-8859-1");
		return html_entity_decode($signature, ENT_COMPAT, $encoding);
	}

	/**
	 * Get signatures related field params
	 *
	 * @param array $mailboxes Mailboxes array
	 *
	 * @return array
	 */
	private function getSignaturesParams(array $mailboxes): array
	{
		$signaturesUrl = (string)($this->arParams['PATH_TO_MAIL_SIGNATURES'] ?? '');
		$signaturesUrl = strpos($signaturesUrl, '/') === 0 ? $signaturesUrl : '/mail/signatures';
		$params = [
			'signatures' => $this->loadSignatures($mailboxes), // compatibility
		];

		if (\Bitrix\Main\Loader::includeModule('mail'))
		{
			$params['allUserSignatures'] = empty($mailboxes) ? [] : $this->getSignaturesFromDb();
			$params['signatureSelectTitle'] = Loc::getMessage('MAIN_MAIL_FORM_EDITOR_SIGNATURE_SELECT');
			$params['signatureConfigureTitle'] = Loc::getMessage('MAIN_MAIL_FORM_EDITOR_SIGNATURE_CONFIGURE');
			$params['pathToMailSignatures'] = $signaturesUrl;
		}

		return $params;
	}

	/**
	 * Interface Controllable requirement
	 *
	 * @return array
	 */
	public function configureActions(): array
	{
		return [];
	}

	/**
	 * Get current user signatures from ajax action
	 *
	 * @return array
	 */
	public function signaturesAction(): array
	{
		return [
			'signatures' => $this->getSignaturesFromDb(),
		];
	}

	/**
	 * Get current user sharing link from ajax action
	 *
	 * @return array{isSharingFeatureEnabled: bool, sharingUrl?: string}
	 */
	public function getCalendarSharingLinkAction(string $entityType = null, int $entityId = null): array
	{
		if (!Loader::includeModule('calendar'))
		{
			return ['isSharingFeatureEnabled' => 'false'];
		}

		if (!Loader::includeModule('crm') || \CCrmOwnerType::DealName !== $entityType)
		{
			$sharing = new Calendar\Sharing\Sharing(CurrentUser::get()->getId());
			return [
				'isSharingFeatureEnabled' => $sharing->isEnabled(),
				'sharingUrl' => $sharing->getActiveLinkShortUrl(),
			];
		}

		$broker = Crm\Service\Container::getInstance()->getEntityBroker(\CCrmOwnerType::Deal);
		if (!$broker)
		{
			return ['isSharingFeatureEnabled' => false];
		}

		$deal = $broker->getById($entityId);
		if (!$deal)
		{
			return ['isSharingFeatureEnabled' => false];
		}

		$ownerId = $deal->getAssignedById();
		$crmDealLink = (new Calendar\Sharing\Link\Factory())->getCrmDealLink($entityId, $ownerId);
		if ($crmDealLink === null)
		{
			$crmDealLink = (new Calendar\Sharing\Link\Factory())->createCrmDealLink($ownerId, $entityId);
		}

		return [
			'isSharingFeatureEnabled' => true,
			'sharingUrl' => Calendar\Sharing\Helper::getShortUrl($crmDealLink->getUrl()),
		];
	}

	private function getSharingCalendarTourId(): string
	{
		return 'mail-start-calendar-sharing-tour';
	}

	private function isSharingCalendarTourAvailable(): bool
	{
		if (Loader::includeModule('calendar'))
		{
			return $this->isSharingCalendarTourAlreadySeen();
		}
		return false;
	}

	private function isSharingCalendarTourAlreadySeen(): bool
	{
		return \CUserOptions::GetOption('ui-tour', 'view_date_' . $this->getSharingCalendarTourId(), null) === null;
	}

	private function getUserCalendarPath(): string
	{
		if (Loader::includeModule('calendar'))
		{
			return \CCalendar::GetPathForCalendarEx(CurrentUser::get()->getId());
		}
		return '/';
	}

	/**
	 * @param array|null $copilotParams
	 * Array can contain fields: ['isCopilotEnabled', 'moduleId', 'contextId', 'category', 'invitationLineMode', 'contextParameters', 'isCopilotImageEnabled', 'isCopilotTextEnabled']
	 */
	private function prepareCopilotParams(?array $copilotParams = null): void
	{
		if (!$copilotParams || !isset($copilotParams['isCopilotEnabled']))
		{
			$this->arParams['IS_COPILOT_ENABLED'] = false;
			$this->arParams['IS_COPILOT_IMAGE_ENABLED'] = false;
			$this->arParams['IS_COPILOT_TEXT_ENABLED'] = false;

			return;
		}

		$this->arParams['IS_COPILOT_ENABLED'] = $copilotParams['isCopilotEnabled'];
		$this->arParams['COPILOT_PARAMS'] = [
			'moduleId' => $copilotParams['moduleId'] ?? 'main',
			'contextId' => $copilotParams['contextId'] ?? 'bxhtmled_copilot',
			'category' => $copilotParams['category'] ?? null,
			'invitationLineMode' => $copilotParams['invitationLineMode'] ?? 'eachLine',
			'contextParameters' => $copilotParams['contextParameters'] ?? [],
		];

		$this->arParams['IS_COPILOT_IMAGE_ENABLED'] = $copilotParams['isCopilotImageEnabled'] ?? false;
		$this->arParams['IS_COPILOT_TEXT_ENABLED'] = $copilotParams['isCopilotTextEnabled'] ?? false;
	}
}