3namespace Bitrix\Landing\Subtype;
5use Bitrix\Crm\Integration\UserConsent;
6use Bitrix\Crm\Settings\LeadSettings;
7use Bitrix\Crm\UI\Webpack;
9use Bitrix\Landing\History;
10use Bitrix\Landing\Landing;
11use Bitrix\Landing\Block;
12use Bitrix\Landing\Internals\BlockTable;
13use Bitrix\Landing\Manager;
14use Bitrix\Landing\Site;
15use Bitrix\Main\Loader;
16use Bitrix\Main\Localization\Loc;
17use Bitrix\Socialservices\ApClient;
19Loc::loadMessages(__FILE__);
52 private static array $errors = [];
64 return self::replaceFormMarkers(
$content);
89 $replace = preg_replace_callback(
90 '/(?<pre><a[^>]+href=|data-b24form=)["\'](form:)?#crmForm(?<type>Inline|Popup)(?<id>[\d]+)["\']/i',
99 $form = self::getFormById($id,
true);
100 if (!$form || !$form[
'URL'])
105 if (strtolower(
$matches[
'type']) ===
'inline')
107 $param =
"{$form['ID']}|{$form['SECURITY_CODE']}|{$form['URL']}";
109 return $matches[
'pre'] .
"\"{$param}\"";
112 if (strtolower(
$matches[
'type']) ===
'popup')
114 $script =
"<script data-b24-form=\"click/{$id}/{$form['SECURITY_CODE']}\" data-skip-moving=\"true\">
116 var s=d.createElement('script');s.async=true;s.src=u+'?'+(Date.now()/180000|0);
117 var h=d.getElementsByTagName('script')[0];h.parentNode.insertBefore(s,h);
118 })(window,document,'{$form['URL']}');
121 return $script .
$matches[
'pre'] .
"\"#\" onclick=\"BX.PreventDefault();\"";
132 $replace = preg_replace_callback(
133 '/(?<pre><img|<i.*)data-pseudo-url="{.*(form:)?#crmForm(?<type>Inline|Popup)(?<id>[\d]+).*}"(?<pre2>.*>)/i',
138 || !($form = self::getFormById((
int)
$matches[
'id'],
true))
144 if (strtolower(
$matches[
'type']) ===
'popup')
146 $script =
"<script data-b24-form=\"click/{$matches['id']}/{$form['SECURITY_CODE']}\" data-skip-moving=\"true\">
148 var s=d.createElement('script');s.async=true;s.src=u+'?'+(Date.now()/180000|0);
149 var h=d.getElementsByTagName('script')[0];h.parentNode.insertBefore(s,h);
150 })(window,document,'{$form['URL']}');
154 preg_match_all(
'/(class="[^"]*)/i',
$matches[
'pre'], $matchesPre);
155 $matches[
'pre'] = str_replace($matchesPre[1][0], $matchesPre[1][0].
' g-cursor-pointer',
$matches[
'pre']);
175 $res = BlockTable::getList(
178 'SITE_ID' =>
'LANDING.SITE_ID',
181 '=LANDING.ACTIVE' =>
'Y',
182 '=LANDING.SITE.ACTIVE' =>
'Y',
185 'CONTENT' =>
'%bitrix24forms%',
192 while ($row =
$res->fetch())
194 if (!in_array($row[
'SITE_ID'],
$sites))
196 $sites[] = $row[
'SITE_ID'];
202 Site::update(
$site, [
203 'DATE_MODIFY' =>
false
218 if ($forms && !$force)
225 $forms = self::getFormsForPortal();
229 $forms = self::getFormsViaConnector();
239 protected static function isCrm(): bool
241 return Loader::includeModule(
'crm');
246 $res = Webform\Internals\FormTable::getDefaultTypeList(
248 'select' => self::AVAILABLE_FORM_FIELDS,
253 'cache' => [
'ttl' => 86400],
258 while ($form =
$res->fetch())
260 $form[
'ID'] = (int)$form[
'ID'];
261 $forms[$form[
'ID']] = $form;
270 $client = ApClient::init();
273 $res = $client->call(
'crm.webform.list', [
'GET_INACTIVE' =>
'Y']);
274 if (isset(
$res[
'result']) && is_array(
$res[
'result']))
276 foreach (
$res[
'result'] as $form)
278 $form[
'ID'] = (int)$form[
'ID'];
279 $forms[$form[
'ID']] = $form;
282 else if (isset(
$res[
'error']))
285 'code' =>
$res[
'error'],
286 'message' =>
$res[
'error_description'] ??
$res[
'error'],
300 $forms = self::getFormsByFilter([
'=ID' => $id]);
301 $form = !empty($forms) ? array_shift($forms) :
null;
311 $webpack = Webpack\Form::instance($form[
'ID']);
312 if (!$webpack->isBuilt())
315 $webpack = Webpack\Form::instance($form[
'ID']);
317 $form[
'URL'] = $webpack->getEmbeddedFileUrl();
330 return self::getFormsByFilter([
'=IS_CALLBACK_FORM' =>
'Y',
'=ACTIVE' =>
'Y']);
336 $cacheKey = serialize(
$filter);
337 if (array_key_exists($cacheKey, $cache))
339 return $cache[$cacheKey];
344 static function (
$key)
347 $equalKey = ltrim(
$key,
'=');
349 in_array(
$key, self::AVAILABLE_FORM_FIELDS,
true)
350 || in_array($equalKey, self::AVAILABLE_FORM_FIELDS,
true)
359 $forms = self::getFormsForPortal(
$filter);
363 foreach (self::getFormsViaConnector() as $form)
368 if (!$form[
$key] || $form[
$key] !== $value)
376 $forms[$form[
'ID']] = $form;
381 $cache[$cacheKey] = $forms;
399 if (!isset($manifest[
'assets']) || !is_array($manifest[
'assets']))
401 $manifest[
'assets'] = [];
403 if (!isset($manifest[
'assets'][
'ext']))
405 $manifest[
'assets'][
'ext'] = [];
407 if (!is_array($manifest[
'assets'][
'ext']))
409 $manifest[
'assets'][
'ext'] = [$manifest[
'assets'][
'ext']];
411 if (!in_array(
'landing_form', $manifest[
'assets'][
'ext'],
true))
413 $manifest[
'assets'][
'ext'][] =
'landing_form';
418 !isset($manifest[
'style'][
'block']) && !isset($manifest[
'style'][
'nodes'])
421 $manifest[
'style'] = [
422 'block' => [
'type' => Block::DEFAULT_WRAPPER_STYLE],
423 'nodes' => $manifest[
'style'] ?? [],
426 $manifest[
'style'][
'nodes'][self::SELECTOR_FORM_NODE] = [
427 'type' => self::STYLE_SETTING,
432 $link =
'/crm/webform/';
436 $link =
'/bitrix/admin/b24connector_crm_forms.php?lang=' . LANGUAGE_ID;
440 $manifest[
'block'][
'attrsFormDescription'] =
'<a href="' . $link .
'" target="_blank">' .
441 Loc::getMessage(
'LANDING_BLOCK_FORM_CONFIG') .
446 $manifest[
'callbacks'] = [
447 'afterAdd' =>
function (
Block &$block)
449 $historyActivity = History::isActive();
450 History::deactivate();
452 $dom = $block->getDom();
453 if (!($node = $dom->querySelector(self::SELECTOR_FORM_NODE)))
458 $attrsToSet = [self::ATTR_FORM_EMBED =>
''];
461 $attrsToSet[self::ATTR_FORM_FROM_CONNECTOR] =
'Y';
466 ($attrsExists = $node->getAttributes())
467 && isset($attrsExists[self::ATTR_FORM_PARAMS])
468 && $attrsExists[self::ATTR_FORM_PARAMS]
469 && $attrsExists[self::ATTR_FORM_PARAMS]->getValue()
472 $attrsToSet[self::ATTR_FORM_PARAMS] = $attrsExists[self::ATTR_FORM_PARAMS]->getValue();
477 $forms = self::getFormsByFilter([
478 '=XML_ID' =>
'crm_preset_fb'
480 $forms = self::prepareFormsToAttrs($forms);
483 $forms = self::getForms(
true);
484 $forms = self::prepareFormsToAttrs($forms);
487 $forms = self::createDefaultForm();
488 $forms = self::prepareFormsToAttrs($forms);
494 self::setFormIdParam(
496 str_replace(self::INLINE_MARKER_PREFIX,
'', $forms[0][
'value'])
503 '<div class="g-landing-alert">'
504 . Loc::getMessage(
'LANDING_BLOCK_WEBFORM_PRELOADER')
507 $block->saveContent($dom->saveHTML());
510 $block->setAttributes([self::SELECTOR_FORM_NODE => $attrsToSet]);
513 $historyActivity ? History::activate() : History::deactivate();
519 !array_key_exists(
'attrs', $manifest)
520 || !is_array($manifest[
'attrs'])
523 $manifest[
'attrs'] = [];
527 $manifest[
'attrs'][self::SELECTOR_FORM_NODE] =
528 Landing::getEditMode()
530 : [[
'attribute' => self::ATTR_FORM_PARAMS]];
548 $forms = self::getForms();
549 $forms = self::prepareFormsToAttrs($forms);
553 'name' =>
'Embed form flag',
554 'attribute' => self::ATTR_FORM_EMBED,
559 'name' =>
'Form design',
560 'attribute' => self::ATTR_FORM_STYLE,
565 'name' =>
'Form from connector flag',
566 'attribute' => self::ATTR_FORM_FROM_CONNECTOR,
576 'name' => Loc::getMessage(
'LANDING_BLOCK_WEBFORM'),
577 'attribute' => self::ATTR_FORM_PARAMS,
584 'name' => Loc::getMessage(
'LANDING_BLOCK_WEBFORM_USE_STYLE'),
585 'attribute' => self::ATTR_FORM_USE_STYLE,
589 'name' => Loc::getMessage(
'LANDING_BLOCK_WEBFORM_USE_STYLE_Y'),
593 'name' => Loc::getMessage(
'LANDING_BLOCK_WEBFORM_USE_STYLE_N'),
603 'name' => Loc::getMessage(
'LANDING_BLOCK_WEBFORM'),
604 'attribute' => self::ATTR_FORM_PARAMS,
606 'items' => !empty(self::$errors)
607 ? array_map(fn ($item) => [
'name' => $item[
'message'],
'value' =>
false], self::$errors)
609 'name' => Loc::getMessage(
'LANDING_BLOCK_WEBFORM_NO_FORM'),
626 foreach ($forms as $form)
628 if (array_key_exists(
'ACTIVE', $form) && $form[
'ACTIVE'] !==
'Y')
634 'name' => $form[
'NAME'],
635 'value' => self::INLINE_MARKER_PREFIX . $form[
'ID'],
638 if ($form[
'IS_CALLBACK_FORM'] ===
'Y')
644 array_unshift($sorted, $item);
662 if (empty($landingIds))
667 if (!is_array($landingIds))
669 $landingIds = [$landingIds];
672 return BlockTable::getList(
674 'select' => [
'ID',
'LID'],
676 '=LID' => $landingIds,
678 'CONTENT' =>
'%data-b24form=%',
692 $block =
new Block($blockId);
693 if (preg_match(self::REGEXP_FORM_ID_INLINE, $block->getContent(),
$matches))
708 $block =
new Block($blockId);
709 self::setFormIdParam($block, $formId);
712 return $block->getError()->isEmpty();
722 if (($form = self::getFormById($formId)))
725 $newParam = self::INLINE_MARKER_PREFIX . $form[
'ID'];
728 self::SELECTOR_FORM_NODE => [self::ATTR_FORM_PARAMS => $newParam],
739 if ($formId = self::createForm([]))
741 return self::getFormsByFilter([
'=ID' => $formId]);
755 $form =
new WebForm\Form;
757 $defaultData = WebForm\Preset::getById(
'crm_preset_cd');
759 $defaultData[
'XML_ID'] =
'';
760 $defaultData[
'ACTIVE'] =
'Y';
761 $defaultData[
'IS_SYSTEM'] =
'N';
762 $defaultData[
'IS_CALLBACK_FORM'] =
'N';
763 $defaultData[
'BUTTON_CAPTION'] = $form->getButtonCaption();
765 $agreementId = UserConsent::getDefaultAgreementId();
766 $defaultData[
'USE_LICENCE'] = $agreementId ?
'Y' :
'N';
769 $defaultData[
'LICENCE_BUTTON_IS_CHECKED'] =
'Y';
770 $defaultData[
'AGREEMENT_ID'] = $agreementId;
773 $isLeadEnabled = LeadSettings::getCurrent()->isEnabled();
774 $defaultData[
'ENTITY_SCHEME'] = (string)(
776 ? WebForm\Entity::ENUM_ENTITY_SCHEME_LEAD
777 : WebForm\Entity::ENUM_ENTITY_SCHEME_DEAL
780 $currentUserId = is_object(
$GLOBALS[
'USER']) ?
$GLOBALS[
'USER']->getId() :
null;
781 $defaultData[
'ACTIVE_CHANGE_BY'] = $currentUserId;
782 $defaultData[
'ASSIGNED_BY_ID'] = $currentUserId;
784 $formData = array_merge($defaultData, $formData);
785 $form->merge($formData);
788 return !$form->hasErrors() ? $form->getId() :
null;
800 if (($formData = self::getSpecialFormsData()[$xmlId]))
803 foreach (self::getForms() as $form)
806 array_key_exists(
'XML_ID', $form)
807 && $form[
'XML_ID'] === $xmlId
810 $formId = $form[
'ID'];
817 $formId = self::createForm($formData);
822 self::setFormIdParam($block, $formId);
833 'crm_preset_store_v3' => [
834 'XML_ID' =>
'crm_preset_store_v3',
835 'NAME' => Loc::getMessage(
'LANDING_FORM_SPECIAL_STOREV3_NAME'),
838 'RESULT_SUCCESS_TEXT' => Loc::getMessage(
'LANDING_FORM_SPECIAL_STOREV3_RESULT_SUCCESS'),
839 'RESULT_FAILURE_TEXT' => Loc::getMessage(
'LANDING_FORM_SPECIAL_STOREV3_RESULT_FAILURE'),
840 'COPYRIGHT_REMOVED' =>
'N',
843 'DEAL_DC_ENABLED' =>
'Y',
845 'BUTTON_CAPTION' =>
'',
849 'CODE' =>
'CONTACT_NAME',
850 'CAPTION' => Loc::getMessage(
'LANDING_FORM_SPECIAL_STOREV3_FIELD_NAME'),
858 'CODE' =>
'CONTACT_PHONE',
859 'CAPTION' => Loc::getMessage(
'LANDING_FORM_SPECIAL_STOREV3_FIELD_PHONE'),
867 'CODE' =>
'DEAL_COMMENTS',
868 'CAPTION' => Loc::getMessage(
'LANDING_FORM_SPECIAL_STOREV3_FIELD_COMMENT'),
878 $isLeadEnabled = LeadSettings::getCurrent()->isEnabled();
880 foreach (
$data as $id => $form)
884 foreach (
$data[$id][
'FIELDS'] as
$key => $field)
886 $field[
'CODE'] = str_replace([
'CONTACT',
'DEAL'],
'LEAD', $field[
'CODE']);
907 $res = BlockTable::getList(
918 while ($row =
$res->fetch())
920 $block =
new Block($row[
'ID']);
921 self::updateBlockToEmbed($block);
934 !$manifest[
'block'][
'subtype']
935 || (!is_array($manifest[
'block'][
'subtype']) && $manifest[
'block'][
'subtype'] !==
'form')
936 || (is_array($manifest[
'block'][
'subtype']) && !in_array(
'form', $manifest[
'block'][
'subtype'],
true))
943 !($resultNode = $dom->querySelector(self::SELECTOR_FORM_NODE))
944 || !($attrs = $resultNode->getAttributes())
945 || !array_key_exists(self::ATTR_FORM_PARAMS, $attrs))
949 $formParams = explode(
'|', $attrs[self::ATTR_FORM_PARAMS]->getValue());
950 if (
count($formParams) !== 2 || !(
int)$formParams[0])
956 $forms = self::getForms();
957 if (array_key_exists($formParams[0], $forms))
959 $form = $forms[$formParams[0]];
960 self::setFormIdParam($block, $form[
'ID']);
961 $resultNode->setAttribute(self::ATTR_FORM_EMBED,
'');
962 $resultNode->removeAttribute(self::ATTR_FORM_OLD_DOMAIN);
963 $resultNode->removeAttribute(self::ATTR_FORM_OLD_HEADER);
966 !array_key_exists(self::ATTR_FORM_STYLE, $attrs)
967 || !$attrs[self::ATTR_FORM_STYLE]->getValue()
971 $contentFromRepo = Block::getContentFromRepository($block->
getCode());
974 && preg_match(self::REGEXP_FORM_STYLE, $contentFromRepo, $style)
977 $resultNode->setAttribute(self::ATTR_FORM_STYLE, $style[1]);
982 if (($oldStyleNode = $dom->querySelector(self::SELECTOR_OLD_STYLE_NODE)))
984 $oldStyleNode->getParentNode()->removeChild($oldStyleNode);
999 "Now using embedded forms, no need domain",
save(array $additionalFields=[])
saveContent(string $content, $designed=false)
getManifest(bool $extended=false, bool $missCache=false, array $params=array())
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
$GLOBALS['____1690880296']
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
if(empty($signedUserToken)) $key
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']