Advertisement
Guest User

Untitled

a guest
Jul 22nd, 2018
1,004
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 174.15 KB | None | 0 0
  1. <?php
  2. use Bitrix\Main,
  3.     Bitrix\Main\Loader,
  4.     Bitrix\Main\Config\Option,
  5.     Bitrix\Main\Web\Json,
  6.     Bitrix\Main\Localization\Loc,
  7.     Bitrix\Sale,
  8.     Bitrix\Sale\Order,
  9.     Bitrix\Sale\PersonType,
  10.     Bitrix\Sale\Shipment,
  11.     Bitrix\Sale\PaySystem,
  12.     Bitrix\Sale\Payment,
  13.     Bitrix\Sale\Delivery,
  14.     Bitrix\Sale\Location\LocationTable,
  15.     Bitrix\Sale\Result,
  16.     Bitrix\Sale\DiscountCouponsManager,
  17.     Bitrix\Sale\Services\Company,
  18.     Bitrix\Sale\Location\GeoIp;
  19.  
  20. if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) die();
  21.  
  22. /**
  23.  * @var $APPLICATION CMain
  24.  * @var $USER CUser
  25.  */
  26.  
  27. Loc::loadMessages(__FILE__);
  28.  
  29. if (!Loader::includeModule("sale"))
  30. {
  31.     ShowError(Loc::getMessage("SOA_MODULE_NOT_INSTALL"));
  32.     return;
  33. }
  34.  
  35. class SaleOrderAjax extends \CBitrixComponent
  36. {
  37.     const AUTH_BLOCK = 'AUTH';
  38.     const REGION_BLOCK = 'REGION';
  39.     const PAY_SYSTEM_BLOCK = 'PAY_SYSTEM';
  40.     const DELIVERY_BLOCK = 'DELIVERY';
  41.     const PROPERTY_BLOCK = 'PROPERTY';
  42.  
  43.     /** @var Order $order */
  44.     protected $order;
  45.     /** @var Sale\Basket\Storage $basketStorage */
  46.     protected $basketStorage;
  47.  
  48.     protected $action;
  49.     protected $arUserResult;
  50.     protected $isOrderConfirmed;
  51.     protected $arCustomSelectFields = array();
  52.     protected $arElementId = array();
  53.     protected $arSku2Parent = array();
  54.     /** @var Delivery\Services\Base[] $arDeliveryServiceAll */
  55.     protected $arDeliveryServiceAll = array();
  56.     protected $arPaySystemServiceAll = array();
  57.     protected $arActivePaySystems = array();
  58.     protected $arIblockProps = array();
  59.     /** @var  PaySystem\Service $prePaymentService */
  60.     protected $prePaymentService;
  61.     protected $useCatalog;
  62.     /** @var Main\Context $context*/
  63.     protected $context;
  64.     protected $checkSession = true;
  65.     protected $isRequestViaAjax;
  66.    
  67.    
  68.    
  69.  
  70.     public function onPrepareComponentParams($arParams)
  71.     {
  72.        
  73.        
  74.         global $APPLICATION;
  75.  
  76.         $this->useCatalog = Loader::includeModule('catalog');
  77.  
  78.         if (!isset($arParams['COMPATIBLE_MODE']) && $this->initComponentTemplate())
  79.         {
  80.             $template = $this->getTemplate();
  81.  
  82.             if (
  83.                 $template instanceof CBitrixComponentTemplate
  84.                 && $template->GetSiteTemplate() == ''
  85.                 && $template->GetName() === '.default'
  86.             )
  87.             {
  88.                 $arParams['COMPATIBLE_MODE'] = 'N';
  89.             }
  90.             else
  91.             {
  92.                 $arParams['COMPATIBLE_MODE'] = 'Y';
  93.             }
  94.         }
  95.         else
  96.         {
  97.             $arParams['COMPATIBLE_MODE'] = $arParams['COMPATIBLE_MODE'] === 'N' ? 'N' : 'Y';
  98.         }
  99.  
  100.         $arParams['USE_PRELOAD'] = $arParams['USE_PRELOAD'] === 'N' ? 'N' : 'Y';
  101.  
  102.         if ($arParams['SET_TITLE'] === 'Y')
  103.         {
  104.             $APPLICATION->SetTitle(Loc::getMessage('SOA_TITLE'));
  105.         }
  106.  
  107.         $arParams['ACTION_VARIABLE'] = isset($arParams['ACTION_VARIABLE']) ? trim($arParams['ACTION_VARIABLE']) : '';
  108.         if ($arParams['ACTION_VARIABLE'] == '')
  109.         {
  110.             $arParams['ACTION_VARIABLE'] = 'soa-action';
  111.         }
  112.  
  113.         $arParams['PATH_TO_BASKET'] = isset($arParams['PATH_TO_BASKET']) ? trim($arParams['PATH_TO_BASKET']) : '';
  114.         if ($arParams['PATH_TO_BASKET'] == '')
  115.         {
  116.             $arParams['PATH_TO_BASKET'] = '/personal/cart/';
  117.         }
  118.  
  119.         $arParams['PATH_TO_PERSONAL'] = isset($arParams['PATH_TO_PERSONAL']) ? trim($arParams['PATH_TO_PERSONAL']) : '';
  120.         if ($arParams['PATH_TO_PERSONAL'] == '')
  121.         {
  122.             $arParams['PATH_TO_PERSONAL'] = 'index.php';
  123.         }
  124.  
  125.         $arParams['PATH_TO_PAYMENT'] = isset($arParams['PATH_TO_PAYMENT']) ? trim($arParams['PATH_TO_PAYMENT']) : '';
  126.         if ($arParams['PATH_TO_PAYMENT'] == '')
  127.         {
  128.             $arParams['PATH_TO_PAYMENT'] = 'payment.php';
  129.         }
  130.  
  131.         $arParams['PATH_TO_AUTH'] = isset($arParams['PATH_TO_AUTH']) ? trim($arParams['PATH_TO_AUTH']) : '';
  132.         if ($arParams['PATH_TO_AUTH'] == '')
  133.         {
  134.             $arParams['PATH_TO_AUTH'] = '/auth/';
  135.         }
  136.  
  137.         $arParams['PAY_FROM_ACCOUNT'] = $arParams['PAY_FROM_ACCOUNT'] === 'Y' ? 'Y' : 'N';
  138.         $arParams['COUNT_DELIVERY_TAX'] = $arParams['COUNT_DELIVERY_TAX'] === 'Y' ? 'Y' : 'N';
  139.         $arParams['ONLY_FULL_PAY_FROM_ACCOUNT'] = $arParams['ONLY_FULL_PAY_FROM_ACCOUNT'] === 'Y' ? 'Y' : 'N';
  140.         $arParams['USE_PREPAYMENT'] = $arParams['USE_PREPAYMENT'] === 'Y' ? 'Y' : 'N';
  141.         $arParams['DISPLAY_IMG_HEIGHT'] = intval($arParams['DISPLAY_IMG_HEIGHT']) <= 0 ? 90 : intval($arParams['DISPLAY_IMG_HEIGHT']);
  142.         $arParams['SHOW_VAT_PRICE'] = $arParams['SHOW_VAT_PRICE'] === 'N' ? 'N' : 'Y';
  143.         $arParams['DELIVERY_TO_PAYSYSTEM'] = $arParams['DELIVERY_TO_PAYSYSTEM'] === 'p2d' ? 'p2d' : 'd2p';
  144.  
  145.         if (!isset($arParams['DISABLE_BASKET_REDIRECT']) || $arParams['DISABLE_BASKET_REDIRECT'] !== 'Y')
  146.         {
  147.             $arParams['DISABLE_BASKET_REDIRECT'] = 'N';
  148.         }
  149.  
  150.         $arParams['ALLOW_AUTO_REGISTER'] = $arParams['ALLOW_AUTO_REGISTER'] === 'Y' ? 'Y' : 'N';
  151.         $arParams['CURRENT_PAGE'] = $APPLICATION->GetCurPage();
  152.  
  153.         $this->arResult = array(
  154.             'PERSON_TYPE' => array(),
  155.             'PAY_SYSTEM' => array(),
  156.             'ORDER_PROP' => array(),
  157.             'DELIVERY' => array(),
  158.             'TAX' => array(),
  159.             'ERROR' => array(),
  160.             'ERROR_SORTED' => array(),
  161.             'WARNING' => array(),
  162.             'JS_DATA' => array(),
  163.             'SHOW_EMPTY_BASKET' => false,
  164.             'ORDER_PRICE' => 0,
  165.             'ORDER_WEIGHT' => 0,
  166.             'VATE_RATE' => 0,
  167.             'VAT_SUM' => 0,
  168.             'bUsingVat' => false,
  169.             'BASKET_ITEMS' => array(),
  170.             'BASE_LANG_CURRENCY' => Bitrix\Sale\Internals\SiteCurrencyTable::getSiteCurrency(SITE_ID),
  171.             'WEIGHT_UNIT' => htmlspecialcharsbx(Option::get('sale', 'weight_unit', false, SITE_ID)),
  172.             'WEIGHT_KOEF' => htmlspecialcharsbx(Option::get('sale', 'weight_koef', 1, SITE_ID)),
  173.             'TaxExempt' => array(),
  174.             'DISCOUNT_PRICE' => 0,
  175.             'DISCOUNT_PERCENT' => 0,
  176.             'DELIVERY_PRICE' => 0,
  177.             'TAX_PRICE' => 0,
  178.             'PAYED_FROM_ACCOUNT_FORMATED' => false,
  179.             'ORDER_TOTAL_PRICE_FORMATED' => false,
  180.             'ORDER_WEIGHT_FORMATED' => false,
  181.             'ORDER_PRICE_FORMATED' => false,
  182.             'VAT_SUM_FORMATED' => false,
  183.             'DELIVERY_SUM' => false,
  184.             'DELIVERY_PROFILE_SUM' => false,
  185.             'DELIVERY_PRICE_FORMATED' => false,
  186.             'DISCOUNT_PERCENT_FORMATED' => false,
  187.             'PAY_FROM_ACCOUNT' => false,
  188.             'CURRENT_BUDGET_FORMATED' => false,
  189.             'DISCOUNTS' => array(),
  190.             'AUTH' => array(),
  191.             'HAVE_PREPAYMENT' => false,
  192.             'PREPAY_PS' => array(),
  193.             'PREPAY_ADIT_FIELDS' => '',
  194.             'PREPAY_ORDER_PROPS' => array(),
  195.         );
  196.  
  197.         $this->arResult['AUTH']['new_user_registration_email_confirmation'] = Option::get('main', 'new_user_registration_email_confirmation', 'N', SITE_ID) === 'Y' ? 'Y' : 'N';
  198.         $this->arResult['AUTH']['new_user_registration'] = Option::get('main', 'new_user_registration', 'Y') === 'Y' ? 'Y' : 'N';
  199.         $this->arResult['AUTH']['new_user_email_required'] = Option::get('main', 'new_user_email_required', '') === 'Y' ? 'Y' : 'N';
  200.  
  201.         if (
  202.             $arParams['ALLOW_AUTO_REGISTER'] === 'Y'
  203.             && (
  204.                 $this->arResult['AUTH']['new_user_registration_email_confirmation'] === 'Y'
  205.                 || $this->arResult['AUTH']['new_user_registration'] === 'N'
  206.             )
  207.         )
  208.         {
  209.             $arParams['ALLOW_AUTO_REGISTER'] = 'N';
  210.         }
  211.  
  212.         $arParams['ALLOW_APPEND_ORDER'] = $arParams['ALLOW_APPEND_ORDER'] === 'N' ? 'N' : 'Y';
  213.         $arParams['SEND_NEW_USER_NOTIFY'] = $arParams['SEND_NEW_USER_NOTIFY'] === 'N' ? 'N' : 'Y';
  214.         $arParams['ALLOW_NEW_PROFILE'] = $arParams['ALLOW_NEW_PROFILE'] === 'N' ? 'N' : 'Y';
  215.         $arParams['DELIVERY_NO_SESSION'] = $arParams['DELIVERY_NO_SESSION'] === 'N' ? 'N' : 'Y';
  216.  
  217.         if (!isset($arParams['DELIVERY_NO_AJAX']) || !in_array($arParams['DELIVERY_NO_AJAX'], array('Y', 'N', 'H')))
  218.         {
  219.             $arParams['DELIVERY_NO_AJAX'] = 'N';
  220.         }
  221.  
  222.         if (
  223.             !isset($arParams['SHOW_NOT_CALCULATED_DELIVERIES'])
  224.             || !in_array($arParams['SHOW_NOT_CALCULATED_DELIVERIES'], array('N', 'L', 'Y'))
  225.         )
  226.         {
  227.             $arParams['SHOW_NOT_CALCULATED_DELIVERIES'] = 'L';
  228.         }
  229.  
  230.         if ($arParams['DELIVERY_NO_AJAX'] !== 'Y')
  231.         {
  232.             $arParams['SHOW_NOT_CALCULATED_DELIVERIES'] = 'Y';
  233.         }
  234.  
  235.         //compatibility to old default columns in basket
  236.         if (!empty($arParams['PRODUCT_COLUMNS_VISIBLE']))
  237.         {
  238.             $arParams['PRODUCT_COLUMNS'] = $arParams['PRODUCT_COLUMNS_VISIBLE'];
  239.         }
  240.         else
  241.         {
  242.             if (!isset($arParams['PRODUCT_COLUMNS_VISIBLE']) && !isset($arParams['PRODUCT_COLUMNS']))
  243.             {
  244.                 $arParams['PRODUCT_COLUMNS'] = array('PREVIEW_PICTURE', 'PROPS');
  245.             }
  246.             elseif (!isset($arParams['PRODUCT_COLUMNS_VISIBLE']) && is_array($arParams['PRODUCT_COLUMNS']))
  247.             {
  248.                 if (!empty($arParams['PRODUCT_COLUMNS']))
  249.                 {
  250.                     $arParams['PRODUCT_COLUMNS'] = array_merge($arParams['PRODUCT_COLUMNS'], array('PRICE_FORMATED'));
  251.                 }
  252.                 else
  253.                 {
  254.                     $arParams['PRODUCT_COLUMNS'] = array('PROPS', 'DISCOUNT_PRICE_PERCENT_FORMATED', 'PRICE_FORMATED');
  255.                 }
  256.             }
  257.  
  258.             $arParams['PRODUCT_COLUMNS_VISIBLE'] = $arParams['PRODUCT_COLUMNS'];
  259.         }
  260.  
  261.         $arDefaults = array('PROPS', 'DISCOUNT_PRICE_PERCENT_FORMATED', 'PRICE_FORMATED');
  262.         $arDiff = array();
  263.         if (!empty($arParams['PRODUCT_COLUMNS']) && is_array($arParams['PRODUCT_COLUMNS']))
  264.         {
  265.             $arDiff = array_diff($arParams['PRODUCT_COLUMNS'], $arDefaults);
  266.         }
  267.  
  268.         $this->arResult['GRID']['DEFAULT_COLUMNS'] = count($arParams['PRODUCT_COLUMNS']) > 2 && empty($arDiff);
  269.  
  270.         if (empty($arParams['PRODUCT_COLUMNS']))
  271.         {
  272.             $arParams['PRODUCT_COLUMNS'] = array(
  273.                 'NAME' => Loc::getMessage('SOA_NAME_DEFAULT_COLUMN'),
  274.                 'QUANTITY' => Loc::getMessage('SOA_QUANTITY_DEFAULT_COLUMN'),
  275.                 'SUM' => Loc::getMessage('SOA_SUM_DEFAULT_COLUMN')
  276.             );
  277.         }
  278.         else
  279.         {
  280.             // processing default or certain iblock fields if they are selected
  281.             if (($key = array_search('PREVIEW_TEXT', $arParams['PRODUCT_COLUMNS'])) !== false)
  282.             {
  283.                 unset($arParams['PRODUCT_COLUMNS'][$key]);
  284.                 $arParams['PRODUCT_COLUMNS']['PREVIEW_TEXT'] = Loc::getMessage('SOA_NAME_COLUMN_PREVIEW_TEXT');
  285.             }
  286.  
  287.             if (($key = array_search('PREVIEW_PICTURE', $arParams['PRODUCT_COLUMNS'])) !== false)
  288.             {
  289.                 unset($arParams['PRODUCT_COLUMNS'][$key]);
  290.                 $arParams['PRODUCT_COLUMNS']['PREVIEW_PICTURE'] = Loc::getMessage('SOA_NAME_COLUMN_PREVIEW_PICTURE');
  291.             }
  292.  
  293.             if (($key = array_search('DETAIL_PICTURE', $arParams['PRODUCT_COLUMNS'])) !== false)
  294.             {
  295.                 unset($arParams['PRODUCT_COLUMNS'][$key]);
  296.                 $arParams['PRODUCT_COLUMNS']['DETAIL_PICTURE'] = Loc::getMessage('SOA_NAME_COLUMN_DETAIL_PICTURE');
  297.             }
  298.  
  299.             if (($key = array_search('PROPS', $arParams['PRODUCT_COLUMNS'])) !== false)
  300.             {
  301.                 unset($arParams['PRODUCT_COLUMNS'][$key]);
  302.                 $arParams['PRODUCT_COLUMNS']['PROPS'] = Loc::getMessage('SOA_PROPS_DEFAULT_COLUMN');
  303.             }
  304.  
  305.             if (($key = array_search('NOTES', $arParams['PRODUCT_COLUMNS'])) !== false)
  306.             {
  307.                 unset($arParams['PRODUCT_COLUMNS'][$key]);
  308.                 $arParams['PRODUCT_COLUMNS']['NOTES'] = Loc::getMessage('SOA_PRICE_TYPE_DEFAULT_COLUMN');
  309.             }
  310.  
  311.             if (($key = array_search('DISCOUNT_PRICE_PERCENT_FORMATED', $arParams['PRODUCT_COLUMNS'])) !== false)
  312.             {
  313.                 unset($arParams['PRODUCT_COLUMNS'][$key]);
  314.                 $arParams['PRODUCT_COLUMNS']['DISCOUNT_PRICE_PERCENT_FORMATED'] = Loc::getMessage('SOA_DISCOUNT_DEFAULT_COLUMN');
  315.             }
  316.  
  317.             if (($key = array_search('PRICE_FORMATED', $arParams['PRODUCT_COLUMNS'])) !== false)
  318.             {
  319.                 unset($arParams['PRODUCT_COLUMNS'][$key]);
  320.                 $arParams['PRODUCT_COLUMNS']['PRICE_FORMATED'] = Loc::getMessage('SOA_PRICE_DEFAULT_COLUMN');
  321.             }
  322.  
  323.             if (($key = array_search('WEIGHT_FORMATED', $arParams['PRODUCT_COLUMNS'])) !== false)
  324.             {
  325.                 unset($arParams['PRODUCT_COLUMNS'][$key]);
  326.                 $arParams['PRODUCT_COLUMNS']['WEIGHT_FORMATED'] = Loc::getMessage('SOA_WEIGHT_DEFAULT_COLUMN');
  327.             }
  328.         }
  329.  
  330.         if (!empty($arParams['PRODUCT_COLUMNS_HIDDEN']))
  331.         {
  332.             // processing default or certain iblock fields if they are selected
  333.             if (($key = array_search('PREVIEW_TEXT', $arParams['PRODUCT_COLUMNS_HIDDEN'])) !== false)
  334.             {
  335.                 unset($arParams['PRODUCT_COLUMNS_HIDDEN'][$key]);
  336.                 $arParams['PRODUCT_COLUMNS_HIDDEN']['PREVIEW_TEXT'] = Loc::getMessage('SOA_NAME_COLUMN_PREVIEW_TEXT');
  337.             }
  338.  
  339.             if (($key = array_search('PREVIEW_PICTURE', $arParams['PRODUCT_COLUMNS_HIDDEN'])) !== false)
  340.             {
  341.                 unset($arParams['PRODUCT_COLUMNS_HIDDEN'][$key]);
  342.                 $arParams['PRODUCT_COLUMNS_HIDDEN']['PREVIEW_PICTURE'] = Loc::getMessage('SOA_NAME_COLUMN_PREVIEW_PICTURE');
  343.             }
  344.  
  345.             if (($key = array_search('DETAIL_PICTURE', $arParams['PRODUCT_COLUMNS_HIDDEN'])) !== false)
  346.             {
  347.                 unset($arParams['PRODUCT_COLUMNS_HIDDEN'][$key]);
  348.                 $arParams['PRODUCT_COLUMNS_HIDDEN']['DETAIL_PICTURE'] = Loc::getMessage('SOA_NAME_COLUMN_DETAIL_PICTURE');
  349.             }
  350.  
  351.             if (($key = array_search('PROPS', $arParams['PRODUCT_COLUMNS_HIDDEN'])) !== false)
  352.             {
  353.                 unset($arParams['PRODUCT_COLUMNS_HIDDEN'][$key]);
  354.                 $arParams['PRODUCT_COLUMNS_HIDDEN']['PROPS'] = Loc::getMessage('SOA_PROPS_DEFAULT_COLUMN');
  355.             }
  356.  
  357.             if (($key = array_search('NOTES', $arParams['PRODUCT_COLUMNS_HIDDEN'])) !== false)
  358.             {
  359.                 unset($arParams['PRODUCT_COLUMNS_HIDDEN'][$key]);
  360.                 $arParams['PRODUCT_COLUMNS_HIDDEN']['NOTES'] = Loc::getMessage('SOA_PRICE_TYPE_DEFAULT_COLUMN');
  361.             }
  362.  
  363.             if (($key = array_search('DISCOUNT_PRICE_PERCENT_FORMATED', $arParams['PRODUCT_COLUMNS_HIDDEN'])) !== false)
  364.             {
  365.                 unset($arParams['PRODUCT_COLUMNS_HIDDEN'][$key]);
  366.                 $arParams['PRODUCT_COLUMNS_HIDDEN']['DISCOUNT_PRICE_PERCENT_FORMATED'] = Loc::getMessage('SOA_DISCOUNT_DEFAULT_COLUMN');
  367.             }
  368.  
  369.             if (($key = array_search('PRICE_FORMATED', $arParams['PRODUCT_COLUMNS_HIDDEN'])) !== false)
  370.             {
  371.                 unset($arParams['PRODUCT_COLUMNS_HIDDEN'][$key]);
  372.                 $arParams['PRODUCT_COLUMNS_HIDDEN']['PRICE_FORMATED'] = Loc::getMessage('SOA_PRICE_DEFAULT_COLUMN');
  373.             }
  374.  
  375.             if (($key = array_search('WEIGHT_FORMATED', $arParams['PRODUCT_COLUMNS_HIDDEN'])) !== false)
  376.             {
  377.                 unset($arParams['PRODUCT_COLUMNS_HIDDEN'][$key]);
  378.                 $arParams['PRODUCT_COLUMNS_HIDDEN']['WEIGHT_FORMATED'] = Loc::getMessage('SOA_WEIGHT_DEFAULT_COLUMN');
  379.             }
  380.         }
  381.  
  382.         // required grid columns
  383.         if (empty($arParams['PRODUCT_COLUMNS']['NAME']))
  384.         {
  385.             $arParams['PRODUCT_COLUMNS'] = array('NAME' => Loc::getMessage('SOA_NAME_DEFAULT_COLUMN')) + $arParams['PRODUCT_COLUMNS'];
  386.         }
  387.  
  388.         if (empty($arParams['PRODUCT_COLUMNS']['QUANTITY']))
  389.         {
  390.             $arParams['PRODUCT_COLUMNS']['QUANTITY'] = Loc::getMessage('SOA_QUANTITY_DEFAULT_COLUMN');
  391.         }
  392.  
  393.         if (empty($arParams['PRODUCT_COLUMNS']['SUM']))
  394.         {
  395.             $arParams['PRODUCT_COLUMNS']['SUM'] = Loc::getMessage('SOA_SUM_DEFAULT_COLUMN');
  396.         }
  397.  
  398.         foreach ($arParams as $k => $v)
  399.         {
  400.             if (strpos($k, 'ADDITIONAL_PICT_PROP_') !== false)
  401.             {
  402.                 $iblockId = intval(substr($k, strlen('ADDITIONAL_PICT_PROP_')));
  403.  
  404.                 if ($v !== '-')
  405.                 {
  406.                     $arParams['ADDITIONAL_PICT_PROP'][$iblockId] = $v;
  407.                 }
  408.  
  409.                 unset($arParams[$k]);
  410.             }
  411.         }
  412.  
  413.         if (!isset($arParams['BASKET_IMAGES_SCALING']) || !in_array($arParams['BASKET_IMAGES_SCALING'], array('standard', 'adaptive', 'no_scale')))
  414.         {
  415.             $arParams['BASKET_IMAGES_SCALING'] = 'adaptive';
  416.         }
  417.  
  418.         return $arParams;
  419.     }
  420.  
  421.     /**
  422.      * Returns array of order properties from request
  423.      *
  424.      * @return array
  425.      */
  426.     protected function getPropertyValuesFromRequest()
  427.     {
  428.         $orderProperties = array();
  429.  
  430.         foreach ($this->request as $k => $v)
  431.         {
  432.             if (strpos($k, "ORDER_PROP_") !== false)
  433.             {
  434.                 if (strpos($k, "[]") !== false)
  435.                     $orderPropId = intval(substr($k, strlen("ORDER_PROP_"), strlen($k) - 2));
  436.                 else
  437.                     $orderPropId = intval(substr($k, strlen("ORDER_PROP_")));
  438.  
  439.                 if ($orderPropId > 0)
  440.                     $orderProperties[$orderPropId] = $v;
  441.             }
  442.         }
  443.  
  444.         foreach ($this->request->getFileList() as $k => $arFileData)
  445.         {
  446.             if (strpos($k, "ORDER_PROP_") !== false)
  447.             {
  448.                 $orderPropId = intval(substr($k, strlen("ORDER_PROP_")));
  449.  
  450.                 if (is_array($arFileData))
  451.                 {
  452.                     foreach ($arFileData as $param_name => $value)
  453.                     {
  454.                         if (is_array($value))
  455.                         {
  456.                             foreach ($value as $nIndex => $val)
  457.                             {
  458.                                 if (strlen($arFileData["name"][$nIndex]) > 0)
  459.                                     $orderProperties[$orderPropId][$nIndex][$param_name] = $val;
  460.                             }
  461.                         }
  462.                         else
  463.                             $orderProperties[$orderPropId][$param_name] = $value;
  464.                     }
  465.                 }
  466.             }
  467.         }
  468.  
  469.         return $orderProperties;
  470.     }
  471.  
  472.     protected function getBasketStorage()
  473.     {
  474.         if (!isset($this->basketStorage))
  475.         {
  476.             $this->basketStorage = Sale\Basket\Storage::getInstance(Sale\Fuser::getId(), Main\Context::getCurrent()->getSite());
  477.         }
  478.  
  479.         return $this->basketStorage;
  480.     }
  481.  
  482.     protected function getLastOrderData(Order $order)
  483.     {
  484.         $lastOrderData = array();
  485.  
  486.         $filter = array(
  487.             'filter' => array(
  488.                 'USER_ID' => $order->getUserId(),
  489.                 'LID' => $order->getSiteId()
  490.             ),
  491.             'select' => array('ID'),
  492.             'order' => array('ID' => 'DESC'),
  493.             'limit' => 1
  494.         );
  495.  
  496.         if ($arOrder = Order::getList($filter)->fetch())
  497.         {
  498.             /** @var Order $lastOrder */
  499.             $lastOrder = Order::load($arOrder['ID']);
  500.             $lastOrderData['PERSON_TYPE_ID'] = $lastOrder->getPersonTypeId();
  501.  
  502.             if ($payment = $this->getInnerPayment($lastOrder))
  503.                 $lastOrderData['PAY_CURRENT_ACCOUNT'] = 'Y';
  504.  
  505.             if ($payment = $this->getExternalPayment($lastOrder))
  506.                 $lastOrderData['PAY_SYSTEM_ID'] = $payment->getPaymentSystemId();
  507.  
  508.             if ($shipment = $this->getCurrentShipment($lastOrder))
  509.             {
  510.                 $lastOrderData['DELIVERY_ID'] = $shipment->getDeliveryId();
  511.                 $lastOrderData['BUYER_STORE'] = $shipment->getStoreId();
  512.                 $lastOrderData['DELIVERY_EXTRA_SERVICES'][$shipment->getDeliveryId()] = $shipment->getExtraServices();
  513.                 if ($storeFields = Delivery\ExtraServices\Manager::getStoresFields($lastOrderData['DELIVERY_ID'], false))
  514.                     unset($lastOrderData['DELIVERY_EXTRA_SERVICES'][$shipment->getDeliveryId()][$storeFields['ID']]);
  515.             }
  516.         }
  517.  
  518.         return $lastOrderData;
  519.     }
  520.  
  521.     protected function initLastOrderData(Order $order)
  522.     {
  523.         global $USER;
  524.  
  525.         if (
  526.             ($this->request->getRequestMethod() === 'GET' || $this->request->get('do_authorize') === 'Y' || $this->request->get('do_register') === 'Y')
  527.             && $this->arUserResult['USE_PRELOAD']
  528.             && $USER->IsAuthorized()
  529.         )
  530.         {
  531.             $showData = array();
  532.             $lastOrderData = $this->getLastOrderData($order);
  533.  
  534.             if (!empty($lastOrderData))
  535.             {
  536.                 if (!empty($lastOrderData['PERSON_TYPE_ID']))
  537.                     $this->arUserResult['PERSON_TYPE_ID'] = $showData['PERSON_TYPE_ID'] = $lastOrderData['PERSON_TYPE_ID'];
  538.  
  539.                 if (!empty($lastOrderData['PAY_CURRENT_ACCOUNT']))
  540.                     $this->arUserResult['PAY_CURRENT_ACCOUNT'] = $showData['PAY_CURRENT_ACCOUNT'] = $lastOrderData['PAY_CURRENT_ACCOUNT'];
  541.  
  542.                 if (!empty($lastOrderData['PAY_SYSTEM_ID']))
  543.                     $this->arUserResult['PAY_SYSTEM_ID'] = $showData['PAY_SYSTEM_ID'] = $lastOrderData['PAY_SYSTEM_ID'];
  544.  
  545.                 if (!empty($lastOrderData['DELIVERY_ID']))
  546.                     $this->arUserResult['DELIVERY_ID'] = $showData['DELIVERY_ID'] = $lastOrderData['DELIVERY_ID'];
  547.  
  548.                 if (!empty($lastOrderData['DELIVERY_EXTRA_SERVICES']))
  549.                     $this->arUserResult['DELIVERY_EXTRA_SERVICES'] = $showData['DELIVERY_EXTRA_SERVICES'] = $lastOrderData['DELIVERY_EXTRA_SERVICES'];
  550.  
  551.                 if (!empty($lastOrderData['BUYER_STORE']))
  552.                     $this->arUserResult['BUYER_STORE'] = $showData['BUYER_STORE'] = $lastOrderData['BUYER_STORE'];
  553.  
  554.                 $this->arUserResult['LAST_ORDER_DATA'] = $showData;
  555.             }
  556.         }
  557.     }
  558.  
  559.     /**
  560.      * Initialization of order properties from request, user profile, default values.
  561.      * Checking properties (if saving order) and setting to order.
  562.      * Execution of 'OnSaleComponentOrderProperties' event.
  563.      *
  564.      * @param Order $order
  565.      * @param       $isPersonTypeChanged
  566.      * @throws Main\ArgumentException
  567.      */
  568.     protected function initProperties(Order $order, $isPersonTypeChanged)
  569.     {
  570.         $arResult =& $this->arResult;
  571.         $orderProperties = $this->getPropertyValuesFromRequest();
  572.  
  573.         $this->initUserProfiles($order, $isPersonTypeChanged);
  574.  
  575.         $firstLoad = $this->request->getRequestMethod() === 'GET';
  576.         $isProfileChanged = $this->arUserResult['PROFILE_CHANGE'] === 'Y';
  577.  
  578.         $loadFromProfile = $firstLoad || $isProfileChanged || $isPersonTypeChanged;
  579.         $justAuthorized = $this->request->get('do_authorize') === 'Y' || $this->request->get('do_register') === 'Y';
  580.         $haveProfileId = intval($this->arUserResult['PROFILE_ID']) > 0;
  581.         $useProfileProperties = ($loadFromProfile || $justAuthorized) && $haveProfileId;
  582.  
  583.         $profileProperties = array();
  584.  
  585.         if ($haveProfileId)
  586.         {
  587.             $profileProperties = Sale\OrderUserProperties::getProfileValues((int)$this->arUserResult['PROFILE_ID']);
  588.         }
  589.  
  590.         $ipAddress = '';
  591.  
  592.         if($this->arParams['SPOT_LOCATION_BY_GEOIP'] === 'Y')
  593.             $ipAddress = \Bitrix\Main\Service\GeoIp\Manager::getRealIp();
  594.  
  595.         $propertyCollection = $order->getPropertyCollection();
  596.         /** @var Sale\PropertyValue $property */
  597.        
  598.         global $USER;
  599.        
  600.         $rsUser = CUser::GetByID($USER->getID());
  601.         $arUser = $rsUser->Fetch();
  602.        
  603.         if(CUser::GetFullName()){
  604.             $profileProperties[1] = CUser::GetFullName();
  605.         }
  606.        
  607.         if($arUser["EMAIL"]){
  608.             $profileProperties[2] = $arUser["EMAIL"];
  609.         }
  610.        
  611.         if($arUser["PERSONAL_PHONE"]){
  612.             $profileProperties[3] = substr($arUser["PERSONAL_PHONE"], 2);
  613.         }
  614.        
  615.         if($arUser["PERSONAL_CITY"]){
  616.             $profileProperties[6] = $arUser["PERSONAL_CITY"];
  617.         }
  618.        
  619.         if($arUser["PERSONAL_STREET"]){
  620.             $profileProperties[7] = $arUser["PERSONAL_STREET"];
  621.         }
  622.        
  623.        
  624.         foreach ($propertyCollection as $property)
  625.         {
  626.        
  627.             if ($property->isUtil())
  628.                 continue;
  629.  
  630.             $arProperty = $property->getProperty();
  631.            
  632.             if($arProperty["CODE"] == "ADDRESS"){
  633.                 $arProperty["DEFAULT_VALUE"] = $arUser["PERSONAL_STREET"];
  634.             }
  635.            
  636.            
  637.             if ($arProperty['USER_PROPS'] === 'Y')
  638.             {
  639.                 if ($isProfileChanged && !$haveProfileId)
  640.                 {
  641.                     $curVal = '';
  642.                 }
  643.                 elseif (
  644.                     $useProfileProperties
  645.                     || (!isset($orderProperties[$arProperty['ID']]) && isset($profileProperties[$arProperty['ID']]))
  646.                 )
  647.                 {
  648.                     $curVal = $profileProperties[$arProperty['ID']];
  649.                    
  650.                    
  651.                    
  652.                 }
  653.                 elseif (isset($orderProperties[$arProperty['ID']]))
  654.                 {
  655.                     $curVal = $orderProperties[$arProperty['ID']];
  656.                 }
  657.                 else
  658.                 {
  659.                     $curVal = '';
  660.                 }
  661.             }
  662.             else
  663.             {
  664.                 $curVal = $orderProperties[$arProperty['ID']];
  665.             }
  666.            
  667.            
  668.             if ($arResult['HAVE_PREPAYMENT'] && !empty($arResult['PREPAY_ORDER_PROPS'][$arProperty['CODE']]))
  669.             {
  670.                 if ($arProperty['TYPE'] === 'LOCATION')
  671.                 {
  672.                     $cityName = ToUpper($arResult['PREPAY_ORDER_PROPS'][$arProperty['CODE']]);
  673.                     $arLocation = LocationTable::getList(array(
  674.                         'select' => array('CODE'),
  675.                         'filter' => array('NAME.NAME_UPPER' => $cityName),
  676.                     ))->fetch();
  677.                     if (!empty($arLocation))
  678.                     {
  679.                         $curVal = $arLocation['CODE'];
  680.                     }
  681.                 }
  682.                 else
  683.                 {
  684.                     $curVal = $arResult['PREPAY_ORDER_PROPS'][$arProperty['CODE']];
  685.                 }
  686.             }
  687.            
  688.            
  689.             if ($arProperty['TYPE'] === 'LOCATION' && empty($curVal) && !empty($ipAddress))
  690.             {
  691.                 $locCode = GeoIp::getLocationCode($ipAddress, LANGUAGE_ID);
  692.                
  693.                 if($arUser["PERSONAL_CITY"]){
  694.                     $curVal = $arUser["PERSONAL_CITY"];
  695.                 }else{
  696.                     if (!empty($locCode))
  697.                     {
  698.                         $curVal = $locCode;
  699.                         //$curVal = $arUser["PERSONAL_CITY"];
  700.                     }
  701.                 }
  702.             }
  703.             elseif ($arProperty['IS_ZIP'] === 'Y' && empty($curVal) && !empty($ipAddress))
  704.             {
  705.                 $zip = GeoIp::getZipCode($ipAddress);
  706.  
  707.                 if (!empty($zip))
  708.                 {
  709.                     $curVal = $zip;
  710.                 }
  711.             }
  712.             elseif ($arProperty['IS_PHONE'] === 'Y' && !empty($curVal))
  713.             {
  714.                 $curVal = NormalizePhone($curVal, 5);
  715.             }
  716.            
  717.            
  718.             if (empty($curVal))
  719.             {
  720.                 // getting default value for all properties except LOCATION (LOCATION - only for first load or person type change)
  721.                 if ($arProperty['TYPE'] !== 'LOCATION' || $firstLoad || $isPersonTypeChanged)
  722.                 {
  723.                     if ($loadFromProfile || $justAuthorized)
  724.                     {
  725.                         $curVal = $this->getValueFromCUser($arProperty);
  726.                     }
  727.  
  728.                     if (empty($curVal) && !empty($arProperty['DEFAULT_VALUE']))
  729.                     {
  730.                         $curVal = $arProperty['DEFAULT_VALUE'];
  731.                     }
  732.                 }
  733.             }
  734.            
  735.            
  736.             if ($arProperty['TYPE'] === 'LOCATION')
  737.             {
  738.                
  739.                 if ((!$loadFromProfile || $this->request->get('PROFILE_ID') === '0')
  740.                     && $this->request->get('location_type') != 'code'
  741.                 )
  742.                 {
  743.                     $curVal = CSaleLocation::getLocationCODEbyID($curVal);
  744.                 }
  745.                
  746.             }
  747.            
  748.            
  749.            
  750.             //global $USER;
  751.             //if($USER->IsAuthorized()){
  752.                 $this->arUserResult['ORDER_PROP'][$arProperty['ID']] = $curVal;
  753.             //}else{
  754.                 //if($arProperty["ID"] == 6){
  755.                     ///$this->arUserResult['ORDER_PROP'][$arProperty['ID']] = $curVal;
  756.                 //}
  757.                 /*?><pre><? print_r($arProperty); ?></pre><?*/
  758.             //}
  759.            
  760.            
  761.         }
  762.  
  763.         $this->checkZipProperty($order, $useProfileProperties);
  764.         $this->checkAltLocationProperty($order, $useProfileProperties, $profileProperties);
  765.  
  766.         foreach (GetModuleEvents('sale', 'OnSaleComponentOrderProperties', true) as $arEvent)
  767.             ExecuteModuleEventEx($arEvent, array(&$this->arUserResult, $this->request, &$this->arParams, &$this->arResult));
  768.  
  769.         if ($this->isOrderConfirmed)
  770.         {
  771.             $res = $propertyCollection->checkErrors(array('PROPERTIES' => $this->arUserResult['ORDER_PROP']), array(), true);
  772.             if (!$res->isSuccess())
  773.             {
  774.                 $this->addError($res, self::PROPERTY_BLOCK);
  775.             }
  776.         }
  777.  
  778.         $res = $propertyCollection->setValuesFromPost(array('PROPERTIES' => $this->arUserResult['ORDER_PROP']), array());
  779.         if ($this->isOrderConfirmed && !$res->isSuccess())
  780.         {
  781.             $this->addError($res, self::PROPERTY_BLOCK);
  782.         }
  783.     }
  784.  
  785.     /**
  786.      * Returns user property value from CUser
  787.      *
  788.      * @param   $property
  789.      * @return  string
  790.      */
  791.     protected function getValueFromCUser($property)
  792.     {
  793.         global $USER;
  794.  
  795.         $value = '';
  796.  
  797.         if ($property['IS_EMAIL'] === 'Y')
  798.         {
  799.             $value = $USER->GetEmail();
  800.         }
  801.         elseif ($property['IS_PAYER'] === 'Y')
  802.         {
  803.             $rsUser = CUser::GetByID($USER->GetID());
  804.             if ($arUser = $rsUser->Fetch())
  805.             {
  806.                 $value = CUser::FormatName(
  807.                     CSite::GetNameFormat(false),
  808.                     array(
  809.                         'NAME' => $arUser['NAME'],
  810.                         'LAST_NAME' => $arUser['LAST_NAME'],
  811.                         'SECOND_NAME' => $arUser['SECOND_NAME']
  812.                     ),
  813.                     false,
  814.                     false
  815.                 );
  816.             }
  817.         }
  818.         elseif ($property['IS_PHONE'] === 'Y')
  819.         {
  820.             $rsUser = CUser::GetByID($USER->GetID());
  821.             if ($arUser = $rsUser->Fetch())
  822.             {
  823.                 if (!empty($arUser['PERSONAL_PHONE']))
  824.                 {
  825.                     $value = $arUser['PERSONAL_PHONE'];
  826.                 }
  827.                 elseif (!empty($arUser['PERSONAL_MOBILE']))
  828.                 {
  829.                     $value = $arUser['PERSONAL_MOBILE'];
  830.                 }
  831.             }
  832.         }
  833.         elseif ($property['IS_ADDRESS'] === 'Y')
  834.         {
  835.             $rsUser = CUser::GetByID($USER->GetID());
  836.             if ($arUser = $rsUser->Fetch())
  837.             {
  838.                 if (!empty($arUser['PERSONAL_STREET']))
  839.                 {
  840.                     $value = $arUser['PERSONAL_STREET'];
  841.                 }
  842.             }
  843.         }
  844.  
  845.         return $value;
  846.     }
  847.  
  848.     /**
  849.      * Defines zip value if location was changed.
  850.      *
  851.      * @param Order $order
  852.      * @param       $loadFromProfile
  853.      */
  854.     protected function checkZipProperty(Order $order, $loadFromProfile)
  855.     {
  856.         $propertyCollection = $order->getPropertyCollection();
  857.         $zip = $propertyCollection->getDeliveryLocationZip();
  858.         $location = $propertyCollection->getDeliveryLocation();
  859.         if (!empty($zip) && !empty($location))
  860.         {
  861.             $locId = $location->getField('ORDER_PROPS_ID');
  862.             $locValue = $this->arUserResult['ORDER_PROP'][$locId];
  863.             // $locationChanged = $locValue != $this->request->get('RECENT_DELIVERY_VALUE');
  864.  
  865.             // need to override flag for zip data from profile
  866.             if ($loadFromProfile)
  867.             {
  868.                 $this->arUserResult['ZIP_PROPERTY_CHANGED'] = 'Y';
  869.             }
  870.  
  871.             // don't autoload zip property if user manually changed it
  872.             if ($this->arUserResult['ZIP_PROPERTY_CHANGED'] !== 'Y')
  873.             {
  874.                 $res = Sale\Location\Admin\LocationHelper::getZipByLocation($locValue);
  875.  
  876.                 if ($arZip = $res->fetch())
  877.                 {
  878.                     if (!empty($arZip['XML_ID']))
  879.                     {
  880.                         $this->arUserResult['ORDER_PROP'][$zip->getField('ORDER_PROPS_ID')] = $arZip['XML_ID'];
  881.                     }
  882.                 }
  883.             }
  884.         }
  885.     }
  886.  
  887.     /**
  888.      * Checks order properties for proper alternate location property display.
  889.      *
  890.      * @param Order $order
  891.      * @param       $useProfileProperties
  892.      * @param array $profileProperties
  893.      */
  894.     protected function checkAltLocationProperty(Order $order, $useProfileProperties, array $profileProperties)
  895.     {
  896.         $locationAltPropDisplayManual = $this->request->get('LOCATION_ALT_PROP_DISPLAY_MANUAL');
  897.         $propertyCollection = $order->getPropertyCollection();
  898.         /** @var Sale\PropertyValue $property */
  899.         foreach ($propertyCollection as $property)
  900.         {
  901.             if ($property->isUtil())
  902.                 continue;
  903.  
  904.             if ($property->getType() == 'LOCATION')
  905.             {
  906.                 $propertyFields = $property->getProperty();
  907.                 if ((int)$propertyFields['INPUT_FIELD_LOCATION'] > 0)
  908.                 {
  909.                     if ($useProfileProperties)
  910.                     {
  911.                         $deleteAltProp = empty($profileProperties[$propertyFields['INPUT_FIELD_LOCATION']]);
  912.                     }
  913.                     else
  914.                     {
  915.                         $deleteAltProp = !isset($locationAltPropDisplayManual[$propertyFields['ID']])
  916.                             || !(bool)$locationAltPropDisplayManual[$propertyFields['ID']];
  917.  
  918.                         // check if have no city at all then show alternate property
  919.                         if (
  920.                             isset($locationAltPropDisplayManual[$propertyFields['ID']])
  921.                             && !$this->haveCitiesInTree($this->arUserResult['ORDER_PROP'][$property->getPropertyId()])
  922.                         )
  923.                         {
  924.                             $deleteAltProp = false;
  925.                         }
  926.                     }
  927.  
  928.                     if ($deleteAltProp)
  929.                     {
  930.                         unset($this->arUserResult['ORDER_PROP'][$propertyFields['INPUT_FIELD_LOCATION']]);
  931.                     }
  932.                 }
  933.             }
  934.         }
  935.     }
  936.  
  937.     protected function haveCitiesInTree($locationCode)
  938.     {
  939.         if (empty($locationCode))
  940.             return false;
  941.  
  942.         $haveCities = false;
  943.         $location = LocationTable::getRow(array('filter' => array('=CODE' => $locationCode)));
  944.  
  945.         if (!empty($location))
  946.         {
  947.             if ($location['TYPE_ID'] >= 5)
  948.             {
  949.                 $haveCities = true;
  950.             }
  951.             else
  952.             {
  953.                 $parameters = array(
  954.                     'filter' => array(
  955.                         '>=LEFT_MARGIN' => (int)$location['LEFT_MARGIN'],
  956.                         '<=RIGHT_MARGIN' => (int)$location['RIGHT_MARGIN'],
  957.                         '>=DEPTH_LEVEL' => (int)$location['DEPTH_LEVEL'],
  958.                         '!CITY_ID' => null,
  959.                     ),
  960.                     'count_total' => true
  961.                 );
  962.                 $haveCities = LocationTable::getList($parameters)->getCount() > 0;
  963.             }
  964.         }
  965.  
  966.         return $haveCities;
  967.     }
  968.  
  969.     /**
  970.      * Returns basket quantity list for orderable items
  971.      *
  972.      * @param Sale\BasketBase $basket
  973.      * @return array
  974.      */
  975.     protected function getActualQuantityList(Sale\BasketBase $basket)
  976.     {
  977.         $quantityList = array();
  978.  
  979.         if (!$basket->isEmpty())
  980.         {
  981.             /** @var Sale\BasketItemBase $basketItem */
  982.             foreach ($basket as $basketItem)
  983.             {
  984.                 if ($basketItem->canBuy() && !$basketItem->isDelay())
  985.                 {
  986.                     $quantityList[$basketItem->getBasketCode()] = $basketItem->getQuantity();
  987.                 }
  988.             }
  989.         }
  990.  
  991.         return $quantityList;
  992.     }
  993.  
  994.     /**
  995.      * Append basket(for current FUser) to order object
  996.      *
  997.      * @param Order $order
  998.      * @throws Main\ObjectNotFoundException
  999.      */
  1000.     protected function initBasket(Order $order)
  1001.     {
  1002.         $basketStorage = $this->getBasketStorage();
  1003.         $basket = $basketStorage->getBasket();
  1004.  
  1005.         $this->arUserResult['QUANTITY_LIST'] = $this->getActualQuantityList($basket);
  1006.  
  1007.         $result = $basket->refresh();
  1008.         if ($result->isSuccess())
  1009.         {
  1010.             $basket->save();
  1011.         }
  1012.  
  1013.         // right NOW we decide to work only with available basket
  1014.         // full basket won't update anymore
  1015.         $availableBasket = $basketStorage->getOrderableBasket();
  1016.         if ($availableBasket->isEmpty())
  1017.         {
  1018.             $this->showEmptyBasket();
  1019.         }
  1020.  
  1021.         $order->appendBasket($availableBasket);
  1022.     }
  1023.  
  1024.     protected function showEmptyBasket()
  1025.     {
  1026.         global $APPLICATION;
  1027.  
  1028.         if ($this->action === 'saveOrderAjax')
  1029.         {
  1030.             $APPLICATION->RestartBuffer();
  1031.             echo json_encode(array(
  1032.                 'order' => array(
  1033.                     'REDIRECT_URL' => $this->arParams['~CURRENT_PAGE']
  1034.                 )
  1035.             ));
  1036.             die();
  1037.         }
  1038.  
  1039.         if ($this->arParams['DISABLE_BASKET_REDIRECT'] === 'Y')
  1040.         {
  1041.             $this->arResult['SHOW_EMPTY_BASKET'] = true;
  1042.  
  1043.             if ($this->request->get('json') === 'Y' || $this->isRequestViaAjax)
  1044.             {
  1045.                 $APPLICATION->RestartBuffer();
  1046.                 echo json_encode(array(
  1047.                     'success' => 'N',
  1048.                     'redirect' => $this->arParams['~CURRENT_PAGE']
  1049.                 ));
  1050.                 die();
  1051.             }
  1052.         }
  1053.         else
  1054.         {
  1055.             if ($this->request->get('json') === 'Y' || $this->isRequestViaAjax)
  1056.             {
  1057.                 $APPLICATION->RestartBuffer();
  1058.                 echo json_encode(array(
  1059.                     'success' => 'N',
  1060.                     'redirect' => $this->arParams['PATH_TO_BASKET']
  1061.                 ));
  1062.                 die();
  1063.             }
  1064.  
  1065.             LocalRedirect($this->arParams['PATH_TO_BASKET']);
  1066.             die();
  1067.         }
  1068.     }
  1069.  
  1070.     protected function addError($res, $type = 'MAIN')
  1071.     {
  1072.         if ($res instanceof Result)
  1073.         {
  1074.             foreach ($res->getErrorMessages() as $error)
  1075.             {
  1076.                 $this->arResult['ERROR'][] = $error;
  1077.  
  1078.                 if (
  1079.                     empty($this->arResult['ERROR_SORTED'][$type])
  1080.                     || (!empty($this->arResult['ERROR_SORTED'][$type]) && !in_array($error, $this->arResult['ERROR_SORTED'][$type]))
  1081.                 )
  1082.                 {
  1083.                     $this->arResult['ERROR_SORTED'][$type][] = $error;
  1084.                 }
  1085.             }
  1086.         }
  1087.         else
  1088.         {
  1089.             $this->arResult['ERROR'][] = $res;
  1090.  
  1091.             if (
  1092.                 empty($this->arResult['ERROR_SORTED'][$type])
  1093.                 || (!empty($this->arResult['ERROR_SORTED'][$type]) && !in_array($res, $this->arResult['ERROR_SORTED'][$type]))
  1094.             )
  1095.             {
  1096.                 $this->arResult['ERROR_SORTED'][$type][] = $res;
  1097.             }
  1098.         }
  1099.     }
  1100.  
  1101.     protected function addWarning($res, $type)
  1102.     {
  1103.         if (
  1104.             !empty($type)
  1105.             && (
  1106.                 empty($this->arResult['WARNING'][$type])
  1107.                 || (!empty($this->arResult['WARNING'][$type]) && !in_array($res, $this->arResult['WARNING'][$type]))
  1108.             )
  1109.         )
  1110.         {
  1111.             $this->arResult['WARNING'][$type][] = $res;
  1112.         }
  1113.     }
  1114.  
  1115.     /**
  1116.      * Action - show and process authorization form
  1117.      *
  1118.      * @throws Main\ArgumentNullException
  1119.      */
  1120.     protected function showAuthFormAction()
  1121.     {
  1122.         global $APPLICATION;
  1123.         $arResult =& $this->arResult;
  1124.  
  1125.         $request = $this->isRequestViaAjax && $this->request->get('save') != 'Y' ? $this->request->get('order') : $this->request;
  1126.  
  1127.         $this->checkSocServicesAuthForm();
  1128.  
  1129.         $arResult['AUTH']['USER_LOGIN'] = strlen($request['USER_LOGIN']) > 0
  1130.             ? htmlspecialcharsbx($request['USER_LOGIN'])
  1131.             : htmlspecialcharsbx(${Option::get('main', 'cookie_name', 'BITRIX_SM').'_LOGIN'});
  1132.         $arResult['AUTH']['captcha_registration'] = Option::get('main', 'captcha_registration', 'N') === 'Y' ? 'Y' : 'N';
  1133.  
  1134.         if ($arResult['AUTH']['captcha_registration'] === 'Y')
  1135.         {
  1136.             $arResult['AUTH']['capCode'] = htmlspecialcharsbx($APPLICATION->CaptchaGetCode());
  1137.         }
  1138.  
  1139.         $arResult['POST'] = array();
  1140.  
  1141.         if ($this->request->isPost() && $this->checkSession)
  1142.         {
  1143.             foreach ($request as $name => $value)
  1144.             {
  1145.                 if (in_array(
  1146.                     $name,
  1147.                     array(
  1148.                         'USER_LOGIN', 'USER_PASSWORD', 'do_authorize', 'NEW_NAME', 'NEW_LAST_NAME', 'NEW_EMAIL',
  1149.                         'NEW_GENERATE', 'NEW_LOGIN', 'NEW_PASSWORD', 'NEW_PASSWORD_CONFIRM', 'captcha_sid',
  1150.                         'captcha_word', 'do_register', 'is_ajax_post'
  1151.                     )
  1152.                 ))
  1153.                     continue;
  1154.  
  1155.                 if (is_array($value))
  1156.                 {
  1157.                     foreach ($value as $k => $v)
  1158.                     {
  1159.                         $arResult['POST'][htmlspecialcharsbx($name.'['.$k.']')] = htmlspecialcharsbx($v);
  1160.                     }
  1161.                 }
  1162.                 else
  1163.                 {
  1164.                     $arResult['POST'][htmlspecialcharsbx($name)] = htmlspecialcharsbx($value);
  1165.                 }
  1166.             }
  1167.  
  1168.             if ($request['do_authorize'] === 'Y')
  1169.             {
  1170.                 $this->doAuthorize();
  1171.             }
  1172.             elseif ($request['do_register'] === 'Y' && $arResult['AUTH']['new_user_registration'] === 'Y')
  1173.             {
  1174.                 $this->doRegister();
  1175.             }
  1176.             elseif ($this->isRequestViaAjax)
  1177.             {
  1178.                 $this->showAjaxAnswer(array(
  1179.                     'order' => array(
  1180.                         'SHOW_AUTH' => true,
  1181.                         'AUTH' => $arResult['AUTH']
  1182.                     )
  1183.                 ));
  1184.             }
  1185.         }
  1186.  
  1187.         if ($this->isRequestViaAjax)
  1188.         {
  1189.             if (empty($arResult['ERROR']))
  1190.             {
  1191.                 $this->refreshOrderAjaxAction();
  1192.             }
  1193.             else
  1194.             {
  1195.                 $this->showAjaxAnswer(array(
  1196.                     'order' => array(
  1197.                         'SHOW_AUTH' => true,
  1198.                         'AUTH' => $arResult['AUTH'],
  1199.                         'ERROR' => $arResult['ERROR_SORTED']
  1200.                     )
  1201.                 ));
  1202.             }
  1203.         }
  1204.         else
  1205.         {
  1206.             $this->processOrderAction();
  1207.         }
  1208.     }
  1209.  
  1210.     protected function checkSocServicesAuthForm()
  1211.     {
  1212.         global $APPLICATION;
  1213.         $arResult =& $this->arResult;
  1214.  
  1215.         $arResult["ALLOW_SOCSERV_AUTHORIZATION"] = Option::get("main", "allow_socserv_authorization", "Y") == "Y" ? "Y" : "N";
  1216.         $arResult["AUTH_SERVICES"] = false;
  1217.         $arResult["CURRENT_SERVICE"] = false;
  1218.         $arResult["FOR_INTRANET"] = false;
  1219.  
  1220.         if (Bitrix\Main\ModuleManager::isModuleInstalled("intranet") || Bitrix\Main\ModuleManager::isModuleInstalled("rest"))
  1221.             $arResult["FOR_INTRANET"] = true;
  1222.  
  1223.         if (Loader::includeModule("socialservices") && $arResult["ALLOW_SOCSERV_AUTHORIZATION"] == 'Y')
  1224.         {
  1225.             $oAuthManager = new CSocServAuthManager();
  1226.             $arServices = $oAuthManager->GetActiveAuthServices(array(
  1227.                 'BACKURL' => $this->arParams['~CURRENT_PAGE'],
  1228.                 'FOR_INTRANET' => $arResult['FOR_INTRANET'],
  1229.             ));
  1230.  
  1231.             if (!empty($arServices))
  1232.             {
  1233.                 $arResult["AUTH_SERVICES"] = $arServices;
  1234.                 if (isset($this->request["auth_service_id"])
  1235.                     && $this->request["auth_service_id"] != ''
  1236.                     && isset($arResult["AUTH_SERVICES"][$this->request["auth_service_id"]])
  1237.                 )
  1238.                 {
  1239.                     $arResult["CURRENT_SERVICE"] = $this->request["auth_service_id"];
  1240.                     if (isset($this->request["auth_service_error"]) && $this->request["auth_service_error"] <> '')
  1241.                     {
  1242.                         $this->addError($oAuthManager->GetError($arResult["CURRENT_SERVICE"], $this->request["auth_service_error"]), self::AUTH_BLOCK);
  1243.                     }
  1244.                     elseif (!$oAuthManager->Authorize($this->request["auth_service_id"]))
  1245.                     {
  1246.                         $ex = $APPLICATION->GetException();
  1247.                         if ($ex)
  1248.                             $this->addError($ex->GetString(), self::AUTH_BLOCK);
  1249.                     }
  1250.                 }
  1251.             }
  1252.         }
  1253.     }
  1254.  
  1255.     protected function doAuthorize()
  1256.     {
  1257.         global $USER;
  1258.         $request = $this->isRequestViaAjax && $this->request->get('save') != 'Y' ? $this->request->get('order') : $this->request;
  1259.  
  1260.         if (strlen($request["USER_LOGIN"]) <= 0)
  1261.             $this->addError(Loc::getMessage("STOF_ERROR_AUTH_LOGIN"), self::AUTH_BLOCK);
  1262.  
  1263.         if (empty($this->arResult["ERROR"]))
  1264.         {
  1265.             $rememberMe = $request["USER_REMEMBER"] == 'Y' ? 'Y' : 'N';
  1266.             $arAuthResult = $USER->Login($request["USER_LOGIN"], $request["USER_PASSWORD"], $rememberMe);
  1267.             if ($arAuthResult != false && $arAuthResult["TYPE"] == "ERROR")
  1268.                 $this->addError(Loc::getMessage("STOF_ERROR_AUTH").(strlen($arAuthResult["MESSAGE"]) > 0 ? ": ".$arAuthResult["MESSAGE"] : "" ), self::AUTH_BLOCK);
  1269.         }
  1270.     }
  1271.  
  1272.     protected function doRegister()
  1273.     {
  1274.         global $APPLICATION, $USER;
  1275.         $arResult =& $this->arResult;
  1276.         $request = $this->isRequestViaAjax && $this->request->get('save') != 'Y' ? $this->request->get('order') : $this->request;
  1277.  
  1278.         if (strlen($request['NEW_NAME']) <= 0)
  1279.         {
  1280.             $this->addError(Loc::getMessage('STOF_ERROR_REG_NAME'), self::AUTH_BLOCK);
  1281.         }
  1282.  
  1283.         if (strlen($request['NEW_LAST_NAME']) <= 0)
  1284.         {
  1285.             $this->addError(Loc::getMessage('STOF_ERROR_REG_LASTNAME'), self::AUTH_BLOCK);
  1286.         }
  1287.  
  1288.         if (Option::get('main', 'new_user_email_required', '') === 'Y')
  1289.         {
  1290.             if (strlen($request['NEW_EMAIL']) <= 0)
  1291.             {
  1292.                 $this->addError(Loc::getMessage('STOF_ERROR_REG_EMAIL'), self::AUTH_BLOCK);
  1293.             }
  1294.             elseif (!check_email($request['NEW_EMAIL']))
  1295.             {
  1296.                 $this->addError(Loc::getMessage('STOF_ERROR_REG_BAD_EMAIL'), self::AUTH_BLOCK);
  1297.             }
  1298.         }
  1299.  
  1300.         $arResult['AUTH']['NEW_EMAIL'] = $request['NEW_EMAIL'];
  1301.  
  1302.         if (empty($arResult['ERROR']))
  1303.         {
  1304.             if ($request['NEW_GENERATE'] === 'Y')
  1305.             {
  1306.                 $generatedData = $this->generateUserData(array('EMAIL' => $request['NEW_EMAIL']));
  1307.                 $arResult['AUTH'] = array_merge($arResult['AUTH'], $generatedData);
  1308.             }
  1309.             else
  1310.             {
  1311.                 if (strlen($request['NEW_LOGIN']) <= 0)
  1312.                 {
  1313.                     $this->addError(Loc::getMessage('STOF_ERROR_REG_FLAG'), self::AUTH_BLOCK);
  1314.                 }
  1315.  
  1316.                 if (strlen($request['NEW_PASSWORD']) <= 0)
  1317.                 {
  1318.                     $this->addError(Loc::getMessage('STOF_ERROR_REG_FLAG1'), self::AUTH_BLOCK);
  1319.                 }
  1320.  
  1321.                 if (strlen($request['NEW_PASSWORD']) > 0 && strlen($request['NEW_PASSWORD_CONFIRM']) <= 0)
  1322.                 {
  1323.                     $this->addError(Loc::getMessage('STOF_ERROR_REG_FLAG1'), self::AUTH_BLOCK);
  1324.                 }
  1325.  
  1326.                 if (
  1327.                     strlen($request['NEW_PASSWORD']) > 0
  1328.                     && strlen($request['NEW_PASSWORD_CONFIRM']) > 0
  1329.                     && $request['NEW_PASSWORD'] != $request['NEW_PASSWORD_CONFIRM']
  1330.                 )
  1331.                 {
  1332.                     $this->addError(Loc::getMessage('STOF_ERROR_REG_PASS'), self::AUTH_BLOCK);
  1333.                 }
  1334.  
  1335.                 $arResult['AUTH']['NEW_LOGIN'] = $request['NEW_LOGIN'];
  1336.                 $arResult['AUTH']['NEW_NAME'] = $request['NEW_NAME'];
  1337.                 $arResult['AUTH']['NEW_PASSWORD'] = $request['NEW_PASSWORD'];
  1338.                 $arResult['AUTH']['NEW_PASSWORD_CONFIRM'] = $request['NEW_PASSWORD_CONFIRM'];
  1339.             }
  1340.         }
  1341.  
  1342.         if (empty($arResult['ERROR']))
  1343.         {
  1344.             $arAuthResult = $USER->Register(
  1345.                 $arResult['AUTH']['NEW_LOGIN'],
  1346.                 $request['NEW_NAME'],
  1347.                 $request['NEW_LAST_NAME'],
  1348.                 $arResult['AUTH']['NEW_PASSWORD'],
  1349.                 $arResult['AUTH']['NEW_PASSWORD_CONFIRM'],
  1350.                 $arResult['AUTH']['NEW_EMAIL'],
  1351.                 LANG,
  1352.                 $request['captcha_word'],
  1353.                 $request['captcha_sid']
  1354.             );
  1355.  
  1356.             if ($arAuthResult != false && $arAuthResult['TYPE'] === 'ERROR')
  1357.             {
  1358.                 $this->addError(Loc::getMessage('STOF_ERROR_REG').(strlen($arAuthResult['MESSAGE']) > 0 ? ': '.$arAuthResult['MESSAGE'] : '' ), self::AUTH_BLOCK);
  1359.             }
  1360.             else
  1361.             {
  1362.                 if ($USER->IsAuthorized())
  1363.                 {
  1364.                     if ($this->arParams['SEND_NEW_USER_NOTIFY'] === 'Y')
  1365.                     {
  1366.                         CUser::SendUserInfo($USER->GetID(), SITE_ID, Loc::getMessage('INFO_REQ'), true);
  1367.                     }
  1368.  
  1369.                     if ($this->isRequestViaAjax)
  1370.                     {
  1371.                         $this->refreshOrderAjaxAction();
  1372.                     }
  1373.                     else
  1374.                     {
  1375.                         LocalRedirect($APPLICATION->GetCurPageParam());
  1376.                     }
  1377.                 }
  1378.                 else
  1379.                 {
  1380.                     $arResult['OK_MESSAGE'][] = Loc::getMessage('STOF_ERROR_REG_CONFIRM');
  1381.                 }
  1382.             }
  1383.         }
  1384.  
  1385.         $arResult['AUTH']['~NEW_LOGIN'] = $arResult['AUTH']['NEW_LOGIN'];
  1386.         $arResult['AUTH']['NEW_LOGIN'] = htmlspecialcharsEx($arResult['AUTH']['NEW_LOGIN']);
  1387.         $arResult['AUTH']['~NEW_NAME'] = $request['NEW_NAME'];
  1388.         $arResult['AUTH']['NEW_NAME'] = htmlspecialcharsEx($request['NEW_NAME']);
  1389.         $arResult['AUTH']['~NEW_LAST_NAME'] = $request['NEW_LAST_NAME'];
  1390.         $arResult['AUTH']['NEW_LAST_NAME'] = htmlspecialcharsEx($request['NEW_LAST_NAME']);
  1391.         $arResult['AUTH']['~NEW_EMAIL'] = $arResult['AUTH']['NEW_EMAIL'];
  1392.         $arResult['AUTH']['NEW_EMAIL'] = htmlspecialcharsEx($arResult['AUTH']['NEW_EMAIL']);
  1393.     }
  1394.  
  1395.     protected function initStatGid()
  1396.     {
  1397.         if (Loader::includeModule("statistic"))
  1398.             $this->order->setField('STAT_GID', CStatistic::GetEventParam());
  1399.     }
  1400.  
  1401.     protected function initAffiliate()
  1402.     {
  1403.         $affiliateID = CSaleAffiliate::GetAffiliate();
  1404.         if ($affiliateID > 0)
  1405.         {
  1406.             $dbAffiliate = CSaleAffiliate::GetList(array(), array("SITE_ID" => $this->context->getSite(), "ID" => $affiliateID));
  1407.             $arAffiliates = $dbAffiliate->Fetch();
  1408.             if (count($arAffiliates) > 1)
  1409.                 $this->order->setField('AFFILIATE_ID', $affiliateID);
  1410.         }
  1411.     }
  1412.  
  1413.     /**
  1414.      * Generation of user registration fields (login, password, etc)
  1415.      *
  1416.      * @param array $userProps
  1417.      * @return array
  1418.      * @throws Main\ArgumentNullException
  1419.      */
  1420.     public function generateUserData($userProps = array())
  1421.     {
  1422.         global $USER;
  1423.  
  1424.         $userEmail = isset($userProps['EMAIL']) ? trim((string)$userProps['EMAIL']) : '';
  1425.         $newLogin = $userEmail;
  1426.  
  1427.         if (empty($userEmail))
  1428.         {
  1429.             $newEmail = false;
  1430.             $normalizedPhone = NormalizePhone((string)$userProps['PHONE'], 5);
  1431.  
  1432.             if (!empty($normalizedPhone))
  1433.             {
  1434.                 $newLogin = $normalizedPhone;
  1435.             }
  1436.         }
  1437.         else
  1438.         {
  1439.             $newEmail = $userEmail;
  1440.         }
  1441.  
  1442.         if (empty($newLogin))
  1443.         {
  1444.             $newLogin = randString(5).mt_rand(0, 99999);
  1445.         }
  1446.  
  1447.         $pos = strpos($newLogin, '@');
  1448.         if ($pos !== false)
  1449.         {
  1450.             $newLogin = substr($newLogin, 0, $pos);
  1451.         }
  1452.  
  1453.         if (strlen($newLogin) > 47)
  1454.         {
  1455.             $newLogin = substr($newLogin, 0, 47);
  1456.         }
  1457.  
  1458.         $newLogin = str_pad($newLogin, 3, '_');
  1459.  
  1460.         $dbUserLogin = CUser::GetByLogin($newLogin);
  1461.         if ($userLoginResult = $dbUserLogin->Fetch())
  1462.         {
  1463.             do
  1464.             {
  1465.                 $newLoginTmp = $newLogin.mt_rand(0, 99999);
  1466.                 $dbUserLogin = CUser::GetByLogin($newLoginTmp);
  1467.             }
  1468.             while ($userLoginResult = $dbUserLogin->Fetch());
  1469.  
  1470.             $newLogin = $newLoginTmp;
  1471.         }
  1472.  
  1473.         $newName = '';
  1474.         $newLastName = '';
  1475.         $payerName = isset($userProps['PAYER']) ? trim((string)$userProps['PAYER']) : '';
  1476.  
  1477.         if (!empty($payerName))
  1478.         {
  1479.             $arNames = explode(' ', $payerName);
  1480.             $newName = $arNames[1];
  1481.             $newLastName = $arNames[0];
  1482.         }
  1483.  
  1484.         $defGroup = Option::get('main', 'new_user_registration_def_group', '');
  1485.         if (!empty($defGroup))
  1486.         {
  1487.             $groupId = explode(',', $defGroup);
  1488.             $arPolicy = $USER->GetGroupPolicy($groupId);
  1489.         }
  1490.         else
  1491.         {
  1492.             $groupId = false;
  1493.             $arPolicy = $USER->GetGroupPolicy(array());
  1494.         }
  1495.  
  1496.         $passwordMinLength = (int)$arPolicy['PASSWORD_LENGTH'];
  1497.         if ($passwordMinLength <= 0)
  1498.         {
  1499.             $passwordMinLength = 6;
  1500.         }
  1501.  
  1502.         $passwordChars = array(
  1503.             'abcdefghijklnmopqrstuvwxyz',
  1504.             'ABCDEFGHIJKLNMOPQRSTUVWXYZ',
  1505.             '0123456789',
  1506.         );
  1507.         if ($arPolicy['PASSWORD_PUNCTUATION'] === 'Y')
  1508.         {
  1509.             $passwordChars[] = ",.<>/?;:'\"[]{}\|`~!@#\$%^&*()-_+=";
  1510.         }
  1511.  
  1512.         $newPassword = $newPasswordConfirm = randString($passwordMinLength + 2, $passwordChars);
  1513.  
  1514.         return array(
  1515.             'NEW_EMAIL' => $newEmail,
  1516.             'NEW_LOGIN' => $newLogin,
  1517.             'NEW_NAME' => $newName,
  1518.             'NEW_LAST_NAME' => $newLastName,
  1519.             'NEW_PASSWORD' => $newPassword,
  1520.             'NEW_PASSWORD_CONFIRM' => $newPasswordConfirm,
  1521.             'GROUP_ID' => $groupId
  1522.         );
  1523.     }
  1524.  
  1525.     /**
  1526.      * Creating new user and logging in
  1527.      *
  1528.      * @param $userProps
  1529.      * @return bool|int
  1530.      */
  1531.     protected function registerAndLogIn($userProps)
  1532.     {
  1533.         $userId = false;
  1534.         $userData = $this->generateUserData($userProps);
  1535.  
  1536.         $user = new CUser;
  1537.         $arAuthResult = $user->Add(array(
  1538.             'LOGIN' => $userData['NEW_LOGIN'],
  1539.             'NAME' => $userData['NEW_NAME'],
  1540.             'LAST_NAME' => $userData['NEW_LAST_NAME'],
  1541.             'PASSWORD' => $userData['NEW_PASSWORD'],
  1542.             'CONFIRM_PASSWORD' => $userData['NEW_PASSWORD_CONFIRM'],
  1543.             'EMAIL' => $userData['NEW_EMAIL'],
  1544.             'GROUP_ID' => $userData['GROUP_ID'],
  1545.             'ACTIVE' => 'Y',
  1546.             'LID' => $this->context->getSite(),
  1547.             'PERSONAL_PHONE' => isset($userProps['PHONE']) ? NormalizePhone($userProps['PHONE'], 5) : '',
  1548.             'PERSONAL_ZIP' => isset($userProps['ZIP']) ? $userProps['ZIP'] : '',
  1549.             'PERSONAL_STREET' => isset($userProps['ADDRESS']) ? $userProps['ADDRESS'] : ''
  1550.         ));
  1551.  
  1552.         if (intval($arAuthResult) <= 0)
  1553.         {
  1554.             $this->addError(Loc::getMessage('STOF_ERROR_REG').((strlen($user->LAST_ERROR) > 0) ? ': '.$user->LAST_ERROR : '' ), self::AUTH_BLOCK);
  1555.         }
  1556.         else
  1557.         {
  1558.             global $USER;
  1559.             $userId = intval($arAuthResult);
  1560.             $USER->Authorize($arAuthResult);
  1561.             if ($USER->IsAuthorized())
  1562.             {
  1563.                 if ($this->arParams['SEND_NEW_USER_NOTIFY'] == 'Y')
  1564.                 {
  1565.                     CUser::SendUserInfo($USER->GetID(), $this->context->getSite(), Loc::getMessage('INFO_REQ'), true);
  1566.                 }
  1567.             }
  1568.             else
  1569.             {
  1570.                 $this->addError(Loc::getMessage('STOF_ERROR_REG_CONFIRM'), self::AUTH_BLOCK);
  1571.             }
  1572.         }
  1573.  
  1574.         return $userId;
  1575.     }
  1576.  
  1577.     /**
  1578.      * Returns array of user id and 'save to session' flag (true if 'unique user e-mails' option
  1579.      * active and we already have this e-mail)
  1580.      *
  1581.      * @return array
  1582.      * @throws Main\ArgumentNullException
  1583.      */
  1584.     protected function autoRegisterUser()
  1585.     {
  1586.         $personType = $this->request->get('PERSON_TYPE');
  1587.         if ($personType <= 0)
  1588.         {
  1589.             $personTypes = PersonType::load(SITE_ID);
  1590.             foreach ($personTypes as $type)
  1591.             {
  1592.                 $personType = $type['ID'];
  1593.                 break;
  1594.             }
  1595.  
  1596.             unset($personTypes, $type);
  1597.         }
  1598.  
  1599.         $userProps = Sale\PropertyValue::getMeaningfulValues($personType, $this->getPropertyValuesFromRequest());
  1600.         $userId = false;
  1601.         $saveToSession = false;
  1602.  
  1603.         if (
  1604.             $this->arParams['ALLOW_APPEND_ORDER'] === 'Y'
  1605.             && Option::get('main', 'new_user_email_uniq_check', '') === 'Y'
  1606.             && ($userProps['EMAIL'] != '' || $userProps['PHONE'] != '')
  1607.         )
  1608.         {
  1609.             $existingUserId = 0;
  1610.  
  1611.             if ($userProps['EMAIL'] != '')
  1612.             {
  1613.                 $res = Bitrix\Main\UserTable::getRow(array(
  1614.                     'filter' => array(
  1615.                         '=EMAIL' => $userProps['EMAIL']
  1616.                     ),
  1617.                     'select' => array('ID')
  1618.                 ));
  1619.                 if (isset($res['ID']))
  1620.                 {
  1621.                     $existingUserId = (int)$res['ID'];
  1622.                 }
  1623.             }
  1624.  
  1625.             if ($existingUserId === 0 && !empty($userProps['PHONE']))
  1626.             {
  1627.                 $normalizedPhone = NormalizePhone((string)$userProps['PHONE'], 5);
  1628.  
  1629.                 if (!empty($normalizedPhone))
  1630.                 {
  1631.                     $res = Bitrix\Main\UserTable::getRow(array(
  1632.                         'filter' => array(
  1633.                             'LOGIC' => 'OR',
  1634.                             '=PERSONAL_PHONE' => $normalizedPhone,
  1635.                             '=PERSONAL_MOBILE' => $normalizedPhone
  1636.                         ),
  1637.                         'select' => array('ID')
  1638.                     ));
  1639.                     if (isset($res['ID']))
  1640.                     {
  1641.                         $existingUserId = (int)$res['ID'];
  1642.                     }
  1643.                 }
  1644.             }
  1645.  
  1646.             if ($existingUserId > 0)
  1647.             {
  1648.                 $userId = $existingUserId;
  1649.                 $saveToSession = true;
  1650.             }
  1651.             else
  1652.             {
  1653.                 $userId = $this->registerAndLogIn($userProps);
  1654.             }
  1655.         }
  1656.         elseif ($userProps['EMAIL'] != '' || Option::get('main', 'new_user_email_required', '') === 'N')
  1657.         {
  1658.             $userId = $this->registerAndLogIn($userProps);
  1659.         }
  1660.         else
  1661.         {
  1662.             $this->addError(Loc::getMessage('STOF_ERROR_EMAIL'), self::AUTH_BLOCK);
  1663.         }
  1664.  
  1665.         return array($userId, $saveToSession);
  1666.     }
  1667.  
  1668.     public function initGrid()
  1669.     {
  1670.         $this->arResult["GRID"]["HEADERS"] = $this->getGridHeaders($this->arParams["PRODUCT_COLUMNS"]);
  1671.         $this->arResult["GRID"]["HEADERS_HIDDEN"] = $this->getGridHeaders($this->arParams["PRODUCT_COLUMNS_HIDDEN"]);
  1672.     }
  1673.  
  1674.     public function getGridHeaders($productColumns)
  1675.     {
  1676.         $arr = array();
  1677.  
  1678.         if (is_array($productColumns) && !empty($productColumns))
  1679.         {
  1680.             $arCodes = array();
  1681.             $iBlockProps = array();
  1682.             foreach ($productColumns as $key => $value) // making grid headers array
  1683.             {
  1684.                 if (strncmp($value, "PROPERTY_", 9) == 0)
  1685.                 {
  1686.                     $propCode = substr($value, 9);
  1687.  
  1688.                     if ($propCode == '')
  1689.                         continue;
  1690.  
  1691.                     $arCodes[] = $propCode;
  1692.                 }
  1693.             }
  1694.  
  1695.             if ($this->useCatalog && !empty($arCodes))
  1696.             {
  1697.                 $iBlockList = array();
  1698.                 $catalogIterator = Bitrix\Catalog\CatalogIblockTable::getList(array(
  1699.                     'select' => array('IBLOCK_ID', 'PRODUCT_IBLOCK_ID', 'SITE_ID' => 'IBLOCK_SITE.SITE_ID'),
  1700.                     'filter' => array('SITE_ID' => SITE_ID),
  1701.                     'runtime' => array(
  1702.                         'IBLOCK_SITE' => array(
  1703.                             'data_type' => 'Bitrix\Iblock\IblockSiteTable',
  1704.                             'reference' => array(
  1705.                                 'ref.IBLOCK_ID' => 'this.IBLOCK_ID',
  1706.                             ),
  1707.                             'join_type' => 'inner'
  1708.                         )
  1709.                     )
  1710.                 ));
  1711.                 while ($catalog = $catalogIterator->fetch())
  1712.                 {
  1713.                     $iBlockList[$catalog['IBLOCK_ID']] = $catalog['IBLOCK_ID'];
  1714.  
  1715.                     if (intval($catalog['PRODUCT_IBLOCK_ID']) > 0)
  1716.                         $iBlockList[$catalog['PRODUCT_IBLOCK_ID']] = $catalog['PRODUCT_IBLOCK_ID'];
  1717.                 }
  1718.  
  1719.                 if (!empty($iBlockList))
  1720.                 {
  1721.                     $propertyIterator = Bitrix\Iblock\PropertyTable::getList(array(
  1722.                         'select' => array('ID', 'IBLOCK_ID', 'NAME', 'ACTIVE', 'SORT', 'CODE', 'TIMESTAMP_X',
  1723.                             'DEFAULT_VALUE', 'PROPERTY_TYPE', 'ROW_COUNT', 'COL_COUNT', 'LIST_TYPE',
  1724.                             'MULTIPLE', 'XML_ID', 'FILE_TYPE', 'MULTIPLE_CNT', 'LINK_IBLOCK_ID', 'WITH_DESCRIPTION',
  1725.                             'SEARCHABLE', 'FILTRABLE', 'IS_REQUIRED', 'VERSION', 'USER_TYPE', 'USER_TYPE_SETTINGS', 'HINT'),
  1726.                         'filter' => array(
  1727.                             '@IBLOCK_ID' => array_keys($iBlockList),
  1728.                             '=ACTIVE' => 'Y',
  1729.                             '@CODE' => $arCodes
  1730.                         ),
  1731.                         'order' => array('SORT' => 'ASC', 'ID' => 'ASC')
  1732.                     ));
  1733.                     while ($property = $propertyIterator->fetch())
  1734.                     {
  1735.                         $this->arIblockProps[$property['IBLOCK_ID']][$property['CODE']] = $property;
  1736.  
  1737.                         if (!isset($iBlockProps[$property['CODE']]))
  1738.                             $iBlockProps[$property['CODE']] = $property;
  1739.                     }
  1740.                 }
  1741.             }
  1742.  
  1743.             // making grid headers array
  1744.             foreach ($productColumns as $key => $value)
  1745.             {
  1746.                 // processing iblock properties
  1747.                 if (strncmp($value, "PROPERTY_", 9) == 0)
  1748.                 {
  1749.                     $propCode = substr($value, 9);
  1750.  
  1751.                     if ($propCode == '')
  1752.                         continue;
  1753.  
  1754.                     // array of iblock properties to select
  1755.                     $this->arCustomSelectFields[] = $value;
  1756.                     $id = $value."_VALUE";
  1757.                     $name = $value;
  1758.  
  1759.                     if (array_key_exists($propCode, $iBlockProps))
  1760.                     {
  1761.                         $name = $iBlockProps[$propCode]["NAME"];
  1762.                     }
  1763.                 }
  1764.                 else
  1765.                 {
  1766.                     $id = $key;
  1767.                     $name = $value;
  1768.                 }
  1769.  
  1770.                 $arColumn = array(
  1771.                     "id" => $id,
  1772.                     "name" => $name
  1773.                 );
  1774.  
  1775.                 if ($key == "PRICE_FORMATED")
  1776.                 {
  1777.                     $arColumn["align"] = "right";
  1778.                 }
  1779.  
  1780.                 $arr[] = $arColumn;
  1781.             }
  1782.         }
  1783.  
  1784.         return $arr;
  1785.     }
  1786.  
  1787.     public function getPropsInfo($source)
  1788.     {
  1789.         $resultHTML = "";
  1790.  
  1791.         foreach ($source["PROPS"] as $val)
  1792.         {
  1793.             $resultHTML .= str_replace(" ", "&nbsp;", $val["NAME"].": ".$val["VALUE"])."<br />";
  1794.         }
  1795.  
  1796.         return $resultHTML;
  1797.     }
  1798.  
  1799.     public function getIblockProps($value, $propData, $arSize = array("WIDTH" => 90, "HEIGHT" => 90), $orderId = 0)
  1800.     {
  1801.         $res = array();
  1802.  
  1803.         if ($propData["MULTIPLE"] == "Y")
  1804.         {
  1805.             $arVal = array();
  1806.             if (!is_array($value))
  1807.             {
  1808.                 if (strpos($value, ",") !== false)
  1809.                     $arVal = explode(",", $value);
  1810.                 else
  1811.                     $arVal[] = $value;
  1812.             }
  1813.             else
  1814.                 $arVal = $value;
  1815.  
  1816.             if (!empty($arVal))
  1817.             {
  1818.                 foreach ($arVal as $key => $val)
  1819.                 {
  1820.                     if ($propData["PROPERTY_TYPE"] == "F")
  1821.                         $res[] = $this->getFileData(trim($val), $orderId, $arSize);
  1822.                     else
  1823.                         $res[] = array("type" => "value", "value" => $val);
  1824.                 }
  1825.             }
  1826.         }
  1827.         else
  1828.         {
  1829.             if ($propData["PROPERTY_TYPE"] == "F")
  1830.                 $res[] = $this->getFileData($value, $orderId, $arSize);
  1831.             else
  1832.                 $res[] = array("type" => "value", "value" => $value);
  1833.         }
  1834.  
  1835.         return $res;
  1836.     }
  1837.  
  1838.     public function getLinkedPropValue($basketItem, $property)
  1839.     {
  1840.         $result = array();
  1841.  
  1842.         if ($property['MULTIPLE'] === 'Y')
  1843.             $property['VALUE'] = explode(',', $property['VALUE']);
  1844.  
  1845.         $formattedProperty = CIBlockFormatProperties::GetDisplayValue($basketItem, $property, 'sale_out');
  1846.         if (!empty($formattedProperty['DISPLAY_VALUE']))
  1847.         {
  1848.             if (is_array($formattedProperty['DISPLAY_VALUE']))
  1849.             {
  1850.                 foreach ($formattedProperty['DISPLAY_VALUE'] as $key => $formatValue)
  1851.                 {
  1852.                     $result[] = array(
  1853.                         'type' => 'linked',
  1854.                         'value' => $property['VALUE'][$key],
  1855.                         'value_format' => $formatValue
  1856.                     );
  1857.                 }
  1858.             }
  1859.             else
  1860.             {
  1861.                 $result[] = array(
  1862.                     'type' => 'linked',
  1863.                     'value' => is_array($property['VALUE']) ? reset($property['VALUE']) : $property['VALUE'],
  1864.                     'value_format' => $formattedProperty['DISPLAY_VALUE']
  1865.                 );
  1866.             }
  1867.         }
  1868.  
  1869.         return $result;
  1870.     }
  1871.  
  1872.     public function getDirectoryProperty($basketItem, $property)
  1873.     {
  1874.         $result = array();
  1875.  
  1876.         if ($property['MULTIPLE'] === 'Y')
  1877.         {
  1878.             $property['VALUE'] = explode(', ', $basketItem['PROPERTY_'.$property['CODE'].'_VALUE']);
  1879.         }
  1880.         else
  1881.         {
  1882.             $property['VALUE'] = $basketItem['PROPERTY_'.$property['CODE'].'_VALUE'];
  1883.         }
  1884.  
  1885.         $property['~VALUE'] = $property['VALUE'];
  1886.  
  1887.         if (CheckSerializedData($property['USER_TYPE_SETTINGS']))
  1888.         {
  1889.             $property['USER_TYPE_SETTINGS'] = unserialize($property['USER_TYPE_SETTINGS']);
  1890.         }
  1891.  
  1892.         $formattedProperty = CIBlockFormatProperties::GetDisplayValue($basketItem, $property, 'sale_out');
  1893.         if (!empty($formattedProperty['DISPLAY_VALUE']))
  1894.         {
  1895.             if (is_array($formattedProperty['DISPLAY_VALUE']))
  1896.             {
  1897.                 foreach ($formattedProperty['DISPLAY_VALUE'] as $key => $formatValue)
  1898.                 {
  1899.                     $result[] = array(
  1900.                         'type' => 'value',
  1901.                         'value' => $formatValue,
  1902.                         'value_raw' => $property['VALUE'][$key]
  1903.                     );
  1904.                 }
  1905.             }
  1906.             else
  1907.             {
  1908.                 $result[] = array(
  1909.                     'type' => 'value',
  1910.                     'value' => $formattedProperty['DISPLAY_VALUE'],
  1911.                     'value_raw' => is_array($property['VALUE']) ? reset($property['VALUE']) : $property['VALUE']
  1912.                 );
  1913.             }
  1914.         }
  1915.  
  1916.         return $result;
  1917.     }
  1918.  
  1919.     public function getFileData($fileId, $orderId = 0, $arSize = array("WIDTH" => 90, "HEIGHT" => 90))
  1920.     {
  1921.         $res = "";
  1922.         $arFile = CFile::GetFileArray($fileId);
  1923.  
  1924.         if ($arFile)
  1925.         {
  1926.             $is_image = CFile::IsImage($arFile["FILE_NAME"], $arFile["CONTENT_TYPE"]);
  1927.             if ($is_image)
  1928.             {
  1929.                 $arImgProduct = CFile::ResizeImageGet($arFile, array("width" => $arSize["WIDTH"], "height" => $arSize["HEIGHT"]), BX_RESIZE_IMAGE_PROPORTIONAL, false, false);
  1930.  
  1931.                 if (is_array($arImgProduct))
  1932.                     $res = array("type" => "image", "value" => $arImgProduct["src"], "source" => $arFile["SRC"]);
  1933.             }
  1934.             else
  1935.                 $res = array("type" => "file", "value" => "<a href=".$arFile["SRC"].">".$arFile["ORIGINAL_NAME"]."</a>");
  1936.         }
  1937.  
  1938.         return $res;
  1939.     }
  1940.  
  1941.     /**
  1942.      * Set formatted order properties to $this->arResult (heavy load due to compatibility)
  1943.      * Execution of 'OnSaleComponentOrderOneStepOrderProps' event
  1944.      */
  1945.     protected function obtainFormattedProperties()
  1946.     {
  1947.         $arResult =& $this->arResult;
  1948.         $arDeleteFieldLocation = array();
  1949.         $propIndex = array();
  1950.         $arOrderProps = $this->order->getPropertyCollection()->getArray();
  1951.         $propsSortedByGroup = array();
  1952.         foreach ($arOrderProps['groups'] as $group)
  1953.         {
  1954.             foreach ($arOrderProps['properties'] as $prop)
  1955.             {
  1956.                 if ($prop['UTIL'] == 'Y' || !empty($prop['RELATION']))
  1957.                     continue;
  1958.  
  1959.                 if ($group['ID'] == $prop['PROPS_GROUP_ID'])
  1960.                 {
  1961.                     $prop['GROUP_NAME'] = $group['NAME'];
  1962.                     $propsSortedByGroup[] = $prop;
  1963.                 }
  1964.             }
  1965.         }
  1966.  
  1967.         foreach ($propsSortedByGroup as $arProperty)
  1968.         {
  1969.             $arProperties = $this->getOrderPropFormatted($arProperty, $arDeleteFieldLocation);
  1970.  
  1971.             $flag = $arProperties["USER_PROPS"] == "Y" ? 'Y' : 'N';
  1972.  
  1973.             $arResult["ORDER_PROP"]["USER_PROPS_".$flag][$arProperties["ID"]] = $arProperties;
  1974.             $propIndex[$arProperties["ID"]] =& $arResult["ORDER_PROP"]["USER_PROPS_".$flag][$arProperties["ID"]];
  1975.  
  1976.             $arResult["ORDER_PROP"]["PRINT"][$arProperties["ID"]] = array(
  1977.                 "ID" => $arProperties["ID"],
  1978.                 "NAME" => $arProperties["NAME"],
  1979.                 "VALUE" => $arProperties["VALUE_FORMATED"],
  1980.                 "SHOW_GROUP_NAME" => $arProperties["SHOW_GROUP_NAME"]
  1981.             );
  1982.         }
  1983.  
  1984.         // additional city property process
  1985.         foreach ($propIndex as $propId => $propDesc)
  1986.         {
  1987.             if (intval($propDesc['INPUT_FIELD_LOCATION']) && isset($propIndex[$propDesc['INPUT_FIELD_LOCATION']]))
  1988.             {
  1989.                 $propIndex[$propDesc['INPUT_FIELD_LOCATION']]['IS_ALTERNATE_LOCATION_FOR'] = $propId;
  1990.                 $propIndex[$propId]['CAN_HAVE_ALTERNATE_LOCATION'] = $propDesc['INPUT_FIELD_LOCATION']; // more strict condition rather INPUT_FIELD_LOCATION, check if the property really exists
  1991.             }
  1992.         }
  1993.  
  1994.         //delete prop for text location (town)
  1995.         if (count($arDeleteFieldLocation) > 0)
  1996.         {
  1997.             foreach ($arDeleteFieldLocation as $fieldId)
  1998.                 unset($arResult["ORDER_PROP"]["USER_PROPS_Y"][$fieldId]);
  1999.         }
  2000.  
  2001.         $this->executeEvent('OnSaleComponentOrderOneStepOrderProps', $this->order);
  2002.     }
  2003.  
  2004.     protected function getOrderPropFormatted($arProperty, &$arDeleteFieldLocation = array())
  2005.     {
  2006.         static $propertyGroupID = 0;
  2007.         static $propertyUSER_PROPS = '';
  2008.  
  2009.         $arProperty['FIELD_NAME'] = 'ORDER_PROP_'.$arProperty['ID'];
  2010.  
  2011.         if ($arProperty['CODE'] != '')
  2012.         {
  2013.             $arProperty['FIELD_ID'] = 'ORDER_PROP_'.$arProperty['CODE'];
  2014.         }
  2015.         else
  2016.         {
  2017.             $arProperty['FIELD_ID'] = 'ORDER_PROP_'.$arProperty['ID'];
  2018.         }
  2019.  
  2020.         if (intval($arProperty['PROPS_GROUP_ID']) != $propertyGroupID || $propertyUSER_PROPS != $arProperty['USER_PROPS'])
  2021.         {
  2022.             $arProperty['SHOW_GROUP_NAME'] = 'Y';
  2023.         }
  2024.  
  2025.         $propertyGroupID = $arProperty['PROPS_GROUP_ID'];
  2026.         $propertyUSER_PROPS = $arProperty['USER_PROPS'];
  2027.  
  2028.         if ($arProperty['REQUIRED'] === 'Y' || $arProperty['IS_PROFILE_NAME'] === 'Y'
  2029.             || $arProperty['IS_LOCATION'] === 'Y' || $arProperty['IS_LOCATION4TAX'] === 'Y'
  2030.             || $arProperty['IS_PAYER'] === 'Y' || $arProperty['IS_ZIP'] === 'Y')
  2031.         {
  2032.             $arProperty['REQUIED'] = 'Y';
  2033.             $arProperty['REQUIED_FORMATED'] = 'Y';
  2034.         }
  2035.  
  2036.         if ($arProperty['IS_LOCATION'] === 'Y')
  2037.         {
  2038.             $deliveryId = CSaleLocation::getLocationIDbyCODE(current($arProperty['VALUE']));
  2039.             $this->arUserResult['DELIVERY_LOCATION'] = $deliveryId;
  2040.             $this->arUserResult['DELIVERY_LOCATION_BCODE'] = current($arProperty['VALUE']);
  2041.         }
  2042.  
  2043.         if ($arProperty['IS_ZIP'] === 'Y')
  2044.         {
  2045.             $this->arUserResult['DELIVERY_LOCATION_ZIP'] = current($arProperty['VALUE']);
  2046.         }
  2047.  
  2048.         if ($arProperty['IS_LOCATION4TAX'] === 'Y')
  2049.         {
  2050.             $taxId = CSaleLocation::getLocationIDbyCODE(current($arProperty['VALUE']));
  2051.             $this->arUserResult['TAX_LOCATION'] = $taxId;
  2052.             $this->arUserResult['TAX_LOCATION_BCODE'] = current($arProperty['VALUE']);
  2053.         }
  2054.  
  2055.         if ($arProperty['IS_PAYER'] === 'Y')
  2056.         {
  2057.             $this->arUserResult['PAYER_NAME'] = current($arProperty['VALUE']);
  2058.         }
  2059.  
  2060.         if ($arProperty['IS_EMAIL'] === 'Y')
  2061.         {
  2062.             $this->arUserResult['USER_EMAIL'] = current($arProperty['VALUE']);
  2063.         }
  2064.  
  2065.         if ($arProperty['IS_PROFILE_NAME'] === 'Y')
  2066.         {
  2067.             $this->arUserResult['PROFILE_NAME'] = current($arProperty['VALUE']);
  2068.         }
  2069.  
  2070.         switch ($arProperty['TYPE'])
  2071.         {
  2072.             case 'Y/N': self::formatYN($arProperty); break;
  2073.             case 'STRING': self::formatString($arProperty); break;
  2074.             case 'NUMBER': self::formatNumber($arProperty); break;
  2075.             case 'ENUM': self::formatEnum($arProperty); break;
  2076.             case 'LOCATION':
  2077.                 self::formatLocation($arProperty, $arDeleteFieldLocation, $this->arResult['LOCATION_ALT_PROP_DISPLAY_MANUAL']);
  2078.                 break;
  2079.             case 'FILE': self::formatFile($arProperty); break;
  2080.             case 'DATE': self::formatDate($arProperty); break;
  2081.         }
  2082.  
  2083.         return $arProperty;
  2084.     }
  2085.  
  2086.     public static function formatYN(array &$arProperty)
  2087.     {
  2088.         $curVal = $arProperty['VALUE'];
  2089.  
  2090.         if (current($curVal) == "Y")
  2091.         {
  2092.             $arProperty["CHECKED"] = "Y";
  2093.             $arProperty["VALUE_FORMATED"] = Loc::getMessage("SOA_Y");
  2094.         }
  2095.         else
  2096.             $arProperty["VALUE_FORMATED"] = Loc::getMessage("SOA_N");
  2097.  
  2098.         $arProperty["SIZE1"] = (intval($arProperty["SIZE1"]) > 0) ? $arProperty["SIZE1"] : 30;
  2099.  
  2100.         $arProperty["VALUE"] = current($curVal);
  2101.         $arProperty["TYPE"] = 'CHECKBOX';
  2102.     }
  2103.  
  2104.     public static function formatString(array &$arProperty)
  2105.     {
  2106.         $curVal = $arProperty['VALUE'];
  2107.  
  2108.         if (!empty($arProperty["MULTILINE"]) && $arProperty["MULTILINE"] == 'Y')
  2109.         {
  2110.             $arProperty["TYPE"] = 'TEXTAREA';
  2111.             $arProperty["SIZE2"] = (intval($arProperty["ROWS"]) > 0) ? $arProperty["ROWS"] : 4;
  2112.             $arProperty["SIZE1"] = (intval($arProperty["COLS"]) > 0) ? $arProperty["COLS"] : 40;
  2113.         }
  2114.         else
  2115.             $arProperty["TYPE"] = 'TEXT';
  2116.  
  2117.         $arProperty["SOURCE"] = current($curVal) == $arProperty['DEFAULT_VALUE'] ? 'DEFAULT' : 'FORM';
  2118.         $arProperty["VALUE"] = current($curVal);
  2119.         $arProperty["VALUE_FORMATED"] = $arProperty["VALUE"];
  2120.     }
  2121.  
  2122.     public static function formatNumber(array &$arProperty)
  2123.     {
  2124.         $curVal = $arProperty['VALUE'];
  2125.         $arProperty["TYPE"] = 'TEXT';
  2126.         $arProperty["VALUE"] = current($curVal);
  2127.         $arProperty["VALUE_FORMATED"] = $arProperty["VALUE"];
  2128.     }
  2129.  
  2130.     public static function formatEnum(array &$arProperty)
  2131.     {
  2132.         $curVal = $arProperty['VALUE'];
  2133.  
  2134.         if ($arProperty["MULTIELEMENT"] == 'Y')
  2135.         {
  2136.             if ($arProperty["MULTIPLE"] == 'Y')
  2137.             {
  2138.                 $setValue = array();
  2139.                 $arProperty["FIELD_NAME"] = "ORDER_PROP_".$arProperty["ID"].'[]';
  2140.                 $arProperty["SIZE1"] = (intval($arProperty["SIZE1"]) > 0) ? $arProperty["SIZE1"] : 5;
  2141.  
  2142.                 $i = 0;
  2143.                 foreach ($arProperty["OPTIONS"] as $val => $name)
  2144.                 {
  2145.                     $arVariants = array(
  2146.                         'VALUE' => $val,
  2147.                         'NAME' => $name
  2148.                     );
  2149.                     if ((is_array($curVal) && in_array($arVariants["VALUE"], $curVal)))
  2150.                     {
  2151.                         $arVariants["SELECTED"] = "Y";
  2152.                         if ($i > 0)
  2153.                             $arProperty["VALUE_FORMATED"] .= ", ";
  2154.                         $arProperty["VALUE_FORMATED"] .= $arVariants["NAME"];
  2155.                         $setValue[] = $arVariants["VALUE"];
  2156.                         $i++;
  2157.                     }
  2158.                     $arProperty["VARIANTS"][] = $arVariants;
  2159.                 }
  2160.  
  2161.                 $arProperty["TYPE"] = 'MULTISELECT';
  2162.             }
  2163.             else
  2164.             {
  2165.                 foreach ($arProperty['OPTIONS'] as $val => $name)
  2166.                 {
  2167.                     $arVariants = array(
  2168.                         'VALUE' => $val,
  2169.                         'NAME' => $name
  2170.                     );
  2171.                     if ($arVariants["VALUE"] == current($curVal))
  2172.                     {
  2173.                         $arVariants["CHECKED"] = "Y";
  2174.                         $arProperty["VALUE_FORMATED"] = $arVariants["NAME"];
  2175.                     }
  2176.  
  2177.                     $arProperty["VARIANTS"][] = $arVariants;
  2178.                 }
  2179.                 $arProperty["TYPE"] = 'RADIO';
  2180.             }
  2181.         }
  2182.         else
  2183.         {
  2184.             if ($arProperty["MULTIPLE"] == 'Y')
  2185.             {
  2186.                 $setValue = array();
  2187.                 $arProperty["FIELD_NAME"] = "ORDER_PROP_".$arProperty["ID"].'[]';
  2188.                 $arProperty["SIZE1"] = ((intval($arProperty["SIZE1"]) > 0) ? $arProperty["SIZE1"] : 5);
  2189.  
  2190.                 $i = 0;
  2191.                 foreach ($arProperty["OPTIONS"] as $val => $name)
  2192.                 {
  2193.                     $arVariants = array(
  2194.                         'VALUE' => $val,
  2195.                         'NAME' => $name
  2196.                     );
  2197.                     if (is_array($curVal) && in_array($arVariants["VALUE"], $curVal))
  2198.                     {
  2199.                         $arVariants["SELECTED"] = "Y";
  2200.                         if ($i > 0)
  2201.                             $arProperty["VALUE_FORMATED"] .= ", ";
  2202.                         $arProperty["VALUE_FORMATED"] .= $arVariants["NAME"];
  2203.                         $setValue[] = $arVariants["VALUE"];
  2204.                         $i++;
  2205.                     }
  2206.                     $arProperty["VARIANTS"][] = $arVariants;
  2207.                 }
  2208.  
  2209.                 $arProperty["TYPE"] = 'MULTISELECT';
  2210.             }
  2211.             else
  2212.             {
  2213.                 $arProperty["SIZE1"] = ((intval($arProperty["SIZE1"]) > 0) ? $arProperty["SIZE1"] : 1);
  2214.                 $flagDefault = "N";
  2215.                 $nameProperty = "";
  2216.                 foreach ($arProperty["OPTIONS"] as $val => $name)
  2217.                 {
  2218.                     $arVariants = array(
  2219.                         'VALUE' => $val,
  2220.                         'NAME' => $name
  2221.                     );
  2222.                     if ($flagDefault == "N" && $nameProperty == "")
  2223.                     {
  2224.                         $nameProperty = $arVariants["NAME"];
  2225.                     }
  2226.                     if ($arVariants["VALUE"] == current($curVal))
  2227.                     {
  2228.                         $arVariants["SELECTED"] = "Y";
  2229.                         $arProperty["VALUE_FORMATED"] = $arVariants["NAME"];
  2230.                         $flagDefault = "Y";
  2231.                     }
  2232.                     $arProperty["VARIANTS"][] = $arVariants;
  2233.                 }
  2234.                 if ($flagDefault == "N")
  2235.                 {
  2236.                     $arProperty["VARIANTS"][0]["SELECTED"]= "Y";
  2237.                     $arProperty["VARIANTS"][0]["VALUE_FORMATED"] = $nameProperty;
  2238.                 }
  2239.                 $arProperty["TYPE"] = 'SELECT';
  2240.             }
  2241.         }
  2242.     }
  2243.  
  2244.     public static function formatLocation(array &$arProperty, array &$arDeleteFieldLocation, $locationAltPropDisplayManual = null)
  2245.     {
  2246.         $curVal = CSaleLocation::getLocationIDbyCODE(current($arProperty['VALUE']));
  2247.         $arProperty["VALUE"] = $curVal;
  2248.  
  2249.         $locationFound = false;
  2250.         //todo select via D7
  2251.         $dbVariants = CSaleLocation::GetList(
  2252.             array("SORT" => "ASC", "COUNTRY_NAME_LANG" => "ASC", "CITY_NAME_LANG" => "ASC"),
  2253.             array("LID" => LANGUAGE_ID),
  2254.             false,
  2255.             false,
  2256.             array("ID", "COUNTRY_NAME", "CITY_NAME", "SORT", "COUNTRY_NAME_LANG", "CITY_NAME_LANG", "CITY_ID", "CODE")
  2257.         );
  2258.         while ($arVariants = $dbVariants->GetNext())
  2259.         {
  2260.             $city = !empty($arVariants['CITY_NAME']) ? ' - '.$arVariants['CITY_NAME'] : '';
  2261.  
  2262.             if ($arVariants['ID'] === $curVal)
  2263.             {
  2264.                 // set formatted value
  2265.                 $locationFound = $arVariants;
  2266.                 $arVariants['SELECTED'] = 'Y';
  2267.                 $arProperty['VALUE_FORMATED'] = $arVariants['COUNTRY_NAME'].$city;
  2268.             }
  2269.  
  2270.             $arVariants['NAME'] = $arVariants['COUNTRY_NAME'].$city;
  2271.             // save to variants
  2272.             $arProperty['VARIANTS'][] = $arVariants;
  2273.         }
  2274.  
  2275.         if(!$locationFound && intval($curVal))
  2276.         {
  2277.             $item = CSaleLocation::GetById($curVal);
  2278.             if ($item)
  2279.             {
  2280.                 // set formatted value
  2281.                 $locationFound = $item;
  2282.                 $arProperty["VALUE_FORMATED"] = $item["COUNTRY_NAME"].((strlen($item["CITY_NAME"]) > 0) ? " - " : "").$item["CITY_NAME"];
  2283.                 $item['SELECTED'] = 'Y';
  2284.                 $item['NAME'] = $item["COUNTRY_NAME"].((strlen($item["CITY_NAME"]) > 0) ? " - " : "").$item["CITY_NAME"];
  2285.  
  2286.                 // save to variants
  2287.                 $arProperty["VARIANTS"][] = $item;
  2288.             }
  2289.         }
  2290.  
  2291.         if ($locationFound)
  2292.         {
  2293.             // enable location town text
  2294.             if (isset($locationAltPropDisplayManual)) // its an ajax-hit and sale.location.selector.steps is used
  2295.             {
  2296.                 if (intval($locationAltPropDisplayManual[$arProperty["ID"]])) // user MANUALLY selected "Other location" in the selector
  2297.                     unset($arDeleteFieldLocation[$arProperty["ID"]]);
  2298.                 else
  2299.                     $arDeleteFieldLocation[$arProperty["ID"]] = $arProperty["INPUT_FIELD_LOCATION"];
  2300.             }
  2301.             else
  2302.             {
  2303.                 if ($arProperty["IS_LOCATION"] == "Y" && intval($arProperty["INPUT_FIELD_LOCATION"]) > 0)
  2304.                 {
  2305.                     if (intval($locationFound["CITY_ID"]) <= 0)
  2306.                         unset($arDeleteFieldLocation[$arProperty["ID"]]);
  2307.                     else
  2308.                         $arDeleteFieldLocation[$arProperty["ID"]] = $arProperty["INPUT_FIELD_LOCATION"];
  2309.                 }
  2310.             }
  2311.         }
  2312.         else
  2313.         {
  2314.             // nothing found, may be it is the first load - hide
  2315.             $arDeleteFieldLocation[$arProperty["ID"]] = $arProperty["INPUT_FIELD_LOCATION"];
  2316.         }
  2317.     }
  2318.  
  2319.     public static function formatFile(array &$arProperty)
  2320.     {
  2321.         $curVal = $arProperty['VALUE'];
  2322.  
  2323.         $arProperty["SIZE1"] = intval($arProperty["SIZE1"]);
  2324.         if ($arProperty['MULTIPLE'] == 'Y')
  2325.         {
  2326.             $arr = array();
  2327.             $curVal = isset($curVal) ? $curVal : $arProperty["DEFAULT_VALUE"];
  2328.             foreach ($curVal as $file)
  2329.             {
  2330.                 $arr[] = $file['ID'];
  2331.             }
  2332.             $arProperty["VALUE"] = serialize($arr);
  2333.         }
  2334.         else
  2335.         {
  2336.             $arFile = isset($curVal) && is_array($curVal) ? current($curVal) : $arProperty["DEFAULT_VALUE"];
  2337.             if (is_array($arFile))
  2338.                 $arProperty["VALUE"] = $arFile['ID'];
  2339.         }
  2340.     }
  2341.  
  2342.     public static function formatDate(array &$arProperty)
  2343.     {
  2344.         $arProperty["VALUE"] = current($arProperty['VALUE']);
  2345.         $arProperty["VALUE_FORMATED"] = $arProperty["VALUE"];
  2346.     }
  2347.  
  2348.     /**
  2349.      * Set basket items data from order object to $this->arResult
  2350.      */
  2351.     protected function obtainBasket()
  2352.     {
  2353.         $arResult =& $this->arResult;
  2354.  
  2355.         $arResult["MAX_DIMENSIONS"] = $arResult["ITEMS_DIMENSIONS"] = array();
  2356.         $arResult["BASKET_ITEMS"] = array();
  2357.         /** @var Sale\BasketItem $basketItem */
  2358.         foreach ($this->order->getBasket() as $basketItem)
  2359.         {
  2360.             $arBasketItem = $basketItem->getFieldValues();
  2361.             if ($basketItem->getVatRate() > 0)
  2362.             {
  2363.                 $arResult["bUsingVat"] = "Y";
  2364.                 $arBasketItem["VAT_VALUE"] = $basketItem->getVat();
  2365.             }
  2366.             $arBasketItem["QUANTITY"] = $basketItem->getQuantity();
  2367.             $arBasketItem["PRICE_FORMATED"] = SaleFormatCurrency($basketItem->getPrice(), $this->order->getCurrency());
  2368.             $arBasketItem["WEIGHT_FORMATED"] = roundEx(doubleval($basketItem->getWeight()/$arResult["WEIGHT_KOEF"]), SALE_WEIGHT_PRECISION)." ".$arResult["WEIGHT_UNIT"];
  2369.             $arBasketItem["DISCOUNT_PRICE"] = $basketItem->getDiscountPrice();
  2370.  
  2371.             if (($basketItem->getDiscountPrice() + $basketItem->getPrice()) > 0)
  2372.                 $arBasketItem["DISCOUNT_PRICE_PERCENT"] = $basketItem->getDiscountPrice() * 100 / ($basketItem->getDiscountPrice() + $basketItem->getPrice());
  2373.             else
  2374.                 $arBasketItem["DISCOUNT_PRICE_PERCENT"] = 0;
  2375.  
  2376.             $arBasketItem["DISCOUNT_PRICE_PERCENT_FORMATED"] = Bitrix\Sale\PriceMaths::roundPrecision($arBasketItem["DISCOUNT_PRICE_PERCENT"])."%";
  2377.             $arBasketItem["BASE_PRICE_FORMATED"] = SaleFormatCurrency($basketItem->getBasePrice(), $this->order->getCurrency());
  2378.  
  2379.             $arDim = unserialize($basketItem->getField('DIMENSIONS'));
  2380.             if (is_array($arDim))
  2381.             {
  2382.                 $arResult["MAX_DIMENSIONS"] = CSaleDeliveryHelper::getMaxDimensions(
  2383.                     array(
  2384.                         $arDim["WIDTH"],
  2385.                         $arDim["HEIGHT"],
  2386.                         $arDim["LENGTH"]
  2387.                     ),
  2388.                     $arResult["MAX_DIMENSIONS"]);
  2389.  
  2390.                 $arResult["ITEMS_DIMENSIONS"][] = $arDim;
  2391.             }
  2392.  
  2393.             $arBasketItem["PROPS"] = array();
  2394.             /** @var Sale\BasketPropertiesCollection $propertyCollection */
  2395.             $propertyCollection = $basketItem->getPropertyCollection();
  2396.             $propList = $propertyCollection->getPropertyValues();
  2397.             foreach ($propList as $key => &$prop)
  2398.             {
  2399.                 if ($prop['CODE'] == 'CATALOG.XML_ID' || $prop['CODE'] == 'PRODUCT.XML_ID' || $prop['CODE'] == 'SUM_OF_CHARGE')
  2400.                     continue;
  2401.  
  2402.                 $prop = array_filter($prop, array("CSaleBasketHelper", "filterFields"));
  2403.                 $arBasketItem["PROPS"][] = $prop;
  2404.             }
  2405.  
  2406.             $this->arElementId[] = $arBasketItem["PRODUCT_ID"];
  2407.             $arBasketItem["SUM_NUM"] = $basketItem->getPrice() * $basketItem->getQuantity();
  2408.             $arBasketItem["SUM"] = SaleFormatCurrency($basketItem->getPrice() * $basketItem->getQuantity(), $this->order->getCurrency());
  2409.             $arBasketItem["SUM_BASE"] = $basketItem->getBasePrice() * $basketItem->getQuantity();
  2410.             $arBasketItem["SUM_BASE_FORMATED"] = SaleFormatCurrency($basketItem->getBasePrice() * $basketItem->getQuantity(), $this->order->getCurrency());
  2411.  
  2412.             $arResult["BASKET_ITEMS"][] = $arBasketItem;
  2413.         }
  2414.     }
  2415.  
  2416.     /**
  2417.      * Set basket items data from iblocks (basket column properties, sku, preview pictures, etc) to $this->arResult
  2418.      */
  2419.     protected function obtainPropertiesForIbElements()
  2420.     {
  2421.         if (empty($this->arElementId))
  2422.         {
  2423.             return;
  2424.         }
  2425.  
  2426.         $arResult =& $this->arResult;
  2427.         $arResult["GRID"]["ROWS"] = array();
  2428.         $arParents = array();
  2429.  
  2430.         if ($this->useCatalog)
  2431.         {
  2432.             $arParents = CCatalogSku::getProductList($this->arElementId);
  2433.             if (!empty($arParents))
  2434.             {
  2435.                 foreach ($arParents as $productId => $arParent)
  2436.                 {
  2437.                     $this->arElementId[] = $arParent["ID"];
  2438.                     $this->arSku2Parent[$productId] = $arParent["ID"];
  2439.                 }
  2440.             }
  2441.         }
  2442.  
  2443.         $arElementData = array();
  2444.         $arProductData = array();
  2445.         $elementIndex = array();
  2446.         $res = CIBlockElement::GetList(
  2447.             array(),
  2448.             array("=ID" => array_unique($this->arElementId)),
  2449.             false,
  2450.             false,
  2451.             array("ID", "IBLOCK_ID", "PREVIEW_PICTURE", "DETAIL_PICTURE", "PREVIEW_TEXT")
  2452.         );
  2453.         while ($arElement = $res->Fetch())
  2454.         {
  2455.             $arElementData[$arElement["IBLOCK_ID"]][] = $arElement["ID"];
  2456.             $arProductData[$arElement["ID"]] = $arElement;
  2457.             $elementIndex[$arElement["ID"]] = array();
  2458.         }
  2459.  
  2460.         foreach ($arElementData as $iBlockId => $arElemId)
  2461.         {
  2462.             $arCodes = array();
  2463.             if (!empty($this->arIblockProps[$iBlockId]))
  2464.                 $arCodes = array_keys($this->arIblockProps[$iBlockId]);
  2465.  
  2466.             $imageCode = $this->arParams['ADDITIONAL_PICT_PROP'][$iBlockId];
  2467.  
  2468.             if (!empty($imageCode) && !in_array($imageCode, $arCodes))
  2469.                 $arCodes[] = $imageCode;
  2470.  
  2471.             if (!empty($arCodes))
  2472.             {
  2473.                 CIBlockElement::GetPropertyValuesArray($elementIndex, $iBlockId,
  2474.                     array("ID" => $arElemId),
  2475.                     array("CODE" => $arCodes)
  2476.                 );
  2477.             }
  2478.         }
  2479.         unset($arElementData);
  2480.  
  2481.         $arAdditionalImages = array();
  2482.         foreach ($elementIndex as $productId => $productProperties)
  2483.         {
  2484.             if (!empty($productProperties) && is_array($productProperties))
  2485.             {
  2486.                 foreach ($productProperties as $code => $property)
  2487.                 {
  2488.                     if (
  2489.                         !empty($this->arParams['ADDITIONAL_PICT_PROP'])
  2490.                         && array_key_exists($arProductData[$productId]['IBLOCK_ID'], $this->arParams['ADDITIONAL_PICT_PROP'])
  2491.                     )
  2492.                     {
  2493.                         if ($this->arParams['ADDITIONAL_PICT_PROP'][$arProductData[$productId]['IBLOCK_ID']] == $code)
  2494.                         {
  2495.                             $arAdditionalImages[$productId] = is_array($property['VALUE']) ? current($property['VALUE']) : $property['VALUE'];
  2496.                         }
  2497.                     }
  2498.  
  2499.                     if (
  2500.                         !empty($this->arIblockProps[$arProductData[$productId]['IBLOCK_ID']])
  2501.                         && array_key_exists($code, $this->arIblockProps[$arProductData[$productId]['IBLOCK_ID']])
  2502.                     )
  2503.                     {
  2504.                         if (is_array($property['VALUE']))
  2505.                         {
  2506.                             $arProductData[$productId]['PROPERTY_'.$code.'_VALUE'] = implode(', ', $property['VALUE']);
  2507.                         }
  2508.                         else
  2509.                         {
  2510.                             $arProductData[$productId]['PROPERTY_'.$code.'_VALUE'] = $property['VALUE'];
  2511.                         }
  2512.  
  2513.                         if (is_array($property['PROPERTY_VALUE_ID']))
  2514.                         {
  2515.                             $arProductData[$productId]['PROPERTY_'.$code.'_VALUE_ID'] = implode(', ', $property['PROPERTY_VALUE_ID']);
  2516.                         }
  2517.                         else
  2518.                         {
  2519.                             $arProductData[$productId]['PROPERTY_'.$code.'_VALUE_ID'] = $property['PROPERTY_VALUE_ID'];
  2520.                         }
  2521.  
  2522.                         if ($property['PROPERTY_TYPE'] == 'L')
  2523.                         {
  2524.                             $arProductData[$productId]['PROPERTY_'.$code.'_ENUM_ID'] = $property['VALUE_ENUM_ID'];
  2525.                         }
  2526.                     }
  2527.                 }
  2528.             }
  2529.         }
  2530.         unset($elementIndex);
  2531.  
  2532.         $currentProductProperties = array();
  2533.  
  2534.         $needToResizeProductImages = $this->arParams['COMPATIBLE_MODE'] === 'Y'
  2535.             || isset($this->arParams['PRODUCT_COLUMNS']['PREVIEW_PICTURE'])
  2536.             || isset($this->arParams['PRODUCT_COLUMNS']['DETAIL_PICTURE'])
  2537.             || isset($this->arParams['PRODUCT_COLUMNS_HIDDEN']['PREVIEW_PICTURE'])
  2538.             || isset($this->arParams['PRODUCT_COLUMNS_HIDDEN']['DETAIL_PICTURE']);
  2539.  
  2540.  
  2541.         foreach ($arResult["BASKET_ITEMS"] as &$arResultItem)
  2542.         {
  2543.             $productId = $arResultItem["PRODUCT_ID"];
  2544.             $arParent = $arParents[$productId];
  2545.             $itemIblockId = intval($arProductData[$productId]['IBLOCK_ID']);
  2546.             $currentProductProperties[$productId] = isset($this->arIblockProps[$itemIblockId])
  2547.                 ? $this->arIblockProps[$itemIblockId]
  2548.                 : array();
  2549.  
  2550.             if (
  2551.                 (int)$arProductData[$productId]["PREVIEW_PICTURE"] <= 0
  2552.                 && (int)$arProductData[$productId]["DETAIL_PICTURE"] <= 0
  2553.                 && $arParent
  2554.             )
  2555.             {
  2556.                 $productId = $arParent["ID"];
  2557.             }
  2558.  
  2559.             if ((int)$arProductData[$productId]["PREVIEW_PICTURE"] > 0)
  2560.             {
  2561.                 $arResultItem["PREVIEW_PICTURE"] = $arProductData[$productId]["PREVIEW_PICTURE"];
  2562.             }
  2563.  
  2564.             if ((int)$arProductData[$productId]["DETAIL_PICTURE"] > 0)
  2565.             {
  2566.                 $arResultItem["DETAIL_PICTURE"] = $arProductData[$productId]["DETAIL_PICTURE"];
  2567.             }
  2568.  
  2569.             if ($arProductData[$productId]["PREVIEW_TEXT"] != '')
  2570.             {
  2571.                 $arResultItem["PREVIEW_TEXT"] = $arProductData[$productId]["PREVIEW_TEXT"];
  2572.                 $arResultItem["PREVIEW_TEXT_TYPE"] = $arProductData[$productId]["PREVIEW_TEXT_TYPE"];
  2573.             }
  2574.  
  2575.             if (!empty($arProductData[$arResultItem["PRODUCT_ID"]]) && is_array($arProductData[$arResultItem["PRODUCT_ID"]]))
  2576.             {
  2577.                 foreach ($arProductData[$arResultItem["PRODUCT_ID"]] as $key => $value)
  2578.                 {
  2579.                     if (strpos($key, "PROPERTY_") !== false)
  2580.                         $arResultItem[$key] = $value;
  2581.                 }
  2582.             }
  2583.  
  2584.             // if sku element doesn't have some property value - we'll show parent element value instead
  2585.             if (isset($this->arSku2Parent[$arResultItem["PRODUCT_ID"]]))
  2586.             {
  2587.                 $parentIblockId = $arProductData[$this->arSku2Parent[$arResultItem["PRODUCT_ID"]]]['IBLOCK_ID'];
  2588.  
  2589.                 if (!empty($this->arIblockProps[$parentIblockId]))
  2590.                 {
  2591.                     $currentProductProperties[$arResultItem["PRODUCT_ID"]] = array_merge(
  2592.                         $this->arIblockProps[$parentIblockId],
  2593.                         $currentProductProperties[$arResultItem["PRODUCT_ID"]]
  2594.                     );
  2595.                 }
  2596.  
  2597.                 foreach ($this->arCustomSelectFields as $field)
  2598.                 {
  2599.                     $fieldVal = $field."_VALUE";
  2600.                     $parentId = $this->arSku2Parent[$arResultItem["PRODUCT_ID"]];
  2601.  
  2602.                     // can be array or string
  2603.                     if (
  2604.                         (!isset($arResultItem[$fieldVal]) || (isset($arResultItem[$fieldVal]) && strlen($arResultItem[$fieldVal]) == 0))
  2605.                         && (isset($arProductData[$parentId][$fieldVal]) && !empty($arProductData[$parentId][$fieldVal]))
  2606.                     )
  2607.                     {
  2608.                         $arResultItem[$fieldVal] = $arProductData[$parentId][$fieldVal];
  2609.                     }
  2610.                 }
  2611.             }
  2612.  
  2613.             // replace PREVIEW_PICTURE with selected ADDITIONAL_PICT_PROP
  2614.             if (
  2615.                 empty($arProductData[$arResultItem["PRODUCT_ID"]]["PREVIEW_PICTURE"])
  2616.                 && empty($arProductData[$arResultItem["PRODUCT_ID"]]["DETAIL_PICTURE"])
  2617.                 && $arAdditionalImages[$arResultItem["PRODUCT_ID"]]
  2618.             )
  2619.             {
  2620.                 $arResultItem["PREVIEW_PICTURE"] = $arAdditionalImages[$arResultItem["PRODUCT_ID"]];
  2621.             }
  2622.             elseif (
  2623.                 empty($arResultItem["PREVIEW_PICTURE"])
  2624.                 && empty($arResultItem["DETAIL_PICTURE"])
  2625.                 && $arAdditionalImages[$productId]
  2626.             )
  2627.             {
  2628.                 $arResultItem["PREVIEW_PICTURE"] = $arAdditionalImages[$productId];
  2629.             }
  2630.  
  2631.             $arResultItem["PREVIEW_PICTURE_SRC"] = "";
  2632.  
  2633.             if (
  2634.                 $needToResizeProductImages
  2635.                 && isset($arResultItem["PREVIEW_PICTURE"])
  2636.                 && (int)$arResultItem["PREVIEW_PICTURE"] > 0
  2637.             )
  2638.             {
  2639.                 $arImage = CFile::GetFileArray($arResultItem["PREVIEW_PICTURE"]);
  2640.                 if (!empty($arImage))
  2641.                 {
  2642.                     self::resizeImage($arResultItem, 'PREVIEW_PICTURE', $arImage,
  2643.                         array("width" => 320, "height" => 320),
  2644.                         array("width" => 110, "height" => 110),
  2645.                         $this->arParams['BASKET_IMAGES_SCALING']
  2646.                     );
  2647.                 }
  2648.             }
  2649.  
  2650.             $arResultItem["DETAIL_PICTURE_SRC"] = "";
  2651.  
  2652.             if (
  2653.                 $needToResizeProductImages
  2654.                 && isset($arResultItem["DETAIL_PICTURE"])
  2655.                 && (int)$arResultItem["DETAIL_PICTURE"] > 0
  2656.             )
  2657.             {
  2658.                 $arImage = CFile::GetFileArray($arResultItem["DETAIL_PICTURE"]);
  2659.                 if (!empty($arImage))
  2660.                 {
  2661.                     self::resizeImage($arResultItem, 'DETAIL_PICTURE', $arImage,
  2662.                         array("width" => 320, "height" => 320),
  2663.                         array("width" => 110, "height" => 110),
  2664.                         $this->arParams['BASKET_IMAGES_SCALING']
  2665.                     );
  2666.                 }
  2667.             }
  2668.         }
  2669.  
  2670.         if (!empty($arResult["BASKET_ITEMS"]) && $this->useCatalog)
  2671.         {
  2672.             $arResult["BASKET_ITEMS"] = getMeasures($arResult["BASKET_ITEMS"]);
  2673.         }
  2674.  
  2675.         foreach ($arResult["BASKET_ITEMS"] as $arBasketItem)
  2676.         {
  2677.             // prepare values for custom-looking columns
  2678.             $arCols = array(
  2679.                 "PROPS" => $this->getPropsInfo($arBasketItem)
  2680.             );
  2681.  
  2682.             if ($this->arParams['COMPATIBLE_MODE'] === 'Y')
  2683.             {
  2684.                 if (isset($arBasketItem["PREVIEW_PICTURE"]) && (int)$arBasketItem["PREVIEW_PICTURE"] > 0)
  2685.                 {
  2686.                     $arCols["PREVIEW_PICTURE"] = CSaleHelper::getFileInfo(
  2687.                         $arBasketItem["PREVIEW_PICTURE"],
  2688.                         array("WIDTH" => 110, "HEIGHT" => 110)
  2689.                     );
  2690.                 }
  2691.  
  2692.                 if (isset($arBasketItem["DETAIL_PICTURE"]) && (int)$arBasketItem["DETAIL_PICTURE"] > 0)
  2693.                 {
  2694.                     $arCols["DETAIL_PICTURE"] = CSaleHelper::getFileInfo(
  2695.                         $arBasketItem["DETAIL_PICTURE"],
  2696.                         array("WIDTH"=> 110, "HEIGHT" => 110)
  2697.                     );
  2698.                 }
  2699.             }
  2700.  
  2701.             if (!empty($arBasketItem["MEASURE_TEXT"]))
  2702.             {
  2703.                 $arCols["QUANTITY"] = $arBasketItem["QUANTITY"]."&nbsp;".$arBasketItem["MEASURE_TEXT"];
  2704.             }
  2705.  
  2706.             foreach ($arBasketItem as $tmpKey => $value)
  2707.             {
  2708.                 if ((strpos($tmpKey, "PROPERTY_", 0) === 0) && (strrpos($tmpKey, "_VALUE") == strlen($tmpKey) - 6))
  2709.                 {
  2710.                     $code = str_replace(array("PROPERTY_", "_VALUE"), "", $tmpKey);
  2711.                     $propData = $currentProductProperties[$arBasketItem['PRODUCT_ID']][$code];
  2712.  
  2713.                     // display linked property type
  2714.                     if ($propData['PROPERTY_TYPE'] === 'E')
  2715.                     {
  2716.                         $propData['VALUE'] = $value;
  2717.                         $arCols[$tmpKey] = $this->getLinkedPropValue($arBasketItem, $propData);
  2718.                     }
  2719.                     elseif ($propData['PROPERTY_TYPE'] === 'S' && $propData['USER_TYPE'] === 'directory')
  2720.                     {
  2721.                         $arCols[$tmpKey] = $this->getDirectoryProperty($arBasketItem, $propData);
  2722.                     }
  2723.                     else
  2724.                     {
  2725.                         $arCols[$tmpKey] = $this->getIblockProps($value, $propData, array('WIDTH' => 110, 'HEIGHT' => 110));
  2726.                     }
  2727.                 }
  2728.             }
  2729.  
  2730.             $arResult["GRID"]["ROWS"][$arBasketItem["ID"]] = array(
  2731.                 "id" => $arBasketItem["ID"],
  2732.                 "data" => $arBasketItem,
  2733.                 "actions" => array(),
  2734.                 "columns" => $arCols,
  2735.                 "editable" => true
  2736.             );
  2737.         }
  2738.     }
  2739.  
  2740.     /**
  2741.      * Set delivery data from shipment object and delivery services object to $this->arResult
  2742.      * Execution of 'OnSaleComponentOrderOneStepDelivery' event
  2743.      *
  2744.      * @throws Main\NotSupportedException
  2745.      */
  2746.     protected function obtainDelivery()
  2747.     {
  2748.         $arResult =& $this->arResult;
  2749.  
  2750.         $arStoreId = array();
  2751.         /** @var Shipment $shipment */
  2752.         $shipment = $this->getCurrentShipment($this->order);
  2753.  
  2754.         if (!empty($this->arDeliveryServiceAll))
  2755.         {
  2756.             foreach ($this->arDeliveryServiceAll as $deliveryObj)
  2757.             {
  2758.                 $arDelivery =& $this->arResult["DELIVERY"][$deliveryObj->getId()];
  2759.  
  2760.                 $arDelivery['ID'] = $deliveryObj->getId();
  2761.                 $arDelivery['NAME'] = $deliveryObj->isProfile() ? $deliveryObj->getNameWithParent() : $deliveryObj->getName();
  2762.                 $arDelivery['OWN_NAME'] = $deliveryObj->getName();
  2763.                 $arDelivery['DESCRIPTION'] = $deliveryObj->getDescription();
  2764.                 $arDelivery['FIELD_NAME'] = 'DELIVERY_ID';
  2765.                 $arDelivery["CURRENCY"] = $this->order->getCurrency();
  2766.                 $arDelivery['SORT'] = $deliveryObj->getSort();
  2767.                 $arDelivery['EXTRA_SERVICES'] = $deliveryObj->getExtraServices()->getItems();
  2768.                 $arDelivery['STORE'] = Delivery\ExtraServices\Manager::getStoresList($deliveryObj->getId());
  2769.  
  2770.                 if (intval($deliveryObj->getLogotip()) > 0)
  2771.                     $arDelivery["LOGOTIP"] = CFile::GetFileArray($deliveryObj->getLogotip());
  2772.  
  2773.                 if (!empty($arDelivery['STORE']) && is_array($arDelivery['STORE']))
  2774.                 {
  2775.                     foreach ($arDelivery['STORE'] as $val)
  2776.                         $arStoreId[$val] = $val;
  2777.                 }
  2778.  
  2779.                 $buyerStore = $this->request->get('BUYER_STORE');
  2780.                 if (!empty($buyerStore) && !empty($arDelivery['STORE']) && is_array($arDelivery['STORE']) && in_array($buyerStore, $arDelivery['STORE']))
  2781.                 {
  2782.                     $this->arUserResult['DELIVERY_STORE'] = $arDelivery["ID"];
  2783.                 }
  2784.             }
  2785.         }
  2786.  
  2787.         $arResult["BUYER_STORE"] = $shipment->getStoreId();
  2788.  
  2789.         $arStore = array();
  2790.         $dbList = CCatalogStore::GetList(
  2791.             array("SORT" => "DESC", "ID" => "DESC"),
  2792.             array("ACTIVE" => "Y", "ID" => $arStoreId, "ISSUING_CENTER" => "Y", "+SITE_ID" => SITE_ID),
  2793.             false,
  2794.             false,
  2795.             array("ID", "TITLE", "ADDRESS", "DESCRIPTION", "IMAGE_ID", "PHONE", "SCHEDULE", "GPS_N", "GPS_S", "ISSUING_CENTER", "SITE_ID")
  2796.         );
  2797.         while ($arStoreTmp = $dbList->Fetch())
  2798.         {
  2799.             if ($arStoreTmp["IMAGE_ID"] > 0)
  2800.                 $arStoreTmp["IMAGE_ID"] = CFile::GetFileArray($arStoreTmp["IMAGE_ID"]);
  2801.             else
  2802.                 $arStoreTmp["IMAGE_ID"] = null;
  2803.  
  2804.             $arStore[$arStoreTmp["ID"]] = $arStoreTmp;
  2805.         }
  2806.  
  2807.         $arResult["STORE_LIST"] = $arStore;
  2808.  
  2809.         $arResult["DELIVERY_EXTRA"] = array();
  2810.         $deliveryExtra = $this->request->get('DELIVERY_EXTRA');
  2811.         if (is_array($deliveryExtra) && !empty($deliveryExtra[$this->arUserResult["DELIVERY_ID"]]))
  2812.             $arResult["DELIVERY_EXTRA"] = $deliveryExtra[$this->arUserResult["DELIVERY_ID"]];
  2813.  
  2814.         $this->executeEvent('OnSaleComponentOrderOneStepDelivery', $this->order);
  2815.     }
  2816.  
  2817.     /**
  2818.      * Set pay system data from inner/external payment object and pay system services object to $this->arResult
  2819.      * Execution of 'OnSaleComponentOrderOneStepPaySystem' event
  2820.      */
  2821.     protected function obtainPaySystem()
  2822.     {
  2823.         $arResult =& $this->arResult;
  2824.  
  2825.         $innerPayment = $this->getInnerPayment($this->order);
  2826.         if (!empty($innerPayment) && $innerPayment->getSum() > 0)
  2827.         {
  2828.             $arResult['PAYED_FROM_ACCOUNT_FORMATED'] = SaleFormatCurrency($innerPayment->getSum(), $this->order->getCurrency());
  2829.             $arResult['ORDER_TOTAL_LEFT_TO_PAY'] = $this->order->getPrice() - $innerPayment->getSum();
  2830.             $arResult['ORDER_TOTAL_LEFT_TO_PAY_FORMATED'] = SaleFormatCurrency($this->order->getPrice() - $innerPayment->getSum(), $this->order->getCurrency());
  2831.         }
  2832.  
  2833.         $paySystemList = $this->arParams['DELIVERY_TO_PAYSYSTEM'] === 'p2d' ? $this->arActivePaySystems : $this->arPaySystemServiceAll;
  2834.         if (!empty($paySystemList))
  2835.         {
  2836.             $innerPaySystemId = PaySystem\Manager::getInnerPaySystemId();
  2837.  
  2838.             if (!empty($paySystemList[$innerPaySystemId]))
  2839.             {
  2840.                 $innerPaySystem = $paySystemList[$innerPaySystemId];
  2841.  
  2842.                 if ($innerPaySystem['LOGOTIP'] > 0)
  2843.                 {
  2844.                     $innerPaySystem['LOGOTIP'] = CFile::GetFileArray($innerPaySystem['LOGOTIP']);
  2845.                 }
  2846.  
  2847.                 $arResult['INNER_PAY_SYSTEM'] = $innerPaySystem;
  2848.                 unset($paySystemList[$innerPaySystemId]);
  2849.             }
  2850.  
  2851.             $extPayment = $this->getExternalPayment($this->order);
  2852.             $paymentId = !empty($extPayment) ? $extPayment->getPaymentSystemId() : null;
  2853.  
  2854.             foreach ($paySystemList as $paySystem)
  2855.             {
  2856.                 $paySystem['PSA_ID'] = $paySystem['ID'];
  2857.  
  2858.                 if ((string)$paySystem['PSA_NAME'] === '')
  2859.                 {
  2860.                     $paySystem['PSA_NAME'] = $paySystem['NAME'];
  2861.                 }
  2862.  
  2863.                 $paySystem['PSA_NAME'] = htmlspecialcharsEx($paySystem['PSA_NAME']);
  2864.  
  2865.                 $keyMap = array(
  2866.                     'ACTION_FILE', 'RESULT_FILE', 'NEW_WINDOW', 'PERSON_TYPE_ID', 'PARAMS', 'TARIF', 'HAVE_PAYMENT',
  2867.                     'HAVE_ACTION', 'HAVE_RESULT', 'HAVE_PREPAY', 'HAVE_RESULT_RECEIVE', 'ENCODING'
  2868.                 );
  2869.                 foreach ($keyMap as $key)
  2870.                 {
  2871.                     $paySystem["PSA_{$key}"] = $paySystem[$key];
  2872.                     unset($paySystem[$key]);
  2873.                 }
  2874.  
  2875.                 if ($paySystem['LOGOTIP'] > 0)
  2876.                 {
  2877.                     $paySystem['PSA_LOGOTIP'] = CFile::GetFileArray($paySystem['LOGOTIP']);
  2878.                 }
  2879.                 unset($paySystem['LOGOTIP']);
  2880.  
  2881.                 if ($paymentId == $paySystem['ID'])
  2882.                 {
  2883.                     $paySystem['CHECKED'] = 'Y';
  2884.                 }
  2885.  
  2886.                 $paySystem['PRICE'] = 0;
  2887.                 if ($paySystem['HAVE_PRICE'] === 'Y' && !empty($extPayment))
  2888.                 {
  2889.                     $service = PaySystem\Manager::getObjectById($paySystem['ID']);
  2890.                     if ($service !== null)
  2891.                     {
  2892.                         $paySystem['PRICE'] = $service->getPaymentPrice($extPayment);
  2893.                         $paySystem['PRICE_FORMATTED'] = SaleFormatCurrency($paySystem['PRICE'], $this->order->getCurrency());
  2894.  
  2895.                         if ($paymentId == $paySystem['ID'])
  2896.                         {
  2897.                             $arResult['PAY_SYSTEM_PRICE'] = $extPayment->getField('PRICE_COD');
  2898.                             $arResult['PAY_SYSTEM_PRICE_FORMATTED'] = SaleFormatCurrency($arResult['PAY_SYSTEM_PRICE'], $this->order->getCurrency());
  2899.                         }
  2900.                     }
  2901.                 }
  2902.  
  2903.                 $arResult['PAY_SYSTEM'][] = $paySystem;
  2904.             }
  2905.         }
  2906.  
  2907.         $this->executeEvent('OnSaleComponentOrderOneStepPaySystem', $this->order);
  2908.     }
  2909.  
  2910.     /**
  2911.      * Set related to payment/delivery order properties data from order object to $this->arResult
  2912.      *
  2913.      * @throws Main\ObjectNotFoundException
  2914.      */
  2915.     protected function obtainRelatedProperties()
  2916.     {
  2917.         $arRes = array();
  2918.         $arProps = $this->order->getPropertyCollection()->getArray();
  2919.         $arPaymentSystemId = $this->order->getPaymentSystemId();
  2920.         $arDeliverySystemId = $this->order->getDeliverySystemId();
  2921.  
  2922.         foreach ($arProps['properties'] as $key => $property)
  2923.         {
  2924.             if ($property['UTIL'] == 'Y')
  2925.                 continue;
  2926.  
  2927.             if (isset($property['RELATION']))
  2928.             {
  2929.                 if ($this->checkRelatedProperty($property, $arPaymentSystemId, $arDeliverySystemId))
  2930.                 {
  2931.                     if (!empty($this->arResult['PERSON_TYPE'][$property['PERSON_TYPE_ID']]))
  2932.                     {
  2933.                         $personType = $this->arResult['PERSON_TYPE'][$property['PERSON_TYPE_ID']];
  2934.                         $property['PERSON_TYPE_LID'] = $personType['ID'];
  2935.                         $property['PERSON_TYPE_NAME'] = $personType['NAME'];
  2936.                         $property['PERSON_TYPE_SORT'] = $personType['SORT'];
  2937.                         $property['PERSON_TYPE_ACTIVE'] = $personType['ACTIVE'];
  2938.                     }
  2939.  
  2940.                     foreach ($arProps['groups'] as $group)
  2941.                     {
  2942.                         if ($group['ID'] == $property['PROPS_GROUP_ID'])
  2943.                         {
  2944.                             $property['GROUP_NAME'] = $group['NAME'];
  2945.                             $property['GROUP_ID'] = $group['ID'];
  2946.                             $property['GROUP_PERSON_TYPE_ID'] = $group['PERSON_TYPE_ID'];
  2947.                             break;
  2948.                         }
  2949.                     }
  2950.  
  2951.                     $property['SETTINGS'] = array(
  2952.                         'MINLENGTH' => $property['MINLENGTH'],
  2953.                         'MAXLENGTH' => $property['MAXLENGTH'],
  2954.                         'PATTERN' => $property['PATTERN'],
  2955.                         'MULTILINE' => $property['MULTILINE'],
  2956.                         'SIZE' => $property['SIZE']
  2957.                     );
  2958.                     $property['PAYSYSTEM_ID'] = $property['ID'];
  2959.                     $property['DELIVERY_ID'] = $property['ID'];
  2960.  
  2961.                     $arRes[] = $this->getOrderPropFormatted($property);
  2962.                 }
  2963.             }
  2964.         }
  2965.  
  2966.         $this->arResult["ORDER_PROP"]["RELATED"] = $arRes;
  2967.     }
  2968.  
  2969.     /**
  2970.      * Set taxes data from order object to $this->arResult
  2971.      */
  2972.     protected function obtainTaxes()
  2973.     {
  2974.         $arResult =& $this->arResult;
  2975.  
  2976.         $arResult["USE_VAT"] = $this->order->isUsedVat();
  2977.         $arResult["VAT_RATE"] = $this->order->getVatRate();
  2978.         $arResult["VAT_SUM"] = $this->order->getVatSum();
  2979.  
  2980.         if ($arResult["VAT_SUM"] === null)
  2981.             $arResult["VAT_SUM"] = 0;
  2982.  
  2983.         $arResult["VAT_SUM_FORMATED"] = SaleFormatCurrency($arResult["VAT_SUM"], $this->order->getCurrency());
  2984.  
  2985.         $taxes = $this->order->getTax();
  2986.         $taxes->refreshData();
  2987.  
  2988.         if ($this->order->isUsedVat())
  2989.         {
  2990.             if ($this->arParams['SHOW_VAT_PRICE'] === 'Y')
  2991.             {
  2992.                 $arResult['TAX_LIST'] = $taxes->getAvailableList();
  2993.             }
  2994.         }
  2995.         else
  2996.         {
  2997.             $arResult['TAX_LIST'] = $taxes->getTaxList();
  2998.             if (is_array($arResult['TAX_LIST']) && !empty($arResult['TAX_LIST']))
  2999.             {
  3000.                 foreach ($arResult['TAX_LIST'] as $key => &$tax)
  3001.                 {
  3002.                     if ($tax['VALUE_MONEY'])
  3003.                         $tax['VALUE_MONEY_FORMATED'] = SaleFormatCurrency($tax['VALUE_MONEY'], $this->order->getCurrency());
  3004.                 }
  3005.             }
  3006.         }
  3007.  
  3008.         $arResult['TAX_PRICE'] = $this->order->getTaxPrice();
  3009.     }
  3010.  
  3011.     /**
  3012.      * Set order total prices data from order object to $this->arResult
  3013.      */
  3014.     protected function obtainTotal()
  3015.     {
  3016.         $arResult =& $this->arResult;
  3017.  
  3018.         $locationAltPropDisplayManual = $this->request->get('LOCATION_ALT_PROP_DISPLAY_MANUAL');
  3019.         if (!empty($locationAltPropDisplayManual) && is_array($locationAltPropDisplayManual))
  3020.         {
  3021.             foreach ($locationAltPropDisplayManual as $propId => $switch)
  3022.             {
  3023.                 if (intval($propId))
  3024.                 {
  3025.                     $arResult['LOCATION_ALT_PROP_DISPLAY_MANUAL'][intval($propId)] = !!$switch;
  3026.                 }
  3027.             }
  3028.         }
  3029.  
  3030.         $basket = $this->order->getBasket();
  3031.  
  3032.         $arResult['ORDER_PRICE'] = $basket->getPrice();
  3033.         $arResult['ORDER_PRICE_FORMATED'] = SaleFormatCurrency($arResult['ORDER_PRICE'], $this->order->getCurrency());
  3034.  
  3035.         $arResult['ORDER_WEIGHT'] = $basket->getWeight();
  3036.         $arResult['ORDER_WEIGHT_FORMATED'] = roundEx(floatval($arResult['ORDER_WEIGHT'] / $arResult['WEIGHT_KOEF']), SALE_WEIGHT_PRECISION).' '.$arResult['WEIGHT_UNIT'];
  3037.  
  3038.         $arResult['PRICE_WITHOUT_DISCOUNT_VALUE'] = $basket->getBasePrice();
  3039.         $arResult['PRICE_WITHOUT_DISCOUNT'] = SaleFormatCurrency($arResult['PRICE_WITHOUT_DISCOUNT_VALUE'], $this->order->getCurrency());
  3040.  
  3041.         $arResult['DISCOUNT_PRICE'] = Sale\PriceMaths::roundPrecision(
  3042.             $this->order->getDiscountPrice() + ($arResult['PRICE_WITHOUT_DISCOUNT_VALUE'] - $arResult['ORDER_PRICE'])
  3043.         );
  3044.         $arResult['DISCOUNT_PRICE_FORMATED'] = SaleFormatCurrency($arResult['DISCOUNT_PRICE'], $this->order->getCurrency());
  3045.  
  3046.         $arResult['DELIVERY_PRICE'] = Sale\PriceMaths::roundPrecision($this->order->getDeliveryPrice());
  3047.         $arResult['DELIVERY_PRICE_FORMATED'] = SaleFormatCurrency($arResult['DELIVERY_PRICE'], $this->order->getCurrency());
  3048.  
  3049.         $arResult['ORDER_TOTAL_PRICE'] = Sale\PriceMaths::roundPrecision($this->order->getPrice());
  3050.         $arResult['ORDER_TOTAL_PRICE_FORMATED'] = SaleFormatCurrency($arResult['ORDER_TOTAL_PRICE'], $this->order->getCurrency());
  3051.     }
  3052.  
  3053.     /**
  3054.      * Obtains all order fields filled by user.
  3055.      */
  3056.     protected function obtainUserConsentInfo()
  3057.     {
  3058.         $propertyNames = array();
  3059.  
  3060.         $propertyIterator = Sale\Internals\OrderPropsTable::getList(array(
  3061.             'select' => array('NAME'),
  3062.             'filter' => array(
  3063.                 'ACTIVE' => 'Y',
  3064.                 'UTIL' => 'N',
  3065.                 'PERSON_TYPE_SITE.SITE_ID' => SITE_ID
  3066.             ),
  3067.             'order' => array(
  3068.                 'SORT' => 'ASC',
  3069.                 'ID' => 'ASC'
  3070.             ),
  3071.             'runtime' => array(
  3072.                 new \Bitrix\Main\Entity\ReferenceField(
  3073.                     'PERSON_TYPE_SITE',
  3074.                     'Bitrix\Sale\Internals\PersonTypeSiteTable',
  3075.                     array('=this.PERSON_TYPE_ID' => 'ref.PERSON_TYPE_ID')
  3076.                 ),
  3077.             )
  3078.         ));
  3079.         while ($property = $propertyIterator->fetch())
  3080.         {
  3081.             $propertyNames[] = $property['NAME'];
  3082.         }
  3083.  
  3084.         $this->arResult['USER_CONSENT_PROPERTY_DATA'] = $propertyNames;
  3085.     }
  3086.  
  3087.     /**
  3088.      * Returns true if current property is valid for selected payment & delivery
  3089.      *
  3090.      * @param $property
  3091.      * @param $arPaymentId
  3092.      * @param $arDeliveryId
  3093.      * @return bool
  3094.      */
  3095.     protected function checkRelatedProperty($property, $arPaymentId, $arDeliveryId)
  3096.     {
  3097.         $okByPs = null;
  3098.         $okByDelivery = null;
  3099.  
  3100.         if (is_array($property['RELATION']) && !empty($property['RELATION']))
  3101.         {
  3102.             foreach ($property['RELATION'] as $relation)
  3103.             {
  3104.                 if (empty($okByPs) && $relation['ENTITY_TYPE'] == 'P')
  3105.                     $okByPs = in_array($relation['ENTITY_ID'], $arPaymentId);
  3106.  
  3107.                 if (empty($okByDelivery) && $relation['ENTITY_TYPE'] == 'D')
  3108.                     $okByDelivery = in_array($relation['ENTITY_ID'], $arDeliveryId);
  3109.             }
  3110.         }
  3111.  
  3112.         return ((is_null($okByPs) || $okByPs) && (is_null($okByDelivery) || $okByDelivery));
  3113.     }
  3114.  
  3115.     /**
  3116.      * Make $arResult compatible ('~' prefixes and htmlspecialcharsEx)
  3117.      */
  3118.     protected function makeResultCompatible()
  3119.     {
  3120.         $arResult =& $this->arResult;
  3121.  
  3122.         if (is_array($arResult['PERSON_TYPE']) && !empty($arResult['PERSON_TYPE']))
  3123.             foreach ($arResult['PERSON_TYPE'] as &$item)
  3124.                 self::makeCompatibleArray($item);
  3125.  
  3126.         if (is_array($arResult['ORDER_PROP']['RELATED']) && !empty($arResult['ORDER_PROP']['RELATED']))
  3127.             foreach ($arResult['ORDER_PROP']['RELATED'] as &$item)
  3128.                 self::makeCompatibleArray($item);
  3129.  
  3130.         if (is_array($arResult['ORDER_PROP']['USER_PROPS_Y']) && !empty($arResult['ORDER_PROP']['USER_PROPS_Y']))
  3131.             foreach ($arResult['ORDER_PROP']['USER_PROPS_Y'] as &$item)
  3132.                 self::makeCompatibleArray($item);
  3133.  
  3134.         if (is_array($arResult['ORDER_PROP']['USER_PROPS_N']) && !empty($arResult['ORDER_PROP']['USER_PROPS_N']))
  3135.             foreach ($arResult['ORDER_PROP']['USER_PROPS_N'] as &$item)
  3136.                 self::makeCompatibleArray($item);
  3137.  
  3138.         if (is_array($arResult['BASKET_ITEMS']) && !empty($arResult['BASKET_ITEMS']))
  3139.             foreach ($arResult['BASKET_ITEMS'] as &$item)
  3140.                 self::makeCompatibleArray($item);
  3141.  
  3142.         if (is_array($arResult['GRID']['ROWS']) && !empty($arResult['GRID']['ROWS']))
  3143.             foreach ($arResult['GRID']['ROWS'] as &$item)
  3144.                 self::makeCompatibleArray($item['data']);
  3145.  
  3146.         if (is_array($arResult['USER_ACCOUNT']) && !empty($arResult['USER_ACCOUNT']))
  3147.             self::makeCompatibleArray($arResult['USER_ACCOUNT']);
  3148.     }
  3149.  
  3150.     public static function makeCompatibleArray(&$array)
  3151.     {
  3152.         if (empty($array) || !is_array($array))
  3153.             return;
  3154.  
  3155.         $arr = array();
  3156.         foreach ($array as $key => $value)
  3157.         {
  3158.             if (is_array($value) || preg_match("/[;&<>\"]/", $value))
  3159.             {
  3160.                 $arr[$key] = htmlspecialcharsEx($value);
  3161.             }
  3162.             else
  3163.             {
  3164.                 $arr[$key] = $value;
  3165.             }
  3166.  
  3167.             $arr["~{$key}"] = $value;
  3168.         }
  3169.  
  3170.         $array = $arr;
  3171.     }
  3172.  
  3173.     /**
  3174.      * Check if PayPal prepayment is available
  3175.      *
  3176.      * @param Order $order
  3177.      * @throws Main\ArgumentException
  3178.      * @throws Main\NotSupportedException
  3179.      */
  3180.     protected function usePrepayment(Order $order)
  3181.     {
  3182.         global $APPLICATION;
  3183.         $arResult =& $this->arResult;
  3184.  
  3185.         $prePayablePs = array();
  3186.         $personTypes = array_keys(PersonType::load($this->context->getSite()));
  3187.  
  3188.         if (!empty($personTypes))
  3189.         {
  3190.             $paySysActionIterator = PaySystem\Manager::getList(array(
  3191.                 'select' => array(
  3192.                     'ID', 'PAY_SYSTEM_ID', 'PERSON_TYPE_ID', 'NAME', 'ACTION_FILE', 'RESULT_FILE',
  3193.                     'NEW_WINDOW', 'PARAMS', 'ENCODING', 'LOGOTIP'
  3194.                 ),
  3195.                 'filter'  => array(
  3196.                     'ACTIVE' => 'Y',
  3197.                     'HAVE_PREPAY' => 'Y'
  3198.                 )
  3199.             ));
  3200.             $helper = Main\Application::getConnection()->getSqlHelper();
  3201.  
  3202.             while ($paySysAction = $paySysActionIterator->fetch())
  3203.             {
  3204.                 $dbRestriction = Sale\Internals\ServiceRestrictionTable::getList(array(
  3205.                     'select' => array('PARAMS'),
  3206.                     'filter' => array(
  3207.                         'SERVICE_ID' => $paySysAction['ID'],
  3208.                         'CLASS_NAME' => $helper->forSql('\Bitrix\Sale\Services\PaySystem\Restrictions\PersonType'),
  3209.                         'SERVICE_TYPE' => Sale\Services\PaySystem\Restrictions\Manager::SERVICE_TYPE_PAYMENT
  3210.                     )
  3211.                 ));
  3212.  
  3213.                 if ($restriction = $dbRestriction->fetch())
  3214.                 {
  3215.                     if (array_intersect($personTypes, $restriction['PARAMS']['PERSON_TYPE_ID']))
  3216.                     {
  3217.                         $prePayablePs = $paySysAction;
  3218.                         break;
  3219.                     }
  3220.                 }
  3221.                 else
  3222.                 {
  3223.                     $prePayablePs = $paySysAction;
  3224.                     break;
  3225.                 }
  3226.             }
  3227.  
  3228.             if ($prePayablePs)
  3229.             {
  3230.                 $arResult['PREPAY_PS'] = $prePayablePs;
  3231.                 $arResult['HAVE_PREPAYMENT'] = true;
  3232.  
  3233.                 $this->prePaymentService = new PaySystem\Service($prePayablePs);
  3234.                 if ($this->prePaymentService->isPrePayable())
  3235.                 {
  3236.                     $this->prePaymentService->initPrePayment(null, $this->request);
  3237.  
  3238.                     if ($this->request->get('paypal') == 'Y' && $this->request->get('token'))
  3239.                     {
  3240.                         $arResult['PREPAY_ORDER_PROPS'] = $this->prePaymentService->getPrePaymentProps();
  3241.  
  3242.                         if (intval($this->arUserResult['PAY_SYSTEM_ID']) <= 0)
  3243.                         {
  3244.                             $this->arUserResult['PERSON_TYPE_ID'] = $arResult['PREPAY_PS']['PERSON_TYPE_ID'];
  3245.                         }
  3246.  
  3247.                         $this->arUserResult['PREPAYMENT_MODE'] = true;
  3248.                         $this->arUserResult['PAY_SYSTEM_ID'] = $arResult['PREPAY_PS']['ID'];
  3249.                     }
  3250.                     else
  3251.                     {
  3252.                         if ($this->arUserResult['PAY_SYSTEM_ID'] == $arResult['PREPAY_PS']['ID'])
  3253.                         {
  3254.                             $basketItems = array();
  3255.                             /** @var Sale\BasketItem $item */
  3256.                             foreach ($this->getBasketStorage()->getBasket() as $key => $item)
  3257.                             {
  3258.                                 if ($item->canBuy() && !$item->isDelay())
  3259.                                 {
  3260.                                     $basketItems[$key]['NAME'] = $item->getField('NAME');
  3261.                                     $basketItems[$key]['PRICE'] = $item->getPrice();
  3262.                                     $basketItems[$key]['QUANTITY'] = $item->getQuantity();
  3263.                                 }
  3264.                             }
  3265.  
  3266.                             $orderData = array(
  3267.                                 'PATH_TO_ORDER' => $APPLICATION->GetCurPage(),
  3268.                                 'AMOUNT' => $order->getPrice(),
  3269.                                 'ORDER_REQUEST' => 'Y',
  3270.                                 'BASKET_ITEMS' => $basketItems
  3271.                             );
  3272.                             $arResult['REDIRECT_URL'] = $this->prePaymentService->basketButtonAction($orderData);
  3273.  
  3274.                             if ($arResult['REDIRECT_URL'] != '')
  3275.                             {
  3276.                                 $arResult['NEED_REDIRECT'] = 'Y';
  3277.                             }
  3278.                         }
  3279.                     }
  3280.  
  3281.                     ob_start();
  3282.                     $this->prePaymentService->setTemplateParams(array(
  3283.                         'TOKEN' => $this->request->get('token'),
  3284.                         'PAYER_ID' => $this->request->get('PayerID')
  3285.                     ));
  3286.                     $this->prePaymentService->showTemplate(null, 'prepay_hidden_fields');
  3287.                     $arResult['PREPAY_ADIT_FIELDS'] = ob_get_contents();
  3288.                     ob_end_clean();
  3289.                 }
  3290.             }
  3291.         }
  3292.     }
  3293.  
  3294.     protected function prepayOrder()
  3295.     {
  3296.         if ($this->prePaymentService && $this->prePaymentService->isPrePayable() && $this->request->get('paypal') == 'Y')
  3297.         {
  3298.             /** @var Payment $payment */
  3299.             $payment = $this->getExternalPayment($this->order);
  3300.             if($payment)
  3301.             {
  3302.                 $this->prePaymentService->setOrderDataForPrePayment(
  3303.                     array(
  3304.                         'ORDER_ID' => $this->order->getId(),
  3305.                         'PAYMENT_ID' => $payment->getId(),
  3306.                         'ORDER_PRICE' => $payment->getSum(),
  3307.                         'DELIVERY_PRICE' => $this->order->getDeliveryPrice(),
  3308.                         'TAX_PRICE' => $this->order->getTaxPrice()
  3309.                     )
  3310.                 );
  3311.  
  3312.                 $orderData = array();
  3313.                 /** @var Sale\BasketItem $item */
  3314.                 foreach ($this->order->getBasket() as $item)
  3315.                     $orderData['BASKET_ITEMS'][] = $item->getFieldValues();
  3316.  
  3317.                 $this->prePaymentService->payOrderByPrePayment($orderData);
  3318.             }
  3319.         }
  3320.     }
  3321.  
  3322.     /**
  3323.      * Initialization of person types. Set person type data to $this->arResult.
  3324.      * Return true if person type changed.
  3325.      * Execution of 'OnSaleComponentOrderOneStepPersonType' event
  3326.      *
  3327.      * @param Order $order
  3328.      * @return bool
  3329.      * @throws Main\ArgumentException
  3330.      */
  3331.     protected function initPersonType(Order $order)
  3332.     {
  3333.         $arResult =& $this->arResult;
  3334.         $personTypeId = intval($this->arUserResult['PERSON_TYPE_ID']);
  3335.         $personTypeIdOld = intval($this->arUserResult['PERSON_TYPE_OLD']);
  3336.  
  3337.         $personTypes = PersonType::load($this->context->getSite());
  3338.         foreach ($personTypes as $personType)
  3339.         {
  3340.             if ($personTypeId === intval($personType["ID"]) || !array_key_exists($personTypeId, $personTypes))
  3341.             {
  3342.                 $personTypeId = intval($personType["ID"]);
  3343.                 $order->setPersonTypeId($personTypeId);
  3344.                 $this->arUserResult['PERSON_TYPE_ID'] = $personTypeId;
  3345.                 $personType["CHECKED"] = "Y";
  3346.             }
  3347.             $arResult["PERSON_TYPE"][$personType["ID"]] = $personType;
  3348.         }
  3349.  
  3350.         if ($personTypeId == 0)
  3351.             $this->addError(Loc::getMessage("SOA_ERROR_PERSON_TYPE"), self::REGION_BLOCK);
  3352.  
  3353.         $this->executeEvent('OnSaleComponentOrderOneStepPersonType', $order);
  3354.  
  3355.         return count($arResult["PERSON_TYPE"]) > 1 && ($personTypeId !== $personTypeIdOld);
  3356.     }
  3357.  
  3358.     /**
  3359.      * Initialization of user profiles. Set user profiles data to $this->arResult.
  3360.      *
  3361.      * @param Order $order
  3362.      * @param       $isPersonTypeChanged
  3363.      */
  3364.     protected function initUserProfiles(Order $order, $isPersonTypeChanged)
  3365.     {
  3366.         $arResult =& $this->arResult;
  3367.  
  3368.         $justAuthorized = $this->request->get('do_authorize') == 'Y' || $this->request->get('do_register') == 'Y';
  3369.         $bFirst = false;
  3370.         $dbUserProfiles = CSaleOrderUserProps::GetList(
  3371.             array("DATE_UPDATE" => "DESC"),
  3372.             array(
  3373.                 "PERSON_TYPE_ID" => $order->getPersonTypeId(),
  3374.                 "USER_ID" => $order->getUserId()
  3375.             )
  3376.         );
  3377.         while ($arUserProfiles = $dbUserProfiles->GetNext())
  3378.         {
  3379.             if (!$bFirst && (empty($this->arUserResult['PROFILE_CHANGE']) || $isPersonTypeChanged || $justAuthorized))
  3380.             {
  3381.                 $bFirst = true;
  3382.                 $this->arUserResult['PROFILE_ID'] = intval($arUserProfiles["ID"]);
  3383.             }
  3384.  
  3385.             if (intval($this->arUserResult['PROFILE_ID']) == intval($arUserProfiles["ID"]))
  3386.                 $arUserProfiles["CHECKED"] = "Y";
  3387.  
  3388.             $arResult["ORDER_PROP"]["USER_PROFILES"][$arUserProfiles["ID"]] = $arUserProfiles;
  3389.         }
  3390.     }
  3391.  
  3392.     public function getCurrentShipment(Order $order)
  3393.     {
  3394.         /** @var Shipment $shipment */
  3395.         foreach ($order->getShipmentCollection() as $shipment)
  3396.         {
  3397.             if (!$shipment->isSystem())
  3398.                 return $shipment;
  3399.         }
  3400.  
  3401.         return null;
  3402.     }
  3403.  
  3404.     /**
  3405.      * Initialization of shipment object with first/selected delivery service.
  3406.      *
  3407.      * @param Shipment $shipment
  3408.      * @throws Main\NotSupportedException
  3409.      */
  3410.     protected function initDelivery(Shipment $shipment)
  3411.     {
  3412.         $deliveryId = intval($this->arUserResult['DELIVERY_ID']);
  3413.         $this->arDeliveryServiceAll = Delivery\Services\Manager::getRestrictedObjectsList($shipment);
  3414.         /** @var Sale\ShipmentCollection $shipmentCollection */
  3415.         $shipmentCollection = $shipment->getCollection();
  3416.         $order = $shipmentCollection->getOrder();
  3417.  
  3418.         if (!empty($this->arDeliveryServiceAll))
  3419.         {
  3420.             if (array_key_exists($deliveryId, $this->arDeliveryServiceAll))
  3421.             {
  3422.                 $deliveryObj = $this->arDeliveryServiceAll[$deliveryId];
  3423.             }
  3424.             else
  3425.             {
  3426.                 $deliveryObj = reset($this->arDeliveryServiceAll);
  3427.                 if ($deliveryId != 0)
  3428.                 {
  3429.                     $this->addWarning(Loc::getMessage("DELIVERY_CHANGE_WARNING"), self::DELIVERY_BLOCK);
  3430.                 }
  3431.             }
  3432.  
  3433.             if ($deliveryObj->isProfile())
  3434.             {
  3435.                 $name = $deliveryObj->getNameWithParent();
  3436.             }
  3437.             else
  3438.             {
  3439.                 $name = $deliveryObj->getName();
  3440.             }
  3441.  
  3442.             $order->isStartField();
  3443.  
  3444.             $shipment->setFields(array(
  3445.                 'DELIVERY_ID' => $deliveryObj->getId(),
  3446.                 'DELIVERY_NAME' => $name,
  3447.                 'CURRENCY' => $order->getCurrency()
  3448.             ));
  3449.             $this->arUserResult['DELIVERY_ID'] = $deliveryObj->getId();
  3450.  
  3451.             $deliveryStoreList = Delivery\ExtraServices\Manager::getStoresList($deliveryObj->getId());
  3452.             if (count($deliveryStoreList) > 0)
  3453.             {
  3454.                 if ($this->arUserResult['BUYER_STORE'] <= 0 || !in_array($this->arUserResult['BUYER_STORE'], $deliveryStoreList))
  3455.                 {
  3456.                     $this->arUserResult['BUYER_STORE'] = current($deliveryStoreList);
  3457.                 }
  3458.  
  3459.                 $shipment->setStoreId($this->arUserResult['BUYER_STORE']);
  3460.             }
  3461.  
  3462.             $deliveryExtraServices = $this->arUserResult['DELIVERY_EXTRA_SERVICES'];
  3463.             if (is_array($deliveryExtraServices) && !empty($deliveryExtraServices[$deliveryObj->getId()]))
  3464.             {
  3465.                 $shipment->setExtraServices($deliveryExtraServices[$deliveryObj->getId()]);
  3466.                 $deliveryObj->getExtraServices()->setValues($deliveryExtraServices[$deliveryObj->getId()]);
  3467.             }
  3468.  
  3469.             $shipmentCollection->calculateDelivery();
  3470.  
  3471.             $order->doFinalAction(true);
  3472.         }
  3473.         else
  3474.         {
  3475.             $service = Delivery\Services\Manager::getById(Delivery\Services\EmptyDeliveryService::getEmptyDeliveryServiceId());
  3476.             $shipment->setFields(array(
  3477.                 'DELIVERY_ID' => $service['ID'],
  3478.                 'DELIVERY_NAME' => $service['NAME'],
  3479.                 'CURRENCY' => $order->getCurrency()
  3480.             ));
  3481.         }
  3482.     }
  3483.  
  3484.     protected function loadUserAccount(Order $order)
  3485.     {
  3486.         if (!isset($this->arResult["USER_ACCOUNT"]))
  3487.         {
  3488.             $dbUserAccount = CSaleUserAccount::GetList(
  3489.                 array(),
  3490.                 array(
  3491.                     "USER_ID" => $order->getUserId(),
  3492.                     "CURRENCY" => $order->getCurrency(),
  3493.                 )
  3494.             );
  3495.             $this->arResult["USER_ACCOUNT"] = $dbUserAccount->Fetch();
  3496.         }
  3497.     }
  3498.  
  3499.     /**
  3500.      * Set user budget data to $this->arResult. Returns sum to spend(including restrictions).
  3501.      *
  3502.      * @param Order $order
  3503.      * @param bool  $recalculate
  3504.      * @return array
  3505.      * @throws Main\ObjectNotFoundException
  3506.      */
  3507.     protected function getInnerPaySystemInfo(Order $order, $recalculate = false)
  3508.     {
  3509.         $arResult =& $this->arResult;
  3510.  
  3511.         $sumToSpend = 0;
  3512.         $arPaySystemServices = array();
  3513.  
  3514.         if ($this->arParams['PAY_FROM_ACCOUNT'] === 'Y' && $order->isAllowPay())
  3515.         {
  3516.             $innerPaySystemId = PaySystem\Manager::getInnerPaySystemId();
  3517.             $innerPayment = $order->getPaymentCollection()->getInnerPayment();
  3518.  
  3519.             $this->loadUserAccount($order);
  3520.             $userBudget = (float)$arResult['USER_ACCOUNT']['CURRENT_BUDGET'];
  3521.  
  3522.             // finding correct inner pay system price ranges to setField()
  3523.             $sumRange = Sale\Services\PaySystem\Restrictions\Manager::getPriceRange($innerPayment, $innerPaySystemId);
  3524.             if (!empty($sumRange))
  3525.             {
  3526.                 if (
  3527.                     (empty($sumRange['MIN']) || $sumRange['MIN'] <= $userBudget)
  3528.                     && (empty($sumRange['MAX']) || $sumRange['MAX'] >= $userBudget)
  3529.                 )
  3530.                 {
  3531.                     $sumToSpend = $userBudget;
  3532.                 }
  3533.  
  3534.                 if (!empty($sumRange['MAX']) && $sumRange['MAX'] <= $userBudget)
  3535.                 {
  3536.                     $sumToSpend = $sumRange['MAX'];
  3537.                 }
  3538.             }
  3539.             else
  3540.             {
  3541.                 $sumToSpend = $userBudget;
  3542.             }
  3543.  
  3544.             $sumToSpend = $sumToSpend >= $order->getPrice() ? $order->getPrice() : $sumToSpend;
  3545.  
  3546.             if ($this->arParams['ONLY_FULL_PAY_FROM_ACCOUNT'] === 'Y' && $sumToSpend < $order->getPrice())
  3547.             {
  3548.                 $sumToSpend = 0;
  3549.             }
  3550.  
  3551.             if (!empty($arResult['USER_ACCOUNT']) && $sumToSpend > 0)
  3552.             {
  3553.                 // setting inner payment price
  3554.                 $innerPayment->setField('SUM', $sumToSpend);
  3555.                 // getting allowed pay systems by restrictions
  3556.                 $arPaySystemServices = PaySystem\Manager::getListWithRestrictions($innerPayment);
  3557.                 // delete inner pay system if restrictions has not passed
  3558.                 if (!isset($arPaySystemServices[$innerPaySystemId]))
  3559.                 {
  3560.                     $innerPayment->delete();
  3561.                     $sumToSpend = 0;
  3562.                 }
  3563.             }
  3564.             else
  3565.             {
  3566.                 $innerPayment->delete();
  3567.             }
  3568.         }
  3569.  
  3570.         if ($sumToSpend > 0)
  3571.         {
  3572.             $arResult['PAY_FROM_ACCOUNT'] = 'Y';
  3573.             $arResult['CURRENT_BUDGET_FORMATED'] = SaleFormatCurrency($arResult['USER_ACCOUNT']['CURRENT_BUDGET'], $order->getCurrency());
  3574.         }
  3575.         else
  3576.         {
  3577.             $arResult['PAY_FROM_ACCOUNT'] = 'N';
  3578.             unset($arResult['CURRENT_BUDGET_FORMATED']);
  3579.         }
  3580.  
  3581.         return array($sumToSpend, $arPaySystemServices);
  3582.     }
  3583.  
  3584.     public function getInnerPayment(Order $order)
  3585.     {
  3586.         /** @var Payment $payment */
  3587.         foreach ($order->getPaymentCollection() as $payment)
  3588.         {
  3589.             if ($payment->getPaymentSystemId() == PaySystem\Manager::getInnerPaySystemId())
  3590.                 return $payment;
  3591.         }
  3592.  
  3593.         return null;
  3594.     }
  3595.  
  3596.     public function getExternalPayment(Order $order)
  3597.     {
  3598.         /** @var Payment $payment */
  3599.         foreach ($order->getPaymentCollection() as $payment)
  3600.         {
  3601.             if ($payment->getPaymentSystemId() != PaySystem\Manager::getInnerPaySystemId())
  3602.                 return $payment;
  3603.         }
  3604.  
  3605.         return null;
  3606.     }
  3607.  
  3608.     protected function showOnlyPrepaymentPs($paySystemId)
  3609.     {
  3610.         if (empty($this->arPaySystemServiceAll) || intval($paySystemId) == 0)
  3611.             return;
  3612.  
  3613.         foreach ($this->arPaySystemServiceAll as $key => $psService)
  3614.         {
  3615.             if ($paySystemId != $psService['ID'])
  3616.             {
  3617.                 unset($this->arPaySystemServiceAll[$key]);
  3618.                 unset($this->arActivePaySystems[$key]);
  3619.             }
  3620.         }
  3621.     }
  3622.  
  3623.     /**
  3624.      * Initialization of inner/external payment objects with first/selected pay system services.
  3625.      *
  3626.      * @param Order $order
  3627.      * @throws Main\ObjectNotFoundException
  3628.      */
  3629.     protected function initPayment(Order $order)
  3630.     {
  3631.         list($sumToSpend, $innerPaySystemList) = $this->getInnerPaySystemInfo($order);
  3632.  
  3633.         if ($sumToSpend > 0)
  3634.         {
  3635.             $innerPayment = $this->getInnerPayment($order);
  3636.             if (!empty($innerPayment))
  3637.             {
  3638.                 if ($this->arUserResult['PAY_CURRENT_ACCOUNT'] === 'Y')
  3639.                 {
  3640.                     $innerPayment->setField('SUM', $sumToSpend);
  3641.                 }
  3642.                 else
  3643.                 {
  3644.                     $innerPayment->delete();
  3645.                     $innerPayment = null;
  3646.                 }
  3647.  
  3648.                 $this->arPaySystemServiceAll = $this->arActivePaySystems = $innerPaySystemList;
  3649.             }
  3650.         }
  3651.  
  3652.         $innerPaySystemId = PaySystem\Manager::getInnerPaySystemId();
  3653.         $extPaySystemId = (int)$this->arUserResult['PAY_SYSTEM_ID'];
  3654.  
  3655.         $paymentCollection = $order->getPaymentCollection();
  3656.         $remainingSum = $order->getPrice() - $paymentCollection->getSum();
  3657.         if ($remainingSum > 0 || $order->getPrice() == 0)
  3658.         {
  3659.             /** @var Payment $extPayment */
  3660.             $extPayment = $paymentCollection->createItem();
  3661.             $extPayment->setField('SUM', $remainingSum);
  3662.  
  3663.             $extPaySystemList = PaySystem\Manager::getListWithRestrictions($extPayment);
  3664.  
  3665.             // we already checked restrictions for inner pay system (could be different by price restrictions)
  3666.             if (empty($innerPaySystemList[$innerPaySystemId]))
  3667.             {
  3668.                 unset($extPaySystemList[$innerPaySystemId]);
  3669.             }
  3670.             elseif (empty($extPaySystemList[$innerPaySystemId]))
  3671.             {
  3672.                 $extPaySystemList[$innerPaySystemId] = $innerPaySystemList[$innerPaySystemId];
  3673.             }
  3674.  
  3675.             $this->arPaySystemServiceAll = $this->arActivePaySystems = $extPaySystemList;
  3676.  
  3677.             if ($extPaySystemId !== 0 && array_key_exists($extPaySystemId, $this->arPaySystemServiceAll))
  3678.             {
  3679.                 $selectedPaySystem = $this->arPaySystemServiceAll[$extPaySystemId];
  3680.             }
  3681.             else
  3682.             {
  3683.                 reset($this->arPaySystemServiceAll);
  3684.  
  3685.                 if (key($this->arPaySystemServiceAll) == $innerPaySystemId)
  3686.                 {
  3687.                     if (count($this->arPaySystemServiceAll) > 1)
  3688.                     {
  3689.                         next($this->arPaySystemServiceAll);
  3690.                     }
  3691.                     elseif ($sumToSpend > 0)
  3692.                     {
  3693.                         $extPayment->delete();
  3694.                         $extPayment = null;
  3695.  
  3696.                         /** @var Payment $innerPayment */
  3697.                         $innerPayment = $this->getInnerPayment($order);
  3698.                         if (empty($innerPayment))
  3699.                         {
  3700.                             $innerPayment = $paymentCollection->getInnerPayment();
  3701.                         }
  3702.  
  3703.                         $sumToPay = $remainingSum > $sumToSpend ? $sumToSpend : $remainingSum;
  3704.                         $innerPayment->setField('SUM', $sumToPay);
  3705.                     }
  3706.                     else
  3707.                     {
  3708.                         unset($this->arActivePaySystems[$innerPaySystemId]);
  3709.                         unset($this->arPaySystemServiceAll[$innerPaySystemId]);
  3710.                     }
  3711.                 }
  3712.  
  3713.                 $selectedPaySystem = current($this->arPaySystemServiceAll);
  3714.  
  3715.                 if (!empty($selectedPaySystem) && $extPaySystemId != 0)
  3716.                 {
  3717.                     $this->addWarning(Loc::getMessage('PAY_SYSTEM_CHANGE_WARNING'), self::PAY_SYSTEM_BLOCK);
  3718.                 }
  3719.             }
  3720.  
  3721.             if (!empty($selectedPaySystem))
  3722.             {
  3723.                 if ($selectedPaySystem['ID'] != $innerPaySystemId)
  3724.                 {
  3725.                     $extPayment->setFields(array(
  3726.                         'PAY_SYSTEM_ID' => $selectedPaySystem['ID'],
  3727.                         'PAY_SYSTEM_NAME' => $selectedPaySystem['NAME']
  3728.                     ));
  3729.  
  3730.                     $this->arUserResult['PAY_SYSTEM_ID'] = $selectedPaySystem['ID'];
  3731.                 }
  3732.             }
  3733.             elseif (!empty($extPayment))
  3734.             {
  3735.                 $extPayment->delete();
  3736.                 $extPayment = null;
  3737.             }
  3738.         }
  3739.  
  3740.         if (empty($this->arPaySystemServiceAll))
  3741.         {
  3742.             $this->addError(Loc::getMessage('SOA_ERROR_PAY_SYSTEM'), self::PAY_SYSTEM_BLOCK);
  3743.         }
  3744.  
  3745.         if (!empty($this->arUserResult['PREPAYMENT_MODE']))
  3746.         {
  3747.             $this->showOnlyPrepaymentPs($this->arUserResult['PAY_SYSTEM_ID']);
  3748.         }
  3749.     }
  3750.  
  3751.     /**
  3752.      * Recalculates payment prices which could change due to shipment/discounts.
  3753.      *
  3754.      * @param Order $order
  3755.      * @throws Main\ObjectNotFoundException
  3756.      */
  3757.     protected function recalculatePayment(Order $order)
  3758.     {
  3759.         // one more delivery calculation for some cases when payment affects delivery price
  3760.         $res = $order->getShipmentCollection()->calculateDelivery();
  3761.         if (!$res->isSuccess())
  3762.         {
  3763.             $shipment = $this->getCurrentShipment($order);
  3764.             if (!empty($shipment))
  3765.             {
  3766.                 $errMessages = '';
  3767.                 $errors = $res->getErrorMessages();
  3768.  
  3769.                 if (!empty($errors))
  3770.                 {
  3771.                     foreach ($errors as $message)
  3772.                     {
  3773.                         $errMessages .= $message.'<br />';
  3774.                     }
  3775.                 }
  3776.                 else
  3777.                 {
  3778.                     $errMessages = Loc::getMessage('SOA_DELIVERY_CALCULATE_ERROR');
  3779.                 }
  3780.  
  3781.                 $r = new Result();
  3782.                 $r->addError(new Sale\ResultWarning(
  3783.                     $errMessages,
  3784.                     'SALE_DELIVERY_CALCULATE_ERROR'
  3785.                 ));
  3786.  
  3787.                 Sale\EntityMarker::addMarker($order, $shipment, $r);
  3788.                 $shipment->setField('MARKED', 'Y');
  3789.             }
  3790.         }
  3791.  
  3792.         list($sumToSpend, $innerPaySystemList) = $this->getInnerPaySystemInfo($order, true);
  3793.  
  3794.         $innerPayment = $this->getInnerPayment($order);
  3795.         if (!empty($innerPayment))
  3796.         {
  3797.             if ($this->arUserResult['PAY_CURRENT_ACCOUNT'] === 'Y' && $sumToSpend > 0)
  3798.             {
  3799.                 $innerPayment->setField('SUM', $sumToSpend);
  3800.             }
  3801.             else
  3802.             {
  3803.                 $innerPayment->delete();
  3804.                 $innerPayment = null;
  3805.             }
  3806.  
  3807.             if ($sumToSpend > 0)
  3808.             {
  3809.                 $this->arPaySystemServiceAll = $innerPaySystemList;
  3810.                 $this->arActivePaySystems += $innerPaySystemList;
  3811.             }
  3812.         }
  3813.  
  3814.         /** @var Payment $innerPayment */
  3815.         $innerPayment = $this->getInnerPayment($order);
  3816.         /** @var Payment $extPayment */
  3817.         $extPayment = $this->getExternalPayment($order);
  3818.  
  3819.         $remainingSum = empty($innerPayment) ? $order->getPrice() : $order->getPrice() - $innerPayment->getSum();
  3820.         if ($remainingSum > 0 || $order->getPrice() == 0)
  3821.         {
  3822.             $paymentCollection = $order->getPaymentCollection();
  3823.             $innerPaySystemId = PaySystem\Manager::getInnerPaySystemId();
  3824.             $extPaySystemId = (int)$this->arUserResult['PAY_SYSTEM_ID'];
  3825.  
  3826.             if (empty($extPayment))
  3827.             {
  3828.                 $extPayment = $paymentCollection->createItem();
  3829.             }
  3830.  
  3831.             $extPayment->setField('SUM', $remainingSum);
  3832.  
  3833.             $extPaySystemList = PaySystem\Manager::getListWithRestrictions($extPayment);
  3834.             // we already checked restrictions for inner pay system (could be different by price restrictions)
  3835.             if (empty($innerPaySystemList[$innerPaySystemId]))
  3836.             {
  3837.                 unset($extPaySystemList[$innerPaySystemId]);
  3838.             }
  3839.             elseif (empty($extPaySystemList[$innerPaySystemId]))
  3840.             {
  3841.                 $extPaySystemList[$innerPaySystemId] = $innerPaySystemList[$innerPaySystemId];
  3842.             }
  3843.  
  3844.             $this->arPaySystemServiceAll = $extPaySystemList;
  3845.             $this->arActivePaySystems += $extPaySystemList;
  3846.  
  3847.             if ($extPaySystemId !== 0 && array_key_exists($extPaySystemId, $this->arPaySystemServiceAll))
  3848.             {
  3849.                 $selectedPaySystem = $this->arPaySystemServiceAll[$extPaySystemId];
  3850.             }
  3851.             else
  3852.             {
  3853.                 reset($this->arPaySystemServiceAll);
  3854.  
  3855.                 if (key($this->arPaySystemServiceAll) == $innerPaySystemId)
  3856.                 {
  3857.                     if (count($this->arPaySystemServiceAll) > 1)
  3858.                     {
  3859.                         next($this->arPaySystemServiceAll);
  3860.                     }
  3861.                     elseif ($sumToSpend > 0)
  3862.                     {
  3863.                         $extPayment->delete();
  3864.                         $extPayment = null;
  3865.  
  3866.                         /** @var Payment $innerPayment */
  3867.                         $innerPayment = $this->getInnerPayment($order);
  3868.                         if (empty($innerPayment))
  3869.                         {
  3870.                             $innerPayment = $paymentCollection->getInnerPayment();
  3871.                         }
  3872.  
  3873.                         $sumToPay = $remainingSum > $sumToSpend ? $sumToSpend : $remainingSum;
  3874.                         $innerPayment->setField('SUM', $sumToPay);
  3875.  
  3876.                         if ($order->getPrice() - $paymentCollection->getSum() > 0)
  3877.                         {
  3878.                             $this->addWarning(Loc::getMessage('INNER_PAYMENT_BALANCE_ERROR'), self::PAY_SYSTEM_BLOCK);
  3879.  
  3880.                             $r = new Result();
  3881.                             $r->addError(new Sale\ResultWarning(
  3882.                                 Loc::getMessage('INNER_PAYMENT_BALANCE_ERROR'),
  3883.                                 'SALE_INNER_PAYMENT_BALANCE_ERROR'
  3884.                             ));
  3885.  
  3886.                             Sale\EntityMarker::addMarker($order, $innerPayment, $r);
  3887.                             $innerPayment->setField('MARKED', 'Y');
  3888.                         }
  3889.                     }
  3890.                     else
  3891.                     {
  3892.                         unset($this->arActivePaySystems[$innerPaySystemId]);
  3893.                         unset($this->arPaySystemServiceAll[$innerPaySystemId]);
  3894.                     }
  3895.                 }
  3896.  
  3897.                 $selectedPaySystem = current($this->arPaySystemServiceAll);
  3898.  
  3899.                 if (!empty($selectedPaySystem) && $extPaySystemId != 0)
  3900.                 {
  3901.                     $this->addWarning(Loc::getMessage('PAY_SYSTEM_CHANGE_WARNING'), self::PAY_SYSTEM_BLOCK);
  3902.                 }
  3903.             }
  3904.  
  3905.             if (!array_key_exists((int)$selectedPaySystem['ID'], $this->arPaySystemServiceAll))
  3906.             {
  3907.                 $this->addError(Loc::getMessage('P2D_CALCULATE_ERROR'), self::PAY_SYSTEM_BLOCK);
  3908.                 $this->addError(Loc::getMessage('P2D_CALCULATE_ERROR'), self::DELIVERY_BLOCK);
  3909.             }
  3910.  
  3911.             if (!empty($selectedPaySystem))
  3912.             {
  3913.                 if ($selectedPaySystem['ID'] != $innerPaySystemId)
  3914.                 {
  3915.                     $codSum = 0;
  3916.                     $service = PaySystem\Manager::getObjectById($selectedPaySystem['ID']);
  3917.                     if ($service !== null)
  3918.                     {
  3919.                         $codSum = $service->getPaymentPrice($extPayment);
  3920.                     }
  3921.  
  3922.                     $extPayment->setFields(array(
  3923.                         'PAY_SYSTEM_ID' => $selectedPaySystem['ID'],
  3924.                         'PAY_SYSTEM_NAME' => $selectedPaySystem['NAME'],
  3925.                         'PRICE_COD' => $codSum
  3926.                     ));
  3927.  
  3928.                     $this->arUserResult['PAY_SYSTEM_ID'] = $selectedPaySystem['ID'];
  3929.                 }
  3930.             }
  3931.             elseif (!empty($extPayment))
  3932.             {
  3933.                 $extPayment->delete();
  3934.                 $extPayment = null;
  3935.             }
  3936.  
  3937.             if (!empty($this->arUserResult['PREPAYMENT_MODE']))
  3938.             {
  3939.                 $this->showOnlyPrepaymentPs($this->arUserResult['PAY_SYSTEM_ID']);
  3940.             }
  3941.         }
  3942.  
  3943.         if (!empty($innerPayment) && !empty($extPayment) && $remainingSum == 0)
  3944.         {
  3945.             $extPayment->delete();
  3946.             $extPayment = null;
  3947.         }
  3948.     }
  3949.  
  3950.     /**
  3951.      * Calculates all available deliveries for order object.
  3952.      * Uses cloned order not to harm real order.
  3953.      * Execution of 'OnSaleComponentOrderDeliveriesCalculated' event
  3954.      *
  3955.      * @param Order $order
  3956.      * @throws Main\NotSupportedException
  3957.      */
  3958.     protected function calculateDeliveries(Order $order)
  3959.     {
  3960.         $this->arResult['DELIVERY'] = array();
  3961.         $problemDeliveries = array();
  3962.  
  3963.         if (!empty($this->arDeliveryServiceAll))
  3964.         {
  3965.             /** @var Order $orderClone */
  3966.             $orderClone = null;
  3967.             $anotherDeliveryCalculated = false;
  3968.             /** @var Shipment $shipment */
  3969.             $shipment = $this->getCurrentShipment($order);
  3970.  
  3971.             foreach ($this->arDeliveryServiceAll as $deliveryId => $deliveryObj)
  3972.             {
  3973.                 $calcResult = false;
  3974.                 $calcOrder = false;
  3975.                 $arDelivery = array();
  3976.  
  3977.                 if ((int)$shipment->getDeliveryId() === $deliveryId)
  3978.                 {
  3979.                     $arDelivery['CHECKED'] = 'Y';
  3980.                     $mustBeCalculated = true;
  3981.                     $calcResult = $deliveryObj->calculate($shipment);
  3982.                     $calcOrder = $order;
  3983.                 }
  3984.                 else
  3985.                 {
  3986.                     $mustBeCalculated = $this->arParams['DELIVERY_NO_AJAX'] === 'Y'
  3987.                         || ($this->arParams['DELIVERY_NO_AJAX'] === 'H' && $deliveryObj->isCalculatePriceImmediately());
  3988.  
  3989.                     if ($mustBeCalculated)
  3990.                     {
  3991.                         $anotherDeliveryCalculated = true;
  3992.  
  3993.                         if (empty($orderClone))
  3994.                         {
  3995.                             $orderClone = $this->getOrderClone($order);
  3996.                         }
  3997.  
  3998.                         $orderClone->isStartField();
  3999.  
  4000.                         $clonedShipment = $this->getCurrentShipment($orderClone);
  4001.                         $clonedShipment->setField('DELIVERY_ID', $deliveryId);
  4002.                         $orderClone->getShipmentCollection()->calculateDelivery();
  4003.  
  4004.                         $orderClone->doFinalAction(true);
  4005.  
  4006.                         $calcResult = $deliveryObj->calculate($clonedShipment);
  4007.                         $calcOrder = $orderClone;
  4008.                     }
  4009.                 }
  4010.  
  4011.                 if ($mustBeCalculated)
  4012.                 {
  4013.                     if ($calcResult->isSuccess())
  4014.                     {
  4015.                         $arDelivery['PRICE'] = Sale\PriceMaths::roundPrecision($calcResult->getPrice());
  4016.                         $arDelivery['PRICE_FORMATED'] = SaleFormatCurrency($arDelivery['PRICE'], $calcOrder->getCurrency());
  4017.  
  4018.                         $currentCalcDeliveryPrice = Sale\PriceMaths::roundPrecision($calcOrder->getDeliveryPrice());
  4019.                         if ($currentCalcDeliveryPrice >= 0 && $arDelivery['PRICE'] != $currentCalcDeliveryPrice)
  4020.                         {
  4021.                             $arDelivery['DELIVERY_DISCOUNT_PRICE'] = $currentCalcDeliveryPrice;
  4022.                             $arDelivery['DELIVERY_DISCOUNT_PRICE_FORMATED'] = SaleFormatCurrency($arDelivery['DELIVERY_DISCOUNT_PRICE'], $calcOrder->getCurrency());
  4023.                         }
  4024.  
  4025.                         if (strlen($calcResult->getPeriodDescription()) > 0)
  4026.                         {
  4027.                             $arDelivery['PERIOD_TEXT'] = $calcResult->getPeriodDescription();
  4028.                         }
  4029.                     }
  4030.                     else
  4031.                     {
  4032.                         if (count($calcResult->getErrorMessages()) > 0)
  4033.                         {
  4034.                             foreach ($calcResult->getErrorMessages() as $message)
  4035.                             {
  4036.                                 $arDelivery['CALCULATE_ERRORS'] .= $message.'<br>';
  4037.                             }
  4038.                         }
  4039.                         else
  4040.                         {
  4041.                             $arDelivery['CALCULATE_ERRORS'] = Loc::getMessage('SOA_DELIVERY_CALCULATE_ERROR');
  4042.                         }
  4043.  
  4044.  
  4045.                         if ($arDelivery['CHECKED'] !== 'Y')
  4046.                         {
  4047.                             if ($this->arParams['SHOW_NOT_CALCULATED_DELIVERIES'] === 'N')
  4048.                             {
  4049.                                 unset($this->arDeliveryServiceAll[$deliveryId]);
  4050.                                 continue;
  4051.                             }
  4052.                             elseif ($this->arParams['SHOW_NOT_CALCULATED_DELIVERIES'] === 'L')
  4053.                             {
  4054.                                 $problemDeliveries[$deliveryId] = $arDelivery;
  4055.                                 continue;
  4056.                             }
  4057.                         }
  4058.                     }
  4059.  
  4060.                     $arDelivery['CALCULATE_DESCRIPTION'] = $calcResult->getDescription();
  4061.                 }
  4062.  
  4063.                 $this->arResult['DELIVERY'][$deliveryId] = $arDelivery;
  4064.             }
  4065.  
  4066.             // for discounts: last delivery calculation need to be on real order with selected delivery
  4067.             if ($anotherDeliveryCalculated)
  4068.             {
  4069.                 $order->doFinalAction(true);
  4070.             }
  4071.         }
  4072.  
  4073.         if (!empty($problemDeliveries))
  4074.         {
  4075.             $this->arResult['DELIVERY'] += $problemDeliveries;
  4076.         }
  4077.  
  4078.         $eventParameters = array(
  4079.             $order, &$this->arUserResult, $this->request,
  4080.             &$this->arParams, &$this->arResult, &$this->arDeliveryServiceAll, &$this->arPaySystemServiceAll
  4081.         );
  4082.         foreach (GetModuleEvents('sale', 'OnSaleComponentOrderDeliveriesCalculated', true) as $arEvent)
  4083.             ExecuteModuleEventEx($arEvent, $eventParameters);
  4084.     }
  4085.  
  4086.     /**
  4087.      * @param Order $order
  4088.      *
  4089.      * @return Order
  4090.      */
  4091.     protected function getOrderClone(Order $order)
  4092.     {
  4093.         /** @var Order $orderClone */
  4094.         $orderClone = $order->createClone();
  4095.  
  4096.         $clonedShipment = $this->getCurrentShipment($orderClone);
  4097.         if (!empty($clonedShipment))
  4098.         {
  4099.             $clonedShipment->setField('CUSTOM_PRICE_DELIVERY', 'N');
  4100.         }
  4101.  
  4102.         return $orderClone;
  4103.     }
  4104.  
  4105.     /**
  4106.      * Check required fields for actual properties(with/without relations). Set user description.
  4107.      *
  4108.      * @param Order $order
  4109.      * @throws Main\ObjectNotFoundException
  4110.      */
  4111.     protected function initOrderFields(Order $order)
  4112.     {
  4113.         if ($this->isOrderConfirmed)
  4114.         {
  4115.             $actualProperties = array();
  4116.             $paymentSystemIds = $order->getPaymentSystemId();
  4117.             $deliverySystemIds = $order->getDeliverySystemId();
  4118.             $propertyCollection = $order->getPropertyCollection();
  4119.             /** @var Sale\PropertyValue $property */
  4120.             foreach ($propertyCollection as $property)
  4121.             {
  4122.                 if ($property->isUtil())
  4123.                     continue;
  4124.  
  4125.                 $arProperty = $property->getProperty();
  4126.                 if (isset($arProperty['RELATION'])
  4127.                     && !$this->checkRelatedProperty($arProperty, $paymentSystemIds, $deliverySystemIds)
  4128.                 )
  4129.                 {
  4130.                     unset($this->arUserResult['ORDER_PROP'][$property->getPropertyId()]);
  4131.                     continue;
  4132.                 }
  4133.  
  4134.                 $actualProperties[$property->getPropertyId()] = $this->arUserResult['ORDER_PROP'][$property->getPropertyId()];
  4135.             }
  4136.  
  4137.             $res = $propertyCollection->checkRequired(array_keys($actualProperties), array('PROPERTIES' => $actualProperties));
  4138.             if (!$res->isSuccess())
  4139.                 $this->addError($res, self::PROPERTY_BLOCK);
  4140.         }
  4141.  
  4142.         $order->setField("USER_DESCRIPTION", $this->arUserResult['ORDER_DESCRIPTION']);
  4143.         $order->setField('COMPANY_ID', Company\Manager::getAvailableCompanyIdByEntity($order));
  4144.  
  4145.         if ($order->getField('COMPANY_ID') > 0)
  4146.         {
  4147.             $responsibleGroups = Sale\Internals\CompanyResponsibleGroupTable::getCompanyGroups($order->getField('COMPANY_ID'));
  4148.             if (!empty($responsibleGroups) && is_array($responsibleGroups))
  4149.             {
  4150.                 $usersList = array();
  4151.                 foreach ($responsibleGroups as $groupId)
  4152.                 {
  4153.                     $usersList = array_merge($usersList, CGroup::GetGroupUser($groupId));
  4154.                 }
  4155.  
  4156.                 if (!empty($usersList) && is_array($usersList))
  4157.                 {
  4158.                     $usersList = array_unique($usersList);
  4159.                     $responsibleUserId = $usersList[array_rand($usersList)];
  4160.  
  4161.                     /** @var Main\Entity\Event $event */
  4162.                     $event = new Main\Event('sale', 'OnSaleComponentBeforeOrderSetResponsibleUserId', array(
  4163.                         'ENTITY' => $order,
  4164.                         'VALUE' => $responsibleUserId,
  4165.                     ));
  4166.                     $event->send();
  4167.  
  4168.                     if ($event->getResults())
  4169.                     {
  4170.                         $result = new Result();
  4171.                         /** @var Main\EventResult $eventResult */
  4172.                         foreach($event->getResults() as $eventResult)
  4173.                         {
  4174.                             if($eventResult->getType() == Main\EventResult::SUCCESS)
  4175.                             {
  4176.                                 if ($eventResultData = $eventResult->getParameters())
  4177.                                 {
  4178.                                     if (isset($eventResultData['VALUE']) && $eventResultData['VALUE'] != $responsibleUserId)
  4179.                                     {
  4180.                                         $responsibleUserId = $eventResultData['VALUE'];
  4181.                                     }
  4182.                                 }
  4183.                             }
  4184.                         }
  4185.                     }
  4186.  
  4187.                     $order->setField('RESPONSIBLE_ID', $responsibleUserId);
  4188.                 }
  4189.  
  4190.             }
  4191.         }
  4192.  
  4193.     }
  4194.  
  4195.     /**
  4196.      * Ajax action - recalculate order and send JSON answer with data/errors
  4197.      */
  4198.     protected function refreshOrderAjaxAction()
  4199.     {
  4200.         global $USER;
  4201.  
  4202.         $error = false;
  4203.         $this->request->set($this->request->get('order'));
  4204.         if ($this->checkSession)
  4205.         {
  4206.             $this->order = $this->createOrder($USER->GetID() ? $USER->GetID() : CSaleUser::GetAnonymousUserID());
  4207.             $this->prepareResultArray();
  4208.             self::scaleImages($this->arResult['JS_DATA'], $this->arParams['SERVICES_IMAGES_SCALING']);
  4209.         }
  4210.         else
  4211.             $error = Loc::getMessage('SESSID_ERROR');
  4212.  
  4213.         $this->showAjaxAnswer(array(
  4214.             'order' => $this->arResult['JS_DATA'],
  4215.             'locations' => $this->arResult['LOCATIONS'],
  4216.             'error' => $error
  4217.         ));
  4218.     }
  4219.  
  4220.     /**
  4221.      * Returns true if basket quantity list is equal to basket "before refresh" state
  4222.      *
  4223.      * @param Order $order
  4224.      * @return bool
  4225.      */
  4226.     protected function checkOrderConsistency(Order $order)
  4227.     {
  4228.         return $this->getActualQuantityList($order->getBasket()) === $this->arUserResult['QUANTITY_LIST'];
  4229.     }
  4230.  
  4231.     /**
  4232.      * Ajax action - attempt to save order and send JSON answer with data/errors
  4233.      */
  4234.     protected function saveOrderAjaxAction()
  4235.     {
  4236.         global $USER;
  4237.  
  4238.         $arOrderRes = array();
  4239.         if ($this->checkSession)
  4240.         {
  4241.             $this->isOrderConfirmed = true;
  4242.             $needToRegister = !$USER->IsAuthorized() && $this->arParams["ALLOW_AUTO_REGISTER"] == "Y";
  4243.             $saveToSession = false;
  4244.  
  4245.             if ($needToRegister)
  4246.             {
  4247.                 list($userId, $saveToSession) = $this->autoRegisterUser();
  4248.             }
  4249.             else
  4250.             {
  4251.                 $userId = $USER->GetID() ? $USER->GetID() : CSaleUser::GetAnonymousUserID();
  4252.             }
  4253.            
  4254.            
  4255.             $this->order = $this->createOrder($userId);
  4256.            
  4257.             $isActiveUser = intval($userId) > 0 && $userId != CSaleUser::GetAnonymousUserID();
  4258.  
  4259.             if (/*$isActiveUser && */empty($this->arResult['ERROR']))
  4260.             {
  4261.                
  4262.                 if (!$this->checkOrderConsistency($this->order))
  4263.                 {
  4264.                     $r = new Result();
  4265.                     $r->addError(new Sale\ResultWarning(
  4266.                         Loc::getMessage('ORDER_CONSISTENCY_CHANGED'),
  4267.                         'SALE_ORDER_CONSISTENCY_CHANGED_ERROR'
  4268.                     ));
  4269.  
  4270.                     Sale\EntityMarker::addMarker($this->order, $this->order, $r);
  4271.                     $this->order->setField('MARKED', 'Y');
  4272.                 }
  4273.  
  4274.                 $this->saveOrder($saveToSession);
  4275.             }
  4276.  
  4277.             if (empty($this->arResult["ERROR"]))
  4278.             {
  4279.                 $arOrderRes["REDIRECT_URL"] = $this->arParams["~CURRENT_PAGE"]."?ORDER_ID=".urlencode($this->arResult["ACCOUNT_NUMBER"]);
  4280.                 $arOrderRes["ID"] = $this->arResult["ACCOUNT_NUMBER"];
  4281.                
  4282.             }
  4283.             else
  4284.             {
  4285.                 $arOrderRes['ERROR'] = $this->arResult['ERROR_SORTED'];
  4286.             }
  4287.         }
  4288.         else
  4289.         {
  4290.             $arOrderRes["ERROR"]['MAIN'] = Loc::getMessage('SESSID_ERROR');
  4291.         }
  4292.        
  4293.         $db_sales = CSaleOrderUserProps::GetList(array(), array());
  4294.         while($ar_sales = $db_sales->Fetch()){
  4295.             if($ar_sales["USER_ID"] == 4){
  4296.                 CSaleOrderUserProps::Delete($ar_sales["ID"]);
  4297.             }
  4298.         }
  4299.  
  4300.         $this->showAjaxAnswer(array('order' => $arOrderRes));
  4301.        
  4302.     }
  4303.  
  4304.     /**
  4305.      * Ajax action - add coupon and if needed recalculate order with JSON answer
  4306.      */
  4307.     protected function enterCouponAction()
  4308.     {
  4309.         $coupon = trim($this->request->get('coupon'));
  4310.  
  4311.         if (!empty($coupon))
  4312.         {
  4313.             if (DiscountCouponsManager::add($coupon))
  4314.             {
  4315.                 $this->refreshOrderAjaxAction();
  4316.             }
  4317.             else
  4318.             {
  4319.                 $this->showAjaxAnswer($coupon);
  4320.             }
  4321.         }
  4322.     }
  4323.  
  4324.     /**
  4325.      * Ajax action - remove coupon and if needed recalculate order with JSON answer
  4326.      */
  4327.     protected function removeCouponAction()
  4328.     {
  4329.         $coupon = htmlspecialchars_decode(trim($this->request->get('coupon')));
  4330.  
  4331.         if (!empty($coupon))
  4332.         {
  4333.             $active = $this->isActiveCoupon($coupon);
  4334.             DiscountCouponsManager::delete($coupon);
  4335.  
  4336.             if ($active)
  4337.             {
  4338.                 $this->refreshOrderAjaxAction();
  4339.             }
  4340.             else
  4341.             {
  4342.                 $this->showAjaxAnswer($coupon);
  4343.             }
  4344.         }
  4345.     }
  4346.  
  4347.     /**
  4348.      * Execution of 'OnSaleComponentOrderShowAjaxAnswer' event
  4349.      *
  4350.      * @param $result
  4351.      */
  4352.     protected function showAjaxAnswer($result)
  4353.     {
  4354.         global $APPLICATION;
  4355.  
  4356.         foreach (GetModuleEvents("sale", 'OnSaleComponentOrderShowAjaxAnswer', true) as $arEvent)
  4357.             ExecuteModuleEventEx($arEvent, array(&$result));
  4358.  
  4359.         $APPLICATION->RestartBuffer();
  4360.  
  4361.         if ($this->request->get('save') != 'Y')
  4362.             header('Content-Type: application/json');
  4363.  
  4364.         echo Json::encode($result);
  4365.  
  4366.         CMain::FinalActions();
  4367.         die();
  4368.     }
  4369.  
  4370.     public static function compareProperties($a, $b)
  4371.     {
  4372.         $sortA = intval($a['SORT']);
  4373.         $sortB = intval($b['SORT']);
  4374.         if ($sortA == $sortB)
  4375.             return 0;
  4376.  
  4377.         return ($sortA < $sortB) ? -1 : 1;
  4378.     }
  4379.  
  4380.     /**
  4381.      * Resize image depending on scale type
  4382.      *
  4383.      * @param array  $item
  4384.      * @param        $imageKey
  4385.      * @param array  $arImage
  4386.      * @param array  $sizeAdaptive
  4387.      * @param array  $sizeStandard
  4388.      * @param string $scale
  4389.      */
  4390.     public static function resizeImage(array &$item, $imageKey, array $arImage, array $sizeAdaptive, array $sizeStandard, $scale = '')
  4391.     {
  4392.         if ($scale == '')
  4393.         {
  4394.             $scale = 'adaptive';
  4395.         }
  4396.  
  4397.         if ($scale === 'no_scale')
  4398.         {
  4399.             $item[$imageKey.'_SRC'] = $arImage['SRC'];
  4400.             $item[$imageKey.'_SRC_ORIGINAL'] = $arImage['SRC'];
  4401.         }
  4402.         elseif ($scale === 'adaptive')
  4403.         {
  4404.             $arFileTmp = CFile::ResizeImageGet(
  4405.                 $arImage,
  4406.                 array('width' => $sizeAdaptive['width'] / 2 , 'height' => $sizeAdaptive['height'] / 2),
  4407.                 BX_RESIZE_IMAGE_PROPORTIONAL,
  4408.                 true
  4409.             );
  4410.             $item[$imageKey.'_SRC'] = $arFileTmp['src'];
  4411.  
  4412.             $arFileTmp = CFile::ResizeImageGet(
  4413.                 $arImage,
  4414.                 $sizeAdaptive,
  4415.                 BX_RESIZE_IMAGE_PROPORTIONAL,
  4416.                 true
  4417.             );
  4418.             $item[$imageKey.'_SRC_2X'] = $arFileTmp['src'];
  4419.  
  4420.             $item[$imageKey.'_SRC_ORIGINAL'] = $arImage['SRC'];
  4421.         }
  4422.         else
  4423.         {
  4424.             $arFileTmp = CFile::ResizeImageGet($arImage, $sizeStandard, BX_RESIZE_IMAGE_PROPORTIONAL, true);
  4425.             $item[$imageKey.'_SRC'] = $arFileTmp['src'];
  4426.  
  4427.             $item[$imageKey.'_SRC_ORIGINAL'] = $arImage['SRC'];
  4428.         }
  4429.     }
  4430.  
  4431.     /**
  4432.      * Obtain all order data to $this->arResult['JS_DATA'] for template js initialization
  4433.      * Execution of 'OnSaleComponentOrderJsData' event
  4434.      *
  4435.      * @throws Main\ObjectNotFoundException
  4436.      */
  4437.     protected function getJsDataResult()
  4438.     {
  4439.         global $USER;
  4440.         $arResult =& $this->arResult;
  4441.         $result =& $this->arResult['JS_DATA'];
  4442.  
  4443.         $result['IS_AUTHORIZED'] = $USER->IsAuthorized();
  4444.         $result['LAST_ORDER_DATA'] = array();
  4445.  
  4446.         if (
  4447.             ($this->request->getRequestMethod() === 'GET' || $this->request->get('do_authorize') === 'Y' || $this->request->get('do_register') === 'Y')
  4448.             && $this->arUserResult['USE_PRELOAD']
  4449.             && $result['IS_AUTHORIZED']
  4450.         )
  4451.         {
  4452.             $lastOrder =& $this->arUserResult['LAST_ORDER_DATA'];
  4453.  
  4454.             if (!empty($lastOrder))
  4455.             {
  4456.                 $status = false;
  4457.                 if (!empty($lastOrder['PERSON_TYPE_ID']))
  4458.                 {
  4459.                     $status = $this->order->getPersonTypeId() == $lastOrder['PERSON_TYPE_ID'];
  4460.                 }
  4461.  
  4462.                 $result['LAST_ORDER_DATA']['PERSON_TYPE'] = $status;
  4463.  
  4464.                 $status = false;
  4465.                 if (!empty($lastOrder['DELIVERY_ID']) && $shipment = $this->getCurrentShipment($this->order))
  4466.                 {
  4467.                     if (empty($lastOrder['DELIVERY_EXTRA_SERVICES'][$lastOrder['DELIVERY_ID']]))
  4468.                     {
  4469.                         $status = $shipment->getDeliveryId() == $lastOrder['DELIVERY_ID'];
  4470.                     }
  4471.                 }
  4472.  
  4473.                 $result['LAST_ORDER_DATA']['DELIVERY'] = $status;
  4474.  
  4475.                 $status = false;
  4476.                 if (empty($lastOrder['PAY_CURRENT_ACCOUNT']) && !empty($lastOrder['PAY_SYSTEM_ID']) && $payment = $this->getExternalPayment($this->order))
  4477.                 {
  4478.                     $status = $payment->getPaymentSystemId() == $lastOrder['PAY_SYSTEM_ID'];
  4479.                 }
  4480.  
  4481.                 $result['LAST_ORDER_DATA']['PAY_SYSTEM'] = $status;
  4482.  
  4483.                 $status = false;
  4484.                 if (!empty($lastOrder['BUYER_STORE']) && $shipment = $this->getCurrentShipment($this->order))
  4485.                 {
  4486.                     $status = $shipment->getStoreId() == $lastOrder['BUYER_STORE'];
  4487.                 }
  4488.  
  4489.                 $result['LAST_ORDER_DATA']['PICK_UP'] = $status;
  4490.             }
  4491.             else
  4492.             {
  4493.                 // last order data cannot initialize
  4494.                 $result['LAST_ORDER_DATA']['FAIL'] = true;
  4495.             }
  4496.         }
  4497.         else
  4498.         {
  4499.             // last order data not initialized
  4500.             $result['LAST_ORDER_DATA']['FAIL'] = false;
  4501.         }
  4502.  
  4503.         $result['ZIP_PROPERTY_CHANGED'] = $this->arUserResult['ZIP_PROPERTY_CHANGED'];
  4504.         $result['ORDER_DESCRIPTION'] = $this->arUserResult['ORDER_DESCRIPTION'];
  4505.         $result['SHOW_AUTH'] = !$USER->IsAuthorized() && $this->arParams["ALLOW_AUTO_REGISTER"] == "N";
  4506.         $result['SHOW_EMPTY_BASKET'] = $arResult['SHOW_EMPTY_BASKET'];
  4507.         $result['AUTH'] = $arResult['AUTH'];
  4508.         $result['OK_MESSAGE'] = $arResult['OK_MESSAGE'];
  4509.         $result['GRID'] = $arResult['GRID'];
  4510.         $result['PERSON_TYPE'] = $arResult["PERSON_TYPE"];
  4511.         $result['PAY_SYSTEM'] = $arResult["PAY_SYSTEM"];
  4512.         $result['INNER_PAY_SYSTEM'] = $arResult["INNER_PAY_SYSTEM"];
  4513.         $result['DELIVERY'] = $arResult["DELIVERY"];
  4514.  
  4515.         foreach ($result['DELIVERY'] as &$delivery)
  4516.         {
  4517.             if (!empty($delivery['EXTRA_SERVICES']))
  4518.             {
  4519.                 $arExtraService =  array();
  4520.                 /** @var Delivery\ExtraServices\Base $extraService*/
  4521.                 foreach ($delivery['EXTRA_SERVICES'] as $extraServiceId => $extraService)
  4522.                 {
  4523.                     if ($extraService->canUserEditValue())
  4524.                     {
  4525.                         $arr = array();
  4526.                         $arr['id'] = $extraServiceId;
  4527.                         $arr['name'] = $extraService->getName();
  4528.                         $arr['value'] = $extraService->getValue();
  4529.                         $arr['price'] = $extraService->getPriceShipment($this->getCurrentShipment($this->order));
  4530.                         $arr['priceFormatted'] = SaleFormatCurrency($extraService->getPriceShipment($this->getCurrentShipment($this->order)), $this->order->getCurrency());
  4531.                         $arr['description'] = $extraService->getDescription();
  4532.                         $arr['canUserEditValue'] = $extraService->canUserEditValue();
  4533.                         $arr['editControl'] = $extraService->getEditControl('DELIVERY_EXTRA_SERVICES['.$delivery['ID'].']['.$extraServiceId.']');
  4534.                         $arr['viewControl'] = $extraService->getViewControl();
  4535.                         $arExtraService[] = $arr;
  4536.                     }
  4537.                 }
  4538.  
  4539.                 $delivery['EXTRA_SERVICES'] = $arExtraService;
  4540.             }
  4541.         }
  4542.  
  4543.         $result["USER_PROFILES"] = $arResult["ORDER_PROP"]['USER_PROFILES'];
  4544.  
  4545.         $arr = $this->order->getPropertyCollection()->getArray();
  4546.         $paymentSystemIds = $this->order->getPaymentSystemId();
  4547.         $deliverySystemIds = $this->order->getDeliverySystemId();
  4548.         foreach ($arr['properties'] as $key => $property)
  4549.         {
  4550.             if ($property['UTIL'] === 'Y'
  4551.                 ||
  4552.                 isset($property['RELATION']) && !$this->checkRelatedProperty($property, $paymentSystemIds, $deliverySystemIds)
  4553.             )
  4554.             {
  4555.                 unset($arr['properties'][$key]);
  4556.             }
  4557.         }
  4558.         usort($arr['properties'], array('self', 'compareProperties'));
  4559.  
  4560.         if (!empty($arr['groups']) && !empty($arr['properties']))
  4561.         {
  4562.             $groupIndexList = array();
  4563.             foreach ($arr['groups'] as $groupdData)
  4564.             {
  4565.                 $groupIndexList[] = intval($groupdData['ID']);
  4566.             }
  4567.  
  4568.             if (!empty($groupIndexList))
  4569.             {
  4570.                 foreach ($arr['properties'] as $index => $propertyData)
  4571.                 {
  4572.                     if (array_key_exists('PROPS_GROUP_ID', $propertyData))
  4573.                     {
  4574.                         if (!in_array($propertyData['PROPS_GROUP_ID'], $groupIndexList))
  4575.                         {
  4576.                             $arr['properties'][$index]['PROPS_GROUP_ID'] = 0;
  4577.                         }
  4578.                     }
  4579.  
  4580.                     if ($propertyData['TYPE'] === 'ENUM' && is_array($propertyData['OPTIONS']))
  4581.                     {
  4582.                         $arr['properties'][$index]['OPTIONS_SORT'] = array_keys($propertyData['OPTIONS']);
  4583.                     }
  4584.                 }
  4585.             }
  4586.  
  4587.         }
  4588.  
  4589.         $result["ORDER_PROP"] = $arr;
  4590.         $result['STORE_LIST'] = $arResult['STORE_LIST'];
  4591.         $result['BUYER_STORE'] = $arResult['BUYER_STORE'];
  4592.  
  4593.         $result['COUPON_LIST'] = array();
  4594.         $arCoupons = DiscountCouponsManager::get(true, array(), true, true);
  4595.         if (!empty($arCoupons))
  4596.         {
  4597.             foreach ($arCoupons as &$oneCoupon)
  4598.             {
  4599.                 if ($oneCoupon['STATUS'] == DiscountCouponsManager::STATUS_NOT_FOUND || $oneCoupon['STATUS'] == DiscountCouponsManager::STATUS_FREEZE)
  4600.                 {
  4601.                     $oneCoupon['JS_STATUS'] = 'BAD';
  4602.                 }
  4603.                 elseif ($oneCoupon['STATUS'] == DiscountCouponsManager::STATUS_NOT_APPLYED || $oneCoupon['STATUS'] == DiscountCouponsManager::STATUS_ENTERED)
  4604.                 {
  4605.                     $oneCoupon['JS_STATUS'] = 'ENTERED';
  4606.                 }
  4607.                 else
  4608.                 {
  4609.                     $oneCoupon['JS_STATUS'] = 'APPLIED';
  4610.                 }
  4611.  
  4612.                 $oneCoupon['JS_CHECK_CODE'] = '';
  4613.                 if (isset($oneCoupon['CHECK_CODE_TEXT']))
  4614.                 {
  4615.                     $oneCoupon['JS_CHECK_CODE'] = is_array($oneCoupon['CHECK_CODE_TEXT'])
  4616.                         ? implode('<br>', $oneCoupon['CHECK_CODE_TEXT'])
  4617.                         : $oneCoupon['CHECK_CODE_TEXT'];
  4618.                 }
  4619.  
  4620.                 $result['COUPON_LIST'][] = $oneCoupon;
  4621.             }
  4622.  
  4623.             unset($oneCoupon);
  4624.             $result['COUPON_LIST'] = array_values($arCoupons);
  4625.         }
  4626.         unset($arCoupons);
  4627.  
  4628.         $result['PAY_CURRENT_ACCOUNT'] = 'N';
  4629.         if ($innerPaySystem = $this->order->getPaymentCollection()->getInnerPayment())
  4630.         {
  4631.             if ($innerPaySystem->getSum() > 0)
  4632.             {
  4633.                 $result['PAY_CURRENT_ACCOUNT'] = 'Y';
  4634.             }
  4635.         }
  4636.  
  4637.         $result['PAY_FROM_ACCOUNT'] = $arResult["PAY_FROM_ACCOUNT"];
  4638.         $result['CURRENT_BUDGET_FORMATED'] = $arResult["CURRENT_BUDGET_FORMATED"];
  4639.  
  4640.         $result['TOTAL'] = array(
  4641.             'PRICE_WITHOUT_DISCOUNT_VALUE' => $arResult["PRICE_WITHOUT_DISCOUNT_VALUE"],
  4642.             'PRICE_WITHOUT_DISCOUNT' => $arResult["PRICE_WITHOUT_DISCOUNT"],
  4643.             'PAYED_FROM_ACCOUNT_FORMATED' => $arResult["PAYED_FROM_ACCOUNT_FORMATED"],
  4644.             'ORDER_TOTAL_PRICE' => $arResult["ORDER_TOTAL_PRICE"],
  4645.             'ORDER_TOTAL_PRICE_FORMATED' => $arResult["ORDER_TOTAL_PRICE_FORMATED"],
  4646.             'ORDER_TOTAL_LEFT_TO_PAY' => $arResult["ORDER_TOTAL_LEFT_TO_PAY"],
  4647.             'ORDER_TOTAL_LEFT_TO_PAY_FORMATED' => $arResult["ORDER_TOTAL_LEFT_TO_PAY_FORMATED"],
  4648.             'ORDER_WEIGHT' => $arResult["ORDER_WEIGHT"],
  4649.             'ORDER_WEIGHT_FORMATED' => $arResult["ORDER_WEIGHT_FORMATED"],
  4650.             'ORDER_PRICE' => $arResult["ORDER_PRICE"],
  4651.             'ORDER_PRICE_FORMATED' => $arResult["ORDER_PRICE_FORMATED"],
  4652.             'USE_VAT' => $arResult["USE_VAT"],
  4653.             'VAT_RATE' => $arResult["VAT_RATE"],
  4654.             'VAT_SUM' => $arResult["VAT_SUM"],
  4655.             'VAT_SUM_FORMATED' => $arResult["VAT_SUM_FORMATED"],
  4656.             'TAX_PRICE' => $arResult["TAX_PRICE"],
  4657.             'TAX_LIST' => $arResult["TAX_LIST"],
  4658.             'DISCOUNT_PRICE' => $arResult["DISCOUNT_PRICE"],
  4659.             'DISCOUNT_PRICE_FORMATED' => $arResult["DISCOUNT_PRICE_FORMATED"],
  4660.             'DELIVERY_PRICE' => $arResult["DELIVERY_PRICE"],
  4661.             'DELIVERY_PRICE_FORMATED' => $arResult["DELIVERY_PRICE_FORMATED"],
  4662.             'PAY_SYSTEM_PRICE' => $arResult["PAY_SYSTEM_PRICE"],
  4663.             'PAY_SYSTEM_PRICE_FORMATTED' => $arResult["PAY_SYSTEM_PRICE_FORMATTED"]
  4664.         );
  4665.  
  4666.         $result['ERROR'] = $arResult["ERROR_SORTED"];
  4667.         $result['WARNING'] = $arResult["WARNING"];
  4668.  
  4669.         $arResult['LOCATIONS'] = $this->getLocationsResult();
  4670.  
  4671.         foreach (GetModuleEvents("sale", 'OnSaleComponentOrderJsData', true) as $arEvent)
  4672.         {
  4673.             ExecuteModuleEventEx($arEvent, array(&$this->arResult, &$this->arParams));
  4674.         }
  4675.     }
  4676.  
  4677.     /**
  4678.      * Scales images of all entities depending on scale parameters
  4679.      *
  4680.      * @param        $result
  4681.      * @param string $scale
  4682.      */
  4683.     public static function scaleImages(&$result, $scale = '')
  4684.     {
  4685.         if (!empty($result) && is_array($result))
  4686.         {
  4687.             if (!empty($result['DELIVERY']) && is_array($result['DELIVERY']))
  4688.             {
  4689.                 foreach ($result['DELIVERY'] as $key => $delivery)
  4690.                 {
  4691.                     if (!empty($delivery["LOGOTIP"]))
  4692.                     {
  4693.                         self::resizeImage($delivery, 'LOGOTIP', $delivery["LOGOTIP"],
  4694.                             array("width" => 600, "height" => 600),
  4695.                             array("width" => 95, "height" => 55),
  4696.                             $scale
  4697.                         );
  4698.                         $result["DELIVERY"][$key] = $delivery;
  4699.                     }
  4700.  
  4701.                 }
  4702.                 unset($logotype, $delivery);
  4703.             }
  4704.  
  4705.             if (!empty($result['PAY_SYSTEM']) && is_array($result['PAY_SYSTEM']))
  4706.             {
  4707.                 foreach ($result['PAY_SYSTEM'] as $key => $paySystem)
  4708.                 {
  4709.                     if (!empty($paySystem["PSA_LOGOTIP"]))
  4710.                     {
  4711.                         self::resizeImage($paySystem, 'PSA_LOGOTIP', $paySystem["PSA_LOGOTIP"],
  4712.                             array("width" => 600, "height" => 600),
  4713.                             array("width" => 95, "height" => 55),
  4714.                             $scale
  4715.                         );
  4716.                         $result["PAY_SYSTEM"][$key] = $paySystem;
  4717.                     }
  4718.                 }
  4719.                 unset($logotype, $paySystem);
  4720.             }
  4721.  
  4722.             if (!empty($result['INNER_PAY_SYSTEM']) && is_array($result['INNER_PAY_SYSTEM']) && !empty($result['INNER_PAY_SYSTEM']["LOGOTIP"]))
  4723.             {
  4724.                 self::resizeImage($result['INNER_PAY_SYSTEM'], 'LOGOTIP', $result['INNER_PAY_SYSTEM']["LOGOTIP"],
  4725.                     array("width" => 600, "height" => 600),
  4726.                     array("width" => 95, "height" => 55),
  4727.                     $scale
  4728.                 );
  4729.             }
  4730.  
  4731.             if (!empty($result['STORE_LIST']) && is_array($result['STORE_LIST']))
  4732.             {
  4733.                 foreach ($result['STORE_LIST'] as $key => $store)
  4734.                 {
  4735.                     if (!empty($store["IMAGE_ID"]))
  4736.                     {
  4737.                         self::resizeImage($store, 'IMAGE_ID', $store["IMAGE_ID"],
  4738.                             array("width" => 320, "height" => 320),
  4739.                             array("width" => 115, "height" => 115),
  4740.                             $scale
  4741.                         );
  4742.                         $result["STORE_LIST"][$key] = $store;
  4743.                     }
  4744.                 }
  4745.                 unset($logotype, $store);
  4746.             }
  4747.         }
  4748.     }
  4749.  
  4750.     /**
  4751.      * Returns array with locations data output
  4752.      *
  4753.      * @return array
  4754.      */
  4755.     protected function getLocationsResult()
  4756.     {
  4757.         $locations = array();
  4758.         $propertyCollection = $this->order->getPropertyCollection();
  4759.         $properties = $propertyCollection->getArray();
  4760.  
  4761.         foreach ($properties['properties'] as $property)
  4762.         {
  4763.             if ($property['UTIL'] == 'Y')
  4764.                 continue;
  4765.  
  4766.             if ($property['TYPE'] == 'LOCATION')
  4767.             {
  4768.                 $locationTemplateP = $this->arParams['TEMPLATE_LOCATION'] == '.default' ? 'steps' : 'search';
  4769.                 $locationTemplate = $this->request->get('PERMANENT_MODE_STEPS') == 1 ? 'steps' : $locationTemplateP;
  4770.  
  4771.                 $locations[$property['ID']]['template'] = $locationTemplate;
  4772.                 $locations[$property['ID']]['output'] = $this->getLocationHtml($property, $locationTemplate);
  4773.                 $locations[$property['ID']]['showAlt'] = isset($this->arUserResult['ORDER_PROP'][$property['INPUT_FIELD_LOCATION']]);
  4774.                 $locations[$property['ID']]['lastValue'] = reset($property['VALUE']);
  4775.  
  4776.                 if ($property['IS_LOCATION'] === 'Y')
  4777.                 {
  4778.                     $locations[$property['ID']]['coordinates'] = LocationTable::getRow(array(
  4779.                         'select' => array('LONGITUDE', 'LATITUDE'),
  4780.                         'filter' => array('=CODE' => reset($property['VALUE']))
  4781.                     ));
  4782.                 }
  4783.             }
  4784.         }
  4785.  
  4786.         return $locations;
  4787.     }
  4788.  
  4789.     protected function getLocationHtml($property, $locationTemplate)
  4790.     {
  4791.         global $APPLICATION;
  4792.  
  4793.         $locationOutput = array();
  4794.         $showDefault = true;
  4795.  
  4796.         $propertyId = (int)$property['ID'];
  4797.         $isMultiple = $property['MULTIPLE'] == 'Y' && $property['IS_LOCATION'] != 'Y';
  4798.  
  4799.         $locationAltPropDisplayManual = $this->request->get('LOCATION_ALT_PROP_DISPLAY_MANUAL');
  4800.         $altPropManual = isset($locationAltPropDisplayManual[$propertyId]) && (bool)$locationAltPropDisplayManual[$propertyId];
  4801.  
  4802.         $location = $this->order->getPropertyCollection()->getItemByOrderPropertyId($propertyId);
  4803.         $actualValues = $location->getValue();
  4804.  
  4805.         if (!is_array($actualValues))
  4806.         {
  4807.             $actualValues = array($actualValues);
  4808.         }
  4809.  
  4810.         if (!empty($actualValues) && is_array($actualValues))
  4811.         {
  4812.             foreach ($actualValues as $key => $value)
  4813.             {
  4814.                 $parameters = array(
  4815.                     'CODE' => $value,
  4816.                     'INPUT_NAME' => 'ORDER_PROP_'.$propertyId.($isMultiple ? '['.$key.']' : ''),
  4817.                     'CACHE_TYPE' => 'A',
  4818.                     'CACHE_TIME' => '36000000',
  4819.                     'SEARCH_BY_PRIMARY' => 'N',
  4820.                     'SHOW_DEFAULT_LOCATIONS' => $showDefault ? 'Y' : 'N',
  4821.                     'PROVIDE_LINK_BY' => 'code',
  4822.                     'JS_CALLBACK' => 'submitFormProxy',
  4823.                     'JS_CONTROL_DEFERRED_INIT' => $propertyId.($isMultiple ? '_'.$key : ''),
  4824.                     'JS_CONTROL_GLOBAL_ID' => $propertyId.($isMultiple ? '_'.$key : ''),
  4825.                     'DISABLE_KEYBOARD_INPUT' => 'Y',
  4826.                     'PRECACHE_LAST_LEVEL' => 'N',
  4827.                     'PRESELECT_TREE_TRUNK' => 'Y',
  4828.                     'SUPPRESS_ERRORS' => 'Y',
  4829.                     'FILTER_BY_SITE' => 'Y',
  4830.                     'FILTER_SITE_ID' => SITE_ID
  4831.                 );
  4832.  
  4833.                 ob_start();
  4834.  
  4835.                 if ($locationTemplate == 'steps')
  4836.                 {
  4837.                     echo '<input type="hidden" id="LOCATION_ALT_PROP_DISPLAY_MANUAL['.$propertyId
  4838.                         .']" name="LOCATION_ALT_PROP_DISPLAY_MANUAL['.$propertyId.']" value="'
  4839.                         .($altPropManual ? '1' : '0').'" />';
  4840.                 }
  4841.  
  4842.                 $APPLICATION->IncludeComponent(
  4843.                     'bitrix:sale.location.selector.'.$locationTemplate,
  4844.                     '',
  4845.                     $parameters,
  4846.                     null,
  4847.                     array('HIDE_ICONS' => 'Y')
  4848.                 );
  4849.  
  4850.                 $locationOutput[] = ob_get_contents();
  4851.                 ob_end_clean();
  4852.  
  4853.                 $showDefault = false;
  4854.             }
  4855.         }
  4856.  
  4857.         if ($isMultiple)
  4858.         {
  4859.             $parameters = array(
  4860.                 'CODE' => '',
  4861.                 'INPUT_NAME' => 'ORDER_PROP_'.$propertyId.'[#key#]',
  4862.                 'CACHE_TYPE' => 'A',
  4863.                 'CACHE_TIME' => '36000000',
  4864.                 'SEARCH_BY_PRIMARY' => 'N',
  4865.                 'SHOW_DEFAULT_LOCATIONS' => 'N',
  4866.                 'PROVIDE_LINK_BY' => 'code',
  4867.                 'JS_CALLBACK' => 'submitFormProxy',
  4868.                 'JS_CONTROL_DEFERRED_INIT' => $propertyId.'_key__',
  4869.                 'JS_CONTROL_GLOBAL_ID' => $propertyId.'_key__',
  4870.                 'DISABLE_KEYBOARD_INPUT' => 'Y',
  4871.                 'PRECACHE_LAST_LEVEL' => 'N',
  4872.                 'PRESELECT_TREE_TRUNK' => 'Y',
  4873.                 'SUPPRESS_ERRORS' => 'Y',
  4874.                 'FILTER_BY_SITE' => 'Y',
  4875.                 'FILTER_SITE_ID' => SITE_ID
  4876.             );
  4877.  
  4878.             ob_start();
  4879.  
  4880.             $APPLICATION->IncludeComponent(
  4881.                 'bitrix:sale.location.selector.'.$locationTemplate,
  4882.                 '',
  4883.                 $parameters,
  4884.                 null,
  4885.                 array('HIDE_ICONS' => 'Y')
  4886.             );
  4887.  
  4888.             $locationOutput['clean'] = ob_get_contents();
  4889.             ob_end_clean();
  4890.         }
  4891.  
  4892.         return $locationOutput;
  4893.     }
  4894.  
  4895.     protected function isActiveCoupon($coupon)
  4896.     {
  4897.         $arCoupons = DiscountCouponsManager::get(true, array('COUPON' => $coupon), true, true);
  4898.         if (!empty($arCoupons))
  4899.         {
  4900.             $arCoupon = array_shift($arCoupons);
  4901.             if ($arCoupon['STATUS'] == DiscountCouponsManager::STATUS_NOT_APPLYED)
  4902.                 return true;
  4903.         }
  4904.  
  4905.         return false;
  4906.     }
  4907.  
  4908.     /**
  4909.      * Prepares $this->arResult
  4910.      * Execution of 'OnSaleComponentOrderOneStepProcess' event
  4911.      */
  4912.     protected function prepareResultArray()
  4913.     {
  4914.         $this->initGrid();
  4915.         $this->obtainBasket();
  4916.         $this->obtainPropertiesForIbElements();
  4917.  
  4918.         if ($this->arParams['COMPATIBLE_MODE'] == 'Y')
  4919.         {
  4920.             $this->obtainFormattedProperties();
  4921.         }
  4922.  
  4923.         $this->obtainDelivery();
  4924.         $this->obtainPaySystem();
  4925.         $this->obtainTaxes();
  4926.         $this->obtainTotal();
  4927.  
  4928.         if ($this->arParams['USER_CONSENT'] === 'Y')
  4929.         {
  4930.             $this->obtainUserConsentInfo();
  4931.         }
  4932.  
  4933.         $this->getJsDataResult();
  4934.  
  4935.         if ($this->arParams['COMPATIBLE_MODE'] == 'Y')
  4936.         {
  4937.             $this->obtainRelatedProperties();
  4938.             $this->makeResultCompatible();
  4939.             $this->makeOrderDataArray();
  4940.         }
  4941.  
  4942.         $this->arResult['USER_VALS'] = $this->arUserResult;
  4943.         $this->executeEvent('OnSaleComponentOrderOneStepProcess', $this->order);
  4944.         $this->arResult['USER_VALS'] = $this->arUserResult;
  4945.  
  4946.         //try to avoid use "executeEvent" methods and use new events like this
  4947.         foreach (GetModuleEvents("sale", 'OnSaleComponentOrderResultPrepared', true) as $arEvent)
  4948.             ExecuteModuleEventEx($arEvent, array($this->order, &$this->arUserResult, $this->request, &$this->arParams, &$this->arResult));
  4949.     }
  4950.  
  4951.     /**
  4952.      * Create $this->arUserResult array and fill with data from request
  4953.      * Execution of 'OnSaleComponentOrderUserResult' event
  4954.      */
  4955.     protected function makeUserResultArray()
  4956.     {
  4957.         $request =& $this->request;
  4958.  
  4959.         $arUserResult = array(
  4960.             "PERSON_TYPE_ID" => false,
  4961.             "PERSON_TYPE_OLD" => false,
  4962.             "PAY_SYSTEM_ID" => false,
  4963.             "DELIVERY_ID" => false,
  4964.             "ORDER_PROP" => array(),
  4965.             "DELIVERY_LOCATION" => false,
  4966.             "TAX_LOCATION" => false,
  4967.             "PAYER_NAME" => false,
  4968.             "USER_EMAIL" => false,
  4969.             "PROFILE_NAME" => false,
  4970.             "PAY_CURRENT_ACCOUNT" => false,
  4971.             "CONFIRM_ORDER" => false,
  4972.             "FINAL_STEP" => false,
  4973.             "ORDER_DESCRIPTION" => false,
  4974.             "PROFILE_ID" => false,
  4975.             "PROFILE_CHANGE" => false,
  4976.             "DELIVERY_LOCATION_ZIP" => false,
  4977.             "ZIP_PROPERTY_CHANGED" => 'N',
  4978.             "QUANTITY_LIST" => array(),
  4979.             "USE_PRELOAD" => $this->arParams['USE_PRELOAD'] === 'Y'
  4980.         );
  4981.  
  4982.         if ($request->isPost())
  4983.         {
  4984.             if (intval($request->get('PERSON_TYPE')) > 0)
  4985.                 $arUserResult["PERSON_TYPE_ID"] = intval($request->get('PERSON_TYPE'));
  4986.  
  4987.             if (intval($request->get('PERSON_TYPE_OLD')) > 0)
  4988.                 $arUserResult["PERSON_TYPE_OLD"] = intval($request->get('PERSON_TYPE_OLD'));
  4989.  
  4990.             if (empty($arUserResult["PERSON_TYPE_OLD"]) || $arUserResult["PERSON_TYPE_OLD"] == $arUserResult["PERSON_TYPE_ID"])
  4991.             {
  4992.                 $profileId = $request->get('PROFILE_ID');
  4993.                 if (!empty($profileId))
  4994.                     $arUserResult["PROFILE_ID"] = intval($profileId);
  4995.  
  4996.                 $paySystemId = $request->get('PAY_SYSTEM_ID');
  4997.                 if (!empty($paySystemId))
  4998.                     $arUserResult["PAY_SYSTEM_ID"] = intval($paySystemId);
  4999.  
  5000.                 $deliveryId = $request->get('DELIVERY_ID');
  5001.                 if (!empty($deliveryId))
  5002.                     $arUserResult["DELIVERY_ID"] = $deliveryId;
  5003.  
  5004.                 $buyerStore = $request->get('BUYER_STORE');
  5005.                 if (!empty($buyerStore))
  5006.                     $arUserResult["BUYER_STORE"] = intval($buyerStore);
  5007.  
  5008.                 $deliveryExtraServices = $request->get('DELIVERY_EXTRA_SERVICES');
  5009.                 if (!empty($deliveryExtraServices))
  5010.                     $arUserResult["DELIVERY_EXTRA_SERVICES"] = $deliveryExtraServices;
  5011.  
  5012.                 if (strlen($request->get('ORDER_DESCRIPTION')) > 0)
  5013.                 {
  5014.                     $arUserResult["~ORDER_DESCRIPTION"] = $request->get('ORDER_DESCRIPTION');
  5015.                     $arUserResult["ORDER_DESCRIPTION"] = htmlspecialcharsbx($request->get('ORDER_DESCRIPTION'));
  5016.                 }
  5017.  
  5018.                 if ($request->get('PAY_CURRENT_ACCOUNT') == "Y")
  5019.                     $arUserResult["PAY_CURRENT_ACCOUNT"] = "Y";
  5020.  
  5021.                 if ($request->get('confirmorder') == "Y")
  5022.                 {
  5023.                     $arUserResult["CONFIRM_ORDER"] = "Y";
  5024.                     $arUserResult["FINAL_STEP"] = "Y";
  5025.                 }
  5026.  
  5027.                 $arUserResult["PROFILE_CHANGE"] = $request->get('profile_change') == "Y" ? "Y" : "N";
  5028.             }
  5029.  
  5030.             $arUserResult['ZIP_PROPERTY_CHANGED'] = $this->request->get('ZIP_PROPERTY_CHANGED') === 'Y' ? 'Y' : 'N';
  5031.         }
  5032.  
  5033.         foreach (GetModuleEvents("sale", 'OnSaleComponentOrderUserResult', true) as $arEvent)
  5034.             ExecuteModuleEventEx($arEvent, array(&$arUserResult, $this->request, &$this->arParams));
  5035.  
  5036.         $this->arUserResult = $arUserResult;
  5037.     }
  5038.  
  5039.     /**
  5040.      * Wrapper for event execution method.
  5041.      * Synchronizes modified data from event if needed.
  5042.      *
  5043.      * @deprecated
  5044.      * Compatibility method for old events.
  5045.      * Use new events like "OnSaleComponentOrderCreated" and "OnSaleComponentOrderResultPrepared" instead.
  5046.      *
  5047.      * @param string $eventName
  5048.      * @param null   $order
  5049.      */
  5050.     protected function executeEvent($eventName = '', $order = null)
  5051.     {
  5052.         $arModifiedResult = $this->arUserResult;
  5053.  
  5054.         foreach (GetModuleEvents("sale", $eventName, true) as $arEvent)
  5055.             ExecuteModuleEventEx($arEvent, array(&$this->arResult, &$arModifiedResult, &$this->arParams, true));
  5056.  
  5057.         if (!empty($order))
  5058.             $this->synchronize($arModifiedResult, $order);
  5059.     }
  5060.  
  5061.     protected function synchronize($arModifiedResult, Order $order)
  5062.     {
  5063.         $modifiedFields = self::arrayDiffRecursive($arModifiedResult, $this->arUserResult);
  5064.  
  5065.         if (!empty($modifiedFields))
  5066.             $this->synchronizeOrder($modifiedFields, $order);
  5067.     }
  5068.  
  5069.     /**
  5070.      * Synchronization of modified fields with current order object.
  5071.      *
  5072.      * @param       $modifiedFields
  5073.      * @param Order $order
  5074.      * @throws Main\NotSupportedException
  5075.      * @throws Main\ObjectNotFoundException
  5076.      */
  5077.     protected function synchronizeOrder($modifiedFields, Order $order)
  5078.     {
  5079.         if (!empty($modifiedFields) && is_array($modifiedFields))
  5080.         {
  5081.             $recalculatePayment = $modifiedFields['CALCULATE_PAYMENT'] === true;
  5082.             unset($modifiedFields['CALCULATE_PAYMENT']);
  5083.             $recalculateDelivery = false;
  5084.  
  5085.             if (!empty($modifiedFields['PERSON_TYPE_ID']))
  5086.             {
  5087.                 $order->setPersonTypeId($modifiedFields['PERSON_TYPE_ID']);
  5088.             }
  5089.  
  5090.             $propertyCollection = $order->getPropertyCollection();
  5091.  
  5092.             foreach ($modifiedFields as $field => $value)
  5093.             {
  5094.                 switch ($field)
  5095.                 {
  5096.                     case 'PAY_SYSTEM_ID':
  5097.                         $recalculatePayment = true;
  5098.                         break;
  5099.                     case 'PAY_CURRENT_ACCOUNT':
  5100.                         $recalculatePayment = true;
  5101.                         break;
  5102.                     case 'DELIVERY_ID':
  5103.                         $recalculateDelivery = true;
  5104.                         break;
  5105.                     case 'ORDER_PROP':
  5106.                         if (is_array($value))
  5107.                         {
  5108.                             /** @var Sale\PropertyValue $property */
  5109.                             foreach ($propertyCollection as $property)
  5110.                             {
  5111.                                 if (array_key_exists($property->getPropertyId(), $value))
  5112.                                 {
  5113.                                     $property->setValue($value[$property->getPropertyId()]);
  5114.                                     $arProperty = $property->getProperty();
  5115.                                     if ($arProperty['IS_LOCATION'] === 'Y' || $arProperty['IS_ZIP'] === 'Y')
  5116.                                     {
  5117.                                         $recalculateDelivery = true;
  5118.                                     }
  5119.                                 }
  5120.                             }
  5121.                         }
  5122.  
  5123.                         break;
  5124.                     case 'ORDER_DESCRIPTION':
  5125.                         $order->setField('USER_DESCRIPTION', $value);
  5126.                         break;
  5127.                     case 'DELIVERY_LOCATION':
  5128.                         $codeValue = CSaleLocation::getLocationCODEbyID($value);
  5129.                         if ($property = $propertyCollection->getDeliveryLocation())
  5130.                         {
  5131.                             $property->setValue($codeValue);
  5132.                             $this->arUserResult['ORDER_PROP'][$property->getPropertyId()] = $codeValue;
  5133.                         }
  5134.  
  5135.                         $recalculateDelivery = true;
  5136.                         break;
  5137.                     case 'DELIVERY_LOCATION_BCODE':
  5138.                         if ($property = $propertyCollection->getDeliveryLocation())
  5139.                         {
  5140.                             $property->setValue($value);
  5141.                             $this->arUserResult['ORDER_PROP'][$property->getPropertyId()] = $value;
  5142.                         }
  5143.  
  5144.                         $recalculateDelivery = true;
  5145.                         break;
  5146.                     case 'DELIVERY_LOCATION_ZIP':
  5147.                         if ($property = $propertyCollection->getDeliveryLocationZip())
  5148.                         {
  5149.                             $property->setValue($value);
  5150.                             $this->arUserResult['ORDER_PROP'][$property->getPropertyId()] = $value;
  5151.                         }
  5152.  
  5153.                         $recalculateDelivery = true;
  5154.                         break;
  5155.                     case 'TAX_LOCATION':
  5156.                         $codeValue = CSaleLocation::getLocationCODEbyID($value);
  5157.                         if ($property = $propertyCollection->getTaxLocation())
  5158.                         {
  5159.                             $property->setValue($codeValue);
  5160.                             $this->arUserResult['ORDER_PROP'][$property->getPropertyId()] = $codeValue;
  5161.                         }
  5162.  
  5163.                         break;
  5164.                     case 'TAX_LOCATION_BCODE':
  5165.                         if ($property = $propertyCollection->getTaxLocation())
  5166.                         {
  5167.                             $property->setValue($value);
  5168.                             $this->arUserResult['ORDER_PROP'][$property->getPropertyId()] = $value;
  5169.                         }
  5170.  
  5171.                         break;
  5172.                     case 'PAYER_NAME':
  5173.                         if ($property = $propertyCollection->getPayerName())
  5174.                         {
  5175.                             $property->setValue($value);
  5176.                             $this->arUserResult['ORDER_PROP'][$property->getPropertyId()] = $value;
  5177.                         }
  5178.  
  5179.                         break;
  5180.                     case 'USER_EMAIL':
  5181.                         if ($property = $propertyCollection->getUserEmail())
  5182.                         {
  5183.                             $property->setValue($value);
  5184.                             $this->arUserResult['ORDER_PROP'][$property->getPropertyId()] = $value;
  5185.                         }
  5186.  
  5187.                         break;
  5188.                     case 'PROFILE_NAME':
  5189.                         if ($property = $propertyCollection->getProfileName())
  5190.                         {
  5191.                             $property->setValue($value);
  5192.                             $this->arUserResult['ORDER_PROP'][$property->getPropertyId()] = $value;
  5193.                         }
  5194.  
  5195.                         break;
  5196.                 }
  5197.  
  5198.                 $this->arUserResult[$field] = $value;
  5199.             }
  5200.  
  5201.             if ($recalculateDelivery)
  5202.             {
  5203.                 if ($shipment = $this->getCurrentShipment($order))
  5204.                 {
  5205.                     $this->initDelivery($shipment);
  5206.                     $recalculatePayment = true;
  5207.                 }
  5208.             }
  5209.  
  5210.             if ($recalculatePayment)
  5211.             {
  5212.                 $this->recalculatePayment($order);
  5213.             }
  5214.         }
  5215.     }
  5216.  
  5217.     public static function arrayDiffRecursive($arr1, $arr2)
  5218.     {
  5219.         $modified = array();
  5220.  
  5221.         foreach ($arr1 as $key => $value)
  5222.         {
  5223.             if (array_key_exists($key, $arr2))
  5224.             {
  5225.                 if (is_array($value) && is_array($arr2[$key]))
  5226.                 {
  5227.                     $arDiff = self::arrayDiffRecursive($value, $arr2[$key]);
  5228.                     if (!empty($arDiff))
  5229.                     {
  5230.                         $modified[$key] = $arDiff;
  5231.                     }
  5232.                 }
  5233.                 elseif ($value != $arr2[$key])
  5234.                 {
  5235.                     $modified[$key] = $value;
  5236.                 }
  5237.             }
  5238.             else
  5239.             {
  5240.                 $modified[$key] = $value;
  5241.             }
  5242.         }
  5243.  
  5244.         return $modified;
  5245.     }
  5246.  
  5247.     protected function makeOrderDataArray()
  5248.     {
  5249.         $orderData = $this->order->getFieldValues();
  5250.         $orderData['ORDER_PRICE'] = $this->arResult['ORDER_PRICE'];
  5251.         $orderData['ORDER_WEIGHT'] = $this->arResult['ORDER_WEIGHT'];
  5252.         $orderData['WEIGHT_UNIT'] = $this->arResult['WEIGHT_UNIT'];
  5253.         $orderData['WEIGHT_KOEF'] = $this->arResult['WEIGHT_KOEF'];
  5254.         $orderData['SITE_ID'] = SITE_ID;
  5255.         $orderData['USE_VAT'] = $this->arResult["USE_VAT"];
  5256.         $orderData['VAT_RATE'] = $this->arResult["VAT_RATE"];
  5257.         $orderData['VAT_SUM'] = $this->arResult["VAT_SUM"];
  5258.  
  5259.         $this->arResult['ORDER_DATA'] = array_merge($orderData, $this->arUserResult);
  5260.     }
  5261.  
  5262.     protected function saveProfileData()
  5263.     {
  5264.         $arResult =& $this->arResult;
  5265.         $profileId = null;
  5266.         $profileName = '';
  5267.         $properties = array();
  5268.  
  5269.         if (isset($arResult['ORDER_PROP']) && is_array($arResult['ORDER_PROP']['USER_PROFILES']))
  5270.         {
  5271.             foreach ($arResult['ORDER_PROP']['USER_PROFILES'] as $profile)
  5272.             {
  5273.                 if ($profile['CHECKED'] == 'Y')
  5274.                 {
  5275.                     $profileId = $profile['ID'];
  5276.                     break;
  5277.                 }
  5278.             }
  5279.         }
  5280.  
  5281.         $propertyCollection = $this->order->getPropertyCollection();
  5282.         if (!empty($propertyCollection))
  5283.         {
  5284.             if ($profileProp = $propertyCollection->getProfileName())
  5285.                 $profileName = $profileProp->getValue();
  5286.  
  5287.             /** @var Sale\PropertyValue $property */
  5288.             foreach ($propertyCollection as $property)
  5289.             {
  5290.                 $properties[$property->getField('ORDER_PROPS_ID')] = $property->getValue();
  5291.             }
  5292.         }
  5293.  
  5294.         CSaleOrderUserProps::DoSaveUserProfile(
  5295.             $this->order->getUserId(),
  5296.             $profileId,
  5297.             $profileName,
  5298.             $this->order->getPersonTypeId(),
  5299.             $properties,
  5300.             $arResult["ERROR"]
  5301.         );
  5302.     }
  5303.  
  5304.     protected function addStatistic()
  5305.     {
  5306.         if (Loader::includeModule("statistic"))
  5307.         {
  5308.             $event1 = "eStore";
  5309.             $event2 = "order_confirm";
  5310.             $event3 = $this->order->getId();
  5311.             $money = $this->order->getPrice();
  5312.             $currency = $this->order->getCurrency();
  5313.  
  5314.             $e = $event1."/".$event2."/".$event3;
  5315.  
  5316.             if (!is_array($_SESSION["ORDER_EVENTS"]) || (is_array($_SESSION["ORDER_EVENTS"]) && !in_array($e, $_SESSION["ORDER_EVENTS"])))
  5317.             {
  5318.                 CStatistic::Set_Event($event1, $event2, $event3, $goto = "", $money, $currency);
  5319.                 $_SESSION["ORDER_EVENTS"][] = $e;
  5320.             }
  5321.         }
  5322.     }
  5323.  
  5324.     /**
  5325.      * Initialization of shipment object. Filling with basket items.
  5326.      *
  5327.      * @param Order $order
  5328.      * @return Shipment
  5329.      * @throws Main\ArgumentTypeException
  5330.      * @throws Main\NotSupportedException
  5331.      */
  5332.     public function initShipment(Order $order)
  5333.     {
  5334.         $shipmentCollection = $order->getShipmentCollection();
  5335.         $shipment = $shipmentCollection->createItem();
  5336.         $shipmentItemCollection = $shipment->getShipmentItemCollection();
  5337.         $shipment->setField('CURRENCY', $order->getCurrency());
  5338.  
  5339.         /** @var Sale\BasketItem $item */
  5340.         foreach ($order->getBasket() as $item)
  5341.         {
  5342.             /** @var Sale\ShipmentItem $shipmentItem */
  5343.             $shipmentItem = $shipmentItemCollection->createItem($item);
  5344.             $shipmentItem->setQuantity($item->getQuantity());
  5345.         }
  5346.  
  5347.         return $shipment;
  5348.     }
  5349.  
  5350.     /**
  5351.      * Initializes user data and creates order.
  5352.      * Checks for event flags for possible order/payments recalculations.
  5353.      * Execution of 'OnSaleComponentOrderOneStepDiscountBefore' event.
  5354.      *
  5355.      * @param $userId
  5356.      * @return Order
  5357.      */
  5358.     protected function createOrder($userId)
  5359.     {
  5360.         $this->makeUserResultArray();
  5361.  
  5362.         DiscountCouponsManager::init();
  5363.         $this->executeEvent('OnSaleComponentOrderOneStepDiscountBefore');
  5364.  
  5365.         /** @var Order $order */
  5366.         $order = $this->getOrder($userId);
  5367.  
  5368.         // $this->arUserResult['RECREATE_ORDER'] - flag for full order recalculation after events manipulations
  5369.         if ($this->arUserResult['RECREATE_ORDER'])
  5370.             $order = $this->getOrder($userId);
  5371.  
  5372.         // $this->arUserResult['CALCULATE_PAYMENT'] - flag for order payments recalculation after events manipulations
  5373.         if ($this->arUserResult['CALCULATE_PAYMENT'])
  5374.             $this->recalculatePayment($order);
  5375.  
  5376.         return $order;
  5377.     }
  5378.  
  5379.  
  5380.     /**
  5381.      * Returns created order object based on user and request data.
  5382.      * Execution of 'OnSaleComponentOrderCreated' event.
  5383.      *
  5384.      * @param $userId
  5385.      * @return Order
  5386.      */
  5387.     protected function getOrder($userId)
  5388.     {
  5389.         /** @var Order $order */
  5390.         $order = Order::create($this->context->getSite(), $userId);
  5391.         $order->isStartField();
  5392.  
  5393.         $this->initLastOrderData($order);
  5394.  
  5395.         $order->setField('STATUS_ID', Sale\OrderStatus::getInitialStatus());
  5396.  
  5397.         if ($this->arParams['USE_PREPAYMENT'] === 'Y')
  5398.         {
  5399.             $this->usePrepayment($order);
  5400.         }
  5401.  
  5402.         $isPersonTypeChanged = $this->initPersonType($order);
  5403.         $this->initProperties($order, $isPersonTypeChanged);
  5404.         $this->initBasket($order);
  5405.  
  5406.         $taxes = $order->getTax();
  5407.         $taxes->setDeliveryCalculate($this->arParams['COUNT_DELIVERY_TAX'] === 'Y');
  5408.  
  5409.         $shipment = $this->initShipment($order);
  5410.  
  5411.         $order->doFinalAction(true);
  5412.  
  5413.         if ($this->arParams['DELIVERY_TO_PAYSYSTEM'] === 'd2p')
  5414.         {
  5415.             $this->initDelivery($shipment);
  5416.             $this->initPayment($order);
  5417.         }
  5418.         else
  5419.         {
  5420.             $this->initPayment($order);
  5421.             $this->initDelivery($shipment);
  5422.         }
  5423.  
  5424.         $this->initEntityCompanyIds($order);
  5425.         $this->initOrderFields($order);
  5426.         $this->recalculatePayment($order);
  5427.  
  5428.         $eventParameters = array(
  5429.             $order, &$this->arUserResult, $this->request,
  5430.             &$this->arParams, &$this->arResult, &$this->arDeliveryServiceAll, &$this->arPaySystemServiceAll
  5431.         );
  5432.         foreach (GetModuleEvents('sale', 'OnSaleComponentOrderCreated', true) as $arEvent)
  5433.         {
  5434.             ExecuteModuleEventEx($arEvent, $eventParameters);
  5435.         }
  5436.  
  5437.         // no need to calculate deliveries when order is saving
  5438.         if ($this->action !== 'saveOrderAjax')
  5439.         {
  5440.             $this->calculateDeliveries($order);
  5441.         }
  5442.  
  5443.         return $order;
  5444.     }
  5445.  
  5446.     /**
  5447.      * Initializes companies for payment and shipment
  5448.      *
  5449.      * @param Order $order
  5450.      */
  5451.     protected function initEntityCompanyIds(Order $order)
  5452.     {
  5453.         $paymentCollection = $order->getPaymentCollection();
  5454.         if ($paymentCollection)
  5455.         {
  5456.             /** @var Payment $payment */
  5457.             foreach ($paymentCollection as $payment)
  5458.             {
  5459.                 if ($payment->isInner())
  5460.                     continue;
  5461.  
  5462.                 $payment->setField('COMPANY_ID', Company\Manager::getAvailableCompanyIdByEntity($payment));
  5463.                 if ($payment->getField('COMPANY_ID') > 0)
  5464.                 {
  5465.                     $responsibleGroups = Sale\Internals\CompanyResponsibleGroupTable::getCompanyGroups($payment->getField('COMPANY_ID'));
  5466.                     if (!empty($responsibleGroups) && is_array($responsibleGroups))
  5467.                     {
  5468.                         $usersList = array();
  5469.                         foreach ($responsibleGroups as $groupId)
  5470.                         {
  5471.                             $usersList = array_merge($usersList, CGroup::GetGroupUser($groupId));
  5472.                         }
  5473.  
  5474.                         if (!empty($usersList) && is_array($usersList))
  5475.                         {
  5476.                             $usersList = array_unique($usersList);
  5477.                             $responsibleUserId = $usersList[array_rand($usersList)];
  5478.  
  5479.                             /** @var Main\Entity\Event $event */
  5480.                             $event = new Main\Event('sale', 'OnSaleComponentBeforePaymentSetResponsibleUserId', array(
  5481.                                 'ENTITY' => $payment,
  5482.                                 'VALUE' => $responsibleUserId,
  5483.                             ));
  5484.                             $event->send();
  5485.  
  5486.                             if ($event->getResults())
  5487.                             {
  5488.                                 $result = new Result();
  5489.                                 /** @var Main\EventResult $eventResult */
  5490.                                 foreach($event->getResults() as $eventResult)
  5491.                                 {
  5492.                                     if($eventResult->getType() == Main\EventResult::SUCCESS)
  5493.                                     {
  5494.                                         if ($eventResultData = $eventResult->getParameters())
  5495.                                         {
  5496.                                             if (isset($eventResultData['VALUE']) && $eventResultData['VALUE'] != $responsibleUserId)
  5497.                                             {
  5498.                                                 $responsibleUserId = $eventResultData['VALUE'];
  5499.                                             }
  5500.                                         }
  5501.                                     }
  5502.                                 }
  5503.                             }
  5504.  
  5505.                             $payment->setField('RESPONSIBLE_ID', $responsibleUserId);
  5506.                         }
  5507.                     }
  5508.                 }
  5509.             }
  5510.         }
  5511.  
  5512.         $shipmentCollection = $order->getShipmentCollection();
  5513.         if ($shipmentCollection)
  5514.         {
  5515.             /** @var Shipment $shipment */
  5516.             foreach ($shipmentCollection as $shipment)
  5517.             {
  5518.                 if ($shipment->isSystem())
  5519.                     continue;
  5520.  
  5521.                 $shipment->setField('COMPANY_ID', Company\Manager::getAvailableCompanyIdByEntity($shipment));
  5522.  
  5523.                 if ($shipment->getField('COMPANY_ID') > 0)
  5524.                 {
  5525.                     $responsibleGroups = Sale\Internals\CompanyResponsibleGroupTable::getCompanyGroups($shipment->getField('COMPANY_ID'));
  5526.                     if (!empty($responsibleGroups) && is_array($responsibleGroups))
  5527.                     {
  5528.                         $usersList = array();
  5529.                         foreach ($responsibleGroups as $groupId)
  5530.                         {
  5531.                             $usersList = array_merge($usersList, CGroup::GetGroupUser($groupId));
  5532.                         }
  5533.  
  5534.                         if (!empty($usersList) && is_array($usersList))
  5535.                         {
  5536.                             $usersList = array_unique($usersList);
  5537.                             $responsibleUserId = $usersList[array_rand($usersList)];
  5538.  
  5539.                             /** @var Main\Entity\Event $event */
  5540.                             $event = new Main\Event('sale', 'OnSaleComponentBeforeShipmentSetResponsibleUserId', array(
  5541.                                 'ENTITY' => $shipment,
  5542.                                 'VALUE' => $responsibleUserId,
  5543.                             ));
  5544.                             $event->send();
  5545.  
  5546.                             if ($event->getResults())
  5547.                             {
  5548.                                 $result = new Result();
  5549.                                 /** @var Main\EventResult $eventResult */
  5550.                                 foreach($event->getResults() as $eventResult)
  5551.                                 {
  5552.                                     if($eventResult->getType() == Main\EventResult::SUCCESS)
  5553.                                     {
  5554.                                         if ($eventResultData = $eventResult->getParameters())
  5555.                                         {
  5556.                                             if (isset($eventResultData['VALUE']) && $eventResultData['VALUE'] != $responsibleUserId)
  5557.                                             {
  5558.                                                 $responsibleUserId = $eventResultData['VALUE'];
  5559.                                             }
  5560.                                         }
  5561.                                     }
  5562.                                 }
  5563.                             }
  5564.  
  5565.                             $shipment->setField('RESPONSIBLE_ID', $responsibleUserId);
  5566.                         }
  5567.                     }
  5568.                 }
  5569.             }
  5570.         }
  5571.     }
  5572.  
  5573.     /**
  5574.      * Prepares action string to execute in doAction
  5575.      *
  5576.      * refreshOrderAjax/saveOrderAjax - process/save order via JSON (new template)
  5577.      * enterCoupon/removeCoupon - add/delete coupons via JSON (new template)
  5578.      * showAuthForm - show authorization form (old/new templates)                [including component template]
  5579.      * processOrder - process order (old(all hits)/new(first hit) templates) [including component template]
  5580.      * showOrder - show created order (old/new templates)                            [including component template]
  5581.      *
  5582.      * @return null|string
  5583.      */
  5584.     protected function prepareAction()
  5585.     {
  5586.         global $USER;
  5587.  
  5588.         $action = $this->request->offsetExists($this->arParams['ACTION_VARIABLE'])
  5589.             ? $this->request->get($this->arParams['ACTION_VARIABLE'])
  5590.             : $this->request->get('action');
  5591.  
  5592.         /*
  5593.         if (!$USER->IsAuthorized() && $this->arParams['ALLOW_AUTO_REGISTER'] === 'N')
  5594.         {
  5595.             $action = 'showAuthForm';
  5596.         }
  5597.         */
  5598.        
  5599.         if (empty($action))
  5600.         {
  5601.             if ($this->request->get('ORDER_ID') == '')
  5602.             {
  5603.                 $action = 'processOrder';
  5604.             }
  5605.             else
  5606.             {
  5607.                 $action = 'showOrder';
  5608.             }
  5609.         }
  5610.  
  5611.         return $action;
  5612.     }
  5613.  
  5614.     /**
  5615.      * Executes prepared action with postfix 'Action'
  5616.      *
  5617.      * @param $action
  5618.      */
  5619.     protected function doAction($action)
  5620.     {
  5621.         if (is_callable(array($this, $action."Action")))
  5622.         {
  5623.             call_user_func(
  5624.                 array($this, $action."Action")
  5625.             );
  5626.         }
  5627.     }
  5628.  
  5629.     protected function processOrderAction()
  5630.     {
  5631.         global $APPLICATION, $USER;
  5632.  
  5633.         $arResult =& $this->arResult;
  5634.         $this->isOrderConfirmed = $this->request->isPost()
  5635.             && $this->request->get("confirmorder") == 'Y'
  5636.             && $this->checkSession;
  5637.         $needToRegister = !$USER->IsAuthorized() && $this->arParams["ALLOW_AUTO_REGISTER"] == "Y";
  5638.         $saveToSession = false;
  5639.  
  5640.         if ($this->isOrderConfirmed && $needToRegister)
  5641.         {
  5642.             list($userId, $saveToSession) = $this->autoRegisterUser();
  5643.         }
  5644.         else
  5645.         {
  5646.             $userId = $USER->GetID();
  5647.         }
  5648.  
  5649.         if (!$userId)
  5650.         {
  5651.             $userId = CSaleUser::GetAnonymousUserID();
  5652.         }
  5653.  
  5654.         $this->order = $this->createOrder($userId);
  5655.         $this->prepareResultArray();
  5656.  
  5657.         $isActiveUser = intval($userId) > 0 && $userId != CSaleUser::GetAnonymousUserID();
  5658.         if ($this->isOrderConfirmed && $isActiveUser && empty($arResult["ERROR"]))
  5659.         {
  5660.             $this->saveOrder($saveToSession);
  5661.  
  5662.             if (empty($arResult["ERROR"]))
  5663.             {
  5664.                 $arResult["REDIRECT_URL"] = $APPLICATION->GetCurPageParam("ORDER_ID=".urlencode(urlencode($arResult["ACCOUNT_NUMBER"])), array("ORDER_ID"));
  5665.  
  5666.                 if ($this->request['json'] == "Y" && ($this->isOrderConfirmed || $arResult["NEED_REDIRECT"] == "Y"))
  5667.                 {
  5668.                     $APPLICATION->RestartBuffer();
  5669.                     echo json_encode(array("success" => "Y", "redirect" => $arResult["REDIRECT_URL"]));
  5670.                     die();
  5671.                 }
  5672.             }
  5673.             else
  5674.             {
  5675.                 $arResult["USER_VALS"]["CONFIRM_ORDER"] = "N";
  5676.             }
  5677.         }
  5678.         else
  5679.         {
  5680.             $arResult["USER_VALS"]["CONFIRM_ORDER"] = "N";
  5681.         }
  5682.     }
  5683.  
  5684.     /**
  5685.      * Action - show created order and payment info
  5686.      */
  5687.     protected function showOrderAction()
  5688.     {
  5689.         global $USER;
  5690.        
  5691.         $arResult =& $this->arResult;
  5692.  
  5693.         $arOrder = false;
  5694.         $arResult["USER_VALS"]["CONFIRM_ORDER"] = "Y";
  5695.         $orderId = urldecode($this->request->get('ORDER_ID'));
  5696.         $checkedBySession = false;
  5697.  
  5698.         /** @var Order $order */
  5699.         if ($order = Order::loadByAccountNumber($orderId))
  5700.         {
  5701.             $arOrder = $order->getFieldValues();
  5702.             $arResult["ORDER_ID"] = $arOrder["ID"];
  5703.             $arResult["ACCOUNT_NUMBER"] = $arOrder["ACCOUNT_NUMBER"];
  5704.             $arOrder["IS_ALLOW_PAY"] = $order->isAllowPay()? 'Y' : 'N';
  5705.             $checkedBySession = !empty($_SESSION['SALE_ORDER_ID']) && is_array($_SESSION['SALE_ORDER_ID'])
  5706.                 && in_array(intval($order->getId()), $_SESSION['SALE_ORDER_ID']);
  5707.         }
  5708.  
  5709.         //if (!empty($arOrder) && ($order->getUserId() == $USER->GetID() || $checkedBySession))
  5710.         //{
  5711.            
  5712.             foreach (GetModuleEvents("sale", "OnSaleComponentOrderOneStepFinal", true) as $arEvent)
  5713.                 ExecuteModuleEventEx($arEvent, array($arResult["ORDER_ID"], &$arOrder, &$this->arParams));
  5714.  
  5715.             $arResult["PAYMENT"] = array();
  5716.             if ($order->isAllowPay())
  5717.             {
  5718.                 $paymentCollection = $order->getPaymentCollection();
  5719.                 /** @var Payment $payment */
  5720.                 foreach ($paymentCollection as $payment)
  5721.                 {
  5722.                     $arResult["PAYMENT"][$payment->getId()] = $payment->getFieldValues();
  5723.  
  5724.                     if (intval($payment->getPaymentSystemId()) > 0 && !$payment->isPaid())
  5725.                     {
  5726.                         $paySystemService = PaySystem\Manager::getObjectById($payment->getPaymentSystemId());
  5727.                         if (!empty($paySystemService))
  5728.                         {
  5729.                             $arPaySysAction = $paySystemService->getFieldsValues();
  5730.  
  5731.                             if ($paySystemService->getField('NEW_WINDOW') === 'N' || $paySystemService->getField('ID') == PaySystem\Manager::getInnerPaySystemId())
  5732.                             {
  5733.                                 /** @var PaySystem\ServiceResult $initResult */
  5734.                                 $initResult = $paySystemService->initiatePay($payment, null, PaySystem\BaseServiceHandler::STRING);
  5735.                                 if ($initResult->isSuccess())
  5736.                                     $arPaySysAction['BUFFERED_OUTPUT'] = $initResult->getTemplate();
  5737.                                 else
  5738.                                     $arPaySysAction["ERROR"] = $initResult->getErrorMessages();
  5739.                             }
  5740.  
  5741.                             $arResult["PAYMENT"][$payment->getId()]['PAID'] = $payment->getField('PAID');
  5742.  
  5743.                             $arOrder['PAYMENT_ID'] = $payment->getId();
  5744.                             $arOrder['PAY_SYSTEM_ID'] = $payment->getPaymentSystemId();
  5745.                             $arPaySysAction["NAME"] = htmlspecialcharsEx($arPaySysAction["NAME"]);
  5746.                             $arPaySysAction["IS_AFFORD_PDF"] = $paySystemService->isAffordPdf();
  5747.  
  5748.                             if ($arPaySysAction > 0)
  5749.                                 $arPaySysAction["LOGOTIP"] = CFile::GetFileArray($arPaySysAction["LOGOTIP"]);
  5750.  
  5751.                             if ($this->arParams['COMPATIBLE_MODE'] == 'Y' && !$payment->isInner())
  5752.                             {
  5753.                                 // compatibility
  5754.                                 \CSalePaySystemAction::InitParamArrays($order->getFieldValues(), $order->getId(), '', array(), $payment->getFieldValues());
  5755.                                 $map = CSalePaySystemAction::getOldToNewHandlersMap();
  5756.                                 $oldHandler = array_search($arPaySysAction["ACTION_FILE"], $map);
  5757.                                 if ($oldHandler !== false && !$paySystemService->isCustom())
  5758.                                     $arPaySysAction["ACTION_FILE"] = $oldHandler;
  5759.  
  5760.                                 if (strlen($arPaySysAction["ACTION_FILE"]) > 0 && $arPaySysAction["NEW_WINDOW"] != "Y")
  5761.                                 {
  5762.                                     $pathToAction = Main\Application::getDocumentRoot().$arPaySysAction["ACTION_FILE"];
  5763.  
  5764.                                     $pathToAction = str_replace("\\", "/", $pathToAction);
  5765.                                     while (substr($pathToAction, strlen($pathToAction) - 1, 1) == "/")
  5766.                                         $pathToAction = substr($pathToAction, 0, strlen($pathToAction) - 1);
  5767.  
  5768.                                     if (file_exists($pathToAction))
  5769.                                     {
  5770.                                         if (is_dir($pathToAction) && file_exists($pathToAction."/payment.php"))
  5771.                                             $pathToAction .= "/payment.php";
  5772.  
  5773.                                         $arPaySysAction["PATH_TO_ACTION"] = $pathToAction;
  5774.                                     }
  5775.                                 }
  5776.  
  5777.                                 $arResult["PAY_SYSTEM"] = $arPaySysAction;
  5778.                             }
  5779.  
  5780.                             $arResult["PAY_SYSTEM_LIST"][$payment->getPaymentSystemId()] = $arPaySysAction;
  5781.                         }
  5782.                         else
  5783.                             $arResult["PAY_SYSTEM_LIST"][$payment->getPaymentSystemId()] = array('ERROR' => true);
  5784.                     }
  5785.                 }
  5786.             }
  5787.  
  5788.             $arResult["ORDER"] = $arOrder;
  5789.         //}
  5790.         //else
  5791.             //$arResult["ACCOUNT_NUMBER"] = $orderId;
  5792.     }
  5793.  
  5794.     /**
  5795.      * Action - saves order if there are no errors
  5796.      * Execution of 'OnSaleComponentOrderOneStepComplete' event
  5797.      *
  5798.      * @param bool $saveToSession
  5799.      */
  5800.     protected function saveOrder($saveToSession = false)
  5801.     {
  5802.         $arResult =& $this->arResult;
  5803.  
  5804.         $this->initStatGid();
  5805.         $this->initAffiliate();
  5806.  
  5807.         $res = $this->order->save();
  5808.         if ($res->isSuccess())
  5809.         {
  5810.             $arResult["ORDER_ID"] = $res->getId();
  5811.             $arResult["ACCOUNT_NUMBER"] = $this->order->getField('ACCOUNT_NUMBER');
  5812.  
  5813.             if ($this->arParams['USER_CONSENT'] === 'Y')
  5814.             {
  5815.                 Main\UserConsent\Consent::addByContext(
  5816.                     $this->arParams['USER_CONSENT_ID'], 'sale/order', $arResult['ORDER_ID']
  5817.                 );
  5818.             }
  5819.  
  5820.             $fUserId = Sale\Fuser::getId();
  5821.             $siteId = $this->getSiteId();
  5822.             Sale\BasketComponentHelper::clearFUserBasketPrice($fUserId, $siteId);
  5823.             Sale\BasketComponentHelper::clearFUserBasketQuantity($fUserId, $siteId);
  5824.         }
  5825.         else
  5826.         {
  5827.             $this->addError($res, 'MAIN');
  5828.         }
  5829.  
  5830.         if ($arResult['HAVE_PREPAYMENT'] && empty($arResult['ERROR']))
  5831.         {
  5832.             $this->prepayOrder();
  5833.         }
  5834.  
  5835.         if (empty($arResult['ERROR']))
  5836.         {
  5837.             $this->saveProfileData();
  5838.         }
  5839.  
  5840.         if (empty($arResult['ERROR']))
  5841.         {
  5842.             $this->addStatistic();
  5843.  
  5844.             if ($saveToSession)
  5845.             {
  5846.                 if (!is_array($_SESSION['SALE_ORDER_ID']))
  5847.                 {
  5848.                     $_SESSION['SALE_ORDER_ID'] = array();
  5849.                 }
  5850.  
  5851.                 $_SESSION['SALE_ORDER_ID'][] = $res->getId();
  5852.             }
  5853.         }
  5854.  
  5855.         foreach (GetModuleEvents('sale', 'OnSaleComponentOrderOneStepComplete', true) as $arEvent)
  5856.         {
  5857.             ExecuteModuleEventEx($arEvent, array($arResult['ORDER_ID'], $this->order->getFieldValues(), $this->arParams));
  5858.         }
  5859.     }
  5860.  
  5861.     public function executeComponent()
  5862.     {
  5863.         global $APPLICATION;
  5864.  
  5865.         $this->setFrameMode(false);
  5866.         $this->context = Main\Application::getInstance()->getContext();
  5867.         $this->checkSession = $this->arParams["DELIVERY_NO_SESSION"] == "N" || check_bitrix_sessid();
  5868.         $this->isRequestViaAjax = $this->request->isPost() && $this->request->get('via_ajax') == 'Y';
  5869.         $isAjaxRequest = $this->request["is_ajax_post"] == "Y";
  5870.  
  5871.         if ($isAjaxRequest)
  5872.             $APPLICATION->RestartBuffer();
  5873.  
  5874.         $this->action = $this->prepareAction();
  5875.         Sale\Compatible\DiscountCompatibility::stopUsageCompatible();
  5876.         $this->doAction($this->action);
  5877.         Sale\Compatible\DiscountCompatibility::revertUsageCompatible();
  5878.  
  5879.         if (!$isAjaxRequest)
  5880.         {
  5881.             CJSCore::Init(array('fx', 'popup', 'window', 'ajax', 'date'));
  5882.         }
  5883.  
  5884.         //is included in all cases for old template
  5885.         $this->includeComponentTemplate();
  5886.  
  5887.         if ($isAjaxRequest)
  5888.         {
  5889.             $APPLICATION->FinalActions();
  5890.             die();
  5891.         }
  5892.     }
  5893. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement