403Webshell
Server IP : 80.87.202.40  /  Your IP : 216.73.216.169
Web Server : Apache
System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64
User : bitrix ( 600)
PHP Version : 8.2.27
Disable Function : NONE
MySQL : OFF |  cURL : ON |  WGET : ON |  Perl : ON |  Python : OFF |  Sudo : ON |  Pkexec : ON
Directory :  /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/landing/lib/subtype/

Upload File :
current_dir [ Writeable] document_root [ Writeable]

 

Command :


[ Back ]     

Current File : /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/landing/lib/subtype/form.php
<?php

namespace Bitrix\Landing\Subtype;

use Bitrix\Crm\Integration\UserConsent;
use Bitrix\Crm\Settings\LeadSettings;
use Bitrix\Crm\UI\Webpack;
use Bitrix\Crm\WebForm;
use Bitrix\Landing\History;
use Bitrix\Landing\Landing;
use Bitrix\Landing\Block;
use Bitrix\Landing\Internals\BlockTable;
use Bitrix\Landing\Manager;
use Bitrix\Landing\Site;
use Bitrix\Main\Loader;
use Bitrix\Main\Localization\Loc;
use Bitrix\Socialservices\ApClient;

Loc::loadMessages(__FILE__);

/**
 * Subtype for blocks with CRM-forms
 * @package Bitrix\Landing\Subtype
 */
class Form
{
	protected const ATTR_FORM_PARAMS = 'data-b24form';
	protected const ATTR_FORM_EMBED = 'data-b24form-embed';
	protected const ATTR_FORM_STYLE = 'data-b24form-design';
	protected const ATTR_FORM_USE_STYLE = 'data-b24form-use-style';
	protected const ATTR_FORM_FROM_CONNECTOR = 'data-b24form-connector';
	protected const ATTR_FORM_OLD_DOMAIN = 'data-b24form-original-domain';
	protected const ATTR_FORM_OLD_HEADER = 'data-b24form-show-header';
	protected const SELECTOR_FORM_NODE = '.bitrix24forms';
	protected const SELECTOR_OLD_STYLE_NODE = '.landing-block-form-styles';
	protected const STYLE_SETTING = 'crm-form';
	protected const REGEXP_FORM_STYLE = '/data-b24form-design *= *[\'"](\{.+\})[\'"]/i';
	protected const REGEXP_FORM_ID_INLINE = '/data-b24form=["\']#crmFormInline(?<id>[\d]+)["\']/i';

	public const INLINE_MARKER_PREFIX = '#crmFormInline';
	public const POPUP_MARKER_PREFIX = '#crmFormPopup';

	protected const AVAILABLE_FORM_FIELDS = [
		'ID',
		'NAME',
		'SECURITY_CODE',
		'IS_CALLBACK_FORM',
		'ACTIVE',
		'XML_ID',
	];

	private static array $errors = [];

	// region replaces for view and public

	/**
	 * Replace form markers in block, put true scripts. Run on publication action
	 * @param string $content - content of block
	 * @return string - replaced content
	 */
	public static function prepareFormsToPublication(string $content): string
	{
		// change - replace markers always, not only if connector
		return self::replaceFormMarkers($content);
	}

	/**
	 * Replace form markers in block, put true scripts. Run on view in public mode
	 * @param string $content - content of block
	 * @return string - replaced content
	 */
	public static function prepareFormsToView(string $content): string
	{
		if (self::isCrm())
		{
			$content = self::replaceFormMarkers($content);
		}
		return $content;
	}

	/**
	 * Replaces and returns all #crmForm-link to the popup codes or in inline forms
	 * For CP - every hit (cached), for SMN - on public
	 * @param string $content Some content.
	 * @return string
	 */
	protected static function replaceFormMarkers(string $content): string
	{
		$replace = preg_replace_callback(
			'/(?<pre><a[^>]+href=|data-b24form=)["\'](form:)?#crmForm(?<type>Inline|Popup)(?<id>[\d]+)["\']/i',
			static function ($matches)
			{
				$id = (int)$matches['id'];
				if (!$id)
				{
					return $matches[0];
				}

				$form = self::getFormById($id, true);
				if (!$form || !$form['URL'])
				{
					return $matches[0];
				}

				if (strtolower($matches['type']) === 'inline')
				{
					$param = "{$form['ID']}|{$form['SECURITY_CODE']}|{$form['URL']}";

					return $matches['pre'] . "\"{$param}\"";
				}

				if (strtolower($matches['type']) === 'popup')
				{
					$script = "<script data-b24-form=\"click/{$id}/{$form['SECURITY_CODE']}\" data-skip-moving=\"true\">
								(function(w,d,u){
									var s=d.createElement('script');s.async=true;s.src=u+'?'+(Date.now()/180000|0);
									var h=d.getElementsByTagName('script')[0];h.parentNode.insertBefore(s,h);
								})(window,document,'{$form['URL']}');
							</script>";

					return $script . $matches['pre'] . "\"#\" onclick=\"BX.PreventDefault();\"";
				}

				return $matches[0];
			},
			$content
		);

		$replace = $replace ?? $content;

		//replace link to form in data-pseudo-url
		$replace = preg_replace_callback(
			'/(?<pre><img|<i.*)data-pseudo-url="{.*(form:)?#crmForm(?<type>Inline|Popup)(?<id>[\d]+).*}"(?<pre2>.*>)/i',
			static function ($matches)
			{
				if (
					!(int)$matches['id']
					|| !($form = self::getFormById((int)$matches['id'], true))
				)
				{
					return $matches[0];
				}

				if (strtolower($matches['type']) === 'popup')
				{
					$script = "<script data-b24-form=\"click/{$matches['id']}/{$form['SECURITY_CODE']}\" data-skip-moving=\"true\">
								(function(w,d,u){
									var s=d.createElement('script');s.async=true;s.src=u+'?'+(Date.now()/180000|0);
									var h=d.getElementsByTagName('script')[0];h.parentNode.insertBefore(s,h);
								})(window,document,'{$form['URL']}');
							</script>";

					//add class g-cursor-pointer
					preg_match_all('/(class="[^"]*)/i', $matches['pre'], $matchesPre);
					$matches['pre'] = str_replace($matchesPre[1][0], $matchesPre[1][0]. ' g-cursor-pointer', $matches['pre']);

					return $script . $matches['pre'] . ' '. $matches['pre2'];
				}

				return $matches[0];
			},
			$replace
		);

		return $replace ?? $content;
	}

	/**
	 * Clears cache all sites with blocks.
	 * @return void
	 */
	public static function clearCache(): void
	{
		$sites = [];
		$res = BlockTable::getList(
			[
				'select' => [
					'SITE_ID' => 'LANDING.SITE_ID',
				],
				'filter' => [
					'=LANDING.ACTIVE' => 'Y',
					'=LANDING.SITE.ACTIVE' => 'Y',
					'=PUBLIC' => 'Y',
					'=DELETED' => 'N',
					'CONTENT' => '%bitrix24forms%',
				],
				'group' => [
					'LANDING.SITE_ID',
				],
			]
		);
		while ($row = $res->fetch())
		{
			if (!in_array($row['SITE_ID'], $sites))
			{
				$sites[] = $row['SITE_ID'];
			}
		}

		foreach ($sites as $site)
		{
			Site::update($site, [
				'DATE_MODIFY' => false
			]);
		}
	}
	// endregion

	// region get forms
	/**
	 * Gets web forms in system.
	 * @param bool $force - if true - get forms forcibly w/o cache
	 * @return array
	 */
	public static function getForms(bool $force = false): array
	{
		static $forms = [];
		if ($forms && !$force)
		{
			return $forms;
		}

		if (self::isCrm())
		{
			$forms = self::getFormsForPortal();
		}
		elseif (Manager::isB24Connector())
		{
			$forms = self::getFormsViaConnector();
		}

		return $forms;
	}

	/**
	 * Check if b24 or box portal
	 * @return bool
	 */
	protected static function isCrm(): bool
	{
		return Loader::includeModule('crm');
	}

	protected static function getFormsForPortal(array $filter = []): array
	{
		$res = Webform\Internals\FormTable::getDefaultTypeList(
			[
				'select' => self::AVAILABLE_FORM_FIELDS,
				'filter' => $filter,
				'order' => [
					'ID' => 'ASC',
				],
				'cache' => ['ttl' => 86400],
			]
		);

		$forms = [];
		while ($form = $res->fetch())
		{
			$form['ID'] = (int)$form['ID'];
			$forms[$form['ID']] = $form;
		}

		return $forms;
	}

	protected static function getFormsViaConnector(): array
	{
		$forms = [];
		$client = ApClient::init();
		if ($client)
		{
			$res = $client->call('crm.webform.list', ['GET_INACTIVE' => 'Y']);
			if (isset($res['result']) && is_array($res['result']))
			{
				foreach ($res['result'] as $form)
				{
					$form['ID'] = (int)$form['ID'];
					$forms[$form['ID']] = $form;
				}
			}
			else if (isset($res['error']))
			{
				self::$errors[] = [
					'code' => $res['error'],
					'message' => $res['error_description'] ?? $res['error'],
				];
			}
		}

		return $forms;
	}

	/**
	 * Find just one form by ID. Return array of form fields, or empty array if not found
	 * @return array
	 */
	public static function getFormById(int $id, bool $full = false): array
	{
		$forms = self::getFormsByFilter(['=ID' => $id]);
		$form = !empty($forms) ? array_shift($forms) : null;
		if (!$form)
		{
			return [];
		}

		if ($full)
		{
			if (self::isCrm())
			{
				$webpack = Webpack\Form::instance($form['ID']);
				if (!$webpack->isBuilt())
				{
					$webpack->build();
					$webpack = Webpack\Form::instance($form['ID']);
				}
				$form['URL'] = $webpack->getEmbeddedFileUrl();
			}
		}

		return $form;
	}

	/**
	 * Find only callback forms. Return array of form arrays, or empty array if not found
	 * @return array
	 */
	public static function getCallbackForms(): array
	{
		return self::getFormsByFilter(['=IS_CALLBACK_FORM' => 'Y', '=ACTIVE' => 'Y']);
	}

	protected static function getFormsByFilter(array $filter): array
	{
		static $cache = [];
		$cacheKey = serialize($filter);
		if (array_key_exists($cacheKey, $cache))
		{
			return $cache[$cacheKey];
		}

		$filter = array_filter(
			$filter,
			static function ($key)
			{
				$key = trim($key);
				$equalKey = ltrim($key, '=');
				return
					in_array($key, self::AVAILABLE_FORM_FIELDS, true)
					|| in_array($equalKey, self::AVAILABLE_FORM_FIELDS, true)
				;
			},
			ARRAY_FILTER_USE_KEY
		);
		$forms = [];

		if (self::isCrm())
		{
			$forms = self::getFormsForPortal($filter);
		}
		elseif (Manager::isB24Connector())
		{
			foreach (self::getFormsViaConnector() as $form)
			{
				$filtred = true;
				foreach ($filter as $key => $value)
				{
					if (!$form[$key] || $form[$key] !== $value)
					{
						$filtred = false;
						break;
					}
				}
				if ($filtred)
				{
					$forms[$form['ID']] = $form;
				}
			}
		}

		$cache[$cacheKey] = $forms;

		return $forms;
	}

	// endregion

	// region prepare manifest
	/**
	 * Prepare manifest.
	 * @param array $manifest Block's manifest.
	 * @param Block|null $block Block instance.
	 * @param array $params Additional params.
	 * @return array
	 */
	public static function prepareManifest(array $manifest, Block $block = null, array $params = []): array
	{
		// add extension
		if (!isset($manifest['assets']) || !is_array($manifest['assets']))
		{
			$manifest['assets'] = [];
		}
		if (!isset($manifest['assets']['ext']))
		{
			$manifest['assets']['ext'] = [];
		}
		if (!is_array($manifest['assets']['ext']))
		{
			$manifest['assets']['ext'] = [$manifest['assets']['ext']];
		}
		if (!in_array('landing_form', $manifest['assets']['ext'], true))
		{
			$manifest['assets']['ext'][] = 'landing_form';
		}

		// style setting
		if (
			!isset($manifest['style']['block']) && !isset($manifest['style']['nodes'])
		)
		{
			$manifest['style'] = [
				'block' => ['type' => Block::DEFAULT_WRAPPER_STYLE],
				'nodes' => $manifest['style'] ?? [],
			];
		}
		$manifest['style']['nodes'][self::SELECTOR_FORM_NODE] = [
			'type' => self::STYLE_SETTING,
		];

		if (Manager::isB24())
		{
			$link = '/crm/webform/';
		}
		else if (Manager::isB24Connector())
		{
			$link = '/bitrix/admin/b24connector_crm_forms.php?lang=' . LANGUAGE_ID;
		}
		if (isset($link))
		{
			$manifest['block']['attrsFormDescription'] = '<a href="' . $link . '" target="_blank">' .
				Loc::getMessage('LANDING_BLOCK_FORM_CONFIG') .
				'</a>';
		}

		// add callbacks
		$manifest['callbacks'] = [
			'afterAdd' => function (Block &$block)
			{
				$historyActivity = History::isActive();
				History::deactivate();

				$dom = $block->getDom();
				if (!($node = $dom->querySelector(self::SELECTOR_FORM_NODE)))
				{
					return;
				}

				$attrsToSet = [self::ATTR_FORM_EMBED => ''];
				if (!self::isCrm())
				{
					$attrsToSet[self::ATTR_FORM_FROM_CONNECTOR] = 'Y';
				}

				// if block copy - not update params
				if (
					($attrsExists = $node->getAttributes())
					&& isset($attrsExists[self::ATTR_FORM_PARAMS])
					&& $attrsExists[self::ATTR_FORM_PARAMS]
					&& $attrsExists[self::ATTR_FORM_PARAMS]->getValue()
				)
				{
					$attrsToSet[self::ATTR_FORM_PARAMS] = $attrsExists[self::ATTR_FORM_PARAMS]->getValue();
				}
				else
				{
					// try to get 1) default callback form 2) last added form 3) create new form
					$forms = self::getFormsByFilter([
						'=XML_ID' => 'crm_preset_fb'
					]);
					$forms = self::prepareFormsToAttrs($forms);
					if (empty($forms))
					{
						$forms = self::getForms(true);  // force to preserve cycle when create form landing block
						$forms = self::prepareFormsToAttrs($forms);
						if (empty($forms))
						{
							$forms = self::createDefaultForm();
							$forms = self::prepareFormsToAttrs($forms);
						}
					}

					if (!empty($forms))
					{
						self::setFormIdParam(
							$block,
							str_replace(self::INLINE_MARKER_PREFIX, '', $forms[0]['value'])
						);
					}
				}

				// preload alert
				$node->setInnerHTML(
					'<div class="g-landing-alert">'
					. Loc::getMessage('LANDING_BLOCK_WEBFORM_PRELOADER')
					. '</div>'
				);
				$block->saveContent($dom->saveHTML());

				// save
				$block->setAttributes([self::SELECTOR_FORM_NODE => $attrsToSet]);
				$block->save();

				$historyActivity ? History::activate() : History::deactivate();
			},
		];

		// add attrs
		if (
			!array_key_exists('attrs', $manifest)
			|| !is_array($manifest['attrs'])
		)
		{
			$manifest['attrs'] = [];
		}

		// hard operation getAttrs is only FOR EDITOR, in public set fake array for saveAttributes later
		$manifest['attrs'][self::SELECTOR_FORM_NODE] =
			Landing::getEditMode()
				? self::getAttrs()
				: [['attribute' => self::ATTR_FORM_PARAMS]];

		return $manifest;
	}

	/**
	 * Gets attrs for form.
	 * @return array
	 */
	protected static function getAttrs(): array
	{
		static $attrs = [];
		if ($attrs)
		{
			return $attrs;
		}

		// get from CRM or via connector
		$forms = self::getForms();
		$forms = self::prepareFormsToAttrs($forms);

		$attrs = [
			$attrs[] = [
				'name' => 'Embed form flag',
				'attribute' => self::ATTR_FORM_EMBED,
				'type' => 'string',
				'hidden' => true,
			],
			[
				'name' => 'Form design',
				'attribute' => self::ATTR_FORM_STYLE,
				'type' => 'string',
				'hidden' => true,
			],
			[
				'name' => 'Form from connector flag',
				'attribute' => self::ATTR_FORM_FROM_CONNECTOR,
				'type' => 'string',
				'hidden' => true,
			],
		];

		if (!empty($forms))
		{
			// get forms list
			$attrs[] = [
				'name' => Loc::getMessage('LANDING_BLOCK_WEBFORM'),
				'attribute' => self::ATTR_FORM_PARAMS,
				'items' => $forms,
				'type' => 'list',
			];
			// show header
			// use custom design
			$attrs[] = [
				'name' => Loc::getMessage('LANDING_BLOCK_WEBFORM_USE_STYLE'),
				'attribute' => self::ATTR_FORM_USE_STYLE,
				'type' => 'list',
				'items' => [
					[
						'name' => Loc::getMessage('LANDING_BLOCK_WEBFORM_USE_STYLE_Y'),
						'value' => 'Y',
					],
					[
						'name' => Loc::getMessage('LANDING_BLOCK_WEBFORM_USE_STYLE_N'),
						'value' => 'N',
					],
				],
			];
		}
		// no form - no settings, just message for user
		else
		{
			$attrs[] = [
				'name' => Loc::getMessage('LANDING_BLOCK_WEBFORM'),
				'attribute' => self::ATTR_FORM_PARAMS,
				'type' => 'list',
				'items' => !empty(self::$errors)
					? array_map(fn ($item) => ['name' => $item['message'], 'value' => false], self::$errors)
					: [[
						'name' => Loc::getMessage('LANDING_BLOCK_WEBFORM_NO_FORM'),
						'value' => false,
					]],
			];
		}

		return $attrs;
	}

	/**
	 * Move callback form to end.
	 * @param array $forms Forms array.
	 * @return array
	 */
	protected static function prepareFormsToAttrs(array $forms): array
	{
		$sorted = [];
		foreach ($forms as $form)
		{
			if (array_key_exists('ACTIVE', $form) && $form['ACTIVE'] !== 'Y')
			{
				continue;
			}

			$item = [
				'name' => $form['NAME'],
				'value' => self::INLINE_MARKER_PREFIX . $form['ID'],
			];

			if ($form['IS_CALLBACK_FORM'] === 'Y')
			{
				$sorted[] = $item;
			}
			else
			{
				array_unshift($sorted, $item);
			}
		}

		return $sorted;
	}
	// endregion

	// region actions with blocks and forms
	/**
	 * @param int|array $landingIds - int or [int] of landing IDs
	 * @return array of all block with CRM-forms at this page
	 * @throws \Bitrix\Main\ArgumentException
	 * @throws \Bitrix\Main\ObjectPropertyException
	 * @throws \Bitrix\Main\SystemException
	 */
	public static function getLandingFormBlocks($landingIds): array
	{
		if (empty($landingIds))
		{
			return [];
		}

		if (!is_array($landingIds))
		{
			$landingIds = [$landingIds];
		}

		return BlockTable::getList(
			[
				'select' => ['ID', 'LID'],
				'filter' => [
					'=LID' => $landingIds,
					'=DELETED' => 'N',
					'CONTENT' => '%data-b24form=%',
				],
			]
		)->fetchAll()
			;
	}

	/**
	 * Return CRM-form ID from block, if exists. Else return null;
	 * @param int $blockId
	 * @return int|null
	 */
	public static function getFormByBlock(int $blockId): ?int
	{
		$block = new Block($blockId);
		if (preg_match(self::REGEXP_FORM_ID_INLINE, $block->getContent(), $matches))
		{
			return (int)$matches[1];
		}
		return null;
	}

	/**
	 * Save form params in block for current form
	 * @param int $blockId - from landing block table
	 * @param int $formId - from webform table
	 * @return bool - true if success, false if errors
	 */
	public static function setFormIdToBlock(int $blockId, int $formId): bool
	{
		$block = new Block($blockId);
		self::setFormIdParam($block, $formId);
		$block->save();

		return $block->getError()->isEmpty();
	}

	/**
	 * Encapsulates the form params save logic
	 * @param Block $block
	 * @param int $formId - from webform table
	 */
	protected static function setFormIdParam(Block $block, int $formId): void
	{
		if (($form = self::getFormById($formId)))
		{
			// todo: can add force public flag for replaces, when we know exactly that block is public
			$newParam = self::INLINE_MARKER_PREFIX . $form['ID'];

			$block->setAttributes([
				self::SELECTOR_FORM_NODE => [self::ATTR_FORM_PARAMS => $newParam],
			]);
		}
	}

	/**
	 * Create form with default params
	 * @return array - array with once item, fields equal getForms(). Or empty array if not created
	 */
	protected static function createDefaultForm(): array
	{
		if ($formId = self::createForm([]))
		{
			return self::getFormsByFilter(['=ID' => $formId]);
		}

		return [];
	}

	/**
	 * @param array $formData
	 * @return int|null - id of created form or null if errors
	 */
	protected static function createForm(array $formData): ?int
	{
		if (self::isCrm())
		{
			$form = new WebForm\Form;

			$defaultData = WebForm\Preset::getById('crm_preset_cd');

			$defaultData['XML_ID'] = '';
			$defaultData['ACTIVE'] = 'Y';
			$defaultData['IS_SYSTEM'] = 'N';
			$defaultData['IS_CALLBACK_FORM'] = 'N';
			$defaultData['BUTTON_CAPTION'] = $form->getButtonCaption();

			$agreementId = UserConsent::getDefaultAgreementId();
			$defaultData['USE_LICENCE'] = $agreementId ? 'Y' : 'N';
			if ($agreementId)
			{
				$defaultData['LICENCE_BUTTON_IS_CHECKED'] = 'Y';
				$defaultData['AGREEMENT_ID'] = $agreementId;
			}

			$isLeadEnabled = LeadSettings::getCurrent()->isEnabled();
			$defaultData['ENTITY_SCHEME'] = (string)(
			$isLeadEnabled
				? WebForm\Entity::ENUM_ENTITY_SCHEME_LEAD
				: WebForm\Entity::ENUM_ENTITY_SCHEME_DEAL
			);

			$currentUserId = is_object($GLOBALS['USER']) ? $GLOBALS['USER']->getId() : null;
			$defaultData['ACTIVE_CHANGE_BY'] = $currentUserId;
			$defaultData['ASSIGNED_BY_ID'] = $currentUserId;

			$formData = array_merge($defaultData, $formData);
			$form->merge($formData);
			$form->save();

			return !$form->hasErrors() ? $form->getId() : null;
		}

		return null;
	}

	/**
	 * @param Block $block
	 * @param string $xmlId
	 */
	public static function setSpecialFormToBlock(Block $block, string $xmlId): void
	{
		if (($formData = self::getSpecialFormsData()[$xmlId]))
		{
			$formId = null;
			foreach (self::getForms() as $form)
			{
				if (
					array_key_exists('XML_ID', $form)
					&& $form['XML_ID'] === $xmlId
				)
				{
					$formId = $form['ID'];
					break;
				}
			}

			if (!$formId)
			{
				$formId = self::createForm($formData);
			}

			if ($formId)
			{
				self::setFormIdParam($block, $formId);
				$block->save();
			}
		}
	}

	protected static function getSpecialFormsData(): ?array
	{
		if (self::isCrm())
		{
			$data = [
				'crm_preset_store_v3' => [
					'XML_ID' => 'crm_preset_store_v3',
					'NAME' => Loc::getMessage('LANDING_FORM_SPECIAL_STOREV3_NAME'),
					'IS_SYSTEM' => 'N',
					'ACTIVE' => 'Y',
					'RESULT_SUCCESS_TEXT' => Loc::getMessage('LANDING_FORM_SPECIAL_STOREV3_RESULT_SUCCESS'),
					'RESULT_FAILURE_TEXT' => Loc::getMessage('LANDING_FORM_SPECIAL_STOREV3_RESULT_FAILURE'),
					'COPYRIGHT_REMOVED' => 'N',
					'IS_PAY' => 'N',
					'FORM_SETTINGS' => [
						'DEAL_DC_ENABLED' => 'Y',
					],
					'BUTTON_CAPTION' => '',
					'FIELDS' => [
						[
							'TYPE' => 'string',
							'CODE' => 'CONTACT_NAME',
							'CAPTION' => Loc::getMessage('LANDING_FORM_SPECIAL_STOREV3_FIELD_NAME'),
							'SORT' => 100,
							'REQUIRED' => 'N',
							'MULTIPLE' => 'N',
							'PLACEHOLDER' => '',
						],
						[
							'TYPE' => 'phone',
							'CODE' => 'CONTACT_PHONE',
							'CAPTION' => Loc::getMessage('LANDING_FORM_SPECIAL_STOREV3_FIELD_PHONE'),
							'SORT' => 200,
							'REQUIRED' => 'N',
							'MULTIPLE' => 'N',
							'PLACEHOLDER' => '',
						],
						[
							'TYPE' => 'text',
							'CODE' => 'DEAL_COMMENTS',
							'CAPTION' => Loc::getMessage('LANDING_FORM_SPECIAL_STOREV3_FIELD_COMMENT'),
							'SORT' => 300,
							'REQUIRED' => 'N',
							'MULTIPLE' => 'N',
							'PLACEHOLDER' => '',
						],
					],
				],
			];

			$isLeadEnabled = LeadSettings::getCurrent()->isEnabled();

			foreach ($data as $id => $form)
			{
				if ($isLeadEnabled)
				{
					foreach ($data[$id]['FIELDS'] as $key => $field)
					{
						$field['CODE'] = str_replace(['CONTACT', 'DEAL'], 'LEAD', $field['CODE']);
						$data[$id]['FIELDS'][$key] = $field;
					}
				}
			}

			return $data;
		}

		return null;
	}

	// endregion

	// region update
	/**
	 * Find old forms blocks and update to embed format
	 * @param int $landingId
	 */
	public static function updateLandingToEmbedForms(int $landingId): void
	{
		$res = BlockTable::getList(
			[
				'select' => [
					'ID',
				],
				'filter' => [
					'LID' => $landingId,
					'=DELETED' => 'N',
				],
			]
		);
		while ($row = $res->fetch())
		{
			$block = new Block($row['ID']);
			self::updateBlockToEmbed($block);
		}
	}

	/**
	 * Migrate from old form to new embed, adjust block params, remove old style nodes
	 * @param Block $block
	 */
	protected static function updateBlockToEmbed(Block $block): void
	{
		// check if update needed
		$manifest = $block->getManifest();
		if (
			!$manifest['block']['subtype']
			|| (!is_array($manifest['block']['subtype']) && $manifest['block']['subtype'] !== 'form')
			|| (is_array($manifest['block']['subtype']) && !in_array('form', $manifest['block']['subtype'], true))
		)
		{
			return;
		}
		$dom = $block->getDom();
		if (
			!($resultNode = $dom->querySelector(self::SELECTOR_FORM_NODE))
			|| !($attrs = $resultNode->getAttributes())
			|| !array_key_exists(self::ATTR_FORM_PARAMS, $attrs))
		{
			return;
		}
		$formParams = explode('|', $attrs[self::ATTR_FORM_PARAMS]->getValue());
		if (count($formParams) !== 2 || !(int)$formParams[0])
		{
			return;
		}

		// update
		$forms = self::getForms();
		if (array_key_exists($formParams[0], $forms))
		{
			$form = $forms[$formParams[0]];
			self::setFormIdParam($block, $form['ID']);
			$resultNode->setAttribute(self::ATTR_FORM_EMBED, '');
			$resultNode->removeAttribute(self::ATTR_FORM_OLD_DOMAIN);
			$resultNode->removeAttribute(self::ATTR_FORM_OLD_HEADER);

			if (
				!array_key_exists(self::ATTR_FORM_STYLE, $attrs)
				|| !$attrs[self::ATTR_FORM_STYLE]->getValue()
			)
			{
				// find new styles
				$contentFromRepo = Block::getContentFromRepository($block->getCode());
				if (
					$contentFromRepo
					&& preg_match(self::REGEXP_FORM_STYLE, $contentFromRepo, $style)
				)
				{
					$resultNode->setAttribute(self::ATTR_FORM_STYLE, $style[1]);
				}
			}
		}

		if (($oldStyleNode = $dom->querySelector(self::SELECTOR_OLD_STYLE_NODE)))
		{
			$oldStyleNode->getParentNode()->removeChild($oldStyleNode);
		}

		$block->saveContent($dom->saveHTML());
		$block->save();
	}

	/**
	 * Get original domain for web-forms.
	 * @return string
	 * @deprecated
	 */
	public static function getOriginalFormDomain(): string
	{
		trigger_error(
			"Now using embedded forms, no need domain",
			E_USER_WARNING
		);

		return '';
	}
	// endregion
}

Youez - 2016 - github.com/yon3zu
LinuXploit