Your IP : 3.23.97.32
<?php
use Bitrix\Main;
use Bitrix\Main\Config\Option;
use Bitrix\Main\Controller\PhoneAuth;
use Bitrix\Main\Loader;
use Bitrix\Main\Localization\Loc;
use Bitrix\Main\Web\Json;
use Bitrix\Sale;
use Bitrix\Sale\Delivery;
use Bitrix\Sale\DiscountCouponsManager;
use Bitrix\Sale\Location\GeoIp;
use Bitrix\Sale\Location\LocationTable;
use Bitrix\Sale\Order;
use Bitrix\Sale\Payment;
use Bitrix\Sale\PaySystem;
use Bitrix\Sale\PersonType;
use Bitrix\Sale\Result;
use Bitrix\Sale\Services\Company;
use Bitrix\Sale\Shipment;
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true)
die();
/**
* @var $APPLICATION CMain
* @var $USER CUser
*/
Loc::loadMessages(__FILE__);
if (!Loader::includeModule("sale"))
{
ShowError(Loc::getMessage("SOA_MODULE_NOT_INSTALL"));
return;
}
class SaleOrderAjax extends \CBitrixComponent
{
const AUTH_BLOCK = 'AUTH';
const REGION_BLOCK = 'REGION';
const PAY_SYSTEM_BLOCK = 'PAY_SYSTEM';
const DELIVERY_BLOCK = 'DELIVERY';
const PROPERTY_BLOCK = 'PROPERTY';
/** @var Order $order */
protected $order;
/** @var Sale\Basket\Storage $basketStorage */
protected $basketStorage;
/** @var Sale\Basket */
private $calculateBasket;
protected $action;
protected $arUserResult;
protected $isOrderConfirmed;
protected $arCustomSelectFields = [];
protected $arElementId = [];
protected $arSku2Parent = [];
/** @var Delivery\Services\Base[] $arDeliveryServiceAll */
protected $arDeliveryServiceAll = [];
protected $arPaySystemServiceAll = [];
protected $arActivePaySystems = [];
protected $arIblockProps = [];
/** @var PaySystem\Service $prePaymentService */
protected $prePaymentService;
protected $useCatalog;
/** @var Main\Context $context */
protected $context;
protected $checkSession = true;
protected $isRequestViaAjax;
public function onPrepareComponentParams($arParams)
{
global $APPLICATION;
if (isset($arParams['CUSTOM_SITE_ID']))
{
$this->setSiteId($arParams['CUSTOM_SITE_ID']);
}
$this->useCatalog = Loader::includeModule('catalog');
if (!isset($arParams['COMPATIBLE_MODE']) && $this->initComponentTemplate())
{
$template = $this->getTemplate();
if (
$template instanceof CBitrixComponentTemplate
&& $template->GetSiteTemplate() == ''
&& $template->GetName() === '.default'
)
{
$arParams['COMPATIBLE_MODE'] = 'N';
}
else
{
$arParams['COMPATIBLE_MODE'] = 'Y';
}
}
else
{
$arParams['COMPATIBLE_MODE'] = $arParams['COMPATIBLE_MODE'] === 'N' ? 'N' : 'Y';
}
$arParams['USE_PRELOAD'] = $arParams['USE_PRELOAD'] === 'N' ? 'N' : 'Y';
if ($arParams['SET_TITLE'] === 'Y')
{
$APPLICATION->SetTitle(Loc::getMessage('SOA_TITLE'));
}
$arParams['ACTION_VARIABLE'] = isset($arParams['ACTION_VARIABLE']) ? trim($arParams['ACTION_VARIABLE']) : '';
if ($arParams['ACTION_VARIABLE'] == '')
{
$arParams['ACTION_VARIABLE'] = 'soa-action';
}
$arParams['PATH_TO_BASKET'] = isset($arParams['PATH_TO_BASKET']) ? trim($arParams['PATH_TO_BASKET']) : '';
if ($arParams['PATH_TO_BASKET'] == '')
{
$arParams['PATH_TO_BASKET'] = '/personal/cart/';
}
$arParams['NO_PERSONAL'] = isset($arParams['NO_PERSONAL']) && $arParams['NO_PERSONAL'] === 'Y' ? 'Y' : 'N';
if ($arParams['NO_PERSONAL'] === 'Y')
{
$arParams['PATH_TO_PERSONAL'] = '';
}
else
{
$arParams['PATH_TO_PERSONAL'] = isset($arParams['PATH_TO_PERSONAL']) ? trim((string)$arParams['PATH_TO_PERSONAL']) : '';
if ($arParams['PATH_TO_PERSONAL'] === '')
{
$arParams['PATH_TO_PERSONAL'] = 'index.php';
}
}
$arParams['PATH_TO_PAYMENT'] = isset($arParams['PATH_TO_PAYMENT']) ? trim($arParams['PATH_TO_PAYMENT']) : '';
if ($arParams['PATH_TO_PAYMENT'] == '')
{
$arParams['PATH_TO_PAYMENT'] = 'payment.php';
}
$arParams['PATH_TO_AUTH'] = isset($arParams['PATH_TO_AUTH']) ? trim($arParams['PATH_TO_AUTH']) : '';
if ($arParams['PATH_TO_AUTH'] == '')
{
$arParams['PATH_TO_AUTH'] = '/auth/';
}
$arParams['PAY_FROM_ACCOUNT'] = $arParams['PAY_FROM_ACCOUNT'] === 'Y' ? 'Y' : 'N';
$arParams['COUNT_DELIVERY_TAX'] = $arParams['COUNT_DELIVERY_TAX'] === 'Y' ? 'Y' : 'N';
$arParams['ONLY_FULL_PAY_FROM_ACCOUNT'] = $arParams['ONLY_FULL_PAY_FROM_ACCOUNT'] === 'Y' ? 'Y' : 'N';
$arParams['USE_PREPAYMENT'] = $arParams['USE_PREPAYMENT'] === 'Y' ? 'Y' : 'N';
$arParams['DISPLAY_IMG_HEIGHT'] = intval($arParams['DISPLAY_IMG_HEIGHT']) <= 0 ? 90 : intval($arParams['DISPLAY_IMG_HEIGHT']);
$arParams['SHOW_VAT_PRICE'] = $arParams['SHOW_VAT_PRICE'] === 'N' ? 'N' : 'Y';
$arParams['DELIVERY_TO_PAYSYSTEM'] = $arParams['DELIVERY_TO_PAYSYSTEM'] === 'p2d' ? 'p2d' : 'd2p';
if (!isset($arParams['DISABLE_BASKET_REDIRECT']) || $arParams['DISABLE_BASKET_REDIRECT'] !== 'Y')
{
$arParams['DISABLE_BASKET_REDIRECT'] = 'N';
}
$arParams['ALLOW_AUTO_REGISTER'] = $arParams['ALLOW_AUTO_REGISTER'] === 'Y' ? 'Y' : 'N';
if (!isset($arParams['CURRENT_PAGE']))
{
$arParams['CURRENT_PAGE'] = $APPLICATION->GetCurPage();
}
$siteId = $this->getSiteId();
$this->arResult = [
'PERSON_TYPE' => [],
'PAY_SYSTEM' => [],
'ORDER_PROP' => [],
'DELIVERY' => [],
'TAX' => [],
'ERROR' => [],
'ERROR_SORTED' => [],
'WARNING' => [],
'JS_DATA' => [],
'SHOW_EMPTY_BASKET' => false,
'ORDER_PRICE' => 0,
'ORDER_WEIGHT' => 0,
'VATE_RATE' => 0,
'VAT_SUM' => 0,
'bUsingVat' => false,
'BASKET_ITEMS' => [],
'BASE_LANG_CURRENCY' => Bitrix\Sale\Internals\SiteCurrencyTable::getSiteCurrency($siteId),
'WEIGHT_UNIT' => htmlspecialcharsbx(Option::get('sale', 'weight_unit', false, $siteId)),
'WEIGHT_KOEF' => htmlspecialcharsbx(Option::get('sale', 'weight_koef', 1, $siteId)),
'TaxExempt' => [],
'DISCOUNT_PRICE' => 0,
'DISCOUNT_PERCENT' => 0,
'DELIVERY_PRICE' => 0,
'TAX_PRICE' => 0,
'PAYED_FROM_ACCOUNT_FORMATED' => false,
'ORDER_TOTAL_PRICE_FORMATED' => false,
'ORDER_WEIGHT_FORMATED' => false,
'ORDER_PRICE_FORMATED' => false,
'VAT_SUM_FORMATED' => false,
'DELIVERY_SUM' => false,
'DELIVERY_PROFILE_SUM' => false,
'DELIVERY_PRICE_FORMATED' => false,
'DISCOUNT_PERCENT_FORMATED' => false,
'PAY_FROM_ACCOUNT' => false,
'CURRENT_BUDGET_FORMATED' => false,
'DISCOUNTS' => [],
'AUTH' => [],
'SMS_AUTH' => [],
'HAVE_PREPAYMENT' => false,
'PREPAY_PS' => [],
'PREPAY_ADIT_FIELDS' => '',
'PREPAY_ORDER_PROPS' => [],
];
if (!isset($arParams['IS_LANDING_SHOP']))
{
if (
!empty($arParams['CONTEXT_SITE_ID'])
&& Main\ModuleManager::isModuleInstalled('intranet')
&& Loader::includeModule('crm')
)
{
$arParams['IS_LANDING_SHOP'] = 'Y';
}
else
{
$arParams['IS_LANDING_SHOP'] = 'N';
}
}
if (!Loader::includeModule('crm'))
{
$arParams['IS_LANDING_SHOP'] = 'N';
}
$arParams['IS_LANDING_SHOP'] = $arParams['IS_LANDING_SHOP'] === 'Y' ? 'Y' : 'N';
if ($arParams['IS_LANDING_SHOP'] === 'Y')
{
$this->arResult['AUTH']['new_user_registration'] = 'N';
$arParams['ALLOW_AUTO_REGISTER'] = 'Y';
}
else
{
$this->arResult['AUTH']['new_user_registration'] = Option::get('main', 'new_user_registration', 'Y', $siteId) === 'Y' ? 'Y' : 'N';
}
$userRegistrationEmailConfirmation = Option::get('main', 'new_user_registration_email_confirmation', 'N', $siteId);
$this->arResult['AUTH']['new_user_registration_email_confirmation'] = $userRegistrationEmailConfirmation === 'Y' ? 'Y' : 'N';
$this->arResult['AUTH']['new_user_email_required'] = Option::get('main', 'new_user_email_required', '', $siteId) === 'Y' ? 'Y' : 'N';
$userPhoneAuth = Option::get('main', 'new_user_phone_auth', 'N', $siteId) === 'Y';
$this->arResult['AUTH']['new_user_phone_auth'] = $userPhoneAuth ? 'Y' : 'N';
$userPhoneAuthRequired = $userPhoneAuth && Option::get('main', 'new_user_phone_required', 'N', $siteId) === 'Y';
$this->arResult['AUTH']['new_user_phone_required'] = $userPhoneAuthRequired ? 'Y' : 'N';
if (
$arParams['ALLOW_AUTO_REGISTER'] === 'Y'
&& $arParams['IS_LANDING_SHOP'] === 'N'
&& (
$this->arResult['AUTH']['new_user_registration_email_confirmation'] === 'Y'
|| $this->arResult['AUTH']['new_user_registration'] === 'N'
)
)
{
$arParams['ALLOW_AUTO_REGISTER'] = 'N';
}
$arParams['ALLOW_APPEND_ORDER'] = $arParams['ALLOW_APPEND_ORDER'] === 'N' ? 'N' : 'Y';
$arParams['SEND_NEW_USER_NOTIFY'] = $arParams['SEND_NEW_USER_NOTIFY'] === 'N' ? 'N' : 'Y';
$arParams['ALLOW_NEW_PROFILE'] = $arParams['ALLOW_NEW_PROFILE'] === 'N' ? 'N' : 'Y';
$arParams['DELIVERY_NO_SESSION'] = $arParams['DELIVERY_NO_SESSION'] === 'N' ? 'N' : 'Y';
if (!isset($arParams['DELIVERY_NO_AJAX']) || !in_array($arParams['DELIVERY_NO_AJAX'], ['Y', 'N', 'H']))
{
$arParams['DELIVERY_NO_AJAX'] = 'N';
}
if (
!isset($arParams['SHOW_NOT_CALCULATED_DELIVERIES'])
|| !in_array($arParams['SHOW_NOT_CALCULATED_DELIVERIES'], ['N', 'L', 'Y'])
)
{
$arParams['SHOW_NOT_CALCULATED_DELIVERIES'] = 'L';
}
if ($arParams['DELIVERY_NO_AJAX'] !== 'Y')
{
$arParams['SHOW_NOT_CALCULATED_DELIVERIES'] = 'Y';
}
//compatibility to old default columns in basket
if (!empty($arParams['PRODUCT_COLUMNS_VISIBLE']))
{
$arParams['PRODUCT_COLUMNS'] = $arParams['PRODUCT_COLUMNS_VISIBLE'];
}
else
{
if (!isset($arParams['PRODUCT_COLUMNS_VISIBLE']) && !isset($arParams['PRODUCT_COLUMNS']))
{
$arParams['PRODUCT_COLUMNS'] = ['PREVIEW_PICTURE', 'PROPS'];
}
elseif (!isset($arParams['PRODUCT_COLUMNS_VISIBLE']) && is_array($arParams['PRODUCT_COLUMNS']))
{
if (!empty($arParams['PRODUCT_COLUMNS']))
{
$arParams['PRODUCT_COLUMNS'] = array_merge($arParams['PRODUCT_COLUMNS'], ['PRICE_FORMATED']);
}
else
{
$arParams['PRODUCT_COLUMNS'] = ['PROPS', 'DISCOUNT_PRICE_PERCENT_FORMATED', 'PRICE_FORMATED'];
}
}
$arParams['PRODUCT_COLUMNS_VISIBLE'] = $arParams['PRODUCT_COLUMNS'];
}
$arDefaults = ['PROPS', 'DISCOUNT_PRICE_PERCENT_FORMATED', 'PRICE_FORMATED'];
$arDiff = [];
if (!empty($arParams['PRODUCT_COLUMNS']) && is_array($arParams['PRODUCT_COLUMNS']))
{
$arDiff = array_diff($arParams['PRODUCT_COLUMNS'], $arDefaults);
}
$this->arResult['GRID']['DEFAULT_COLUMNS'] = count($arParams['PRODUCT_COLUMNS']) > 2 && empty($arDiff);
if (empty($arParams['PRODUCT_COLUMNS']))
{
$arParams['PRODUCT_COLUMNS'] = [
'NAME' => Loc::getMessage('SOA_NAME_DEFAULT_COLUMN'),
'QUANTITY' => Loc::getMessage('SOA_QUANTITY_DEFAULT_COLUMN'),
'SUM' => Loc::getMessage('SOA_SUM_DEFAULT_COLUMN'),
];
}
else
{
// processing default or certain iblock fields if they are selected
if (($key = array_search('PREVIEW_TEXT', $arParams['PRODUCT_COLUMNS'])) !== false)
{
unset($arParams['PRODUCT_COLUMNS'][$key]);
$arParams['PRODUCT_COLUMNS']['PREVIEW_TEXT'] = Loc::getMessage('SOA_NAME_COLUMN_PREVIEW_TEXT');
}
if (($key = array_search('PREVIEW_PICTURE', $arParams['PRODUCT_COLUMNS'])) !== false)
{
unset($arParams['PRODUCT_COLUMNS'][$key]);
$arParams['PRODUCT_COLUMNS']['PREVIEW_PICTURE'] = Loc::getMessage('SOA_NAME_COLUMN_PREVIEW_PICTURE');
}
if (($key = array_search('DETAIL_PICTURE', $arParams['PRODUCT_COLUMNS'])) !== false)
{
unset($arParams['PRODUCT_COLUMNS'][$key]);
$arParams['PRODUCT_COLUMNS']['DETAIL_PICTURE'] = Loc::getMessage('SOA_NAME_COLUMN_DETAIL_PICTURE');
}
if (($key = array_search('PROPS', $arParams['PRODUCT_COLUMNS'])) !== false)
{
unset($arParams['PRODUCT_COLUMNS'][$key]);
$arParams['PRODUCT_COLUMNS']['PROPS'] = Loc::getMessage('SOA_PROPS_DEFAULT_COLUMN');
}
if (($key = array_search('NOTES', $arParams['PRODUCT_COLUMNS'])) !== false)
{
unset($arParams['PRODUCT_COLUMNS'][$key]);
$arParams['PRODUCT_COLUMNS']['NOTES'] = Loc::getMessage('SOA_PRICE_TYPE_DEFAULT_COLUMN');
}
if (($key = array_search('DISCOUNT_PRICE_PERCENT_FORMATED', $arParams['PRODUCT_COLUMNS'])) !== false)
{
unset($arParams['PRODUCT_COLUMNS'][$key]);
$arParams['PRODUCT_COLUMNS']['DISCOUNT_PRICE_PERCENT_FORMATED'] = Loc::getMessage('SOA_DISCOUNT_DEFAULT_COLUMN');
}
if (($key = array_search('PRICE_FORMATED', $arParams['PRODUCT_COLUMNS'])) !== false)
{
unset($arParams['PRODUCT_COLUMNS'][$key]);
$arParams['PRODUCT_COLUMNS']['PRICE_FORMATED'] = Loc::getMessage('SOA_PRICE_DEFAULT_COLUMN');
}
if (($key = array_search('WEIGHT_FORMATED', $arParams['PRODUCT_COLUMNS'])) !== false)
{
unset($arParams['PRODUCT_COLUMNS'][$key]);
$arParams['PRODUCT_COLUMNS']['WEIGHT_FORMATED'] = Loc::getMessage('SOA_WEIGHT_DEFAULT_COLUMN');
}
}
if (!empty($arParams['PRODUCT_COLUMNS_HIDDEN']))
{
// processing default or certain iblock fields if they are selected
if (($key = array_search('PREVIEW_TEXT', $arParams['PRODUCT_COLUMNS_HIDDEN'])) !== false)
{
unset($arParams['PRODUCT_COLUMNS_HIDDEN'][$key]);
$arParams['PRODUCT_COLUMNS_HIDDEN']['PREVIEW_TEXT'] = Loc::getMessage('SOA_NAME_COLUMN_PREVIEW_TEXT');
}
if (($key = array_search('PREVIEW_PICTURE', $arParams['PRODUCT_COLUMNS_HIDDEN'])) !== false)
{
unset($arParams['PRODUCT_COLUMNS_HIDDEN'][$key]);
$arParams['PRODUCT_COLUMNS_HIDDEN']['PREVIEW_PICTURE'] = Loc::getMessage('SOA_NAME_COLUMN_PREVIEW_PICTURE');
}
if (($key = array_search('DETAIL_PICTURE', $arParams['PRODUCT_COLUMNS_HIDDEN'])) !== false)
{
unset($arParams['PRODUCT_COLUMNS_HIDDEN'][$key]);
$arParams['PRODUCT_COLUMNS_HIDDEN']['DETAIL_PICTURE'] = Loc::getMessage('SOA_NAME_COLUMN_DETAIL_PICTURE');
}
if (($key = array_search('PROPS', $arParams['PRODUCT_COLUMNS_HIDDEN'])) !== false)
{
unset($arParams['PRODUCT_COLUMNS_HIDDEN'][$key]);
$arParams['PRODUCT_COLUMNS_HIDDEN']['PROPS'] = Loc::getMessage('SOA_PROPS_DEFAULT_COLUMN');
}
if (($key = array_search('NOTES', $arParams['PRODUCT_COLUMNS_HIDDEN'])) !== false)
{
unset($arParams['PRODUCT_COLUMNS_HIDDEN'][$key]);
$arParams['PRODUCT_COLUMNS_HIDDEN']['NOTES'] = Loc::getMessage('SOA_PRICE_TYPE_DEFAULT_COLUMN');
}
if (($key = array_search('DISCOUNT_PRICE_PERCENT_FORMATED', $arParams['PRODUCT_COLUMNS_HIDDEN'])) !== false)
{
unset($arParams['PRODUCT_COLUMNS_HIDDEN'][$key]);
$arParams['PRODUCT_COLUMNS_HIDDEN']['DISCOUNT_PRICE_PERCENT_FORMATED'] = Loc::getMessage('SOA_DISCOUNT_DEFAULT_COLUMN');
}
if (($key = array_search('PRICE_FORMATED', $arParams['PRODUCT_COLUMNS_HIDDEN'])) !== false)
{
unset($arParams['PRODUCT_COLUMNS_HIDDEN'][$key]);
$arParams['PRODUCT_COLUMNS_HIDDEN']['PRICE_FORMATED'] = Loc::getMessage('SOA_PRICE_DEFAULT_COLUMN');
}
if (($key = array_search('WEIGHT_FORMATED', $arParams['PRODUCT_COLUMNS_HIDDEN'])) !== false)
{
unset($arParams['PRODUCT_COLUMNS_HIDDEN'][$key]);
$arParams['PRODUCT_COLUMNS_HIDDEN']['WEIGHT_FORMATED'] = Loc::getMessage('SOA_WEIGHT_DEFAULT_COLUMN');
}
}
// required grid columns
if (empty($arParams['PRODUCT_COLUMNS']['NAME']))
{
$arParams['PRODUCT_COLUMNS'] = ['NAME' => Loc::getMessage('SOA_NAME_DEFAULT_COLUMN')] + $arParams['PRODUCT_COLUMNS'];
}
if (empty($arParams['PRODUCT_COLUMNS']['QUANTITY']))
{
$arParams['PRODUCT_COLUMNS']['QUANTITY'] = Loc::getMessage('SOA_QUANTITY_DEFAULT_COLUMN');
}
if (empty($arParams['PRODUCT_COLUMNS']['SUM']))
{
$arParams['PRODUCT_COLUMNS']['SUM'] = Loc::getMessage('SOA_SUM_DEFAULT_COLUMN');
}
foreach ($arParams as $k => $v)
{
if (mb_strpos($k, 'ADDITIONAL_PICT_PROP_') !== false)
{
$iblockId = intval(mb_substr($k, mb_strlen('ADDITIONAL_PICT_PROP_')));
if ($v !== '-')
{
$arParams['ADDITIONAL_PICT_PROP'][$iblockId] = $v;
}
unset($arParams[$k]);
}
}
// check for direct initialization with ADDITIONAL_PICT_PROP parameter
if (!empty($arParams['ADDITIONAL_PICT_PROP']) && is_array($arParams['ADDITIONAL_PICT_PROP']))
{
$pictProp = [];
foreach ($arParams['ADDITIONAL_PICT_PROP'] as $iblockId => $property)
{
$pictProp[(int)$iblockId] = $property;
}
$arParams['ADDITIONAL_PICT_PROP'] = $pictProp;
}
if (!isset($arParams['BASKET_IMAGES_SCALING']) || !in_array($arParams['BASKET_IMAGES_SCALING'], ['standard', 'adaptive', 'no_scale']))
{
$arParams['BASKET_IMAGES_SCALING'] = 'adaptive';
}
$arParams['USE_PHONE_NORMALIZATION'] = isset($arParams['USE_PHONE_NORMALIZATION']) && $arParams['USE_PHONE_NORMALIZATION'] === 'N' ? 'N' : 'Y';
return $arParams;
}
/**
* Returns array of order properties from request
*
* @return array
*/
protected function getPropertyValuesFromRequest()
{
$orderProperties = [];
foreach ($this->request as $k => $v)
{
if (mb_strpos($k, "ORDER_PROP_") !== false)
{
if (mb_strpos($k, "[]") !== false)
$orderPropId = intval(mb_substr($k, mb_strlen("ORDER_PROP_"), mb_strlen($k) - 2));
else
$orderPropId = intval(mb_substr($k, mb_strlen("ORDER_PROP_")));
if ($orderPropId > 0)
$orderProperties[$orderPropId] = $v;
}
}
foreach ($this->request->getFileList() as $k => $arFileData)
{
if (mb_strpos($k, "ORDER_PROP_") !== false)
{
$orderPropId = intval(mb_substr($k, mb_strlen("ORDER_PROP_")));
if (is_array($arFileData))
{
foreach ($arFileData as $param_name => $value)
{
if (is_array($value))
{
foreach ($value as $nIndex => $val)
{
if ($arFileData["name"][$nIndex] <> '')
{
$orderProperties[$orderPropId][$nIndex][$param_name] = $val;
}
if (!isset($orderProperties[$orderPropId][$nIndex]['ID']))
{
$orderProperties[$orderPropId][$nIndex]['ID'] = '';
}
}
}
else
{
$orderProperties[$orderPropId][$param_name] = $value;
if (!isset($orderProperties[$orderPropId]['ID']))
{
$orderProperties[$orderPropId]['ID'] = '';
}
}
}
}
}
}
return $orderProperties;
}
protected function addLastLocationPropertyValues($orderProperties)
{
$currentPersonType = (int)$this->arUserResult['PERSON_TYPE_ID'];
$lastPersonType = (int)$this->arUserResult['PERSON_TYPE_OLD'];
if (!empty($lastPersonType) && $currentPersonType !== $lastPersonType)
{
$propsByPersonType = [];
$props = Sale\Property::getList([
'select' => ['ID', 'PERSON_TYPE_ID', 'IS_LOCATION', 'IS_ZIP', 'DEFAULT_VALUE'],
'filter' => [
[
'LOGIC' => 'OR',
'=IS_ZIP' => 'Y',
'=IS_LOCATION' => 'Y',
],
[
'@PERSON_TYPE_ID' => [$currentPersonType, $lastPersonType],
],
],
]);
foreach ($props as $prop)
{
if ($prop['PERSON_TYPE_ID'] == $currentPersonType && !empty($prop['DEFAULT_VALUE']))
{
continue;
}
if ($prop['IS_LOCATION'] === 'Y')
{
$propsByPersonType[$prop['PERSON_TYPE_ID']]['IS_LOCATION'] = $prop['ID'];
}
else
{
$propsByPersonType[$prop['PERSON_TYPE_ID']]['IS_ZIP'] = $prop['ID'];
}
}
if (!empty($propsByPersonType[$lastPersonType]))
{
foreach ($propsByPersonType[$lastPersonType] as $code => $id)
{
if (!empty($propsByPersonType[$currentPersonType][$code]))
{
$newId = $propsByPersonType[$currentPersonType][$code];
if (empty($orderProperties[$newId]) && !empty($orderProperties[$id]))
{
$orderProperties[$newId] = $orderProperties[$id];
}
}
}
}
}
return $orderProperties;
}
protected function getBasketStorage()
{
if (!isset($this->basketStorage))
{
$this->basketStorage = Sale\Basket\Storage::getInstance(Sale\Fuser::getId(), $this->getSiteId());
}
return $this->basketStorage;
}
protected function getLastOrderData(Order $order)
{
$lastOrderData = [];
$registry = Sale\Registry::getInstance(Sale\Registry::REGISTRY_TYPE_ORDER);
/** @var Order $orderClassName */
$orderClassName = $registry->getOrderClassName();
$filter = [
'filter' => [
'USER_ID' => $order->getUserId(),
'LID' => $order->getSiteId(),
],
'select' => ['ID'],
'order' => ['ID' => 'DESC'],
'limit' => 1,
];
if ($arOrder = $orderClassName::getList($filter)->fetch())
{
/** @var Order $lastOrder */
$lastOrder = $orderClassName::load($arOrder['ID']);
$lastOrderData['PERSON_TYPE_ID'] = $lastOrder->getPersonTypeId();
if ($payment = $this->getInnerPayment($lastOrder))
$lastOrderData['PAY_CURRENT_ACCOUNT'] = 'Y';
if ($payment = $this->getExternalPayment($lastOrder))
$lastOrderData['PAY_SYSTEM_ID'] = $payment->getPaymentSystemId();
if ($shipment = $this->getCurrentShipment($lastOrder))
{
$lastOrderData['DELIVERY_ID'] = $shipment->getDeliveryId();
$lastOrderData['BUYER_STORE'] = $shipment->getStoreId();
$lastOrderData['DELIVERY_EXTRA_SERVICES'][$shipment->getDeliveryId()] = $shipment->getExtraServices();
if ($storeFields = Delivery\ExtraServices\Manager::getStoresFields($lastOrderData['DELIVERY_ID'], false))
unset($lastOrderData['DELIVERY_EXTRA_SERVICES'][$shipment->getDeliveryId()][$storeFields['ID']]);
}
}
return $lastOrderData;
}
protected function initLastOrderData(Order $order)
{
global $USER;
if (
($this->request->getRequestMethod() === 'GET' || $this->request->get('do_authorize') === 'Y' || $this->request->get('do_register') === 'Y')
&& $this->arUserResult['USE_PRELOAD']
&& $USER->IsAuthorized()
)
{
$showData = [];
$lastOrderData = $this->getLastOrderData($order);
if (!empty($lastOrderData))
{
if (!empty($lastOrderData['PERSON_TYPE_ID']))
$this->arUserResult['PERSON_TYPE_ID'] = $showData['PERSON_TYPE_ID'] = $lastOrderData['PERSON_TYPE_ID'];
if (!empty($lastOrderData['PAY_CURRENT_ACCOUNT']))
$this->arUserResult['PAY_CURRENT_ACCOUNT'] = $showData['PAY_CURRENT_ACCOUNT'] = $lastOrderData['PAY_CURRENT_ACCOUNT'];
if (!empty($lastOrderData['PAY_SYSTEM_ID']))
$this->arUserResult['PAY_SYSTEM_ID'] = $showData['PAY_SYSTEM_ID'] = $lastOrderData['PAY_SYSTEM_ID'];
if (!empty($lastOrderData['DELIVERY_ID']))
$this->arUserResult['DELIVERY_ID'] = $showData['DELIVERY_ID'] = $lastOrderData['DELIVERY_ID'];
if (!empty($lastOrderData['DELIVERY_EXTRA_SERVICES']))
$this->arUserResult['DELIVERY_EXTRA_SERVICES'] = $showData['DELIVERY_EXTRA_SERVICES'] = $lastOrderData['DELIVERY_EXTRA_SERVICES'];
if (!empty($lastOrderData['BUYER_STORE']))
$this->arUserResult['BUYER_STORE'] = $showData['BUYER_STORE'] = $lastOrderData['BUYER_STORE'];
$this->arUserResult['LAST_ORDER_DATA'] = $showData;
}
}
}
/**
* Gets full order property list including all potential related properties (e.g. related to delivery or pay system).
*
* @param \Bitrix\Sale\Order $order
* @return array
*/
protected function getFullPropertyList(Order $order)
{
$registry = Sale\Registry::getInstance(Sale\Registry::REGISTRY_TYPE_ORDER);
/** @var \Bitrix\Sale\PropertyBase $propertyClassName */
$propertyClassName = $registry->getPropertyClassName();
$result = $propertyClassName::getList([
'select' => [
'ID', 'PERSON_TYPE_ID', 'NAME', 'TYPE', 'REQUIRED', 'DEFAULT_VALUE', 'SORT',
'USER_PROPS', 'IS_LOCATION', 'PROPS_GROUP_ID', 'DESCRIPTION', 'IS_EMAIL', 'IS_PROFILE_NAME',
'IS_PAYER', 'IS_LOCATION4TAX', 'IS_FILTERED', 'CODE', 'IS_ZIP', 'IS_PHONE', 'IS_ADDRESS',
'ACTIVE', 'UTIL', 'INPUT_FIELD_LOCATION', 'MULTIPLE', 'SETTINGS',
],
'filter' => [
'=PERSON_TYPE_ID' => $order->getPersonTypeId(),
],
'order' => ['SORT' => 'ASC'],
]);
return $result->fetchAll();
}
/**
* Initializes order properties from request, user profile, default values.
* Checks properties (if order saves) and sets to the order.
* Execution of 'OnSaleComponentOrderProperties' event.
*
* @param Order $order
* @param $isPersonTypeChanged
*/
protected function initProperties(Order $order, $isPersonTypeChanged)
{
$arResult =& $this->arResult;
$orderProperties = $this->getPropertyValuesFromRequest();
$orderProperties = $this->addLastLocationPropertyValues($orderProperties);
$this->initUserProfiles($order, $isPersonTypeChanged);
$firstLoad = $this->request->getRequestMethod() === 'GET';
$justAuthorized = $this->request->get('do_authorize') === 'Y'
|| $this->request->get('do_register') === 'Y'
|| $this->request->get('SMS_CODE');
$isProfileChanged = $this->arUserResult['PROFILE_CHANGE'] === 'Y';
$haveProfileId = (int)$this->arUserResult['PROFILE_ID'] > 0;
$shouldUseProfile = ($firstLoad || $justAuthorized || $isPersonTypeChanged || $isProfileChanged);
$willUseProfile = $shouldUseProfile && $haveProfileId;
$profileProperties = [];
if ($haveProfileId)
{
$profileProperties = Sale\OrderUserProperties::getProfileValues((int)$this->arUserResult['PROFILE_ID']);
}
$ipAddress = '';
if ($this->arParams['SPOT_LOCATION_BY_GEOIP'] === 'Y')
{
$ipAddress = \Bitrix\Main\Service\GeoIp\Manager::getRealIp();
}
foreach ($this->getFullPropertyList($order) as $property)
{
if ($property['USER_PROPS'] === 'Y')
{
if ($isProfileChanged && !$haveProfileId)
{
$curVal = '';
}
elseif (
$willUseProfile
|| (
!isset($orderProperties[$property['ID']])
&& isset($profileProperties[$property['ID']])
)
)
{
$curVal = $profileProperties[$property['ID']];
}
elseif (isset($orderProperties[$property['ID']]))
{
$curVal = $orderProperties[$property['ID']];
}
else
{
$curVal = '';
}
}
else
{
$curVal = isset($orderProperties[$property['ID']]) ? $orderProperties[$property['ID']] : '';
}
if ($arResult['HAVE_PREPAYMENT'] && !empty($arResult['PREPAY_ORDER_PROPS'][$property['CODE']]))
{
if ($property['TYPE'] === 'LOCATION')
{
$cityName = ToUpper($arResult['PREPAY_ORDER_PROPS'][$property['CODE']]);
$arLocation = LocationTable::getList([
'select' => ['CODE'],
'filter' => ['NAME.NAME_UPPER' => $cityName],
])
->fetch()
;
if (!empty($arLocation))
{
$curVal = $arLocation['CODE'];
}
}
else
{
$curVal = $arResult['PREPAY_ORDER_PROPS'][$property['CODE']];
}
}
if ($property['TYPE'] === 'LOCATION' && empty($curVal) && !empty($ipAddress))
{
$locCode = GeoIp::getLocationCode($ipAddress);
if (!empty($locCode))
{
$curVal = $locCode;
}
}
elseif ($property['IS_ZIP'] === 'Y' && empty($curVal) && !empty($ipAddress))
{
$zip = GeoIp::getZipCode($ipAddress);
if (!empty($zip))
{
$curVal = $zip;
}
}
elseif ($property['IS_PHONE'] === 'Y' && !empty($curVal))
{
$curVal = $this->getNormalizedPhone($curVal);
}
if (empty($curVal))
{
// getting default value for all properties except LOCATION
// (LOCATION - just for first load or person type change or new profile)
if ($property['TYPE'] !== 'LOCATION' || !$willUseProfile)
{
global $USER;
if ($shouldUseProfile && $USER->IsAuthorized())
{
$curVal = $this->getValueFromCUser($property);
}
if (empty($curVal) && !empty($property['DEFAULT_VALUE']))
{
$curVal = $property['DEFAULT_VALUE'];
}
}
}
if ($property['TYPE'] === 'LOCATION')
{
if (
(!$shouldUseProfile || $this->request->get('PROFILE_ID') === '0')
&& $this->request->get('location_type') !== 'code'
)
{
$curVal = CSaleLocation::getLocationCODEbyID($curVal);
}
}
$this->arUserResult['ORDER_PROP'][$property['ID']] = $curVal;
}
$this->checkZipProperty($order, $willUseProfile);
$this->checkAltLocationProperty($order, $willUseProfile, $profileProperties);
foreach (GetModuleEvents('sale', 'OnSaleComponentOrderProperties', true) as $arEvent)
{
ExecuteModuleEventEx($arEvent, [&$this->arUserResult, $this->request, &$this->arParams, &$this->arResult]);
}
$this->setOrderProperties($order);
}
/**
* Sets properties from $this->arUserResult['ORDER_PROP'] to the order.
*
* @param \Bitrix\Sale\Order $order
*/
protected function setOrderProperties(Order $order)
{
$propertyCollection = $order->getPropertyCollection();
$res = $propertyCollection->setValuesFromPost(['PROPERTIES' => $this->arUserResult['ORDER_PROP']], []);
if ($this->isOrderConfirmed)
{
if (!$res->isSuccess())
{
$this->addError($res, self::PROPERTY_BLOCK);
}
/** @var Sale\PropertyValue $propertyValue */
foreach ($propertyCollection as $propertyValue)
{
if ($propertyValue->isUtil())
{
continue;
}
$res = $propertyValue->verify();
if (!$res->isSuccess())
{
$this->addError($res, self::PROPERTY_BLOCK);
}
$res = $propertyValue->checkRequiredValue($propertyValue->getPropertyId(), $propertyValue->getValue());
if (!$res->isSuccess())
{
$this->addError($res, self::PROPERTY_BLOCK);
}
}
}
}
/**
* Returns user property value from CUser
*
* @param $property
* @return string
*/
protected function getValueFromCUser($property)
{
global $USER;
$value = '';
if ($property['IS_EMAIL'] === 'Y')
{
$value = $USER->GetEmail();
}
elseif ($property['IS_PAYER'] === 'Y')
{
$rsUser = CUser::GetByID($USER->GetID());
if ($arUser = $rsUser->Fetch())
{
$value = CUser::FormatName(
CSite::GetNameFormat(false),
[
'NAME' => $arUser['NAME'],
'LAST_NAME' => $arUser['LAST_NAME'],
'SECOND_NAME' => $arUser['SECOND_NAME'],
],
false,
false
);
}
}
elseif ($property['IS_PHONE'] === 'Y')
{
$phoneRow = \Bitrix\Main\UserPhoneAuthTable::getRow([
'select' => ['PHONE_NUMBER'],
'filter' => ['=USER_ID' => $USER->GetID()],
]);
if ($phoneRow)
{
$value = $phoneRow['PHONE_NUMBER'];
}
else
{
$rsUser = CUser::GetByID($USER->GetID());
if ($arUser = $rsUser->Fetch())
{
if (!empty($arUser['PERSONAL_PHONE']))
{
$value = $arUser['PERSONAL_PHONE'];
}
elseif (!empty($arUser['PERSONAL_MOBILE']))
{
$value = $arUser['PERSONAL_MOBILE'];
}
}
}
}
elseif ($property['IS_ADDRESS'] === 'Y')
{
$rsUser = CUser::GetByID($USER->GetID());
if ($arUser = $rsUser->Fetch())
{
if (!empty($arUser['PERSONAL_STREET']))
{
$value = $arUser['PERSONAL_STREET'];
}
}
}
return $value;
}
/**
* Defines zip value if location was changed.
*
* @param Order $order
* @param $loadFromProfile
*/
protected function checkZipProperty(Order $order, $loadFromProfile)
{
$propertyCollection = $order->getPropertyCollection();
$zip = $propertyCollection->getDeliveryLocationZip();
$location = $propertyCollection->getDeliveryLocation();
if (!empty($zip) && !empty($location))
{
$locId = $location->getField('ORDER_PROPS_ID');
$locValue = $this->arUserResult['ORDER_PROP'][$locId];
// need to override flag for zip data from profile
if ($loadFromProfile)
{
$this->arUserResult['ZIP_PROPERTY_CHANGED'] = 'Y';
}
$requestLocation = $this->request->get('RECENT_DELIVERY_VALUE');
// reload zip when user manually choose another location
if ($requestLocation !== null && $locValue !== $requestLocation)
{
$this->arUserResult['ZIP_PROPERTY_CHANGED'] = 'N';
}
// don't autoload zip property if user manually changed it
if ($this->arUserResult['ZIP_PROPERTY_CHANGED'] !== 'Y')
{
$res = Sale\Location\Admin\LocationHelper::getZipByLocation($locValue);
if ($arZip = $res->fetch())
{
if (!empty($arZip['XML_ID']))
{
$this->arUserResult['ORDER_PROP'][$zip->getField('ORDER_PROPS_ID')] = $arZip['XML_ID'];
}
}
}
}
}
/**
* Checks order properties for proper alternate location property display.
*
* @param Order $order
* @param $useProfileProperties
* @param array $profileProperties
*/
protected function checkAltLocationProperty(Order $order, $useProfileProperties, array $profileProperties)
{
$locationAltPropDisplayManual = $this->request->get('LOCATION_ALT_PROP_DISPLAY_MANUAL');
$propertyCollection = $order->getPropertyCollection();
/** @var Sale\PropertyValue $property */
foreach ($propertyCollection as $property)
{
if ($property->isUtil())
continue;
if ($property->getType() == 'LOCATION')
{
$propertyFields = $property->getProperty();
if ((int)$propertyFields['INPUT_FIELD_LOCATION'] > 0)
{
if ($useProfileProperties)
{
$deleteAltProp = empty($profileProperties[$propertyFields['INPUT_FIELD_LOCATION']]);
}
else
{
$deleteAltProp = !isset($locationAltPropDisplayManual[$propertyFields['ID']])
|| !(bool)$locationAltPropDisplayManual[$propertyFields['ID']];
// check if have no city at all then show alternate property
if (
isset($locationAltPropDisplayManual[$propertyFields['ID']])
&& !$this->haveCitiesInTree($this->arUserResult['ORDER_PROP'][$property->getPropertyId()])
)
{
$deleteAltProp = false;
}
}
if ($deleteAltProp)
{
unset($this->arUserResult['ORDER_PROP'][$propertyFields['INPUT_FIELD_LOCATION']]);
}
}
}
}
}
protected function haveCitiesInTree($locationCode)
{
if (empty($locationCode))
return false;
$haveCities = false;
$location = LocationTable::getRow(['filter' => ['=CODE' => $locationCode]]);
if (!empty($location))
{
if ($location['TYPE_ID'] >= 5)
{
$haveCities = true;
}
else
{
$parameters = [
'filter' => [
'>=LEFT_MARGIN' => (int)$location['LEFT_MARGIN'],
'<=RIGHT_MARGIN' => (int)$location['RIGHT_MARGIN'],
'>=DEPTH_LEVEL' => (int)$location['DEPTH_LEVEL'],
'!CITY_ID' => null,
],
'count_total' => true,
];
$haveCities = LocationTable::getList($parameters)->getCount() > 0;
}
}
return $haveCities;
}
/**
* Returns basket quantity list for orderable items
*
* @param Sale\BasketBase $basket
* @return array
*/
protected function getActualQuantityList(Sale\BasketBase $basket)
{
$quantityList = [];
if (!$basket->isEmpty())
{
/** @var Sale\BasketItemBase $basketItem */
foreach ($basket as $basketItem)
{
if ($basketItem->canBuy() && !$basketItem->isDelay())
{
$quantityList[$basketItem->getBasketCode()] = $basketItem->getQuantity();
}
}
}
return $quantityList;
}
/**
* Append basket(for current FUser) to order object
*
* @param Order $order
* @throws Main\ObjectNotFoundException
*/
protected function initBasket(Order $order)
{
$basket = $this->loadBasket();
$this->arUserResult['QUANTITY_LIST'] = $this->getActualQuantityList($basket);
$result = $basket->refresh();
if ($result->isSuccess())
{
$basket->save();
}
// right NOW we decide to work only with available basket
// full basket won't update anymore
$availableBasket = $basket->getOrderableItems();
if ($availableBasket->isEmpty())
{
$this->showEmptyBasket();
}
$order->appendBasket($availableBasket);
}
private function loadBasket()
{
$registry = Sale\Registry::getInstance(Sale\Registry::REGISTRY_TYPE_ORDER);
/** @var Sale\Basket $basketClassName */
$basketClassName = $registry->getBasketClassName();
return $basketClassName::loadItemsForFUser(Sale\Fuser::getId(), $this->getSiteId());
}
protected function showEmptyBasket()
{
global $APPLICATION;
if ($this->action === 'saveOrderAjax')
{
$APPLICATION->RestartBuffer();
echo json_encode([
'order' => [
'REDIRECT_URL' => $this->arParams['~CURRENT_PAGE'],
],
]);
die();
}
if ($this->arParams['DISABLE_BASKET_REDIRECT'] === 'Y')
{
$this->arResult['SHOW_EMPTY_BASKET'] = true;
if ($this->request->get('json') === 'Y' || $this->isRequestViaAjax)
{
$APPLICATION->RestartBuffer();
echo json_encode([
'success' => 'N',
'redirect' => $this->arParams['~CURRENT_PAGE'],
]);
die();
}
}
else
{
if ($this->request->get('json') === 'Y' || $this->isRequestViaAjax)
{
$APPLICATION->RestartBuffer();
echo json_encode([
'success' => 'N',
'redirect' => $this->arParams['PATH_TO_BASKET'],
]);
die();
}
LocalRedirect($this->arParams['PATH_TO_BASKET']);
die();
}
}
protected function addError($res, $type = 'MAIN')
{
if ($res instanceof Result)
{
$errors = $res->getErrorMessages();
}
else
{
$errors = [$res];
}
foreach ($errors as $error)
{
if (!in_array($error, $this->arResult['ERROR'], true))
{
$this->arResult['ERROR'][] = $error;
}
if (
empty($this->arResult['ERROR_SORTED'][$type])
|| !in_array($error, $this->arResult['ERROR_SORTED'][$type], true)
)
{
$this->arResult['ERROR_SORTED'][$type][] = $error;
}
}
}
protected function addWarning($res, $type)
{
if (
!empty($type)
&& (
empty($this->arResult['WARNING'][$type])
|| (!empty($this->arResult['WARNING'][$type]) && !in_array($res, $this->arResult['WARNING'][$type]))
)
)
{
$this->arResult['WARNING'][$type][] = $res;
}
}
protected static function getEscapedPostValue($name, $value)
{
$escapedValue = [];
if (!empty($name))
{
if (is_array($value))
{
foreach ($value as $k => $v)
{
$escapedValue += static::getEscapedPostValue("{$name}[{$k}]", $v);
}
}
else
{
$escapedValue[htmlspecialcharsbx($name)] = htmlspecialcharsbx($value);
}
}
return $escapedValue;
}
/**
* Action - show and process authorization form
*
* @throws Main\ArgumentNullException
*/
protected function showAuthFormAction()
{
global $APPLICATION;
$arResult =& $this->arResult;
$request = $this->isRequestViaAjax && $this->request->get('save') != 'Y' ? $this->request->get('order') : $this->request;
$this->checkSocServicesAuthForm();
$arResult['AUTH']['USER_LOGIN'] = $request['USER_LOGIN'] <> ''
? htmlspecialcharsbx($request['USER_LOGIN'])
: htmlspecialcharsbx(${Option::get('main', 'cookie_name', 'BITRIX_SM').'_LOGIN'});
$arResult['AUTH']['captcha_registration'] = Option::get('main', 'captcha_registration', 'N') === 'Y' ? 'Y' : 'N';
if ($arResult['AUTH']['captcha_registration'] === 'Y')
{
$arResult['AUTH']['capCode'] = htmlspecialcharsbx($APPLICATION->CaptchaGetCode());
}
$arResult['POST'] = [];
if ($this->request->isPost() && $this->checkSession)
{
foreach ($request as $name => $value)
{
if (in_array(
$name,
[
'USER_LOGIN', 'USER_PASSWORD', 'do_authorize', 'NEW_NAME', 'NEW_LAST_NAME', 'NEW_EMAIL',
'NEW_GENERATE', 'NEW_LOGIN', 'NEW_PASSWORD', 'NEW_PASSWORD_CONFIRM', 'captcha_sid',
'captcha_word', 'do_register', 'is_ajax_post', 'PHONE_NUMBER',
]
))
continue;
$arResult['POST'] += static::getEscapedPostValue($name, $value);
}
if ($request['do_authorize'] === 'Y')
{
$this->doAuthorize();
}
elseif ($request['do_register'] === 'Y' && $arResult['AUTH']['new_user_registration'] === 'Y')
{
$this->doRegister();
}
elseif ($this->isRequestViaAjax)
{
$this->showAjaxAnswer([
'order' => [
'SHOW_AUTH' => true,
'AUTH' => $arResult['AUTH'],
],
]);
}
}
if ($this->isRequestViaAjax)
{
if (empty($arResult['ERROR']) && empty($arResult['SMS_AUTH']))
{
$this->refreshOrderAjaxAction();
}
else
{
$this->showAjaxAnswer([
'order' => [
'SHOW_AUTH' => true,
'AUTH' => $arResult['AUTH'],
'SMS_AUTH' => $arResult['SMS_AUTH'],
'ERROR' => $arResult['ERROR_SORTED'],
],
]);
}
}
else
{
$this->processOrderAction();
}
}
protected function confirmSmsCodeAction()
{
global $USER;
if ($USER->IsAuthorized())
{
$this->refreshOrderAjaxAction();
}
$request = $this->request->get('order') ?: [];
$code = isset($request['SMS_CODE']) ? trim((string)$request['SMS_CODE']) : '';
if (!empty($code))
{
$signedData = isset($request['SIGNED_DATA']) ? trim((string)$request['SIGNED_DATA']) : '';
$params = PhoneAuth::extractData($signedData);
if ($params)
{
$userId = CUser::VerifyPhoneCode($params['phoneNumber'], $code);
if ($userId)
{
if ($this->arResult['AUTH']['new_user_phone_required'] === 'Y')
{
//the user was added as inactive, now phone number is confirmed, activate them
$user = new CUser();
$user->Update($userId, ['ACTIVE' => 'Y']);
}
// authorize user
$USER->Authorize($userId);
if ($USER->IsAuthorized())
{
$this->refreshOrderAjaxAction();
}
}
}
}
$this->showAjaxAnswer([
'error' => Loc::getMessage('SOA_WRONG_SMS_CODE'),
]);
}
protected function checkSocServicesAuthForm()
{
global $APPLICATION;
$arResult =& $this->arResult;
$arResult["ALLOW_SOCSERV_AUTHORIZATION"] = Option::get("main", "allow_socserv_authorization", "Y") == "Y" ? "Y" : "N";
$arResult["AUTH_SERVICES"] = false;
$arResult["CURRENT_SERVICE"] = false;
$arResult["FOR_INTRANET"] = false;
if (Loader::includeModule("socialservices") && $arResult["ALLOW_SOCSERV_AUTHORIZATION"] == 'Y')
{
$oAuthManager = new CSocServAuthManager();
$arServices = $oAuthManager->GetActiveAuthServices([
'BACKURL' => $this->arParams['~CURRENT_PAGE'],
'FOR_INTRANET' => $arResult['FOR_INTRANET'],
]);
if (!empty($arServices))
{
$arResult["AUTH_SERVICES"] = $arServices;
if (isset($this->request["auth_service_id"])
&& $this->request["auth_service_id"] != ''
&& isset($arResult["AUTH_SERVICES"][$this->request["auth_service_id"]])
)
{
$arResult["CURRENT_SERVICE"] = $this->request["auth_service_id"];
if (isset($this->request["auth_service_error"]) && $this->request["auth_service_error"] <> '')
{
$this->addError($oAuthManager->GetError($arResult["CURRENT_SERVICE"], $this->request["auth_service_error"]), self::AUTH_BLOCK);
}
elseif (!$oAuthManager->Authorize($this->request["auth_service_id"]))
{
$ex = $APPLICATION->GetException();
if ($ex)
$this->addError($ex->GetString(), self::AUTH_BLOCK);
}
}
}
}
}
protected function doAuthorize()
{
global $USER;
$request = $this->isRequestViaAjax && $this->request->get('save') != 'Y' ? $this->request->get('order') : $this->request;
if ($request["USER_LOGIN"] == '')
$this->addError(Loc::getMessage("STOF_ERROR_AUTH_LOGIN"), self::AUTH_BLOCK);
if (empty($this->arResult["ERROR"]))
{
$rememberMe = $request["USER_REMEMBER"] == 'Y' ? 'Y' : 'N';
$arAuthResult = $USER->Login($request["USER_LOGIN"], $request["USER_PASSWORD"], $rememberMe);
if ($arAuthResult != false && $arAuthResult["TYPE"] == "ERROR")
$this->addError(Loc::getMessage("STOF_ERROR_AUTH").($arAuthResult["MESSAGE"] <> '' ? ": ".$arAuthResult["MESSAGE"] : ""), self::AUTH_BLOCK);
}
}
protected function doRegister()
{
global $APPLICATION, $USER;
$arResult =& $this->arResult;
$request = $this->isRequestViaAjax && $this->request->get('save') != 'Y' ? $this->request->get('order') : $this->request;
if ($request['NEW_NAME'] == '')
{
$this->addError(Loc::getMessage('STOF_ERROR_REG_NAME'), self::AUTH_BLOCK);
}
if ($request['NEW_LAST_NAME'] == '')
{
$this->addError(Loc::getMessage('STOF_ERROR_REG_LASTNAME'), self::AUTH_BLOCK);
}
if (Option::get('main', 'new_user_email_required', '') === 'Y')
{
if ($request['NEW_EMAIL'] == '')
{
$this->addError(Loc::getMessage('STOF_ERROR_REG_EMAIL'), self::AUTH_BLOCK);
}
elseif (!check_email($request['NEW_EMAIL']))
{
$this->addError(Loc::getMessage('STOF_ERROR_REG_BAD_EMAIL'), self::AUTH_BLOCK);
}
}
$arResult['AUTH']['NEW_EMAIL'] = $request['NEW_EMAIL'];
$arResult['AUTH']['PHONE_NUMBER'] = $request['PHONE_NUMBER'];
if (empty($arResult['ERROR']))
{
if ($request['NEW_GENERATE'] === 'Y')
{
$generatedData = $this->generateUserData(['EMAIL' => $request['NEW_EMAIL']]);
$arResult['AUTH'] = array_merge($arResult['AUTH'], $generatedData);
}
else
{
if ($request['NEW_LOGIN'] == '')
{
$this->addError(Loc::getMessage('STOF_ERROR_REG_FLAG'), self::AUTH_BLOCK);
}
if ($request['NEW_PASSWORD'] == '')
{
$this->addError(Loc::getMessage('STOF_ERROR_REG_FLAG1'), self::AUTH_BLOCK);
}
if ($request['NEW_PASSWORD'] <> '' && $request['NEW_PASSWORD_CONFIRM'] == '')
{
$this->addError(Loc::getMessage('STOF_ERROR_REG_FLAG1'), self::AUTH_BLOCK);
}
if (
$request['NEW_PASSWORD'] <> ''
&& $request['NEW_PASSWORD_CONFIRM'] <> ''
&& $request['NEW_PASSWORD'] != $request['NEW_PASSWORD_CONFIRM']
)
{
$this->addError(Loc::getMessage('STOF_ERROR_REG_PASS'), self::AUTH_BLOCK);
}
$arResult['AUTH']['NEW_LOGIN'] = $request['NEW_LOGIN'];
$arResult['AUTH']['NEW_NAME'] = $request['NEW_NAME'];
$arResult['AUTH']['NEW_PASSWORD'] = $request['NEW_PASSWORD'];
$arResult['AUTH']['NEW_PASSWORD_CONFIRM'] = $request['NEW_PASSWORD_CONFIRM'];
}
}
if (empty($arResult['ERROR']))
{
$arAuthResult = $USER->Register(
$arResult['AUTH']['NEW_LOGIN'],
$request['NEW_NAME'],
$request['NEW_LAST_NAME'],
$arResult['AUTH']['NEW_PASSWORD'],
$arResult['AUTH']['NEW_PASSWORD_CONFIRM'],
$arResult['AUTH']['NEW_EMAIL'],
LANG,
$request['captcha_word'],
$request['captcha_sid'],
false,
$arResult['AUTH']['PHONE_NUMBER']
);
if ($arAuthResult != false && $arAuthResult['TYPE'] === 'ERROR')
{
$this->addError(Loc::getMessage('STOF_ERROR_REG').($arAuthResult['MESSAGE'] <> '' ? ': '.$arAuthResult['MESSAGE'] : ''), self::AUTH_BLOCK);
}
else
{
if ($USER->IsAuthorized())
{
if ($this->arParams['SEND_NEW_USER_NOTIFY'] === 'Y')
{
CUser::SendUserInfo($USER->GetID(), $this->getSiteId(), Loc::getMessage('INFO_REQ'), true);
}
if ($this->isRequestViaAjax)
{
$this->refreshOrderAjaxAction();
}
else
{
LocalRedirect($APPLICATION->GetCurPageParam());
}
}
elseif ($arResult['AUTH']['new_user_phone_auth'] === 'Y' && $arResult['AUTH']['PHONE_NUMBER'] !== '')
{
$arResult['SMS_AUTH'] = $arAuthResult;
}
else
{
$arResult['OK_MESSAGE'][] = Loc::getMessage('STOF_ERROR_REG_CONFIRM');
}
}
}
$arResult['AUTH']['~NEW_LOGIN'] = $arResult['AUTH']['NEW_LOGIN'];
$arResult['AUTH']['NEW_LOGIN'] = htmlspecialcharsEx($arResult['AUTH']['NEW_LOGIN']);
$arResult['AUTH']['~NEW_NAME'] = $request['NEW_NAME'];
$arResult['AUTH']['NEW_NAME'] = htmlspecialcharsEx($request['NEW_NAME']);
$arResult['AUTH']['~NEW_LAST_NAME'] = $request['NEW_LAST_NAME'];
$arResult['AUTH']['NEW_LAST_NAME'] = htmlspecialcharsEx($request['NEW_LAST_NAME']);
$arResult['AUTH']['~NEW_EMAIL'] = $arResult['AUTH']['NEW_EMAIL'];
$arResult['AUTH']['NEW_EMAIL'] = htmlspecialcharsEx($arResult['AUTH']['NEW_EMAIL']);
$arResult['AUTH']['~PHONE_NUMBER'] = $arResult['AUTH']['PHONE_NUMBER'];
$arResult['AUTH']['PHONE_NUMBER'] = htmlspecialcharsEx($arResult['AUTH']['PHONE_NUMBER']);
}
protected function initStatGid()
{
if (Loader::includeModule("statistic"))
$this->order->setField('STAT_GID', CStatistic::GetEventParam());
}
protected function initAffiliate()
{
$affiliateID = CSaleAffiliate::GetAffiliate();
if ($affiliateID > 0)
{
$dbAffiliate = CSaleAffiliate::GetList([], ["SITE_ID" => $this->getSiteId(), "ID" => $affiliateID]);
$arAffiliates = $dbAffiliate->Fetch();
if (count($arAffiliates) > 1)
$this->order->setField('AFFILIATE_ID', $affiliateID);
}
}
/**
* Generation of user registration fields (login, password, etc)
*
* @param array $userProps
* @return array
* @throws Main\ArgumentNullException
*/
public function generateUserData($userProps = [])
{
global $USER;
$userEmail = isset($userProps['EMAIL']) ? trim((string)$userProps['EMAIL']) : '';
$newLogin = $userEmail;
if (empty($userEmail))
{
$newEmail = false;
$normalizedPhone = $this->getNormalizedPhone($userProps['PHONE']);
if (!empty($normalizedPhone))
{
$newLogin = $normalizedPhone;
}
}
else
{
$newEmail = $userEmail;
}
if (empty($newLogin))
{
$newLogin = randString(5).mt_rand(0, 99999);
}
$pos = mb_strpos($newLogin, '@');
if ($pos !== false)
{
$newLogin = mb_substr($newLogin, 0, $pos);
}
if (mb_strlen($newLogin) > 47)
{
$newLogin = mb_substr($newLogin, 0, 47);
}
$newLogin = str_pad($newLogin, 3, '_');
$dbUserLogin = CUser::GetByLogin($newLogin);
if ($userLoginResult = $dbUserLogin->Fetch())
{
do
{
$newLoginTmp = $newLogin.mt_rand(0, 99999);
$dbUserLogin = CUser::GetByLogin($newLoginTmp);
} while ($userLoginResult = $dbUserLogin->Fetch());
$newLogin = $newLoginTmp;
}
$newName = '';
$newLastName = '';
$payerName = isset($userProps['PAYER']) ? trim((string)$userProps['PAYER']) : '';
if (!empty($payerName))
{
$arNames = explode(' ', $payerName);
if (isset($arNames[1]))
{
$newName = $arNames[1];
$newLastName = $arNames[0];
}
else
{
$newName = $arNames[0];
}
}
$groupIds = [];
$defaultGroups = Option::get('main', 'new_user_registration_def_group', '');
if (!empty($defaultGroups))
{
$groupIds = explode(',', $defaultGroups);
}
$arPolicy = $USER->GetGroupPolicy($groupIds);
$passwordMinLength = (int)$arPolicy['PASSWORD_LENGTH'];
if ($passwordMinLength <= 0)
{
$passwordMinLength = 6;
}
$passwordChars = [
'abcdefghijklnmopqrstuvwxyz',
'ABCDEFGHIJKLNMOPQRSTUVWXYZ',
'0123456789',
];
if ($arPolicy['PASSWORD_PUNCTUATION'] === 'Y')
{
$passwordChars[] = ",.<>/?;:'\"[]{}\|`~!@#\$%^&*()-_+=";
}
$newPassword = $newPasswordConfirm = randString($passwordMinLength + 2, $passwordChars);
return [
'NEW_EMAIL' => $newEmail,
'NEW_LOGIN' => $newLogin,
'NEW_NAME' => $newName,
'NEW_LAST_NAME' => $newLastName,
'NEW_PASSWORD' => $newPassword,
'NEW_PASSWORD_CONFIRM' => $newPasswordConfirm,
'GROUP_ID' => $groupIds,
];
}
protected function getNormalizedPhone($phone)
{
if ($this->arParams['USE_PHONE_NORMALIZATION'] === 'Y')
{
$phone = NormalizePhone((string)$phone, 3);
}
return $phone;
}
protected function getNormalizedPhoneForRegistration($phone)
{
return Main\UserPhoneAuthTable::normalizePhoneNumber($phone) ?: '';
}
/**
* Creating new user and logging in
*
* @param $userProps
* @return bool|int
*/
protected function registerAndLogIn($userProps)
{
$userId = false;
$userData = $this->generateUserData($userProps);
$fields = [
'LOGIN' => $userData['NEW_LOGIN'],
'NAME' => $userData['NEW_NAME'],
'LAST_NAME' => $userData['NEW_LAST_NAME'],
'PASSWORD' => $userData['NEW_PASSWORD'],
'CONFIRM_PASSWORD' => $userData['NEW_PASSWORD_CONFIRM'],
'EMAIL' => $userData['NEW_EMAIL'],
'GROUP_ID' => $userData['GROUP_ID'],
'ACTIVE' => 'Y',
'LID' => $this->getSiteId(),
'PERSONAL_PHONE' => isset($userProps['PHONE']) ? $this->getNormalizedPhone($userProps['PHONE']) : '',
'PERSONAL_ZIP' => isset($userProps['ZIP']) ? $userProps['ZIP'] : '',
'PERSONAL_STREET' => isset($userProps['ADDRESS']) ? $userProps['ADDRESS'] : '',
];
if ($this->arResult['AUTH']['new_user_phone_auth'] === 'Y')
{
$fields['PHONE_NUMBER'] = isset($userProps['PHONE']) ? $userProps['PHONE'] : '';
}
if ($this->arParams['IS_LANDING_SHOP'] === 'Y')
{
$fields['GROUP_ID'] = \Bitrix\Crm\Order\BuyerGroup::getDefaultGroups();
$fields['EXTERNAL_AUTH_ID'] = 'shop';
// reset department for intranet
$fields['UF_DEPARTMENT'] = [];
// rewrite login with email
if (!empty($userData['NEW_EMAIL']))
{
$fields['LOGIN'] = $userData['NEW_EMAIL'];
}
}
$user = new CUser;
$addResult = $user->Add($fields);
if (intval($addResult) <= 0)
{
$this->addError(Loc::getMessage('STOF_ERROR_REG').(($user->LAST_ERROR <> '') ? ': '.$user->LAST_ERROR : ''), self::AUTH_BLOCK);
}
else
{
global $USER;
$userId = intval($addResult);
$USER->Authorize($addResult);
if ($USER->IsAuthorized())
{
if ($this->arParams['SEND_NEW_USER_NOTIFY'] == 'Y')
{
if (
isset($this->arParams['CONTEXT_SITE_ID']) &&
$this->arParams['CONTEXT_SITE_ID'] > 0 &&
Loader::includeModule('landing')
)
{
$componentName = 'bitrix:landing.pub';
/** @var LandingPubComponent $className */
$className = \CBitrixComponent::includeComponentClass($componentName);
$className::replaceUrlInLetter(
$this->arParams['CONTEXT_SITE_ID']
);
}
CUser::SendUserInfo($USER->GetID(), $this->getSiteId(), Loc::getMessage('INFO_REQ'), true);
}
}
else
{
$this->addError(Loc::getMessage('STOF_ERROR_REG_CONFIRM'), self::AUTH_BLOCK);
}
}
return $userId;
}
/**
* Returns array of user id and 'save to session' flag (true if 'unique user e-mails' option
* active and we already have this e-mail)
*
* @return array
* @throws Main\ArgumentNullException
*/
protected function autoRegisterUser()
{
$personType = $this->request->get('PERSON_TYPE');
if ($personType <= 0)
{
$personTypes = PersonType::load($this->getSiteId());
foreach ($personTypes as $type)
{
$personType = $type['ID'];
break;
}
unset($personTypes, $type);
}
$userProps = Sale\PropertyValue::getMeaningfulValues($personType, $this->getPropertyValuesFromRequest());
$userId = false;
$saveToSession = false;
if (
$this->arParams['ALLOW_APPEND_ORDER'] === 'Y'
&& (
Option::get('main', 'new_user_email_uniq_check', '') === 'Y'
|| Option::get('main', 'new_user_phone_auth', '') === 'Y'
)
&& ($userProps['EMAIL'] != '' || $userProps['PHONE'] != '')
)
{
$existingUserId = 0;
if ($userProps['EMAIL'] != '')
{
$res = Bitrix\Main\UserTable::getRow([
'filter' => [
'=ACTIVE' => 'Y',
'=EMAIL' => $userProps['EMAIL'],
],
'select' => ['ID'],
]);
if (isset($res['ID']))
{
$existingUserId = (int)$res['ID'];
}
}
if ($existingUserId == 0 && !empty($userProps['PHONE']))
{
$normalizedPhone = $this->getNormalizedPhone($userProps['PHONE']);
$normalizedPhoneForRegistration = $this->getNormalizedPhoneForRegistration($userProps['PHONE']);
if (!empty($normalizedPhone))
{
$res = Bitrix\Main\UserTable::getRow([
'filter' => [
'ACTIVE' => 'Y',
[
'LOGIC' => 'OR',
'=PHONE_AUTH.PHONE_NUMBER' => $normalizedPhoneForRegistration,
'=PERSONAL_PHONE' => $normalizedPhone,
'=PERSONAL_MOBILE' => $normalizedPhone,
],
],
'select' => ['ID'],
]);
if (isset($res['ID']))
{
$existingUserId = (int)$res['ID'];
}
}
}
if ($existingUserId > 0)
{
$userId = $existingUserId;
$saveToSession = true;
if ($this->arParams['IS_LANDING_SHOP'] === 'Y')
{
CUser::AppendUserGroup($userId, \Bitrix\Crm\Order\BuyerGroup::getDefaultGroups());
}
}
else
{
$userId = $this->registerAndLogIn($userProps);
}
}
elseif ($userProps['EMAIL'] != '' || Option::get('main', 'new_user_email_required', '') === 'N')
{
$userId = $this->registerAndLogIn($userProps);
}
else
{
$this->addError(Loc::getMessage('STOF_ERROR_EMAIL'), self::AUTH_BLOCK);
}
return [$userId, $saveToSession];
}
public function initGrid()
{
$this->arResult["GRID"]["HEADERS"] = $this->getGridHeaders($this->arParams["PRODUCT_COLUMNS"]);
$this->arResult["GRID"]["HEADERS_HIDDEN"] = $this->getGridHeaders($this->arParams["PRODUCT_COLUMNS_HIDDEN"]);
}
public function getGridHeaders($productColumns)
{
$arr = [];
if (is_array($productColumns) && !empty($productColumns))
{
$arCodes = [];
$iBlockProps = [];
foreach ($productColumns as $key => $value) // making grid headers array
{
if (strncmp($value, "PROPERTY_", 9) == 0)
{
$propCode = mb_substr($value, 9);
if ($propCode == '')
continue;
$arCodes[] = $propCode;
}
}
if ($this->useCatalog && !empty($arCodes))
{
$iBlockList = [];
$catalogIterator = Bitrix\Catalog\CatalogIblockTable::getList([
'select' => ['IBLOCK_ID', 'PRODUCT_IBLOCK_ID', 'SITE_ID' => 'IBLOCK_SITE.SITE_ID'],
'filter' => ['SITE_ID' => $this->getSiteId()],
'runtime' => [
'IBLOCK_SITE' => [
'data_type' => 'Bitrix\Iblock\IblockSiteTable',
'reference' => [
'ref.IBLOCK_ID' => 'this.IBLOCK_ID',
],
'join_type' => 'inner',
],
],
]);
while ($catalog = $catalogIterator->fetch())
{
$iBlockList[$catalog['IBLOCK_ID']] = $catalog['IBLOCK_ID'];
if (intval($catalog['PRODUCT_IBLOCK_ID']) > 0)
$iBlockList[$catalog['PRODUCT_IBLOCK_ID']] = $catalog['PRODUCT_IBLOCK_ID'];
}
if (!empty($iBlockList))
{
$propertyIterator = Bitrix\Iblock\PropertyTable::getList([
'select' => ['ID', 'IBLOCK_ID', 'NAME', 'ACTIVE', 'SORT', 'CODE', 'TIMESTAMP_X',
'DEFAULT_VALUE', 'PROPERTY_TYPE', 'ROW_COUNT', 'COL_COUNT', 'LIST_TYPE',
'MULTIPLE', 'XML_ID', 'FILE_TYPE', 'MULTIPLE_CNT', 'LINK_IBLOCK_ID', 'WITH_DESCRIPTION',
'SEARCHABLE', 'FILTRABLE', 'IS_REQUIRED', 'VERSION', 'USER_TYPE', 'USER_TYPE_SETTINGS', 'HINT'],
'filter' => [
'@IBLOCK_ID' => array_keys($iBlockList),
'=ACTIVE' => 'Y',
'@CODE' => $arCodes,
],
'order' => ['SORT' => 'ASC', 'ID' => 'ASC'],
]);
while ($property = $propertyIterator->fetch())
{
$this->arIblockProps[$property['IBLOCK_ID']][$property['CODE']] = $property;
if (!isset($iBlockProps[$property['CODE']]))
$iBlockProps[$property['CODE']] = $property;
}
}
}
// making grid headers array
foreach ($productColumns as $key => $value)
{
// processing iblock properties
if (strncmp($value, "PROPERTY_", 9) == 0)
{
$propCode = mb_substr($value, 9);
if ($propCode == '')
continue;
// array of iblock properties to select
$this->arCustomSelectFields[] = $value;
$id = $value."_VALUE";
$name = $value;
if (array_key_exists($propCode, $iBlockProps))
{
$name = $iBlockProps[$propCode]["NAME"];
}
}
else
{
$id = $key;
$name = $value;
}
$arColumn = [
"id" => $id,
"name" => $name,
];
if ($key == "PRICE_FORMATED")
{
$arColumn["align"] = "right";
}
$arr[] = $arColumn;
}
}
return $arr;
}
public function getPropsInfo($source)
{
$resultHTML = "";
foreach ($source["PROPS"] as $val)
{
$resultHTML .= str_replace(" ", " ", $val["NAME"].": ".$val["VALUE"])."<br />";
}
return $resultHTML;
}
public function getIblockProps($value, $propData, $arSize = ["WIDTH" => 90, "HEIGHT" => 90], $orderId = 0)
{
$res = [];
if ($propData["MULTIPLE"] == "Y")
{
$arVal = [];
if (!is_array($value))
{
if (mb_strpos($value, ",") !== false)
$arVal = explode(",", $value);
else
$arVal[] = $value;
}
else
$arVal = $value;
if (!empty($arVal))
{
foreach ($arVal as $key => $val)
{
if ($propData["PROPERTY_TYPE"] == "F")
$res[] = $this->getFileData(trim($val), $orderId, $arSize);
else
$res[] = ["type" => "value", "value" => $val];
}
}
}
else
{
if ($propData["PROPERTY_TYPE"] == "F")
$res[] = $this->getFileData($value, $orderId, $arSize);
else
$res[] = ["type" => "value", "value" => $value];
}
return $res;
}
public function getLinkedPropValue($basketItem, $property)
{
$result = [];
if ($property['MULTIPLE'] === 'Y')
$property['VALUE'] = explode(',', $property['VALUE']);
$formattedProperty = CIBlockFormatProperties::GetDisplayValue($basketItem, $property, 'sale_out');
if (!empty($formattedProperty['DISPLAY_VALUE']))
{
if (is_array($formattedProperty['DISPLAY_VALUE']))
{
foreach ($formattedProperty['DISPLAY_VALUE'] as $key => $formatValue)
{
$result[] = [
'type' => 'linked',
'value' => $property['VALUE'][$key],
'value_format' => $formatValue,
];
}
}
else
{
$result[] = [
'type' => 'linked',
'value' => is_array($property['VALUE']) ? reset($property['VALUE']) : $property['VALUE'],
'value_format' => $formattedProperty['DISPLAY_VALUE'],
];
}
}
return $result;
}
public function getDirectoryProperty($basketItem, $property)
{
$result = [];
if ($property['MULTIPLE'] === 'Y')
{
$property['VALUE'] = explode(', ', $basketItem['PROPERTY_'.$property['CODE'].'_VALUE']);
}
else
{
$property['VALUE'] = $basketItem['PROPERTY_'.$property['CODE'].'_VALUE'];
}
$property['~VALUE'] = $property['VALUE'];
if (CheckSerializedData($property['USER_TYPE_SETTINGS']))
{
$property['USER_TYPE_SETTINGS'] = unserialize($property['USER_TYPE_SETTINGS']);
}
$formattedProperty = CIBlockFormatProperties::GetDisplayValue($basketItem, $property, 'sale_out');
if (!empty($formattedProperty['DISPLAY_VALUE']))
{
if (is_array($formattedProperty['DISPLAY_VALUE']))
{
foreach ($formattedProperty['DISPLAY_VALUE'] as $key => $formatValue)
{
$result[] = [
'type' => 'value',
'value' => $formatValue,
'value_raw' => $property['VALUE'][$key],
];
}
}
else
{
$result[] = [
'type' => 'value',
'value' => $formattedProperty['DISPLAY_VALUE'],
'value_raw' => is_array($property['VALUE']) ? reset($property['VALUE']) : $property['VALUE'],
];
}
}
return $result;
}
public function getFileData($fileId, $orderId = 0, $arSize = ["WIDTH" => 90, "HEIGHT" => 90])
{
$res = "";
$arFile = CFile::GetFileArray($fileId);
if ($arFile)
{
$is_image = CFile::IsImage($arFile["FILE_NAME"], $arFile["CONTENT_TYPE"]);
if ($is_image)
{
$arImgProduct = CFile::ResizeImageGet($arFile, ["width" => $arSize["WIDTH"], "height" => $arSize["HEIGHT"]], BX_RESIZE_IMAGE_PROPORTIONAL, false, false);
if (is_array($arImgProduct))
$res = ["type" => "image", "value" => $arImgProduct["src"], "source" => $arFile["SRC"]];
}
else
$res = ["type" => "file", "value" => "<a href=".$arFile["SRC"].">".$arFile["ORIGINAL_NAME"]."</a>"];
}
return $res;
}
/**
* Set formatted order properties to $this->arResult (heavy load due to compatibility)
* Execution of 'OnSaleComponentOrderOneStepOrderProps' event
*/
protected function obtainFormattedProperties()
{
$arResult =& $this->arResult;
$arDeleteFieldLocation = [];
$propIndex = [];
$arOrderProps = $this->order->getPropertyCollection()->getArray();
$propsSortedByGroup = [];
foreach ($arOrderProps['groups'] as $group)
{
foreach ($arOrderProps['properties'] as $prop)
{
if ($prop['UTIL'] == 'Y' || !empty($prop['RELATION']))
continue;
if ($group['ID'] == $prop['PROPS_GROUP_ID'])
{
$prop['GROUP_NAME'] = $group['NAME'];
$propsSortedByGroup[] = $prop;
}
}
}
foreach ($propsSortedByGroup as $arProperty)
{
$arProperties = $this->getOrderPropFormatted($arProperty, $arDeleteFieldLocation);
$flag = $arProperties["USER_PROPS"] == "Y" ? 'Y' : 'N';
$arResult["ORDER_PROP"]["USER_PROPS_".$flag][$arProperties["ID"]] = $arProperties;
$propIndex[$arProperties["ID"]] =& $arResult["ORDER_PROP"]["USER_PROPS_".$flag][$arProperties["ID"]];
$arResult["ORDER_PROP"]["PRINT"][$arProperties["ID"]] = [
"ID" => $arProperties["ID"],
"NAME" => $arProperties["NAME"],
"VALUE" => $arProperties["VALUE_FORMATED"],
"SHOW_GROUP_NAME" => $arProperties["SHOW_GROUP_NAME"],
];
}
// additional city property process
foreach ($propIndex as $propId => $propDesc)
{
if (intval($propDesc['INPUT_FIELD_LOCATION']) && isset($propIndex[$propDesc['INPUT_FIELD_LOCATION']]))
{
$propIndex[$propDesc['INPUT_FIELD_LOCATION']]['IS_ALTERNATE_LOCATION_FOR'] = $propId;
$propIndex[$propId]['CAN_HAVE_ALTERNATE_LOCATION'] = $propDesc['INPUT_FIELD_LOCATION']; // more strict condition rather INPUT_FIELD_LOCATION, check if the property really exists
}
}
//delete prop for text location (town)
if (count($arDeleteFieldLocation) > 0)
{
foreach ($arDeleteFieldLocation as $fieldId)
unset($arResult["ORDER_PROP"]["USER_PROPS_Y"][$fieldId]);
}
$this->executeEvent('OnSaleComponentOrderOneStepOrderProps', $this->order);
}
protected function getOrderPropFormatted($arProperty, &$arDeleteFieldLocation = [])
{
static $propertyGroupID = 0;
static $propertyUSER_PROPS = '';
$arProperty['FIELD_NAME'] = 'ORDER_PROP_'.$arProperty['ID'];
if ($arProperty['CODE'] != '')
{
$arProperty['FIELD_ID'] = 'ORDER_PROP_'.$arProperty['CODE'];
}
else
{
$arProperty['FIELD_ID'] = 'ORDER_PROP_'.$arProperty['ID'];
}
if (intval($arProperty['PROPS_GROUP_ID']) != $propertyGroupID || $propertyUSER_PROPS != $arProperty['USER_PROPS'])
{
$arProperty['SHOW_GROUP_NAME'] = 'Y';
}
$propertyGroupID = $arProperty['PROPS_GROUP_ID'];
$propertyUSER_PROPS = $arProperty['USER_PROPS'];
if ($arProperty['REQUIRED'] === 'Y' || $arProperty['IS_PROFILE_NAME'] === 'Y'
|| $arProperty['IS_LOCATION'] === 'Y' || $arProperty['IS_LOCATION4TAX'] === 'Y'
|| $arProperty['IS_PAYER'] === 'Y' || $arProperty['IS_ZIP'] === 'Y')
{
$arProperty['REQUIED'] = 'Y';
$arProperty['REQUIED_FORMATED'] = 'Y';
}
if ($arProperty['IS_LOCATION'] === 'Y')
{
$deliveryId = CSaleLocation::getLocationIDbyCODE(current($arProperty['VALUE']));
$this->arUserResult['DELIVERY_LOCATION'] = $deliveryId;
$this->arUserResult['DELIVERY_LOCATION_BCODE'] = current($arProperty['VALUE']);
}
if ($arProperty['IS_ZIP'] === 'Y')
{
$this->arUserResult['DELIVERY_LOCATION_ZIP'] = current($arProperty['VALUE']);
}
if ($arProperty['IS_LOCATION4TAX'] === 'Y')
{
$taxId = CSaleLocation::getLocationIDbyCODE(current($arProperty['VALUE']));
$this->arUserResult['TAX_LOCATION'] = $taxId;
$this->arUserResult['TAX_LOCATION_BCODE'] = current($arProperty['VALUE']);
}
if ($arProperty['IS_PAYER'] === 'Y')
{
$this->arUserResult['PAYER_NAME'] = current($arProperty['VALUE']);
}
if ($arProperty['IS_EMAIL'] === 'Y')
{
$this->arUserResult['USER_EMAIL'] = current($arProperty['VALUE']);
}
if ($arProperty['IS_PROFILE_NAME'] === 'Y')
{
$this->arUserResult['PROFILE_NAME'] = current($arProperty['VALUE']);
}
switch ($arProperty['TYPE'])
{
case 'Y/N':
self::formatYN($arProperty);
break;
case 'STRING':
self::formatString($arProperty);
break;
case 'NUMBER':
self::formatNumber($arProperty);
break;
case 'ENUM':
self::formatEnum($arProperty);
break;
case 'LOCATION':
self::formatLocation($arProperty, $arDeleteFieldLocation, $this->arResult['LOCATION_ALT_PROP_DISPLAY_MANUAL']);
break;
case 'FILE':
self::formatFile($arProperty);
break;
case 'DATE':
self::formatDate($arProperty);
break;
}
return $arProperty;
}
public static function formatYN(array &$arProperty)
{
$curVal = $arProperty['VALUE'];
if (current($curVal) == "Y")
{
$arProperty["CHECKED"] = "Y";
$arProperty["VALUE_FORMATED"] = Loc::getMessage("SOA_Y");
}
else
$arProperty["VALUE_FORMATED"] = Loc::getMessage("SOA_N");
$arProperty["SIZE1"] = (intval($arProperty["SIZE1"]) > 0) ? $arProperty["SIZE1"] : 30;
$arProperty["VALUE"] = current($curVal);
$arProperty["TYPE"] = 'CHECKBOX';
}
public static function formatString(array &$arProperty)
{
$curVal = $arProperty['VALUE'];
if (!empty($arProperty["MULTILINE"]) && $arProperty["MULTILINE"] == 'Y')
{
$arProperty["TYPE"] = 'TEXTAREA';
$arProperty["SIZE2"] = (intval($arProperty["ROWS"]) > 0) ? $arProperty["ROWS"] : 4;
$arProperty["SIZE1"] = (intval($arProperty["COLS"]) > 0) ? $arProperty["COLS"] : 40;
}
else
$arProperty["TYPE"] = 'TEXT';
$arProperty["SOURCE"] = current($curVal) == $arProperty['DEFAULT_VALUE'] ? 'DEFAULT' : 'FORM';
$arProperty["VALUE"] = current($curVal);
$arProperty["VALUE_FORMATED"] = $arProperty["VALUE"];
}
public static function formatNumber(array &$arProperty)
{
$curVal = $arProperty['VALUE'];
$arProperty["TYPE"] = 'TEXT';
$arProperty["VALUE"] = current($curVal);
$arProperty["VALUE_FORMATED"] = $arProperty["VALUE"];
}
public static function formatEnum(array &$arProperty)
{
$curVal = $arProperty['VALUE'];
if ($arProperty["MULTIELEMENT"] == 'Y')
{
if ($arProperty["MULTIPLE"] == 'Y')
{
$setValue = [];
$arProperty["FIELD_NAME"] = "ORDER_PROP_".$arProperty["ID"].'[]';
$arProperty["SIZE1"] = (intval($arProperty["SIZE1"]) > 0) ? $arProperty["SIZE1"] : 5;
$i = 0;
foreach ($arProperty["OPTIONS"] as $val => $name)
{
$arVariants = [
'VALUE' => $val,
'NAME' => $name,
];
if ((is_array($curVal) && in_array($arVariants["VALUE"], $curVal)))
{
$arVariants["SELECTED"] = "Y";
if ($i > 0)
$arProperty["VALUE_FORMATED"] .= ", ";
$arProperty["VALUE_FORMATED"] .= $arVariants["NAME"];
$setValue[] = $arVariants["VALUE"];
$i++;
}
$arProperty["VARIANTS"][] = $arVariants;
}
$arProperty["TYPE"] = 'MULTISELECT';
}
else
{
foreach ($arProperty['OPTIONS'] as $val => $name)
{
$arVariants = [
'VALUE' => $val,
'NAME' => $name,
];
if ($arVariants["VALUE"] == current($curVal))
{
$arVariants["CHECKED"] = "Y";
$arProperty["VALUE_FORMATED"] = $arVariants["NAME"];
}
$arProperty["VARIANTS"][] = $arVariants;
}
$arProperty["TYPE"] = 'RADIO';
}
}
else
{
if ($arProperty["MULTIPLE"] == 'Y')
{
$setValue = [];
$arProperty["FIELD_NAME"] = "ORDER_PROP_".$arProperty["ID"].'[]';
$arProperty["SIZE1"] = ((intval($arProperty["SIZE1"]) > 0) ? $arProperty["SIZE1"] : 5);
$i = 0;
foreach ($arProperty["OPTIONS"] as $val => $name)
{
$arVariants = [
'VALUE' => $val,
'NAME' => $name,
];
if (is_array($curVal) && in_array($arVariants["VALUE"], $curVal))
{
$arVariants["SELECTED"] = "Y";
if ($i > 0)
$arProperty["VALUE_FORMATED"] .= ", ";
$arProperty["VALUE_FORMATED"] .= $arVariants["NAME"];
$setValue[] = $arVariants["VALUE"];
$i++;
}
$arProperty["VARIANTS"][] = $arVariants;
}
$arProperty["TYPE"] = 'MULTISELECT';
}
else
{
$arProperty["SIZE1"] = ((intval($arProperty["SIZE1"]) > 0) ? $arProperty["SIZE1"] : 1);
$flagDefault = "N";
$nameProperty = "";
foreach ($arProperty["OPTIONS"] as $val => $name)
{
$arVariants = [
'VALUE' => $val,
'NAME' => $name,
];
if ($flagDefault == "N" && $nameProperty == "")
{
$nameProperty = $arVariants["NAME"];
}
if ($arVariants["VALUE"] == current($curVal))
{
$arVariants["SELECTED"] = "Y";
$arProperty["VALUE_FORMATED"] = $arVariants["NAME"];
$flagDefault = "Y";
}
$arProperty["VARIANTS"][] = $arVariants;
}
if ($flagDefault == "N")
{
$arProperty["VARIANTS"][0]["SELECTED"] = "Y";
$arProperty["VARIANTS"][0]["VALUE_FORMATED"] = $nameProperty;
}
$arProperty["TYPE"] = 'SELECT';
}
}
}
public static function formatLocation(array &$arProperty, array &$arDeleteFieldLocation, $locationAltPropDisplayManual = null)
{
$curVal = CSaleLocation::getLocationIDbyCODE(current($arProperty['VALUE']));
$arProperty["VALUE"] = $curVal;
$locationFound = false;
//todo select via D7
$dbVariants = CSaleLocation::GetList(
["SORT" => "ASC", "COUNTRY_NAME_LANG" => "ASC", "CITY_NAME_LANG" => "ASC"],
["LID" => LANGUAGE_ID],
false,
false,
["ID", "COUNTRY_NAME", "CITY_NAME", "SORT", "COUNTRY_NAME_LANG", "CITY_NAME_LANG", "CITY_ID", "CODE"]
);
while ($arVariants = $dbVariants->GetNext())
{
$city = !empty($arVariants['CITY_NAME']) ? ' - '.$arVariants['CITY_NAME'] : '';
if ($arVariants['ID'] === $curVal)
{
// set formatted value
$locationFound = $arVariants;
$arVariants['SELECTED'] = 'Y';
$arProperty['VALUE_FORMATED'] = $arVariants['COUNTRY_NAME'].$city;
}
$arVariants['NAME'] = $arVariants['COUNTRY_NAME'].$city;
// save to variants
$arProperty['VARIANTS'][] = $arVariants;
}
if (!$locationFound && intval($curVal))
{
$item = CSaleLocation::GetById($curVal);
if ($item)
{
// set formatted value
$locationFound = $item;
$arProperty["VALUE_FORMATED"] = $item["COUNTRY_NAME"].(($item["CITY_NAME"] <> '') ? " - " : "").$item["CITY_NAME"];
$item['SELECTED'] = 'Y';
$item['NAME'] = $item["COUNTRY_NAME"].(($item["CITY_NAME"] <> '') ? " - " : "").$item["CITY_NAME"];
// save to variants
$arProperty["VARIANTS"][] = $item;
}
}
if ($locationFound)
{
// enable location town text
if (isset($locationAltPropDisplayManual)) // its an ajax-hit and sale.location.selector.steps is used
{
if (intval($locationAltPropDisplayManual[$arProperty["ID"]])) // user MANUALLY selected "Other location" in the selector
unset($arDeleteFieldLocation[$arProperty["ID"]]);
else
$arDeleteFieldLocation[$arProperty["ID"]] = $arProperty["INPUT_FIELD_LOCATION"];
}
else
{
if ($arProperty["IS_LOCATION"] == "Y" && intval($arProperty["INPUT_FIELD_LOCATION"]) > 0)
{
if (intval($locationFound["CITY_ID"]) <= 0)
unset($arDeleteFieldLocation[$arProperty["ID"]]);
else
$arDeleteFieldLocation[$arProperty["ID"]] = $arProperty["INPUT_FIELD_LOCATION"];
}
}
}
else
{
// nothing found, may be it is the first load - hide
$arDeleteFieldLocation[$arProperty["ID"]] = $arProperty["INPUT_FIELD_LOCATION"];
}
}
public static function formatFile(array &$arProperty)
{
$curVal = $arProperty['VALUE'];
$arProperty["SIZE1"] = intval($arProperty["SIZE1"]);
if ($arProperty['MULTIPLE'] == 'Y')
{
$arr = [];
$curVal = isset($curVal) ? $curVal : $arProperty["DEFAULT_VALUE"];
foreach ($curVal as $file)
{
$arr[] = $file['ID'];
}
$arProperty["VALUE"] = serialize($arr);
}
else
{
$arFile = isset($curVal) && is_array($curVal) ? current($curVal) : $arProperty["DEFAULT_VALUE"];
if (is_array($arFile))
$arProperty["VALUE"] = $arFile['ID'];
}
}
public static function formatDate(array &$arProperty)
{
$arProperty["VALUE"] = current($arProperty['VALUE']);
$arProperty["VALUE_FORMATED"] = $arProperty["VALUE"];
}
/**
* Set basket items data from order object to $this->arResult
*/
protected function obtainBasket()
{
$arResult =& $this->arResult;
$arResult["MAX_DIMENSIONS"] = $arResult["ITEMS_DIMENSIONS"] = [];
$arResult["BASKET_ITEMS"] = [];
$this->calculateBasket = $this->order->getBasket()->createClone();
$discounts = $this->order->getDiscount();
$showPrices = $discounts->getShowPrices();
if (!empty($showPrices['BASKET']))
{
foreach ($showPrices['BASKET'] as $basketCode => $data)
{
$basketItem = $this->calculateBasket->getItemByBasketCode($basketCode);
if ($basketItem instanceof Sale\BasketItemBase)
{
$basketItem->setFieldNoDemand('BASE_PRICE', $data['SHOW_BASE_PRICE']);
$basketItem->setFieldNoDemand('PRICE', $data['SHOW_PRICE']);
$basketItem->setFieldNoDemand('DISCOUNT_PRICE', $data['SHOW_DISCOUNT']);
}
}
}
unset($showPrices);
/** @var Sale\BasketItem $basketItem */
foreach ($this->calculateBasket as $basketItem)
{
$arBasketItem = $basketItem->getFieldValues();
if ($basketItem->getVatRate() > 0)
{
$arResult["bUsingVat"] = "Y";
$arBasketItem["VAT_VALUE"] = $basketItem->getVat();
}
$arBasketItem["QUANTITY"] = $basketItem->getQuantity();
$arBasketItem["PRICE_FORMATED"] = SaleFormatCurrency($basketItem->getPrice(), $this->order->getCurrency());
$arBasketItem["WEIGHT_FORMATED"] = roundEx(doubleval($basketItem->getWeight() / $arResult["WEIGHT_KOEF"]), SALE_WEIGHT_PRECISION)." ".$arResult["WEIGHT_UNIT"];
$arBasketItem["DISCOUNT_PRICE"] = $basketItem->getDiscountPrice();
$arBasketItem["DISCOUNT_PRICE_PERCENT"] = 0;
if ($arBasketItem['CUSTOM_PRICE'] != 'Y')
{
$arBasketItem['DISCOUNT_PRICE_PERCENT'] = Sale\Discount::calculateDiscountPercent(
$arBasketItem['BASE_PRICE'],
$arBasketItem['DISCOUNT_PRICE']
);
if ($arBasketItem['DISCOUNT_PRICE_PERCENT'] === null)
$arBasketItem['DISCOUNT_PRICE_PERCENT'] = 0;
}
$arBasketItem["DISCOUNT_PRICE_PERCENT_FORMATED"] = $arBasketItem['DISCOUNT_PRICE_PERCENT'].'%';
$arBasketItem["BASE_PRICE_FORMATED"] = SaleFormatCurrency($basketItem->getBasePrice(), $this->order->getCurrency());
$arDim = $basketItem->getField('DIMENSIONS');
if (is_string($arDim))
{
$arDim = unserialize($basketItem->getField('DIMENSIONS'));
}
if (is_array($arDim))
{
$arResult["MAX_DIMENSIONS"] = CSaleDeliveryHelper::getMaxDimensions(
[
$arDim["WIDTH"],
$arDim["HEIGHT"],
$arDim["LENGTH"],
],
$arResult["MAX_DIMENSIONS"]);
$arResult["ITEMS_DIMENSIONS"][] = $arDim;
}
$arBasketItem["PROPS"] = [];
/** @var Sale\BasketPropertiesCollection $propertyCollection */
$propertyCollection = $basketItem->getPropertyCollection();
$propList = $propertyCollection->getPropertyValues();
foreach ($propList as $key => &$prop)
{
if ($prop['CODE'] == 'CATALOG.XML_ID' || $prop['CODE'] == 'PRODUCT.XML_ID' || $prop['CODE'] == 'SUM_OF_CHARGE')
continue;
$prop = array_filter($prop, ["CSaleBasketHelper", "filterFields"]);
$arBasketItem["PROPS"][] = $prop;
}
$this->arElementId[] = $arBasketItem["PRODUCT_ID"];
$arBasketItem["SUM_NUM"] = $basketItem->getPrice() * $basketItem->getQuantity();
$arBasketItem["SUM"] = SaleFormatCurrency($basketItem->getPrice() * $basketItem->getQuantity(), $this->order->getCurrency());
$arBasketItem["SUM_BASE"] = $basketItem->getBasePrice() * $basketItem->getQuantity();
$arBasketItem["SUM_BASE_FORMATED"] = SaleFormatCurrency($basketItem->getBasePrice() * $basketItem->getQuantity(), $this->order->getCurrency());
$arResult["BASKET_ITEMS"][] = $arBasketItem;
}
}
/**
* Set basket items data from iblocks (basket column properties, sku, preview pictures, etc) to $this->arResult
*/
protected function obtainPropertiesForIbElements()
{
if (empty($this->arElementId))
{
return;
}
$arResult =& $this->arResult;
$arResult["GRID"]["ROWS"] = [];
$arParents = [];
if ($this->useCatalog)
{
$arParents = CCatalogSku::getProductList($this->arElementId);
if (!empty($arParents))
{
foreach ($arParents as $productId => $arParent)
{
$this->arElementId[] = $arParent["ID"];
$this->arSku2Parent[$productId] = $arParent["ID"];
}
}
}
$arElementData = [];
$arProductData = [];
$elementIndex = [];
$res = CIBlockElement::GetList(
[],
["=ID" => array_unique($this->arElementId)],
false,
false,
["ID", "IBLOCK_ID", "PREVIEW_PICTURE", "DETAIL_PICTURE", "PREVIEW_TEXT"]
);
while ($arElement = $res->Fetch())
{
$arElementData[$arElement["IBLOCK_ID"]][] = $arElement["ID"];
$arProductData[$arElement["ID"]] = $arElement;
$elementIndex[$arElement["ID"]] = [];
}
foreach ($arElementData as $iBlockId => $arElemId)
{
$arCodes = [];
if (!empty($this->arIblockProps[$iBlockId]))
$arCodes = array_keys($this->arIblockProps[$iBlockId]);
$imageCode = $this->arParams['ADDITIONAL_PICT_PROP'][$iBlockId];
if (!empty($imageCode) && !in_array($imageCode, $arCodes))
$arCodes[] = $imageCode;
if (!empty($arCodes))
{
CIBlockElement::GetPropertyValuesArray($elementIndex, $iBlockId,
["ID" => $arElemId],
["CODE" => $arCodes]
);
}
}
unset($arElementData);
$arAdditionalImages = [];
foreach ($elementIndex as $productId => $productProperties)
{
if (!empty($productProperties) && is_array($productProperties))
{
foreach ($productProperties as $code => $property)
{
if (
!empty($this->arParams['ADDITIONAL_PICT_PROP'])
&& array_key_exists($arProductData[$productId]['IBLOCK_ID'], $this->arParams['ADDITIONAL_PICT_PROP'])
)
{
if ($this->arParams['ADDITIONAL_PICT_PROP'][$arProductData[$productId]['IBLOCK_ID']] == $code)
{
$arAdditionalImages[$productId] = is_array($property['VALUE']) ? current($property['VALUE']) : $property['VALUE'];
}
}
if (
!empty($this->arIblockProps[$arProductData[$productId]['IBLOCK_ID']])
&& array_key_exists($code, $this->arIblockProps[$arProductData[$productId]['IBLOCK_ID']])
)
{
if (is_array($property['VALUE']))
{
$arProductData[$productId]['PROPERTY_'.$code.'_VALUE'] = implode(', ', $property['VALUE']);
}
else
{
$arProductData[$productId]['PROPERTY_'.$code.'_VALUE'] = $property['VALUE'];
}
if (is_array($property['PROPERTY_VALUE_ID']))
{
$arProductData[$productId]['PROPERTY_'.$code.'_VALUE_ID'] = implode(', ', $property['PROPERTY_VALUE_ID']);
}
else
{
$arProductData[$productId]['PROPERTY_'.$code.'_VALUE_ID'] = $property['PROPERTY_VALUE_ID'];
}
if ($property['PROPERTY_TYPE'] == 'L')
{
$arProductData[$productId]['PROPERTY_'.$code.'_ENUM_ID'] = $property['VALUE_ENUM_ID'];
}
}
}
}
}
unset($elementIndex);
$currentProductProperties = [];
$needToResizeProductImages = $this->arParams['COMPATIBLE_MODE'] === 'Y'
|| isset($this->arParams['PRODUCT_COLUMNS']['PREVIEW_PICTURE'])
|| isset($this->arParams['PRODUCT_COLUMNS']['DETAIL_PICTURE'])
|| isset($this->arParams['PRODUCT_COLUMNS_HIDDEN']['PREVIEW_PICTURE'])
|| isset($this->arParams['PRODUCT_COLUMNS_HIDDEN']['DETAIL_PICTURE']);
foreach ($arResult["BASKET_ITEMS"] as &$arResultItem)
{
$productId = $arResultItem["PRODUCT_ID"];
$arParent = $arParents[$productId];
$itemIblockId = intval($arProductData[$productId]['IBLOCK_ID']);
$currentProductProperties[$productId] = isset($this->arIblockProps[$itemIblockId])
? $this->arIblockProps[$itemIblockId]
: [];
if (
(int)$arProductData[$productId]["PREVIEW_PICTURE"] <= 0
&& (int)$arProductData[$productId]["DETAIL_PICTURE"] <= 0
&& $arParent
)
{
$productId = $arParent["ID"];
}
if ((int)$arProductData[$productId]["PREVIEW_PICTURE"] > 0)
{
$arResultItem["PREVIEW_PICTURE"] = $arProductData[$productId]["PREVIEW_PICTURE"];
}
if ((int)$arProductData[$productId]["DETAIL_PICTURE"] > 0)
{
$arResultItem["DETAIL_PICTURE"] = $arProductData[$productId]["DETAIL_PICTURE"];
}
if ($arProductData[$productId]["PREVIEW_TEXT"] != '')
{
$arResultItem["PREVIEW_TEXT"] = $arProductData[$productId]["PREVIEW_TEXT"];
$arResultItem["PREVIEW_TEXT_TYPE"] = $arProductData[$productId]["PREVIEW_TEXT_TYPE"];
}
if (!empty($arProductData[$arResultItem["PRODUCT_ID"]]) && is_array($arProductData[$arResultItem["PRODUCT_ID"]]))
{
foreach ($arProductData[$arResultItem["PRODUCT_ID"]] as $key => $value)
{
if (mb_strpos($key, "PROPERTY_") !== false)
$arResultItem[$key] = $value;
}
}
// if sku element doesn't have some property value - we'll show parent element value instead
if (isset($this->arSku2Parent[$arResultItem["PRODUCT_ID"]]))
{
$parentIblockId = $arProductData[$this->arSku2Parent[$arResultItem["PRODUCT_ID"]]]['IBLOCK_ID'];
if (!empty($this->arIblockProps[$parentIblockId]))
{
$currentProductProperties[$arResultItem["PRODUCT_ID"]] = array_merge(
$this->arIblockProps[$parentIblockId],
$currentProductProperties[$arResultItem["PRODUCT_ID"]]
);
}
foreach ($this->arCustomSelectFields as $field)
{
$fieldVal = $field."_VALUE";
$parentId = $this->arSku2Parent[$arResultItem["PRODUCT_ID"]];
// can be array or string
if (
(!isset($arResultItem[$fieldVal]) || (isset($arResultItem[$fieldVal]) && $arResultItem[$fieldVal] == ''))
&& (isset($arProductData[$parentId][$fieldVal]) && !empty($arProductData[$parentId][$fieldVal]))
)
{
$arResultItem[$fieldVal] = $arProductData[$parentId][$fieldVal];
}
}
}
// replace PREVIEW_PICTURE with selected ADDITIONAL_PICT_PROP
if (
empty($arProductData[$arResultItem["PRODUCT_ID"]]["PREVIEW_PICTURE"])
&& empty($arProductData[$arResultItem["PRODUCT_ID"]]["DETAIL_PICTURE"])
&& $arAdditionalImages[$arResultItem["PRODUCT_ID"]]
)
{
$arResultItem["PREVIEW_PICTURE"] = $arAdditionalImages[$arResultItem["PRODUCT_ID"]];
}
elseif (
empty($arResultItem["PREVIEW_PICTURE"])
&& empty($arResultItem["DETAIL_PICTURE"])
&& $arAdditionalImages[$productId]
)
{
$arResultItem["PREVIEW_PICTURE"] = $arAdditionalImages[$productId];
}
$arResultItem["PREVIEW_PICTURE_SRC"] = "";
if (
$needToResizeProductImages
&& isset($arResultItem["PREVIEW_PICTURE"])
&& (int)$arResultItem["PREVIEW_PICTURE"] > 0
)
{
$arImage = CFile::GetFileArray($arResultItem["PREVIEW_PICTURE"]);
if (!empty($arImage))
{
self::resizeImage($arResultItem, 'PREVIEW_PICTURE', $arImage,
["width" => 320, "height" => 320],
["width" => 110, "height" => 110],
$this->arParams['BASKET_IMAGES_SCALING']
);
}
}
$arResultItem["DETAIL_PICTURE_SRC"] = "";
if (
$needToResizeProductImages
&& isset($arResultItem["DETAIL_PICTURE"])
&& (int)$arResultItem["DETAIL_PICTURE"] > 0
)
{
$arImage = CFile::GetFileArray($arResultItem["DETAIL_PICTURE"]);
if (!empty($arImage))
{
self::resizeImage($arResultItem, 'DETAIL_PICTURE', $arImage,
["width" => 320, "height" => 320],
["width" => 110, "height" => 110],
$this->arParams['BASKET_IMAGES_SCALING']
);
}
}
}
if (!empty($arResult["BASKET_ITEMS"]) && $this->useCatalog)
{
$arResult["BASKET_ITEMS"] = getMeasures($arResult["BASKET_ITEMS"]);
}
foreach ($arResult["BASKET_ITEMS"] as $arBasketItem)
{
// prepare values for custom-looking columns
$arCols = [
"PROPS" => $this->getPropsInfo($arBasketItem),
];
if ($this->arParams['COMPATIBLE_MODE'] === 'Y')
{
if (isset($arBasketItem["PREVIEW_PICTURE"]) && (int)$arBasketItem["PREVIEW_PICTURE"] > 0)
{
$arCols["PREVIEW_PICTURE"] = CSaleHelper::getFileInfo(
$arBasketItem["PREVIEW_PICTURE"],
["WIDTH" => 110, "HEIGHT" => 110]
);
}
if (isset($arBasketItem["DETAIL_PICTURE"]) && (int)$arBasketItem["DETAIL_PICTURE"] > 0)
{
$arCols["DETAIL_PICTURE"] = CSaleHelper::getFileInfo(
$arBasketItem["DETAIL_PICTURE"],
["WIDTH" => 110, "HEIGHT" => 110]
);
}
}
if (!empty($arBasketItem["MEASURE_TEXT"]))
{
$arCols["QUANTITY"] = $arBasketItem["QUANTITY"]." ".$arBasketItem["MEASURE_TEXT"];
}
foreach ($arBasketItem as $tmpKey => $value)
{
if ((mb_strpos($tmpKey, "PROPERTY_", 0) === 0) && (mb_strrpos($tmpKey, "_VALUE") == mb_strlen($tmpKey) - 6))
{
$code = str_replace(["PROPERTY_", "_VALUE"], "", $tmpKey);
$propData = $currentProductProperties[$arBasketItem['PRODUCT_ID']][$code];
// display linked property type
if ($propData['PROPERTY_TYPE'] === 'E')
{
$propData['VALUE'] = $value;
$arCols[$tmpKey] = $this->getLinkedPropValue($arBasketItem, $propData);
}
elseif ($propData['PROPERTY_TYPE'] === 'S' && $propData['USER_TYPE'] === 'directory')
{
$arCols[$tmpKey] = $this->getDirectoryProperty($arBasketItem, $propData);
}
else
{
$arCols[$tmpKey] = $this->getIblockProps($value, $propData, ['WIDTH' => 110, 'HEIGHT' => 110]);
}
}
}
$arResult["GRID"]["ROWS"][$arBasketItem["ID"]] = [
"id" => $arBasketItem["ID"],
"data" => $arBasketItem,
"actions" => [],
"columns" => $arCols,
"editable" => true,
];
}
}
/**
* Set delivery data from shipment object and delivery services object to $this->arResult
* Execution of 'OnSaleComponentOrderOneStepDelivery' event
*
* @throws Main\NotSupportedException
*/
protected function obtainDelivery()
{
$arResult =& $this->arResult;
$arStoreId = [];
/** @var Shipment $shipment */
$shipment = $this->getCurrentShipment($this->order);
if (!empty($this->arDeliveryServiceAll))
{
foreach ($this->arDeliveryServiceAll as $deliveryObj)
{
$arDelivery =& $this->arResult["DELIVERY"][$deliveryObj->getId()];
$arDelivery['ID'] = $deliveryObj->getId();
$arDelivery['NAME'] = $deliveryObj->isProfile() ? $deliveryObj->getNameWithParent() : $deliveryObj->getName();
$arDelivery['OWN_NAME'] = $deliveryObj->getName();
$arDelivery['DESCRIPTION'] = $deliveryObj->getDescription();
$arDelivery['FIELD_NAME'] = 'DELIVERY_ID';
$arDelivery["CURRENCY"] = $this->order->getCurrency();
$arDelivery['SORT'] = $deliveryObj->getSort();
$arDelivery['EXTRA_SERVICES'] = $deliveryObj->getExtraServices()->getItems();
$arDelivery['STORE'] = Delivery\ExtraServices\Manager::getStoresList($deliveryObj->getId());
if (intval($deliveryObj->getLogotip()) > 0)
$arDelivery["LOGOTIP"] = CFile::GetFileArray($deliveryObj->getLogotip());
if (!empty($arDelivery['STORE']) && is_array($arDelivery['STORE']))
{
foreach ($arDelivery['STORE'] as $val)
$arStoreId[$val] = $val;
}
$buyerStore = $this->request->get('BUYER_STORE');
if (!empty($buyerStore) && !empty($arDelivery['STORE']) && is_array($arDelivery['STORE']) && in_array($buyerStore, $arDelivery['STORE']))
{
$this->arUserResult['DELIVERY_STORE'] = $arDelivery["ID"];
}
}
}
$arResult["BUYER_STORE"] = $shipment->getStoreId();
$arStore = [];
$dbList = CCatalogStore::GetList(
["SORT" => "DESC", "ID" => "DESC"],
["ACTIVE" => "Y", "ID" => $arStoreId, "ISSUING_CENTER" => "Y", "+SITE_ID" => $this->getSiteId()],
false,
false,
["ID", "TITLE", "ADDRESS", "DESCRIPTION", "IMAGE_ID", "PHONE", "SCHEDULE", "GPS_N", "GPS_S", "ISSUING_CENTER", "SITE_ID"]
);
while ($arStoreTmp = $dbList->Fetch())
{
if ($arStoreTmp["IMAGE_ID"] > 0)
$arStoreTmp["IMAGE_ID"] = CFile::GetFileArray($arStoreTmp["IMAGE_ID"]);
else
$arStoreTmp["IMAGE_ID"] = null;
$arStore[$arStoreTmp["ID"]] = $arStoreTmp;
}
$arResult["STORE_LIST"] = $arStore;
$arResult["DELIVERY_EXTRA"] = [];
$deliveryExtra = $this->request->get('DELIVERY_EXTRA');
if (is_array($deliveryExtra) && !empty($deliveryExtra[$this->arUserResult["DELIVERY_ID"]]))
$arResult["DELIVERY_EXTRA"] = $deliveryExtra[$this->arUserResult["DELIVERY_ID"]];
$this->executeEvent('OnSaleComponentOrderOneStepDelivery', $this->order);
}
/**
* Set pay system data from inner/external payment object and pay system services object to $this->arResult
* Execution of 'OnSaleComponentOrderOneStepPaySystem' event
*/
protected function obtainPaySystem()
{
$arResult =& $this->arResult;
$innerPayment = $this->getInnerPayment($this->order);
if (!empty($innerPayment) && $innerPayment->getSum() > 0)
{
$arResult['PAYED_FROM_ACCOUNT_FORMATED'] = SaleFormatCurrency($innerPayment->getSum(), $this->order->getCurrency());
$arResult['ORDER_TOTAL_LEFT_TO_PAY'] = $this->order->getPrice() - $innerPayment->getSum();
$arResult['ORDER_TOTAL_LEFT_TO_PAY_FORMATED'] = SaleFormatCurrency($this->order->getPrice() - $innerPayment->getSum(), $this->order->getCurrency());
}
$paySystemList = $this->arParams['DELIVERY_TO_PAYSYSTEM'] === 'p2d' ? $this->arActivePaySystems : $this->arPaySystemServiceAll;
if (!empty($paySystemList))
{
$innerPaySystemId = PaySystem\Manager::getInnerPaySystemId();
if (!empty($paySystemList[$innerPaySystemId]))
{
$innerPaySystem = $paySystemList[$innerPaySystemId];
if ($innerPaySystem['LOGOTIP'] > 0)
{
$innerPaySystem['LOGOTIP'] = CFile::GetFileArray($innerPaySystem['LOGOTIP']);
}
$arResult['INNER_PAY_SYSTEM'] = $innerPaySystem;
unset($paySystemList[$innerPaySystemId]);
}
$extPayment = $this->getExternalPayment($this->order);
$paymentId = !empty($extPayment) ? $extPayment->getPaymentSystemId() : null;
foreach ($paySystemList as $paySystem)
{
$paySystem['PSA_ID'] = $paySystem['ID'];
if ((string)$paySystem['PSA_NAME'] === '')
{
$paySystem['PSA_NAME'] = $paySystem['NAME'];
}
$paySystem['PSA_NAME'] = htmlspecialcharsEx($paySystem['PSA_NAME']);
$keyMap = [
'ACTION_FILE', 'RESULT_FILE', 'NEW_WINDOW', 'PERSON_TYPE_ID', 'PARAMS', 'TARIF', 'HAVE_PAYMENT',
'HAVE_ACTION', 'HAVE_RESULT', 'HAVE_PREPAY', 'HAVE_RESULT_RECEIVE', 'ENCODING',
];
foreach ($keyMap as $key)
{
$paySystem["PSA_{$key}"] = $paySystem[$key];
unset($paySystem[$key]);
}
if ($paySystem['LOGOTIP'] > 0)
{
$paySystem['PSA_LOGOTIP'] = CFile::GetFileArray($paySystem['LOGOTIP']);
}
unset($paySystem['LOGOTIP']);
if ($paymentId == $paySystem['ID'])
{
$paySystem['CHECKED'] = 'Y';
}
$paySystem['PRICE'] = 0;
if ($paySystem['HAVE_PRICE'] === 'Y' && !empty($extPayment))
{
$service = PaySystem\Manager::getObjectById($paySystem['ID']);
if ($service !== null)
{
$paySystem['PRICE'] = $service->getPaymentPrice($extPayment);
$paySystem['PRICE_FORMATTED'] = SaleFormatCurrency($paySystem['PRICE'], $this->order->getCurrency());
if ($paymentId == $paySystem['ID'])
{
$arResult['PAY_SYSTEM_PRICE'] = $extPayment->getField('PRICE_COD');
$arResult['PAY_SYSTEM_PRICE_FORMATTED'] = SaleFormatCurrency($arResult['PAY_SYSTEM_PRICE'], $this->order->getCurrency());
}
}
}
$arResult['PAY_SYSTEM'][] = $paySystem;
}
}
$this->executeEvent('OnSaleComponentOrderOneStepPaySystem', $this->order);
}
/**
* Set related to payment/delivery order properties data from order object to $this->arResult
*
* @throws Main\ObjectNotFoundException
*/
protected function obtainRelatedProperties()
{
$arRes = [];
$arProps = $this->order->getPropertyCollection()->getArray();
foreach ($arProps['properties'] as $key => $property)
{
if ($property['UTIL'] == 'Y')
continue;
if (isset($property['RELATION']))
{
if (!empty($this->arResult['PERSON_TYPE'][$property['PERSON_TYPE_ID']]))
{
$personType = $this->arResult['PERSON_TYPE'][$property['PERSON_TYPE_ID']];
$property['PERSON_TYPE_LID'] = $personType['ID'];
$property['PERSON_TYPE_NAME'] = $personType['NAME'];
$property['PERSON_TYPE_SORT'] = $personType['SORT'];
$property['PERSON_TYPE_ACTIVE'] = $personType['ACTIVE'];
}
foreach ($arProps['groups'] as $group)
{
if ($group['ID'] == $property['PROPS_GROUP_ID'])
{
$property['GROUP_NAME'] = $group['NAME'];
$property['GROUP_ID'] = $group['ID'];
$property['GROUP_PERSON_TYPE_ID'] = $group['PERSON_TYPE_ID'];
break;
}
}
$property['SETTINGS'] = [
'MINLENGTH' => $property['MINLENGTH'],
'MAXLENGTH' => $property['MAXLENGTH'],
'PATTERN' => $property['PATTERN'],
'MULTILINE' => $property['MULTILINE'],
'SIZE' => $property['SIZE'],
];
$property['PAYSYSTEM_ID'] = $property['ID'];
$property['DELIVERY_ID'] = $property['ID'];
$arRes[] = $this->getOrderPropFormatted($property);
}
}
$this->arResult["ORDER_PROP"]["RELATED"] = $arRes;
}
/**
* Set taxes data from order object to $this->arResult
*/
protected function obtainTaxes()
{
$arResult =& $this->arResult;
$arResult["USE_VAT"] = $this->order->isUsedVat();
$arResult["VAT_RATE"] = $this->order->getVatRate();
$arResult["VAT_SUM"] = $this->order->getVatSum();
if ($arResult["VAT_SUM"] === null)
$arResult["VAT_SUM"] = 0;
$arResult["VAT_SUM_FORMATED"] = SaleFormatCurrency($arResult["VAT_SUM"], $this->order->getCurrency());
$taxes = $this->order->getTax();
$taxes->refreshData();
if ($this->order->isUsedVat())
{
if ($this->arParams['SHOW_VAT_PRICE'] === 'Y')
{
$arResult['TAX_LIST'] = $taxes->getAvailableList();
}
}
else
{
$arResult['TAX_LIST'] = $taxes->getTaxList();
if (is_array($arResult['TAX_LIST']) && !empty($arResult['TAX_LIST']))
{
foreach ($arResult['TAX_LIST'] as $key => &$tax)
{
if ($tax['VALUE_MONEY'])
$tax['VALUE_MONEY_FORMATED'] = SaleFormatCurrency($tax['VALUE_MONEY'], $this->order->getCurrency());
}
}
}
$arResult['TAX_PRICE'] = $this->order->getTaxPrice();
}
/**
* Set order total prices data from order object to $this->arResult
*/
protected function obtainTotal()
{
$arResult =& $this->arResult;
$locationAltPropDisplayManual = $this->request->get('LOCATION_ALT_PROP_DISPLAY_MANUAL');
if (!empty($locationAltPropDisplayManual) && is_array($locationAltPropDisplayManual))
{
foreach ($locationAltPropDisplayManual as $propId => $switch)
{
if (intval($propId))
{
$arResult['LOCATION_ALT_PROP_DISPLAY_MANUAL'][intval($propId)] = !!$switch;
}
}
}
$basket = $this->calculateBasket;
$arResult['ORDER_PRICE'] = $basket->getPrice();
$arResult['ORDER_PRICE_FORMATED'] = SaleFormatCurrency($arResult['ORDER_PRICE'], $this->order->getCurrency());
$arResult['ORDER_WEIGHT'] = $basket->getWeight();
$arResult['ORDER_WEIGHT_FORMATED'] = roundEx(floatval($arResult['ORDER_WEIGHT'] / $arResult['WEIGHT_KOEF']), SALE_WEIGHT_PRECISION).' '.$arResult['WEIGHT_UNIT'];
$arResult['PRICE_WITHOUT_DISCOUNT_VALUE'] = $basket->getBasePrice();
$arResult['PRICE_WITHOUT_DISCOUNT'] = SaleFormatCurrency($arResult['PRICE_WITHOUT_DISCOUNT_VALUE'], $this->order->getCurrency());
$arResult['DISCOUNT_PRICE'] = Sale\PriceMaths::roundPrecision(
$this->order->getDiscountPrice() + ($arResult['PRICE_WITHOUT_DISCOUNT_VALUE'] - $arResult['ORDER_PRICE'])
);
$arResult['DISCOUNT_PRICE_FORMATED'] = SaleFormatCurrency($arResult['DISCOUNT_PRICE'], $this->order->getCurrency());
$arResult['DELIVERY_PRICE'] = Sale\PriceMaths::roundPrecision($this->order->getDeliveryPrice());
$arResult['DELIVERY_PRICE_FORMATED'] = SaleFormatCurrency($arResult['DELIVERY_PRICE'], $this->order->getCurrency());
$arResult['ORDER_TOTAL_PRICE'] = Sale\PriceMaths::roundPrecision($this->order->getPrice());
$arResult['ORDER_TOTAL_PRICE_FORMATED'] = SaleFormatCurrency($arResult['ORDER_TOTAL_PRICE'], $this->order->getCurrency());
}
/**
* Obtains all order fields filled by user.
*/
protected function obtainUserConsentInfo()
{
$propertyNames = [];
$propertyIterator = Sale\Property::getList([
'select' => ['NAME'],
'filter' => [
'ACTIVE' => 'Y',
'UTIL' => 'N',
'PERSON_TYPE_SITE.SITE_ID' => $this->getSiteId(),
],
'order' => [
'SORT' => 'ASC',
'ID' => 'ASC',
],
'runtime' => [
new \Bitrix\Main\Entity\ReferenceField(
'PERSON_TYPE_SITE',
'Bitrix\Sale\Internals\PersonTypeSiteTable',
['=this.PERSON_TYPE_ID' => 'ref.PERSON_TYPE_ID']
),
],
]);
while ($property = $propertyIterator->fetch())
{
$propertyNames[] = $property['NAME'];
}
$this->arResult['USER_CONSENT_PROPERTY_DATA'] = $propertyNames;
}
/**
* Make $arResult compatible ('~' prefixes and htmlspecialcharsEx)
*/
protected function makeResultCompatible()
{
$arResult =& $this->arResult;
if (is_array($arResult['PERSON_TYPE']) && !empty($arResult['PERSON_TYPE']))
foreach ($arResult['PERSON_TYPE'] as &$item)
self::makeCompatibleArray($item);
if (is_array($arResult['ORDER_PROP']['RELATED']) && !empty($arResult['ORDER_PROP']['RELATED']))
foreach ($arResult['ORDER_PROP']['RELATED'] as &$item)
self::makeCompatibleArray($item);
if (is_array($arResult['ORDER_PROP']['USER_PROPS_Y']) && !empty($arResult['ORDER_PROP']['USER_PROPS_Y']))
foreach ($arResult['ORDER_PROP']['USER_PROPS_Y'] as &$item)
self::makeCompatibleArray($item);
if (is_array($arResult['ORDER_PROP']['USER_PROPS_N']) && !empty($arResult['ORDER_PROP']['USER_PROPS_N']))
foreach ($arResult['ORDER_PROP']['USER_PROPS_N'] as &$item)
self::makeCompatibleArray($item);
if (is_array($arResult['BASKET_ITEMS']) && !empty($arResult['BASKET_ITEMS']))
foreach ($arResult['BASKET_ITEMS'] as &$item)
self::makeCompatibleArray($item);
if (is_array($arResult['GRID']['ROWS']) && !empty($arResult['GRID']['ROWS']))
foreach ($arResult['GRID']['ROWS'] as &$item)
self::makeCompatibleArray($item['data']);
if (is_array($arResult['USER_ACCOUNT']) && !empty($arResult['USER_ACCOUNT']))
self::makeCompatibleArray($arResult['USER_ACCOUNT']);
}
public static function makeCompatibleArray(&$array)
{
if (empty($array) || !is_array($array))
return;
$arr = [];
foreach ($array as $key => $value)
{
if (is_array($value) || preg_match("/[;&<>\"]/", $value))
{
$arr[$key] = htmlspecialcharsEx($value);
}
else
{
$arr[$key] = $value;
}
$arr["~{$key}"] = $value;
}
$array = $arr;
}
/**
* Check if PayPal prepayment is available
*
* @param Order $order
* @throws Main\ArgumentException
* @throws Main\NotSupportedException
*/
protected function usePrepayment(Order $order)
{
global $APPLICATION;
$arResult =& $this->arResult;
$prePayablePs = [];
$personTypes = array_keys(PersonType::load($this->getSiteId()));
if (!empty($personTypes))
{
$paySysActionIterator = PaySystem\Manager::getList([
'select' => [
'ID', 'PAY_SYSTEM_ID', 'PERSON_TYPE_ID', 'NAME', 'ACTION_FILE', 'RESULT_FILE',
'NEW_WINDOW', 'PARAMS', 'ENCODING', 'LOGOTIP',
],
'filter' => [
'ACTIVE' => 'Y',
'HAVE_PREPAY' => 'Y',
],
]);
$helper = Main\Application::getConnection()->getSqlHelper();
while ($paySysAction = $paySysActionIterator->fetch())
{
$dbRestriction = Sale\Internals\ServiceRestrictionTable::getList([
'select' => ['PARAMS'],
'filter' => [
'SERVICE_ID' => $paySysAction['ID'],
'CLASS_NAME' => $helper->forSql('\\'.Sale\Services\PaySystem\Restrictions\PersonType::class),
'SERVICE_TYPE' => Sale\Services\PaySystem\Restrictions\Manager::SERVICE_TYPE_PAYMENT,
],
]);
if ($restriction = $dbRestriction->fetch())
{
if (array_intersect($personTypes, $restriction['PARAMS']['PERSON_TYPE_ID']))
{
$prePayablePs = $paySysAction;
break;
}
}
else
{
$prePayablePs = $paySysAction;
break;
}
}
if ($prePayablePs)
{
$arResult['PREPAY_PS'] = $prePayablePs;
$arResult['HAVE_PREPAYMENT'] = true;
$this->prePaymentService = new PaySystem\Service($prePayablePs);
if ($this->prePaymentService->isPrePayable())
{
$this->prePaymentService->initPrePayment(null, $this->request);
if ($this->request->get('paypal') == 'Y' && $this->request->get('token'))
{
$arResult['PREPAY_ORDER_PROPS'] = $this->prePaymentService->getPrePaymentProps();
if (intval($this->arUserResult['PAY_SYSTEM_ID']) <= 0)
{
$this->arUserResult['PERSON_TYPE_ID'] = $arResult['PREPAY_PS']['PERSON_TYPE_ID'];
}
$this->arUserResult['PREPAYMENT_MODE'] = true;
$this->arUserResult['PAY_SYSTEM_ID'] = $arResult['PREPAY_PS']['ID'];
}
else
{
if ($this->arUserResult['PAY_SYSTEM_ID'] == $arResult['PREPAY_PS']['ID'])
{
$basketItems = [];
/** @var Sale\BasketItem $item */
foreach ($this->getBasketStorage()->getBasket() as $key => $item)
{
if ($item->canBuy() && !$item->isDelay())
{
$basketItems[$key]['NAME'] = $item->getField('NAME');
$basketItems[$key]['PRICE'] = $item->getPrice();
$basketItems[$key]['QUANTITY'] = $item->getQuantity();
}
}
$orderData = [
'PATH_TO_ORDER' => $APPLICATION->GetCurPage(),
'AMOUNT' => $order->getPrice(),
'ORDER_REQUEST' => 'Y',
'BASKET_ITEMS' => $basketItems,
];
$arResult['REDIRECT_URL'] = $this->prePaymentService->basketButtonAction($orderData);
if ($arResult['REDIRECT_URL'] != '')
{
$arResult['NEED_REDIRECT'] = 'Y';
}
}
}
$this->prePaymentService->setTemplateMode(PaySystem\BaseServiceHandler::STRING);
$this->prePaymentService->setTemplateParams([
'TOKEN' => $this->request->get('token'),
'PAYER_ID' => $this->request->get('PayerID'),
]);
$r = $this->prePaymentService->showTemplate(null, 'prepay_hidden_fields');
$arResult['PREPAY_ADIT_FIELDS'] = $r->getTemplate();
}
}
}
}
protected function prepayOrder()
{
if ($this->prePaymentService && $this->prePaymentService->isPrePayable() && $this->request->get('paypal') == 'Y')
{
/** @var Payment $payment */
$payment = $this->getExternalPayment($this->order);
if ($payment)
{
$this->prePaymentService->setOrderDataForPrePayment(
[
'ORDER_ID' => $this->order->getId(),
'PAYMENT_ID' => $payment->getId(),
'ORDER_PRICE' => $payment->getSum(),
'DELIVERY_PRICE' => $this->order->getDeliveryPrice(),
'TAX_PRICE' => $this->order->getTaxPrice(),
]
);
$orderData = [];
/** @var Sale\BasketItem $item */
foreach ($this->order->getBasket() as $item)
$orderData['BASKET_ITEMS'][] = $item->getFieldValues();
$this->prePaymentService->payOrderByPrePayment($orderData);
}
}
}
/**
* Initialization of person types. Set person type data to $this->arResult.
* Return true if person type changed.
* Execution of 'OnSaleComponentOrderOneStepPersonType' event
*
* @param Order $order
* @return bool
* @throws Main\ArgumentException
*/
protected function initPersonType(Order $order)
{
$arResult =& $this->arResult;
$personTypeId = intval($this->arUserResult['PERSON_TYPE_ID']);
$personTypeIdOld = intval($this->arUserResult['PERSON_TYPE_OLD']);
$personTypes = PersonType::load($this->getSiteId());
foreach ($personTypes as $personType)
{
if ($personTypeId === intval($personType["ID"]) || !array_key_exists($personTypeId, $personTypes))
{
$personTypeId = intval($personType["ID"]);
$order->setPersonTypeId($personTypeId);
$this->arUserResult['PERSON_TYPE_ID'] = $personTypeId;
$personType["CHECKED"] = "Y";
}
$arResult["PERSON_TYPE"][$personType["ID"]] = $personType;
}
if ($personTypeId == 0)
$this->addError(Loc::getMessage("SOA_ERROR_PERSON_TYPE"), self::REGION_BLOCK);
$this->executeEvent('OnSaleComponentOrderOneStepPersonType', $order);
return count($arResult["PERSON_TYPE"]) > 1 && ($personTypeId !== $personTypeIdOld);
}
/**
* Initialization of user profiles. Set user profiles data to $this->arResult.
*
* @param Order $order
* @param $isPersonTypeChanged
*/
protected function initUserProfiles(Order $order, $isPersonTypeChanged)
{
$arResult =& $this->arResult;
$justAuthorized = $this->request->get('do_authorize') === 'Y' || $this->request->get('do_register') === 'Y';
$profileIsNotSelected = $this->arUserResult['PROFILE_CHANGE'] === false || $this->arUserResult['PROFILE_ID'] === false;
$bFirst = false;
$dbUserProfiles = CSaleOrderUserProps::GetList(
['DATE_UPDATE' => 'DESC'],
[
'PERSON_TYPE_ID' => $order->getPersonTypeId(),
'USER_ID' => $order->getUserId(),
]
);
while ($arUserProfiles = $dbUserProfiles->GetNext())
{
if (!$bFirst && ($profileIsNotSelected || $isPersonTypeChanged || $justAuthorized))
{
$bFirst = true;
$this->arUserResult['PROFILE_ID'] = (int)$arUserProfiles['ID'];
}
if ((int)$this->arUserResult['PROFILE_ID'] === (int)$arUserProfiles['ID'])
{
$arUserProfiles['CHECKED'] = 'Y';
}
$arResult['ORDER_PROP']['USER_PROFILES'][$arUserProfiles['ID']] = $arUserProfiles;
}
}
public function getCurrentShipment(Order $order)
{
/** @var Shipment $shipment */
foreach ($order->getShipmentCollection() as $shipment)
{
if (!$shipment->isSystem())
return $shipment;
}
return null;
}
protected function getDeliveryIds(Order $order)
{
$deliveryIds = [];
/** @var Shipment $shipment */
foreach ($order->getShipmentCollection() as $shipment)
{
if (!$shipment->isSystem())
{
$deliveryIds[] = $shipment->getDeliveryId();
}
}
return $deliveryIds;
}
/**
* Initialization of shipment object with first/selected delivery service.
*
* @param Shipment $shipment
* @throws Main\NotSupportedException
*/
protected function initDelivery(Shipment $shipment)
{
$deliveryId = intval($this->arUserResult['DELIVERY_ID']);
$this->arDeliveryServiceAll = Delivery\Services\Manager::getRestrictedObjectsList($shipment);
/** @var Sale\ShipmentCollection $shipmentCollection */
$shipmentCollection = $shipment->getCollection();
$order = $shipmentCollection->getOrder();
if (!empty($this->arDeliveryServiceAll))
{
if (isset($this->arDeliveryServiceAll[$deliveryId]))
{
$deliveryObj = $this->arDeliveryServiceAll[$deliveryId];
}
else
{
$deliveryObj = reset($this->arDeliveryServiceAll);
if (!empty($deliveryId))
{
$this->addWarning(Loc::getMessage("DELIVERY_CHANGE_WARNING"), self::DELIVERY_BLOCK);
}
$deliveryId = $deliveryObj->getId();
}
if ($deliveryObj->isProfile())
{
$name = $deliveryObj->getNameWithParent();
}
else
{
$name = $deliveryObj->getName();
}
$order->isStartField();
$shipment->setFields([
'DELIVERY_ID' => $deliveryId,
'DELIVERY_NAME' => $name,
'CURRENCY' => $order->getCurrency(),
]);
$this->arUserResult['DELIVERY_ID'] = $deliveryId;
$deliveryStoreList = Delivery\ExtraServices\Manager::getStoresList($deliveryId);
if (!empty($deliveryStoreList))
{
if ($this->arUserResult['BUYER_STORE'] <= 0 || !in_array($this->arUserResult['BUYER_STORE'], $deliveryStoreList))
{
$this->arUserResult['BUYER_STORE'] = current($deliveryStoreList);
}
$shipment->setStoreId($this->arUserResult['BUYER_STORE']);
}
$deliveryExtraServices = $this->arUserResult['DELIVERY_EXTRA_SERVICES'];
if (is_array($deliveryExtraServices) && !empty($deliveryExtraServices[$deliveryId]))
{
$shipment->setExtraServices($deliveryExtraServices[$deliveryId]);
$deliveryObj->getExtraServices()->setValues($deliveryExtraServices[$deliveryId]);
}
$shipmentCollection->calculateDelivery();
$order->doFinalAction(true);
}
else
{
$service = Delivery\Services\Manager::getById(Delivery\Services\EmptyDeliveryService::getEmptyDeliveryServiceId());
$shipment->setFields([
'DELIVERY_ID' => $service['ID'],
'DELIVERY_NAME' => $service['NAME'],
'CURRENCY' => $order->getCurrency(),
]);
}
}
protected function loadUserAccount(Order $order)
{
if (!isset($this->arResult["USER_ACCOUNT"]))
{
$dbUserAccount = CSaleUserAccount::GetList(
[],
[
"USER_ID" => $order->getUserId(),
"CURRENCY" => $order->getCurrency(),
]
);
$this->arResult["USER_ACCOUNT"] = $dbUserAccount->Fetch();
}
}
/**
* Set user budget data to $this->arResult. Returns sum to spend(including restrictions).
*
* @param Order $order
* @param bool $recalculate
* @return array
* @throws Main\ObjectNotFoundException
*/
protected function getInnerPaySystemInfo(Order $order, $recalculate = false)
{
$arResult =& $this->arResult;
$sumToSpend = 0;
$arPaySystemServices = [];
if ($this->arParams['PAY_FROM_ACCOUNT'] === 'Y' && $order->isAllowPay())
{
$innerPaySystemId = PaySystem\Manager::getInnerPaySystemId();
$innerPayment = $order->getPaymentCollection()->getInnerPayment();
if (!$innerPayment)
{
$innerPayment = $order->getPaymentCollection()->createInnerPayment();
}
if (!$innerPayment)
{
return [0, $arPaySystemServices];
}
$this->loadUserAccount($order);
$userBudget = (float)$arResult['USER_ACCOUNT']['CURRENT_BUDGET'];
// finding correct inner pay system price ranges to setField()
$sumRange = Sale\Services\PaySystem\Restrictions\Manager::getPriceRange($innerPayment, $innerPaySystemId);
if (!empty($sumRange))
{
if (
(empty($sumRange['MIN']) || $sumRange['MIN'] <= $userBudget)
&& (empty($sumRange['MAX']) || $sumRange['MAX'] >= $userBudget)
)
{
$sumToSpend = $userBudget;
}
if (!empty($sumRange['MAX']) && $sumRange['MAX'] <= $userBudget)
{
$sumToSpend = $sumRange['MAX'];
}
}
else
{
$sumToSpend = $userBudget;
}
$sumToSpend = $sumToSpend >= $order->getPrice() ? $order->getPrice() : $sumToSpend;
if ($this->arParams['ONLY_FULL_PAY_FROM_ACCOUNT'] === 'Y' && $sumToSpend < $order->getPrice())
{
$sumToSpend = 0;
}
if (!empty($arResult['USER_ACCOUNT']) && $sumToSpend > 0)
{
// setting inner payment price
$innerPayment->setField('SUM', $sumToSpend);
// getting allowed pay systems by restrictions
$arPaySystemServices = PaySystem\Manager::getListWithRestrictions($innerPayment);
// delete inner pay system if restrictions has not passed
if (!isset($arPaySystemServices[$innerPaySystemId]))
{
$innerPayment->delete();
$sumToSpend = 0;
}
}
else
{
$innerPayment->delete();
}
}
if ($sumToSpend > 0)
{
$arResult['PAY_FROM_ACCOUNT'] = 'Y';
$arResult['CURRENT_BUDGET_FORMATED'] = SaleFormatCurrency($arResult['USER_ACCOUNT']['CURRENT_BUDGET'], $order->getCurrency());
}
else
{
$arResult['PAY_FROM_ACCOUNT'] = 'N';
unset($arResult['CURRENT_BUDGET_FORMATED']);
}
return [$sumToSpend, $arPaySystemServices];
}
public function getInnerPayment(Order $order)
{
/** @var Payment $payment */
foreach ($order->getPaymentCollection() as $payment)
{
if ($payment->getPaymentSystemId() == PaySystem\Manager::getInnerPaySystemId())
return $payment;
}
return null;
}
public function getExternalPayment(Order $order)
{
/** @var Payment $payment */
foreach ($order->getPaymentCollection() as $payment)
{
if ($payment->getPaymentSystemId() != PaySystem\Manager::getInnerPaySystemId())
return $payment;
}
return null;
}
protected function showOnlyPrepaymentPs($paySystemId)
{
if (empty($this->arPaySystemServiceAll) || intval($paySystemId) == 0)
return;
foreach ($this->arPaySystemServiceAll as $key => $psService)
{
if ($paySystemId != $psService['ID'])
{
unset($this->arPaySystemServiceAll[$key]);
unset($this->arActivePaySystems[$key]);
}
}
}
/**
* Initialization of inner/external payment objects with first/selected pay system services.
*
* @param Order $order
* @throws Main\ObjectNotFoundException
*/
protected function initPayment(Order $order)
{
[$sumToSpend, $innerPaySystemList] = $this->getInnerPaySystemInfo($order);
if ($sumToSpend > 0)
{
$innerPayment = $this->getInnerPayment($order);
if (!empty($innerPayment))
{
if ($this->arUserResult['PAY_CURRENT_ACCOUNT'] === 'Y')
{
$innerPayment->setField('SUM', $sumToSpend);
}
else
{
$innerPayment->delete();
$innerPayment = null;
}
$this->arPaySystemServiceAll = $this->arActivePaySystems = $innerPaySystemList;
}
}
$innerPaySystemId = PaySystem\Manager::getInnerPaySystemId();
$extPaySystemId = (int)$this->arUserResult['PAY_SYSTEM_ID'];
$paymentCollection = $order->getPaymentCollection();
$remainingSum = $order->getPrice() - $paymentCollection->getSum();
if ($remainingSum > 0 || $order->getPrice() == 0)
{
/** @var Payment $extPayment */
$extPayment = $paymentCollection->createItem();
$extPayment->setField('SUM', $remainingSum);
$extPaySystemList = PaySystem\Manager::getListWithRestrictions($extPayment);
// we already checked restrictions for inner pay system (could be different by price restrictions)
if (empty($innerPaySystemList[$innerPaySystemId]))
{
unset($extPaySystemList[$innerPaySystemId]);
}
elseif (empty($extPaySystemList[$innerPaySystemId]))
{
$extPaySystemList[$innerPaySystemId] = $innerPaySystemList[$innerPaySystemId];
}
$this->arPaySystemServiceAll = $this->arActivePaySystems = $extPaySystemList;
if ($extPaySystemId !== 0 && array_key_exists($extPaySystemId, $this->arPaySystemServiceAll))
{
$selectedPaySystem = $this->arPaySystemServiceAll[$extPaySystemId];
}
else
{
reset($this->arPaySystemServiceAll);
if (key($this->arPaySystemServiceAll) == $innerPaySystemId)
{
if (count($this->arPaySystemServiceAll) > 1)
{
next($this->arPaySystemServiceAll);
}
elseif ($sumToSpend > 0)
{
$extPayment->delete();
$extPayment = null;
/** @var Payment $innerPayment */
$innerPayment = $this->getInnerPayment($order);
if (empty($innerPayment))
{
$innerPayment = $paymentCollection->getInnerPayment();
if (!$innerPayment)
{
$innerPayment = $paymentCollection->createInnerPayment();
}
}
$sumToPay = $remainingSum > $sumToSpend ? $sumToSpend : $remainingSum;
$innerPayment->setField('SUM', $sumToPay);
}
else
{
unset($this->arActivePaySystems[$innerPaySystemId]);
unset($this->arPaySystemServiceAll[$innerPaySystemId]);
}
}
$selectedPaySystem = current($this->arPaySystemServiceAll);
if (!empty($selectedPaySystem) && $extPaySystemId != 0)
{
$this->addWarning(Loc::getMessage('PAY_SYSTEM_CHANGE_WARNING'), self::PAY_SYSTEM_BLOCK);
}
}
if (!empty($selectedPaySystem))
{
if ($selectedPaySystem['ID'] != $innerPaySystemId)
{
$extPayment->setFields([
'PAY_SYSTEM_ID' => $selectedPaySystem['ID'],
'PAY_SYSTEM_NAME' => $selectedPaySystem['NAME'],
]);
$this->arUserResult['PAY_SYSTEM_ID'] = $selectedPaySystem['ID'];
}
}
elseif (!empty($extPayment))
{
$extPayment->delete();
$extPayment = null;
}
}
if (empty($this->arPaySystemServiceAll))
{
$this->addError(Loc::getMessage('SOA_ERROR_PAY_SYSTEM'), self::PAY_SYSTEM_BLOCK);
}
if (!empty($this->arUserResult['PREPAYMENT_MODE']))
{
$this->showOnlyPrepaymentPs($this->arUserResult['PAY_SYSTEM_ID']);
}
}
/**
* Recalculates payment prices which could change due to shipment/discounts.
*
* @param Order $order
* @throws Main\ObjectNotFoundException
*/
protected function recalculatePayment(Order $order)
{
$res = $order->getShipmentCollection()->calculateDelivery();
if (!$res->isSuccess())
{
$shipment = $this->getCurrentShipment($order);
if (!empty($shipment))
{
$errMessages = '';
$errors = $res->getErrorMessages();
if (!empty($errors))
{
foreach ($errors as $message)
{
$errMessages .= $message.'<br />';
}
}
else
{
$errMessages = Loc::getMessage('SOA_DELIVERY_CALCULATE_ERROR');
}
$r = new Result();
$r->addError(new Sale\ResultWarning(
$errMessages,
'SALE_DELIVERY_CALCULATE_ERROR'
));
Sale\EntityMarker::addMarker($order, $shipment, $r);
$shipment->setField('MARKED', 'Y');
}
}
[$sumToSpend, $innerPaySystemList] = $this->getInnerPaySystemInfo($order, true);
$innerPayment = $this->getInnerPayment($order);
if (!empty($innerPayment))
{
if ($this->arUserResult['PAY_CURRENT_ACCOUNT'] === 'Y' && $sumToSpend > 0)
{
$innerPayment->setField('SUM', $sumToSpend);
}
else
{
$innerPayment->delete();
$innerPayment = null;
}
if ($sumToSpend > 0)
{
$this->arPaySystemServiceAll = $innerPaySystemList;
$this->arActivePaySystems += $innerPaySystemList;
}
}
/** @var Payment $innerPayment */
$innerPayment = $this->getInnerPayment($order);
/** @var Payment $extPayment */
$extPayment = $this->getExternalPayment($order);
$remainingSum = empty($innerPayment) ? $order->getPrice() : $order->getPrice() - $innerPayment->getSum();
if ($remainingSum > 0 || $order->getPrice() == 0)
{
$paymentCollection = $order->getPaymentCollection();
$innerPaySystemId = PaySystem\Manager::getInnerPaySystemId();
$extPaySystemId = (int)$this->arUserResult['PAY_SYSTEM_ID'];
if (empty($extPayment))
{
$extPayment = $paymentCollection->createItem();
}
$extPayment->setField('SUM', $remainingSum);
$extPaySystemList = PaySystem\Manager::getListWithRestrictions($extPayment);
// we already checked restrictions for inner pay system (could be different by price restrictions)
if (empty($innerPaySystemList[$innerPaySystemId]))
{
unset($extPaySystemList[$innerPaySystemId]);
}
elseif (empty($extPaySystemList[$innerPaySystemId]))
{
$extPaySystemList[$innerPaySystemId] = $innerPaySystemList[$innerPaySystemId];
}
$this->arPaySystemServiceAll = $extPaySystemList;
$this->arActivePaySystems += $extPaySystemList;
if ($extPaySystemId !== 0 && array_key_exists($extPaySystemId, $this->arPaySystemServiceAll))
{
$selectedPaySystem = $this->arPaySystemServiceAll[$extPaySystemId];
}
else
{
reset($this->arPaySystemServiceAll);
if (key($this->arPaySystemServiceAll) == $innerPaySystemId)
{
if (count($this->arPaySystemServiceAll) > 1)
{
next($this->arPaySystemServiceAll);
}
elseif ($sumToSpend > 0)
{
$extPayment->delete();
$extPayment = null;
/** @var Payment $innerPayment */
$innerPayment = $this->getInnerPayment($order);
if (empty($innerPayment))
{
$innerPayment = $paymentCollection->getInnerPayment();
if (!$innerPayment)
{
$innerPayment = $paymentCollection->createInnerPayment();
}
}
$sumToPay = $remainingSum > $sumToSpend ? $sumToSpend : $remainingSum;
$innerPayment->setField('SUM', $sumToPay);
if ($order->getPrice() - $paymentCollection->getSum() > 0)
{
$this->addWarning(Loc::getMessage('INNER_PAYMENT_BALANCE_ERROR'), self::PAY_SYSTEM_BLOCK);
$r = new Result();
$r->addError(new Sale\ResultWarning(
Loc::getMessage('INNER_PAYMENT_BALANCE_ERROR'),
'SALE_INNER_PAYMENT_BALANCE_ERROR'
));
Sale\EntityMarker::addMarker($order, $innerPayment, $r);
$innerPayment->setField('MARKED', 'Y');
}
}
else
{
unset($this->arActivePaySystems[$innerPaySystemId]);
unset($this->arPaySystemServiceAll[$innerPaySystemId]);
}
}
$selectedPaySystem = current($this->arPaySystemServiceAll);
if (!empty($selectedPaySystem) && $extPaySystemId != 0)
{
$this->addWarning(Loc::getMessage('PAY_SYSTEM_CHANGE_WARNING'), self::PAY_SYSTEM_BLOCK);
}
}
if (!array_key_exists((int)$selectedPaySystem['ID'], $this->arPaySystemServiceAll))
{
$this->addError(Loc::getMessage('P2D_CALCULATE_ERROR'), self::PAY_SYSTEM_BLOCK);
$this->addError(Loc::getMessage('P2D_CALCULATE_ERROR'), self::DELIVERY_BLOCK);
}
if (!empty($selectedPaySystem))
{
if ($selectedPaySystem['ID'] != $innerPaySystemId)
{
$codSum = 0;
$service = PaySystem\Manager::getObjectById($selectedPaySystem['ID']);
if ($service !== null)
{
$codSum = $service->getPaymentPrice($extPayment);
}
$extPayment->setFields([
'PAY_SYSTEM_ID' => $selectedPaySystem['ID'],
'PAY_SYSTEM_NAME' => $selectedPaySystem['NAME'],
'PRICE_COD' => $codSum,
]);
$this->arUserResult['PAY_SYSTEM_ID'] = $selectedPaySystem['ID'];
}
}
elseif (!empty($extPayment))
{
$extPayment->delete();
$extPayment = null;
}
if (!empty($this->arUserResult['PREPAYMENT_MODE']))
{
$this->showOnlyPrepaymentPs($this->arUserResult['PAY_SYSTEM_ID']);
}
}
if (!empty($innerPayment) && !empty($extPayment) && $remainingSum == 0)
{
$extPayment->delete();
$extPayment = null;
}
}
/**
* Calculates all available deliveries for order object.
* Uses cloned order not to harm real order.
* Execution of 'OnSaleComponentOrderDeliveriesCalculated' event
*
* @param Order $order
* @throws Main\NotSupportedException
*/
protected function calculateDeliveries(Order $order)
{
$this->arResult['DELIVERY'] = [];
$problemDeliveries = [];
if (!empty($this->arDeliveryServiceAll))
{
/** @var Order $orderClone */
$orderClone = null;
$anotherDeliveryCalculated = false;
/** @var Shipment $shipment */
$shipment = $this->getCurrentShipment($order);
foreach ($this->arDeliveryServiceAll as $deliveryId => $deliveryObj)
{
$calcResult = false;
$calcOrder = false;
$arDelivery = [];
if ((int)$shipment->getDeliveryId() === $deliveryId)
{
$arDelivery['CHECKED'] = 'Y';
$mustBeCalculated = true;
$calcResult = $deliveryObj->calculate($shipment);
$calcOrder = $order;
}
else
{
$mustBeCalculated = $this->arParams['DELIVERY_NO_AJAX'] === 'Y'
|| ($this->arParams['DELIVERY_NO_AJAX'] === 'H' && $deliveryObj->isCalculatePriceImmediately());
if ($mustBeCalculated)
{
$anotherDeliveryCalculated = true;
if (empty($orderClone))
{
$orderClone = $this->getOrderClone($order);
}
$orderClone->isStartField();
$clonedShipment = $this->getCurrentShipment($orderClone);
$clonedShipment->setField('DELIVERY_ID', $deliveryId);
$calculationResult = $orderClone->getShipmentCollection()->calculateDelivery();
if ($calculationResult->isSuccess())
{
$calcDeliveries = $calculationResult->get('CALCULATED_DELIVERIES');
$calcResult = reset($calcDeliveries);
}
else
{
$calcResult = new Delivery\CalculationResult();
$calcResult->addErrors($calculationResult->getErrors());
}
$orderClone->doFinalAction(true);
$calcOrder = $orderClone;
}
}
if ($mustBeCalculated)
{
if ($calcResult->isSuccess())
{
$arDelivery['PRICE'] = Sale\PriceMaths::roundPrecision($calcResult->getPrice());
$arDelivery['PRICE_FORMATED'] = SaleFormatCurrency($arDelivery['PRICE'], $calcOrder->getCurrency());
$currentCalcDeliveryPrice = Sale\PriceMaths::roundPrecision($calcOrder->getDeliveryPrice());
if ($currentCalcDeliveryPrice >= 0 && $arDelivery['PRICE'] != $currentCalcDeliveryPrice)
{
$arDelivery['DELIVERY_DISCOUNT_PRICE'] = $currentCalcDeliveryPrice;
$arDelivery['DELIVERY_DISCOUNT_PRICE_FORMATED'] = SaleFormatCurrency($arDelivery['DELIVERY_DISCOUNT_PRICE'], $calcOrder->getCurrency());
}
if ($calcResult->getPeriodDescription() <> '')
{
$arDelivery['PERIOD_TEXT'] = $calcResult->getPeriodDescription();
}
}
else
{
if (count($calcResult->getErrorMessages()) > 0)
{
foreach ($calcResult->getErrorMessages() as $message)
{
$arDelivery['CALCULATE_ERRORS'] .= $message.'<br>';
}
}
else
{
$arDelivery['CALCULATE_ERRORS'] = Loc::getMessage('SOA_DELIVERY_CALCULATE_ERROR');
}
if ($arDelivery['CHECKED'] !== 'Y')
{
if ($this->arParams['SHOW_NOT_CALCULATED_DELIVERIES'] === 'N')
{
unset($this->arDeliveryServiceAll[$deliveryId]);
continue;
}
elseif ($this->arParams['SHOW_NOT_CALCULATED_DELIVERIES'] === 'L')
{
$problemDeliveries[$deliveryId] = $arDelivery;
continue;
}
}
}
$arDelivery['CALCULATE_DESCRIPTION'] = $calcResult->getDescription();
}
$this->arResult['DELIVERY'][$deliveryId] = $arDelivery;
}
// for discounts: last delivery calculation need to be on real order with selected delivery
if ($anotherDeliveryCalculated)
{
$order->doFinalAction(true);
}
}
if (!empty($problemDeliveries))
{
$this->arResult['DELIVERY'] += $problemDeliveries;
}
$eventParameters = [
$order, &$this->arUserResult, $this->request,
&$this->arParams, &$this->arResult, &$this->arDeliveryServiceAll, &$this->arPaySystemServiceAll,
];
foreach (GetModuleEvents('sale', 'OnSaleComponentOrderDeliveriesCalculated', true) as $arEvent)
{
ExecuteModuleEventEx($arEvent, $eventParameters);
}
}
/**
* @param Order $order
*
* @return Order
*/
protected function getOrderClone(Order $order)
{
/** @var Order $orderClone */
$orderClone = $order->createClone();
$clonedShipment = $this->getCurrentShipment($orderClone);
if (!empty($clonedShipment))
{
$clonedShipment->setField('CUSTOM_PRICE_DELIVERY', 'N');
}
return $orderClone;
}
/**
* Set specific order fields and user description.
*
* @param Order $order
* @throws Main\ObjectNotFoundException
*/
protected function initOrderFields(Order $order)
{
$order->setField("USER_DESCRIPTION", $this->arUserResult['ORDER_DESCRIPTION']);
$order->setField('COMPANY_ID', Company\Manager::getAvailableCompanyIdByEntity($order));
if ($order->getField('COMPANY_ID') > 0)
{
$responsibleGroups = Sale\Internals\CompanyResponsibleGroupTable::getCompanyGroups($order->getField('COMPANY_ID'));
if (!empty($responsibleGroups) && is_array($responsibleGroups))
{
$usersList = [];
foreach ($responsibleGroups as $groupId)
{
$usersList[] = CGroup::GetGroupUser($groupId);
}
$usersList = array_merge(...$usersList);
if (!empty($usersList) && is_array($usersList))
{
$usersList = array_unique($usersList);
$responsibleUserId = $usersList[array_rand($usersList)];
/** @var Main\Entity\Event $event */
$event = new Main\Event('sale', 'OnSaleComponentBeforeOrderSetResponsibleUserId', [
'ENTITY' => $order,
'VALUE' => $responsibleUserId,
]);
$event->send();
if ($event->getResults())
{
$result = new Result();
/** @var Main\EventResult $eventResult */
foreach ($event->getResults() as $eventResult)
{
if ($eventResult->getType() == Main\EventResult::SUCCESS)
{
if ($eventResultData = $eventResult->getParameters())
{
if (isset($eventResultData['VALUE']) && $eventResultData['VALUE'] != $responsibleUserId)
{
$responsibleUserId = $eventResultData['VALUE'];
}
}
}
}
}
$order->setField('RESPONSIBLE_ID', $responsibleUserId);
}
}
}
}
/**
* Ajax action - recalculate order and send JSON answer with data/errors
*/
protected function refreshOrderAjaxAction()
{
global $USER;
$error = false;
$this->request->set($this->request->get('order'));
if ($this->checkSession)
{
$this->order = $this->createOrder($USER->GetID() ? $USER->GetID() : CSaleUser::GetAnonymousUserID());
$this->prepareResultArray();
self::scaleImages($this->arResult['JS_DATA'], $this->arParams['SERVICES_IMAGES_SCALING']);
}
else
$error = Loc::getMessage('SESSID_ERROR');
$this->showAjaxAnswer([
'order' => $this->arResult['JS_DATA'],
'locations' => $this->arResult['LOCATIONS'],
'error' => $error,
]);
}
/**
* Returns true if basket quantity list is equal to basket "before refresh" state
*
* @param Order $order
* @return bool
*/
protected function checkOrderConsistency(Order $order)
{
return $this->getActualQuantityList($order->getBasket()) === $this->arUserResult['QUANTITY_LIST'];
}
/**
* Ajax action - attempt to save order and send JSON answer with data/errors
*/
protected function saveOrderAjaxAction()
{
global $USER;
$arOrderRes = [];
if ($this->checkSession)
{
$this->isOrderConfirmed = true;
$needToRegister = !$USER->IsAuthorized() && $this->arParams["ALLOW_AUTO_REGISTER"] == "Y";
$saveToSession = false;
if ($needToRegister)
{
[$userId, $saveToSession] = $this->autoRegisterUser();
}
else
{
$userId = $USER->GetID() ? $USER->GetID() : CSaleUser::GetAnonymousUserID();
}
$this->order = $this->createOrder($userId);
$isActiveUser = intval($userId) > 0 && $userId != CSaleUser::GetAnonymousUserID();
if ($isActiveUser && empty($this->arResult['ERROR']))
{
if (!$this->checkOrderConsistency($this->order))
{
$r = new Result();
$r->addError(new Sale\ResultWarning(
Loc::getMessage('ORDER_CONSISTENCY_CHANGED'),
'SALE_ORDER_CONSISTENCY_CHANGED_ERROR'
));
Sale\EntityMarker::addMarker($this->order, $this->order, $r);
$this->order->setField('MARKED', 'Y');
}
$this->saveOrder($saveToSession);
}
if (empty($this->arResult["ERROR"]))
{
$arOrderRes["REDIRECT_URL"] = $this->arParams["~CURRENT_PAGE"]."?ORDER_ID=".urlencode($this->arResult["ACCOUNT_NUMBER"]);
$arOrderRes["ID"] = $this->arResult["ACCOUNT_NUMBER"];
}
else
{
$arOrderRes['ERROR'] = $this->arResult['ERROR_SORTED'];
}
}
else
{
$arOrderRes["ERROR"]['MAIN'] = Loc::getMessage('SESSID_ERROR');
}
$this->showAjaxAnswer(['order' => $arOrderRes]);
}
/**
* Ajax action - add coupon and if needed recalculate order with JSON answer
*/
protected function enterCouponAction()
{
$coupon = trim($this->request->get('coupon'));
if (!empty($coupon))
{
if (DiscountCouponsManager::add($coupon))
{
$this->refreshOrderAjaxAction();
}
else
{
$this->showAjaxAnswer($coupon);
}
}
}
/**
* Ajax action - remove coupon and if needed recalculate order with JSON answer
*/
protected function removeCouponAction()
{
$coupon = htmlspecialchars_decode(trim($this->request->get('coupon')));
if (!empty($coupon))
{
$active = $this->isActiveCoupon($coupon);
DiscountCouponsManager::delete($coupon);
if ($active)
{
$this->refreshOrderAjaxAction();
}
else
{
$this->showAjaxAnswer($coupon);
}
}
}
/**
* Execution of 'OnSaleComponentOrderShowAjaxAnswer' event
*
* @param $result
*/
protected function showAjaxAnswer($result)
{
global $APPLICATION;
foreach (GetModuleEvents("sale", 'OnSaleComponentOrderShowAjaxAnswer', true) as $arEvent)
ExecuteModuleEventEx($arEvent, [&$result]);
$APPLICATION->RestartBuffer();
if ($this->request->get('save') != 'Y')
header('Content-Type: application/json');
echo Json::encode($result);
CMain::FinalActions();
die();
}
public static function compareProperties($a, $b)
{
$sortA = intval($a['SORT']);
$sortB = intval($b['SORT']);
if ($sortA == $sortB)
return 0;
return ($sortA < $sortB) ? -1 : 1;
}
/**
* Resize image depending on scale type
*
* @param array $item
* @param $imageKey
* @param array $arImage
* @param array $sizeAdaptive
* @param array $sizeStandard
* @param string $scale
*/
public static function resizeImage(array &$item, $imageKey, array $arImage, array $sizeAdaptive, array $sizeStandard, $scale = '')
{
if ($scale == '')
{
$scale = 'adaptive';
}
if ($scale === 'no_scale')
{
$item[$imageKey.'_SRC'] = $arImage['SRC'];
$item[$imageKey.'_SRC_ORIGINAL'] = $arImage['SRC'];
}
elseif ($scale === 'adaptive')
{
$arFileTmp = CFile::ResizeImageGet(
$arImage,
['width' => $sizeAdaptive['width'] / 2, 'height' => $sizeAdaptive['height'] / 2],
BX_RESIZE_IMAGE_PROPORTIONAL,
true
);
$item[$imageKey.'_SRC'] = $arFileTmp['src'];
$arFileTmp = CFile::ResizeImageGet(
$arImage,
$sizeAdaptive,
BX_RESIZE_IMAGE_PROPORTIONAL,
true
);
$item[$imageKey.'_SRC_2X'] = $arFileTmp['src'];
$item[$imageKey.'_SRC_ORIGINAL'] = $arImage['SRC'];
}
else
{
$arFileTmp = CFile::ResizeImageGet($arImage, $sizeStandard, BX_RESIZE_IMAGE_PROPORTIONAL, true);
$item[$imageKey.'_SRC'] = $arFileTmp['src'];
$item[$imageKey.'_SRC_ORIGINAL'] = $arImage['SRC'];
}
}
/**
* Obtain all order data to $this->arResult['JS_DATA'] for template js initialization
* Execution of 'OnSaleComponentOrderJsData' event
*
* @throws Main\ObjectNotFoundException
*/
protected function getJsDataResult()
{
global $USER;
$arResult =& $this->arResult;
$result =& $this->arResult['JS_DATA'];
$result['IS_AUTHORIZED'] = $USER->IsAuthorized();
$result['LAST_ORDER_DATA'] = [];
if (
($this->request->getRequestMethod() === 'GET' || $this->request->get('do_authorize') === 'Y' || $this->request->get('do_register') === 'Y')
&& $this->arUserResult['USE_PRELOAD']
&& $result['IS_AUTHORIZED']
)
{
$lastOrder =& $this->arUserResult['LAST_ORDER_DATA'];
if (!empty($lastOrder))
{
$status = false;
if (!empty($lastOrder['PERSON_TYPE_ID']))
{
$status = $this->order->getPersonTypeId() == $lastOrder['PERSON_TYPE_ID'];
}
$result['LAST_ORDER_DATA']['PERSON_TYPE'] = $status;
$status = false;
if (!empty($lastOrder['DELIVERY_ID']) && $shipment = $this->getCurrentShipment($this->order))
{
if (empty($lastOrder['DELIVERY_EXTRA_SERVICES'][$lastOrder['DELIVERY_ID']]))
{
$status = $shipment->getDeliveryId() == $lastOrder['DELIVERY_ID'];
}
}
$result['LAST_ORDER_DATA']['DELIVERY'] = $status;
$status = false;
if (empty($lastOrder['PAY_CURRENT_ACCOUNT']) && !empty($lastOrder['PAY_SYSTEM_ID']) && $payment = $this->getExternalPayment($this->order))
{
$status = $payment->getPaymentSystemId() == $lastOrder['PAY_SYSTEM_ID'];
}
$result['LAST_ORDER_DATA']['PAY_SYSTEM'] = $status;
$status = false;
if (!empty($lastOrder['BUYER_STORE']) && $shipment = $this->getCurrentShipment($this->order))
{
$status = $shipment->getStoreId() == $lastOrder['BUYER_STORE'];
}
$result['LAST_ORDER_DATA']['PICK_UP'] = $status;
}
else
{
// last order data cannot initialize
$result['LAST_ORDER_DATA']['FAIL'] = true;
}
}
else
{
// last order data not initialized
$result['LAST_ORDER_DATA']['FAIL'] = false;
}
$result['ZIP_PROPERTY_CHANGED'] = $this->arUserResult['ZIP_PROPERTY_CHANGED'];
$result['ORDER_DESCRIPTION'] = $this->arUserResult['ORDER_DESCRIPTION'];
$result['SHOW_AUTH'] = !$USER->IsAuthorized() && $this->arParams['ALLOW_AUTO_REGISTER'] === 'N';
$result['SHOW_EMPTY_BASKET'] = $arResult['SHOW_EMPTY_BASKET'];
$result['AUTH'] = $arResult['AUTH'];
$result['SMS_AUTH'] = $arResult['SMS_AUTH'];
$result['OK_MESSAGE'] = $arResult['OK_MESSAGE'];
$result['GRID'] = $arResult['GRID'];
$result['PERSON_TYPE'] = $arResult["PERSON_TYPE"];
$result['PAY_SYSTEM'] = $arResult["PAY_SYSTEM"];
$result['INNER_PAY_SYSTEM'] = $arResult["INNER_PAY_SYSTEM"];
$result['DELIVERY'] = $arResult["DELIVERY"];
foreach ($result['DELIVERY'] as &$delivery)
{
if (!empty($delivery['EXTRA_SERVICES']))
{
$arExtraService = [];
/** @var Delivery\ExtraServices\Base $extraService */
foreach ($delivery['EXTRA_SERVICES'] as $extraServiceId => $extraService)
{
if ($extraService->canUserEditValue())
{
$arr = [];
$arr['id'] = $extraServiceId;
$arr['name'] = $extraService->getName();
$arr['value'] = $extraService->getValue();
$arr['price'] = $extraService->getPriceShipment($this->getCurrentShipment($this->order));
$arr['priceFormatted'] = SaleFormatCurrency($extraService->getPriceShipment($this->getCurrentShipment($this->order)), $this->order->getCurrency());
$arr['description'] = $extraService->getDescription();
$arr['canUserEditValue'] = $extraService->canUserEditValue();
$arr['editControl'] = $extraService->getEditControl('DELIVERY_EXTRA_SERVICES['.$delivery['ID'].']['.$extraServiceId.']');
$arr['viewControl'] = $extraService->getViewControl();
$arExtraService[] = $arr;
}
}
$delivery['EXTRA_SERVICES'] = $arExtraService;
}
}
$result["USER_PROFILES"] = $arResult["ORDER_PROP"]['USER_PROFILES'];
$arr = $this->order->getPropertyCollection()->getArray();
foreach ($arr['properties'] as $key => $property)
{
if ($property['UTIL'] === 'Y')
{
unset($arr['properties'][$key]);
}
}
if (!empty($arr['groups']) && !empty($arr['properties']))
{
$arr['groups'] = array_values($arr['groups']);
$arr['properties'] = array_values($arr['properties']);
$groupIndexList = [];
foreach ($arr['groups'] as $groupData)
{
$groupIndexList[] = (int)$groupData['ID'];
}
if (!empty($groupIndexList))
{
foreach ($arr['properties'] as $index => $propertyData)
{
if (array_key_exists('PROPS_GROUP_ID', $propertyData))
{
if (!in_array($propertyData['PROPS_GROUP_ID'], $groupIndexList))
{
$arr['properties'][$index]['PROPS_GROUP_ID'] = 0;
}
}
if ($propertyData['TYPE'] === 'ENUM' && is_array($propertyData['OPTIONS']))
{
$arr['properties'][$index]['OPTIONS_SORT'] = array_keys($propertyData['OPTIONS']);
}
}
}
}
$result["ORDER_PROP"] = $arr;
$result['STORE_LIST'] = $arResult['STORE_LIST'];
$result['BUYER_STORE'] = $arResult['BUYER_STORE'];
$result['COUPON_LIST'] = [];
$arCoupons = DiscountCouponsManager::get(true, [], true, true);
if (!empty($arCoupons))
{
foreach ($arCoupons as &$oneCoupon)
{
if ($oneCoupon['STATUS'] == DiscountCouponsManager::STATUS_NOT_FOUND || $oneCoupon['STATUS'] == DiscountCouponsManager::STATUS_FREEZE)
{
$oneCoupon['JS_STATUS'] = 'BAD';
}
elseif ($oneCoupon['STATUS'] == DiscountCouponsManager::STATUS_NOT_APPLYED || $oneCoupon['STATUS'] == DiscountCouponsManager::STATUS_ENTERED)
{
$oneCoupon['JS_STATUS'] = 'ENTERED';
}
else
{
$oneCoupon['JS_STATUS'] = 'APPLIED';
}
$oneCoupon['JS_CHECK_CODE'] = '';
if (isset($oneCoupon['CHECK_CODE_TEXT']))
{
$oneCoupon['JS_CHECK_CODE'] = is_array($oneCoupon['CHECK_CODE_TEXT'])
? implode(', ', $oneCoupon['CHECK_CODE_TEXT'])
: $oneCoupon['CHECK_CODE_TEXT'];
}
$result['COUPON_LIST'][] = $oneCoupon;
}
unset($oneCoupon);
$result['COUPON_LIST'] = array_values($arCoupons);
}
unset($arCoupons);
$result['PAY_CURRENT_ACCOUNT'] = 'N';
if ($innerPaySystem = $this->order->getPaymentCollection()->getInnerPayment())
{
if ($innerPaySystem->getSum() > 0)
{
$result['PAY_CURRENT_ACCOUNT'] = 'Y';
}
}
$result['PAY_FROM_ACCOUNT'] = $arResult["PAY_FROM_ACCOUNT"];
$result['CURRENT_BUDGET_FORMATED'] = $arResult["CURRENT_BUDGET_FORMATED"];
$result['TOTAL'] = [
'PRICE_WITHOUT_DISCOUNT_VALUE' => $arResult["PRICE_WITHOUT_DISCOUNT_VALUE"],
'PRICE_WITHOUT_DISCOUNT' => $arResult["PRICE_WITHOUT_DISCOUNT"],
'PAYED_FROM_ACCOUNT_FORMATED' => $arResult["PAYED_FROM_ACCOUNT_FORMATED"],
'ORDER_TOTAL_PRICE' => $arResult["ORDER_TOTAL_PRICE"],
'ORDER_TOTAL_PRICE_FORMATED' => $arResult["ORDER_TOTAL_PRICE_FORMATED"],
'ORDER_TOTAL_LEFT_TO_PAY' => $arResult["ORDER_TOTAL_LEFT_TO_PAY"],
'ORDER_TOTAL_LEFT_TO_PAY_FORMATED' => $arResult["ORDER_TOTAL_LEFT_TO_PAY_FORMATED"],
'ORDER_WEIGHT' => $arResult["ORDER_WEIGHT"],
'ORDER_WEIGHT_FORMATED' => $arResult["ORDER_WEIGHT_FORMATED"],
'ORDER_PRICE' => $arResult["ORDER_PRICE"],
'ORDER_PRICE_FORMATED' => $arResult["ORDER_PRICE_FORMATED"],
'USE_VAT' => $arResult["USE_VAT"],
'VAT_RATE' => $arResult["VAT_RATE"],
'VAT_SUM' => $arResult["VAT_SUM"],
'VAT_SUM_FORMATED' => $arResult["VAT_SUM_FORMATED"],
'TAX_PRICE' => $arResult["TAX_PRICE"],
'TAX_LIST' => $arResult["TAX_LIST"],
'DISCOUNT_PRICE' => $arResult["DISCOUNT_PRICE"],
'DISCOUNT_PRICE_FORMATED' => $arResult["DISCOUNT_PRICE_FORMATED"],
'DELIVERY_PRICE' => $arResult["DELIVERY_PRICE"],
'DELIVERY_PRICE_FORMATED' => $arResult["DELIVERY_PRICE_FORMATED"],
'PAY_SYSTEM_PRICE' => $arResult["PAY_SYSTEM_PRICE"],
'PAY_SYSTEM_PRICE_FORMATTED' => $arResult["PAY_SYSTEM_PRICE_FORMATTED"],
];
$result['ERROR'] = $arResult["ERROR_SORTED"];
$result['WARNING'] = $arResult["WARNING"];
$arResult['LOCATIONS'] = $this->getLocationsResult();
foreach (GetModuleEvents("sale", 'OnSaleComponentOrderJsData', true) as $arEvent)
{
ExecuteModuleEventEx($arEvent, [&$this->arResult, &$this->arParams]);
}
}
/**
* Scales images of all entities depending on scale parameters
*
* @param $result
* @param string $scale
*/
public static function scaleImages(&$result, $scale = '')
{
if (!empty($result) && is_array($result))
{
if (!empty($result['DELIVERY']) && is_array($result['DELIVERY']))
{
foreach ($result['DELIVERY'] as $key => $delivery)
{
if (!empty($delivery["LOGOTIP"]))
{
self::resizeImage($delivery, 'LOGOTIP', $delivery["LOGOTIP"],
["width" => 600, "height" => 600],
["width" => 95, "height" => 55],
$scale
);
$result["DELIVERY"][$key] = $delivery;
}
}
unset($logotype, $delivery);
}
if (!empty($result['PAY_SYSTEM']) && is_array($result['PAY_SYSTEM']))
{
foreach ($result['PAY_SYSTEM'] as $key => $paySystem)
{
if (!empty($paySystem["PSA_LOGOTIP"]))
{
self::resizeImage($paySystem, 'PSA_LOGOTIP', $paySystem["PSA_LOGOTIP"],
["width" => 600, "height" => 600],
["width" => 95, "height" => 55],
$scale
);
$result["PAY_SYSTEM"][$key] = $paySystem;
}
}
unset($logotype, $paySystem);
}
if (!empty($result['INNER_PAY_SYSTEM']) && is_array($result['INNER_PAY_SYSTEM']) && !empty($result['INNER_PAY_SYSTEM']["LOGOTIP"]))
{
self::resizeImage($result['INNER_PAY_SYSTEM'], 'LOGOTIP', $result['INNER_PAY_SYSTEM']["LOGOTIP"],
["width" => 600, "height" => 600],
["width" => 95, "height" => 55],
$scale
);
}
if (!empty($result['STORE_LIST']) && is_array($result['STORE_LIST']))
{
foreach ($result['STORE_LIST'] as $key => $store)
{
if (!empty($store["IMAGE_ID"]))
{
self::resizeImage($store, 'IMAGE_ID', $store["IMAGE_ID"],
["width" => 320, "height" => 320],
["width" => 115, "height" => 115],
$scale
);
$result["STORE_LIST"][$key] = $store;
}
}
unset($logotype, $store);
}
}
}
/**
* Returns array with locations data output
*
* @return array
*/
protected function getLocationsResult()
{
$locations = [];
$propertyCollection = $this->order->getPropertyCollection();
$properties = $propertyCollection->getArray();
foreach ($properties['properties'] as $property)
{
if ($property['UTIL'] == 'Y')
continue;
if ($property['TYPE'] == 'LOCATION')
{
$locationTemplateP = $this->arParams['TEMPLATE_LOCATION'] == '.default' ? 'steps' : 'search';
$locationTemplate = $this->request->get('PERMANENT_MODE_STEPS') == 1 ? 'steps' : $locationTemplateP;
$locations[$property['ID']]['template'] = $locationTemplate;
$locations[$property['ID']]['output'] = $this->getLocationHtml($property, $locationTemplate);
$locations[$property['ID']]['showAlt'] = isset($this->arUserResult['ORDER_PROP'][$property['INPUT_FIELD_LOCATION']]);
$locations[$property['ID']]['lastValue'] = reset($property['VALUE']);
if ($property['IS_LOCATION'] === 'Y')
{
$locations[$property['ID']]['coordinates'] = LocationTable::getRow([
'select' => ['LONGITUDE', 'LATITUDE'],
'filter' => ['=CODE' => reset($property['VALUE'])],
]);
}
}
}
return $locations;
}
protected function getLocationHtml($property, $locationTemplate)
{
global $APPLICATION;
$locationOutput = [];
$showDefault = true;
$propertyId = (int)$property['ID'];
$isMultiple = $property['MULTIPLE'] == 'Y' && $property['IS_LOCATION'] != 'Y';
$locationAltPropDisplayManual = $this->request->get('LOCATION_ALT_PROP_DISPLAY_MANUAL');
$altPropManual = isset($locationAltPropDisplayManual[$propertyId]) && (bool)$locationAltPropDisplayManual[$propertyId];
$location = $this->order->getPropertyCollection()->getItemByOrderPropertyId($propertyId);
$actualValues = $location->getValue();
if (!is_array($actualValues))
{
$actualValues = [$actualValues];
}
if (!empty($actualValues) && is_array($actualValues))
{
foreach ($actualValues as $key => $value)
{
$parameters = [
'CODE' => $value,
'INPUT_NAME' => 'ORDER_PROP_'.$propertyId.($isMultiple ? '['.$key.']' : ''),
'CACHE_TYPE' => 'A',
'CACHE_TIME' => '36000000',
'SEARCH_BY_PRIMARY' => 'N',
'SHOW_DEFAULT_LOCATIONS' => $showDefault ? 'Y' : 'N',
'PROVIDE_LINK_BY' => 'code',
'JS_CALLBACK' => 'submitFormProxy',
'JS_CONTROL_DEFERRED_INIT' => $propertyId.($isMultiple ? '_'.$key : ''),
'JS_CONTROL_GLOBAL_ID' => $propertyId.($isMultiple ? '_'.$key : ''),
'DISABLE_KEYBOARD_INPUT' => 'Y',
'PRECACHE_LAST_LEVEL' => 'N',
'PRESELECT_TREE_TRUNK' => 'Y',
'SUPPRESS_ERRORS' => 'Y',
'FILTER_BY_SITE' => 'Y',
'FILTER_SITE_ID' => $this->getSiteId(),
];
ob_start();
if ($locationTemplate == 'steps')
{
echo '<input type="hidden" id="LOCATION_ALT_PROP_DISPLAY_MANUAL['.$propertyId
.']" name="LOCATION_ALT_PROP_DISPLAY_MANUAL['.$propertyId.']" value="'
.($altPropManual ? '1' : '0').'" />';
}
$APPLICATION->IncludeComponent(
'bitrix:sale.location.selector.'.$locationTemplate,
'',
$parameters,
null,
['HIDE_ICONS' => 'Y']
);
$locationOutput[] = ob_get_contents();
ob_end_clean();
$showDefault = false;
}
}
if ($isMultiple)
{
$parameters = [
'CODE' => '',
'INPUT_NAME' => 'ORDER_PROP_'.$propertyId.'[#key#]',
'CACHE_TYPE' => 'A',
'CACHE_TIME' => '36000000',
'SEARCH_BY_PRIMARY' => 'N',
'SHOW_DEFAULT_LOCATIONS' => 'N',
'PROVIDE_LINK_BY' => 'code',
'JS_CALLBACK' => 'submitFormProxy',
'JS_CONTROL_DEFERRED_INIT' => $propertyId.'_key__',
'JS_CONTROL_GLOBAL_ID' => $propertyId.'_key__',
'DISABLE_KEYBOARD_INPUT' => 'Y',
'PRECACHE_LAST_LEVEL' => 'N',
'PRESELECT_TREE_TRUNK' => 'Y',
'SUPPRESS_ERRORS' => 'Y',
'FILTER_BY_SITE' => 'Y',
'FILTER_SITE_ID' => $this->getSiteId(),
];
ob_start();
$APPLICATION->IncludeComponent(
'bitrix:sale.location.selector.'.$locationTemplate,
'',
$parameters,
null,
['HIDE_ICONS' => 'Y']
);
$locationOutput['clean'] = ob_get_contents();
ob_end_clean();
}
return $locationOutput;
}
protected function isActiveCoupon($coupon)
{
$arCoupons = DiscountCouponsManager::get(true, ['COUPON' => $coupon], true, true);
if (!empty($arCoupons))
{
$arCoupon = array_shift($arCoupons);
if ($arCoupon['STATUS'] == DiscountCouponsManager::STATUS_NOT_APPLYED)
return true;
}
return false;
}
/**
* Prepares $this->arResult
* Execution of 'OnSaleComponentOrderOneStepProcess' event
*/
protected function prepareResultArray()
{
$this->initGrid();
$this->obtainBasket();
$this->obtainPropertiesForIbElements();
if ($this->arParams['COMPATIBLE_MODE'] == 'Y')
{
$this->obtainFormattedProperties();
}
$this->obtainDelivery();
$this->obtainPaySystem();
$this->obtainTaxes();
$this->obtainTotal();
if ($this->arParams['USER_CONSENT'] === 'Y')
{
$this->obtainUserConsentInfo();
}
$this->getJsDataResult();
if ($this->arParams['COMPATIBLE_MODE'] == 'Y')
{
$this->obtainRelatedProperties();
$this->makeResultCompatible();
$this->makeOrderDataArray();
}
$this->arResult['USER_VALS'] = $this->arUserResult;
$this->executeEvent('OnSaleComponentOrderOneStepProcess', $this->order);
$this->arResult['USER_VALS'] = $this->arUserResult;
//try to avoid use "executeEvent" methods and use new events like this
foreach (GetModuleEvents("sale", 'OnSaleComponentOrderResultPrepared', true) as $arEvent)
ExecuteModuleEventEx($arEvent, [$this->order, &$this->arUserResult, $this->request, &$this->arParams, &$this->arResult]);
}
/**
* Create $this->arUserResult array and fill with data from request
* Execution of 'OnSaleComponentOrderUserResult' event
*/
protected function makeUserResultArray()
{
$request =& $this->request;
$arUserResult = [
"PERSON_TYPE_ID" => false,
"PERSON_TYPE_OLD" => false,
"PAY_SYSTEM_ID" => false,
"DELIVERY_ID" => false,
"ORDER_PROP" => [],
"DELIVERY_LOCATION" => false,
"TAX_LOCATION" => false,
"PAYER_NAME" => false,
"USER_EMAIL" => false,
"PROFILE_NAME" => false,
"PAY_CURRENT_ACCOUNT" => false,
"CONFIRM_ORDER" => false,
"FINAL_STEP" => false,
"ORDER_DESCRIPTION" => false,
"PROFILE_ID" => false,
"PROFILE_CHANGE" => false,
"DELIVERY_LOCATION_ZIP" => false,
"ZIP_PROPERTY_CHANGED" => 'N',
"QUANTITY_LIST" => [],
"USE_PRELOAD" => $this->arParams['USE_PRELOAD'] === 'Y',
];
if ($request->isPost())
{
if (intval($request->get('PERSON_TYPE')) > 0)
$arUserResult["PERSON_TYPE_ID"] = intval($request->get('PERSON_TYPE'));
if (intval($request->get('PERSON_TYPE_OLD')) > 0)
$arUserResult["PERSON_TYPE_OLD"] = intval($request->get('PERSON_TYPE_OLD'));
if (empty($arUserResult["PERSON_TYPE_OLD"]) || $arUserResult["PERSON_TYPE_OLD"] == $arUserResult["PERSON_TYPE_ID"])
{
$profileId = $request->get('PROFILE_ID');
if ($profileId !== null)
{
$arUserResult['PROFILE_ID'] = (int)$profileId;
}
$paySystemId = $request->get('PAY_SYSTEM_ID');
if (!empty($paySystemId))
$arUserResult["PAY_SYSTEM_ID"] = intval($paySystemId);
$deliveryId = $request->get('DELIVERY_ID');
if (!empty($deliveryId))
$arUserResult["DELIVERY_ID"] = $deliveryId;
$buyerStore = $request->get('BUYER_STORE');
if (!empty($buyerStore))
$arUserResult["BUYER_STORE"] = intval($buyerStore);
$deliveryExtraServices = $request->get('DELIVERY_EXTRA_SERVICES');
if (!empty($deliveryExtraServices))
$arUserResult["DELIVERY_EXTRA_SERVICES"] = $deliveryExtraServices;
if ($request->get('ORDER_DESCRIPTION') <> '')
{
$arUserResult["~ORDER_DESCRIPTION"] = $request->get('ORDER_DESCRIPTION');
$arUserResult["ORDER_DESCRIPTION"] = htmlspecialcharsbx($request->get('ORDER_DESCRIPTION'));
}
if ($request->get('PAY_CURRENT_ACCOUNT') == "Y")
$arUserResult["PAY_CURRENT_ACCOUNT"] = "Y";
if ($request->get('confirmorder') == "Y")
{
$arUserResult["CONFIRM_ORDER"] = "Y";
$arUserResult["FINAL_STEP"] = "Y";
}
$arUserResult["PROFILE_CHANGE"] = $request->get('profile_change') == "Y" ? "Y" : "N";
}
$arUserResult['ZIP_PROPERTY_CHANGED'] = $this->request->get('ZIP_PROPERTY_CHANGED') === 'Y' ? 'Y' : 'N';
}
foreach (GetModuleEvents("sale", 'OnSaleComponentOrderUserResult', true) as $arEvent)
ExecuteModuleEventEx($arEvent, [&$arUserResult, $this->request, &$this->arParams]);
$this->arUserResult = $arUserResult;
}
/**
* Wrapper for event execution method.
* Synchronizes modified data from event if needed.
*
* @param string $eventName
* @param null $order
* @deprecated
* Compatibility method for old events.
* Use new events like "OnSaleComponentOrderCreated" and "OnSaleComponentOrderResultPrepared" instead.
*
*/
protected function executeEvent($eventName = '', $order = null)
{
$arModifiedResult = $this->arUserResult;
foreach (GetModuleEvents("sale", $eventName, true) as $arEvent)
ExecuteModuleEventEx($arEvent, [&$this->arResult, &$arModifiedResult, &$this->arParams, true]);
if (!empty($order))
$this->synchronize($arModifiedResult, $order);
}
protected function synchronize($arModifiedResult, Order $order)
{
$modifiedFields = self::arrayDiffRecursive($arModifiedResult, $this->arUserResult);
if (!empty($modifiedFields))
$this->synchronizeOrder($modifiedFields, $order);
}
/**
* Synchronization of modified fields with current order object.
*
* @param $modifiedFields
* @param Order $order
* @throws Main\NotSupportedException
* @throws Main\ObjectNotFoundException
*/
protected function synchronizeOrder($modifiedFields, Order $order)
{
if (!empty($modifiedFields) && is_array($modifiedFields))
{
$recalculatePayment = $modifiedFields['CALCULATE_PAYMENT'] === true;
unset($modifiedFields['CALCULATE_PAYMENT']);
$recalculateDelivery = false;
if (!empty($modifiedFields['PERSON_TYPE_ID']))
{
$order->setPersonTypeId($modifiedFields['PERSON_TYPE_ID']);
}
$propertyCollection = $order->getPropertyCollection();
foreach ($modifiedFields as $field => $value)
{
switch ($field)
{
case 'PAY_SYSTEM_ID':
$recalculatePayment = true;
break;
case 'PAY_CURRENT_ACCOUNT':
$recalculatePayment = true;
break;
case 'DELIVERY_ID':
$recalculateDelivery = true;
break;
case 'ORDER_PROP':
if (is_array($value))
{
/** @var Sale\PropertyValue $property */
foreach ($propertyCollection as $property)
{
if (array_key_exists($property->getPropertyId(), $value))
{
$property->setValue($value[$property->getPropertyId()]);
$arProperty = $property->getProperty();
if ($arProperty['IS_LOCATION'] === 'Y' || $arProperty['IS_ZIP'] === 'Y')
{
$recalculateDelivery = true;
}
}
}
}
break;
case 'ORDER_DESCRIPTION':
$order->setField('USER_DESCRIPTION', $value);
break;
case 'DELIVERY_LOCATION':
$codeValue = CSaleLocation::getLocationCODEbyID($value);
if ($property = $propertyCollection->getDeliveryLocation())
{
$property->setValue($codeValue);
$this->arUserResult['ORDER_PROP'][$property->getPropertyId()] = $codeValue;
}
$recalculateDelivery = true;
break;
case 'DELIVERY_LOCATION_BCODE':
if ($property = $propertyCollection->getDeliveryLocation())
{
$property->setValue($value);
$this->arUserResult['ORDER_PROP'][$property->getPropertyId()] = $value;
}
$recalculateDelivery = true;
break;
case 'DELIVERY_LOCATION_ZIP':
if ($property = $propertyCollection->getDeliveryLocationZip())
{
$property->setValue($value);
$this->arUserResult['ORDER_PROP'][$property->getPropertyId()] = $value;
}
$recalculateDelivery = true;
break;
case 'TAX_LOCATION':
$codeValue = CSaleLocation::getLocationCODEbyID($value);
if ($property = $propertyCollection->getTaxLocation())
{
$property->setValue($codeValue);
$this->arUserResult['ORDER_PROP'][$property->getPropertyId()] = $codeValue;
}
break;
case 'TAX_LOCATION_BCODE':
if ($property = $propertyCollection->getTaxLocation())
{
$property->setValue($value);
$this->arUserResult['ORDER_PROP'][$property->getPropertyId()] = $value;
}
break;
case 'PAYER_NAME':
if ($property = $propertyCollection->getPayerName())
{
$property->setValue($value);
$this->arUserResult['ORDER_PROP'][$property->getPropertyId()] = $value;
}
break;
case 'USER_EMAIL':
if ($property = $propertyCollection->getUserEmail())
{
$property->setValue($value);
$this->arUserResult['ORDER_PROP'][$property->getPropertyId()] = $value;
}
break;
case 'PROFILE_NAME':
if ($property = $propertyCollection->getProfileName())
{
$property->setValue($value);
$this->arUserResult['ORDER_PROP'][$property->getPropertyId()] = $value;
}
break;
}
$this->arUserResult[$field] = $value;
}
if ($recalculateDelivery)
{
if ($shipment = $this->getCurrentShipment($order))
{
$this->initDelivery($shipment);
$recalculatePayment = true;
}
}
if ($recalculatePayment)
{
$this->recalculatePayment($order);
}
}
}
public static function arrayDiffRecursive($arr1, $arr2)
{
$modified = [];
foreach ($arr1 as $key => $value)
{
if (array_key_exists($key, $arr2))
{
if (is_array($value) && is_array($arr2[$key]))
{
$arDiff = self::arrayDiffRecursive($value, $arr2[$key]);
if (!empty($arDiff))
{
$modified[$key] = $arDiff;
}
}
elseif ($value != $arr2[$key])
{
$modified[$key] = $value;
}
}
else
{
$modified[$key] = $value;
}
}
return $modified;
}
protected function makeOrderDataArray()
{
$orderData = $this->order->getFieldValues();
$orderData['ORDER_PRICE'] = $this->arResult['ORDER_PRICE'];
$orderData['ORDER_WEIGHT'] = $this->arResult['ORDER_WEIGHT'];
$orderData['WEIGHT_UNIT'] = $this->arResult['WEIGHT_UNIT'];
$orderData['WEIGHT_KOEF'] = $this->arResult['WEIGHT_KOEF'];
$orderData['SITE_ID'] = $this->getSiteId();
$orderData['USE_VAT'] = $this->arResult["USE_VAT"];
$orderData['VAT_RATE'] = $this->arResult["VAT_RATE"];
$orderData['VAT_SUM'] = $this->arResult["VAT_SUM"];
$this->arResult['ORDER_DATA'] = array_merge($orderData, $this->arUserResult);
}
protected function saveProfileData()
{
$arResult =& $this->arResult;
$profileId = 0;
$profileName = '';
$properties = [];
if (isset($arResult['ORDER_PROP']) && is_array($arResult['ORDER_PROP']['USER_PROFILES']))
{
foreach ($arResult['ORDER_PROP']['USER_PROFILES'] as $profile)
{
if ($profile['CHECKED'] === 'Y')
{
$profileId = (int)$profile['ID'];
break;
}
}
}
$propertyCollection = $this->order->getPropertyCollection();
if (!empty($propertyCollection))
{
if ($profileProp = $propertyCollection->getProfileName())
$profileName = $profileProp->getValue();
/** @var Sale\PropertyValue $property */
foreach ($propertyCollection as $property)
{
$properties[$property->getField('ORDER_PROPS_ID')] = $property->getValue();
}
}
CSaleOrderUserProps::DoSaveUserProfile(
$this->order->getUserId(),
$profileId,
$profileName,
$this->order->getPersonTypeId(),
$properties,
$arResult["ERROR"]
);
}
protected function addStatistic()
{
if (Loader::includeModule("statistic"))
{
$event1 = "eStore";
$event2 = "order_confirm";
$event3 = $this->order->getId();
$money = $this->order->getPrice();
$currency = $this->order->getCurrency();
$e = $event1."/".$event2."/".$event3;
if (!is_array($_SESSION["ORDER_EVENTS"]) || (is_array($_SESSION["ORDER_EVENTS"]) && !in_array($e, $_SESSION["ORDER_EVENTS"])))
{
CStatistic::Set_Event($event1, $event2, $event3, $goto = "", $money, $currency);
$_SESSION["ORDER_EVENTS"][] = $e;
}
}
}
/**
* Initialization of shipment object. Filling with basket items.
*
* @param Order $order
* @return Shipment
* @throws Main\ArgumentTypeException
* @throws Main\NotSupportedException
*/
public function initShipment(Order $order)
{
$shipmentCollection = $order->getShipmentCollection();
$shipment = $shipmentCollection->createItem();
$shipmentItemCollection = $shipment->getShipmentItemCollection();
$shipment->setField('CURRENCY', $order->getCurrency());
/** @var Sale\BasketItem $item */
foreach ($order->getBasket() as $item)
{
/** @var Sale\ShipmentItem $shipmentItem */
$shipmentItem = $shipmentItemCollection->createItem($item);
$shipmentItem->setQuantity($item->getQuantity());
}
return $shipment;
}
/**
* Initializes user data and creates order.
* Checks for event flags for possible order/payments recalculations.
* Execution of 'OnSaleComponentOrderOneStepDiscountBefore' event.
*
* @param $userId
* @return Order
*/
protected function createOrder($userId)
{
$this->makeUserResultArray();
DiscountCouponsManager::init(DiscountCouponsManager::MODE_CLIENT, ['userId' => $userId]);
$this->executeEvent('OnSaleComponentOrderOneStepDiscountBefore');
/** @var Order $order */
$order = $this->getOrder($userId);
// $this->arUserResult['RECREATE_ORDER'] - flag for full order recalculation after events manipulations
if ($this->arUserResult['RECREATE_ORDER'])
$order = $this->getOrder($userId);
// $this->arUserResult['CALCULATE_PAYMENT'] - flag for order payments recalculation after events manipulations
if ($this->arUserResult['CALCULATE_PAYMENT'])
$this->recalculatePayment($order);
return $order;
}
/**
* Returns created order object based on user and request data.
* Execution of 'OnSaleComponentOrderCreated' event.
*
* @param $userId
* @return Order
*/
protected function getOrder($userId)
{
$registry = Sale\Registry::getInstance(Sale\Registry::REGISTRY_TYPE_ORDER);
/** @var Order $orderClassName */
$orderClassName = $registry->getOrderClassName();
$order = $orderClassName::create($this->getSiteId(), $userId);
$order->isStartField();
$this->initLastOrderData($order);
$order->setField('STATUS_ID', Sale\OrderStatus::getInitialStatus());
if ($this->arParams['USE_PREPAYMENT'] === 'Y')
{
$this->usePrepayment($order);
}
$isPersonTypeChanged = $this->initPersonType($order);
$this->initTradeBinding($order);
$this->initProperties($order, $isPersonTypeChanged);
$this->initBasket($order);
$taxes = $order->getTax();
$taxes->setDeliveryCalculate($this->arParams['COUNT_DELIVERY_TAX'] === 'Y');
$shipment = $this->initShipment($order);
$order->doFinalAction(true);
if ($this->arParams['DELIVERY_TO_PAYSYSTEM'] === 'd2p')
{
$this->initDelivery($shipment);
$this->initPayment($order);
}
else
{
$this->initPayment($order);
$this->initDelivery($shipment);
}
$this->initEntityCompanyIds($order);
$this->initOrderFields($order);
// initialization of related properties
$this->setOrderProperties($order);
$this->recalculatePayment($order);
$eventParameters = [
$order, &$this->arUserResult, $this->request,
&$this->arParams, &$this->arResult, &$this->arDeliveryServiceAll, &$this->arPaySystemServiceAll,
];
foreach (GetModuleEvents('sale', 'OnSaleComponentOrderCreated', true) as $arEvent)
{
ExecuteModuleEventEx($arEvent, $eventParameters);
}
// no need to calculate deliveries when order is saving
if ($this->action !== 'saveOrderAjax')
{
$this->calculateDeliveries($order);
}
return $order;
}
/**
* Initializes companies for payment and shipment
*
* @param Order $order
*/
protected function initEntityCompanyIds(Order $order)
{
$paymentCollection = $order->getPaymentCollection();
if ($paymentCollection)
{
/** @var Payment $payment */
foreach ($paymentCollection as $payment)
{
if ($payment->isInner())
continue;
$payment->setField('COMPANY_ID', Company\Manager::getAvailableCompanyIdByEntity($payment));
if ($payment->getField('COMPANY_ID') > 0)
{
$responsibleGroups = Sale\Internals\CompanyResponsibleGroupTable::getCompanyGroups($payment->getField('COMPANY_ID'));
if (!empty($responsibleGroups) && is_array($responsibleGroups))
{
$usersList = [];
foreach ($responsibleGroups as $groupId)
{
$usersList[] = CGroup::GetGroupUser($groupId);
}
$usersList = array_merge(...$usersList);
if (!empty($usersList) && is_array($usersList))
{
$usersList = array_unique($usersList);
$responsibleUserId = $usersList[array_rand($usersList)];
/** @var Main\Entity\Event $event */
$event = new Main\Event('sale', 'OnSaleComponentBeforePaymentSetResponsibleUserId', [
'ENTITY' => $payment,
'VALUE' => $responsibleUserId,
]);
$event->send();
if ($event->getResults())
{
$result = new Result();
/** @var Main\EventResult $eventResult */
foreach ($event->getResults() as $eventResult)
{
if ($eventResult->getType() == Main\EventResult::SUCCESS)
{
if ($eventResultData = $eventResult->getParameters())
{
if (isset($eventResultData['VALUE']) && $eventResultData['VALUE'] != $responsibleUserId)
{
$responsibleUserId = $eventResultData['VALUE'];
}
}
}
}
}
$payment->setField('RESPONSIBLE_ID', $responsibleUserId);
}
}
}
}
}
$shipmentCollection = $order->getShipmentCollection();
if ($shipmentCollection)
{
/** @var Shipment $shipment */
foreach ($shipmentCollection as $shipment)
{
if ($shipment->isSystem())
continue;
$shipment->setField('COMPANY_ID', Company\Manager::getAvailableCompanyIdByEntity($shipment));
if ($shipment->getField('COMPANY_ID') > 0)
{
$responsibleGroups = Sale\Internals\CompanyResponsibleGroupTable::getCompanyGroups($shipment->getField('COMPANY_ID'));
if (!empty($responsibleGroups) && is_array($responsibleGroups))
{
$usersList = [];
foreach ($responsibleGroups as $groupId)
{
$usersList[] = CGroup::GetGroupUser($groupId);
}
$usersList = array_merge(...$usersList);
if (!empty($usersList) && is_array($usersList))
{
$usersList = array_unique($usersList);
$responsibleUserId = $usersList[array_rand($usersList)];
/** @var Main\Entity\Event $event */
$event = new Main\Event('sale', 'OnSaleComponentBeforeShipmentSetResponsibleUserId', [
'ENTITY' => $shipment,
'VALUE' => $responsibleUserId,
]);
$event->send();
if ($event->getResults())
{
$result = new Result();
/** @var Main\EventResult $eventResult */
foreach ($event->getResults() as $eventResult)
{
if ($eventResult->getType() == Main\EventResult::SUCCESS)
{
if ($eventResultData = $eventResult->getParameters())
{
if (isset($eventResultData['VALUE']) && $eventResultData['VALUE'] != $responsibleUserId)
{
$responsibleUserId = $eventResultData['VALUE'];
}
}
}
}
}
$shipment->setField('RESPONSIBLE_ID', $responsibleUserId);
}
}
}
}
}
}
protected function initTradeBinding(Order $order)
{
if (isset($this->arParams['CONTEXT_SITE_ID']) && $this->arParams['CONTEXT_SITE_ID'] > 0)
{
if (!Loader::includeModule('landing'))
{
return;
}
$code = \Bitrix\Sale\TradingPlatform\Landing\Landing::getCodeBySiteId($this->arParams['CONTEXT_SITE_ID']);
$platform = \Bitrix\Sale\TradingPlatform\Landing\Landing::getInstanceByCode($code);
if (!$platform->isInstalled())
{
return;
}
$collection = $order->getTradeBindingCollection();
$collection->createItem($platform);
}
}
/**
* Prepares action string to execute in doAction
*
* refreshOrderAjax/saveOrderAjax - process/save order via JSON (new template)
* enterCoupon/removeCoupon - add/delete coupons via JSON (new template)
* showAuthForm - show authorization form (old/new templates) [including component template]
* processOrder - process order (old(all hits)/new(first hit) templates) [including component template]
* showOrder - show created order (old/new templates) [including component template]
*
* @return null|string
*/
protected function prepareAction()
{
global $USER;
$action = $this->request->offsetExists($this->arParams['ACTION_VARIABLE'])
? $this->request->get($this->arParams['ACTION_VARIABLE'])
: $this->request->get('action');
if (!$USER->IsAuthorized() && $this->arParams['ALLOW_AUTO_REGISTER'] === 'N' && $action !== 'confirmSmsCode')
{
$action = 'showAuthForm';
}
if (empty($action) || !$this->actionExists($action))
{
if ($this->request->get('ORDER_ID') == '')
{
$action = 'processOrder';
}
else
{
$action = 'showOrder';
}
}
return $action;
}
/**
* Checks whether component implements selected action.
*
* @param $action
* @return bool
*/
protected function actionExists($action)
{
return is_callable([$this, $action.'Action']);
}
/**
* Executes prepared action with postfix 'Action'
*
* @param $action
*/
protected function doAction($action)
{
if ($this->actionExists($action))
{
$this->{$action.'Action'}();
}
}
protected function processOrderAction()
{
global $APPLICATION, $USER;
$arResult =& $this->arResult;
$this->isOrderConfirmed = $this->request->isPost()
&& $this->request->get("confirmorder") == 'Y'
&& $this->checkSession;
$needToRegister = !$USER->IsAuthorized() && $this->arParams["ALLOW_AUTO_REGISTER"] == "Y";
$saveToSession = false;
if ($this->isOrderConfirmed && $needToRegister)
{
[$userId, $saveToSession] = $this->autoRegisterUser();
}
else
{
$userId = $USER->GetID();
}
if (!$userId)
{
$userId = CSaleUser::GetAnonymousUserID();
}
$this->order = $this->createOrder($userId);
$this->prepareResultArray();
$isActiveUser = intval($userId) > 0 && $userId != CSaleUser::GetAnonymousUserID();
if ($this->isOrderConfirmed && $isActiveUser && empty($arResult["ERROR"]))
{
$this->saveOrder($saveToSession);
if (empty($arResult["ERROR"]))
{
$arResult["REDIRECT_URL"] = $APPLICATION->GetCurPageParam("ORDER_ID=".urlencode(urlencode($arResult["ACCOUNT_NUMBER"])), ["ORDER_ID"]);
if ($this->request['json'] == "Y" && ($this->isOrderConfirmed || $arResult["NEED_REDIRECT"] == "Y"))
{
$APPLICATION->RestartBuffer();
echo json_encode(["success" => "Y", "redirect" => $arResult["REDIRECT_URL"]]);
die();
}
}
else
{
$arResult["USER_VALS"]["CONFIRM_ORDER"] = "N";
}
}
else
{
$arResult["USER_VALS"]["CONFIRM_ORDER"] = "N";
}
}
/**
* Action - show created order and payment info
*/
protected function showOrderAction()
{
global $USER;
$arResult =& $this->arResult;
$arOrder = false;
$arResult["USER_VALS"]["CONFIRM_ORDER"] = "Y";
$orderId = urldecode($this->request->get('ORDER_ID'));
$checkedBySession = false;
$registry = Sale\Registry::getInstance(Sale\Registry::REGISTRY_TYPE_ORDER);
/** @var Order $orderClassName */
$orderClassName = $registry->getOrderClassName();
/** @var Order $order */
if ($order = $orderClassName::loadByAccountNumber($orderId))
{
$arOrder = $order->getFieldValues();
$arResult["ORDER_ID"] = $arOrder["ID"];
$arResult["ACCOUNT_NUMBER"] = $arOrder["ACCOUNT_NUMBER"];
$arOrder["IS_ALLOW_PAY"] = $order->isAllowPay() ? 'Y' : 'N';
$checkedBySession = !empty($_SESSION['SALE_ORDER_ID']) && is_array($_SESSION['SALE_ORDER_ID'])
&& in_array(intval($order->getId()), $_SESSION['SALE_ORDER_ID']);
}
if (!empty($arOrder) && ($order->getUserId() == $USER->GetID() || $checkedBySession))
{
foreach (GetModuleEvents("sale", "OnSaleComponentOrderOneStepFinal", true) as $arEvent)
ExecuteModuleEventEx($arEvent, [$arResult["ORDER_ID"], &$arOrder, &$this->arParams]);
$arResult["PAYMENT"] = [];
if ($order->isAllowPay())
{
$paymentCollection = $order->getPaymentCollection();
/** @var Payment $payment */
foreach ($paymentCollection as $payment)
{
$arResult["PAYMENT"][$payment->getId()] = $payment->getFieldValues();
if (intval($payment->getPaymentSystemId()) > 0 && !$payment->isPaid())
{
$paySystemService = PaySystem\Manager::getObjectById($payment->getPaymentSystemId());
if (!empty($paySystemService))
{
$arPaySysAction = $paySystemService->getFieldsValues();
if ($paySystemService->getField('NEW_WINDOW') === 'N' || $paySystemService->getField('ID') == PaySystem\Manager::getInnerPaySystemId())
{
/** @var PaySystem\ServiceResult $initResult */
$initResult = $paySystemService->initiatePay($payment, null, PaySystem\BaseServiceHandler::STRING);
if ($initResult->isSuccess())
$arPaySysAction['BUFFERED_OUTPUT'] = $initResult->getTemplate();
else
$arPaySysAction["ERROR"] = $initResult->getErrorMessages();
}
$arResult["PAYMENT"][$payment->getId()]['PAID'] = $payment->getField('PAID');
$arOrder['PAYMENT_ID'] = $payment->getId();
$arOrder['PAY_SYSTEM_ID'] = $payment->getPaymentSystemId();
$arPaySysAction["NAME"] = htmlspecialcharsEx($arPaySysAction["NAME"]);
$arPaySysAction["IS_AFFORD_PDF"] = $paySystemService->isAffordPdf();
if ($arPaySysAction > 0)
$arPaySysAction["LOGOTIP"] = CFile::GetFileArray($arPaySysAction["LOGOTIP"]);
if ($this->arParams['COMPATIBLE_MODE'] == 'Y' && !$payment->isInner())
{
// compatibility
\CSalePaySystemAction::InitParamArrays($order->getFieldValues(), $order->getId(), '', [], $payment->getFieldValues());
$map = CSalePaySystemAction::getOldToNewHandlersMap();
$oldHandler = array_search($arPaySysAction["ACTION_FILE"], $map);
if ($oldHandler !== false && !$paySystemService->isCustom())
$arPaySysAction["ACTION_FILE"] = $oldHandler;
if ($arPaySysAction["ACTION_FILE"] <> '' && $arPaySysAction["NEW_WINDOW"] != "Y")
{
$pathToAction = Main\Application::getDocumentRoot().$arPaySysAction["ACTION_FILE"];
$pathToAction = str_replace("\\", "/", $pathToAction);
while (mb_substr($pathToAction, mb_strlen($pathToAction) - 1, 1) == "/")
$pathToAction = mb_substr($pathToAction, 0, mb_strlen($pathToAction) - 1);
if (file_exists($pathToAction))
{
if (is_dir($pathToAction) && file_exists($pathToAction."/payment.php"))
$pathToAction .= "/payment.php";
$arPaySysAction["PATH_TO_ACTION"] = $pathToAction;
}
}
$arResult["PAY_SYSTEM"] = $arPaySysAction;
}
$arResult["PAY_SYSTEM_LIST"][$payment->getPaymentSystemId()] = $arPaySysAction;
$arResult["PAY_SYSTEM_LIST_BY_PAYMENT_ID"][$payment->getId()] = $arPaySysAction;
}
else
$arResult["PAY_SYSTEM_LIST"][$payment->getPaymentSystemId()] = ['ERROR' => true];
}
}
}
$arResult["ORDER"] = $arOrder;
}
else
$arResult["ACCOUNT_NUMBER"] = $orderId;
}
/**
* Action - saves order if there are no errors
* Execution of 'OnSaleComponentOrderOneStepComplete' event
*
* @param bool $saveToSession
*/
protected function saveOrder($saveToSession = false)
{
$arResult =& $this->arResult;
$this->initStatGid();
$this->initAffiliate();
$res = $this->order->save();
if ($res->isSuccess())
{
$arResult["ORDER_ID"] = $res->getId();
$arResult["ACCOUNT_NUMBER"] = $this->order->getField('ACCOUNT_NUMBER');
if ($this->arParams['USER_CONSENT'] === 'Y')
{
Main\UserConsent\Consent::addByContext(
$this->arParams['USER_CONSENT_ID'], 'sale/order', $arResult['ORDER_ID']
);
}
$fUserId = Sale\Fuser::getId();
$siteId = $this->getSiteId();
Sale\BasketComponentHelper::clearFUserBasketPrice($fUserId, $siteId);
Sale\BasketComponentHelper::clearFUserBasketQuantity($fUserId, $siteId);
}
else
{
$this->addError($res, 'MAIN');
}
if ($arResult['HAVE_PREPAYMENT'] && empty($arResult['ERROR']))
{
$this->prepayOrder();
}
if (empty($arResult['ERROR']))
{
$this->saveProfileData();
}
if (empty($arResult['ERROR']))
{
$this->addStatistic();
if ($saveToSession)
{
if (!is_array($_SESSION['SALE_ORDER_ID']))
{
$_SESSION['SALE_ORDER_ID'] = [];
}
$_SESSION['SALE_ORDER_ID'][] = $res->getId();
}
}
foreach (GetModuleEvents('sale', 'OnSaleComponentOrderOneStepComplete', true) as $arEvent)
{
ExecuteModuleEventEx($arEvent, [$arResult['ORDER_ID'], $this->order->getFieldValues(), $this->arParams]);
}
}
public function executeComponent()
{
global $APPLICATION;
$this->setFrameMode(false);
$this->context = Main\Application::getInstance()->getContext();
$this->checkSession = $this->arParams["DELIVERY_NO_SESSION"] == "N" || check_bitrix_sessid();
$this->isRequestViaAjax = $this->request->isPost() && $this->request->get('via_ajax') == 'Y';
$isAjaxRequest = $this->request["is_ajax_post"] == "Y";
if ($isAjaxRequest)
$APPLICATION->RestartBuffer();
$this->action = $this->prepareAction();
Sale\Compatible\DiscountCompatibility::stopUsageCompatible();
$this->doAction($this->action);
Sale\Compatible\DiscountCompatibility::revertUsageCompatible();
if (!$isAjaxRequest)
{
CJSCore::Init(['fx', 'popup', 'window', 'ajax', 'date']);
}
//is included in all cases for old template
$this->includeComponentTemplate();
if ($isAjaxRequest)
{
$APPLICATION->FinalActions();
die();
}
}
}