<?php
declare(strict_types=1);
namespace WebBundle\Service;
use Doctrine\ORM\NonUniqueResultException;
use Doctrine\ORM\NoResultException;
use Exception;
use Symfony\Component\HttpFoundation\Request;
use WebBundle\Constant\CookieKeysConstant;
use WebBundle\Dto\ShowUserLocaleDto;
use WebBundle\Entity\BuyOrder;
use WebBundle\Enum\BuyOrderStatusEnum;
use WebBundle\Helper\App;
use WebBundle\Helper\ArrHelper;
use WebBundle\Helper\CookieHelper;
use WebBundle\Helper\FilterHelper;
use WebBundle\Helper\LocaleHelper;
use WebBundle\Helper\StrHelper;
use WebBundle\Helper\UserHelper;
use WebBundle\Repository\BuyOrderRepository;
use WebBundle\Repository\ListCountryRepository;
use WebBundle\Repository\OrderAddressRepository;
/**
* Сервис для работы с локализацией
*/
class LocalizationService
{
/** @required */
public OrderService $orderService;
/** @required */
public ListCountryRepository $listCountryRepository;
/** @required */
public OrderAddressRepository $orderAddressRepository;
/** @required */
public BuyOrderRepository $buyOrderRepository;
/**
* Получение uri без локали
*/
public function getUriWithoutLocale(): string
{
$request = App::getRequest();
$localeFromUri = LocaleHelper::getLocaleFromUri($request->getRequestUri());
return str_ireplace('index.php', '', $localeFromUri->getStringWithUrlWithoutLocale());
}
/**
* Получение списка доступных локалей для выпадающего списка
* @return array
*/
public function getSelectLocales(ShowUserLocaleDto $showUserLocaleDto): array
{
$userCountryWas = $showUserLocaleDto->getUserCountryWas();
$uri = $this->getUriWithoutLocale();
$selectLocales = [];
foreach (LocaleHelper::getListAvailable() as $code => $row) {
if ($code === 'cn') {
continue;
}
if (false !== stripos($uri, 'catalogue')) {
$url = FilterHelper::getUrl(null, $code);
$url = str_replace('/' . $code . '/', '/' . $code . '-' . $userCountryWas . '/', $url);
} else {
if ($code != $userCountryWas) {
$url = '/' . $code . '-' . $userCountryWas . '/' . $uri;
} else {
$url = '/' . $code . '/' . $uri;
}
}
$url = rtrim($url, '/');
$selectLocales[$code] = [
'code' => $code,
'name' => $row['name'][$code],
'uri' => $url,
];
}
return $selectLocales;
}
public function getShowUserLocaleDto(): ShowUserLocaleDto
{
$showUserLocaleDto = new ShowUserLocaleDto();
$request = App::getRequest();
$showLocale = $request->getSession()->get('showLocale');
if ($showLocale
&& !$request->get('qr') // Запрет на показ плашки если просматривается образец по ссылке QR кода
) {
$showUserLocaleDto
->setUserLocaleWas($showLocale['lang'])
->setUserCountryWas($showLocale['country'])
->setUserCurrencyWas($showLocale['currency'])
->setUserMeasureWas($showLocale['measure'])
->setShowLocale(true);
} else {
$showUserLocaleDto
->setUserLocaleWas(App::getCurLocale())
->setUserCountryWas(App::getCurCountry())
->setUserCurrencyWas(LocaleHelper::getCur())
->setUserMeasureWas(LocaleHelper::getUserMeasure())
->setShowLocale(false);
}
$request->getSession()->remove('showLocale');
return $showUserLocaleDto;
}
public function setLocalizationAndGetUrlForRedirect(Request $request): string
{
$data = $request->get('data', []);
$localeFromUri = LocaleHelper::getLocaleFromUri($request->getRequestUri());
// установка языка
$nowLocale = $this->setLanguage($data);
// установка страны
$nowLocale = $this->setCountry($data, $nowLocale);
// установка валюты
$this->setCurrency($data);
// установка единиц измерения
$this->setMeasure($data);
// удаляем данные высвечиваемой плашки
$request->getSession()->remove('showLocale');
$request->getSession()->remove('showLocaleReact');
CookieHelper::set(CookieKeysConstant::USER_APPROVED, 'yes', ['httponly' => false]);
CookieHelper::set(CookieKeysConstant::SHOW_POPUP, 'yes', ['httponly' => false]);
$reqLastUrl = empty($_SERVER['HTTP_REFERER']) ? null : $_SERVER['HTTP_REFERER'];
// проверяем с какой страницы была смена валюты заказа
$this->checkIfThisIsOrderThenChangeCountryForDelivery($data, $reqLastUrl);
return empty($nowLocale)
? $reqLastUrl
: $request->getSchemeAndHttpHost() . '/' . $nowLocale . '/' . $localeFromUri->getStringWithUrlWithoutLocale();
}
private function setLanguage(array $data): string
{
$lang = CookieHelper::get(CookieKeysConstant::LANG, 'en');
if (!empty($data['lang'])) {
if (ArrHelper::get(LocaleHelper::getListCode(), $data['lang'])) {
$lang = $data['lang'];
}
}
CookieHelper::set(CookieKeysConstant::LANG, $lang, ['httponly' => false]);
return $lang;
}
private function setCountry(array $data, string $nowLocale): string
{
$country = CookieHelper::get(CookieKeysConstant::COUNTRY, 'us');
if (!empty($data['country'])) {
try {
$availableCountry = $this->listCountryRepository->getCountry($data['country']);
} catch (NonUniqueResultException $_) {
$availableCountry = null;
}
try {
if (null !== $availableCountry
&& array_key_exists(strtolower($availableCountry->getCode()), App::getCountryList())
) {
$country = strtolower($availableCountry->getCode());
}
} catch (Exception $_) {
}
if ($nowLocale !== $country) {
$nowLocale .= '-' . $country;
}
}
if (!empty($data['first'])) {
CookieHelper::set('first', $country);
}
CookieHelper::set(CookieKeysConstant::COUNTRY, $country, ['httponly' => false]);
return $nowLocale;
}
private function setCurrency(array $data): void
{
if (!empty($data['currency'])
&& !empty($data['country'])
&& in_array($data['currency'], LocaleHelper::getCurrencyList($data['country']))
) {
CookieHelper::set(CookieKeysConstant::CURRENCY, $data['currency'], ['httponly' => false]);
} else {
CookieHelper::set(CookieKeysConstant::CURRENCY, 'EUR', ['httponly' => false]);
}
}
private function setMeasure(array $data): void
{
$isUsaOrCanada = in_array(StrHelper::toLower($data['country'] ?? ''), ['us', 'ca']);
$measureKey = $isUsaOrCanada ? CookieKeysConstant::MEASURE_FT : CookieKeysConstant::MEASURE;
if ($isUsaOrCanada) {
if ($data['measure'] && in_array($data['measure'], LocaleHelper::getMeasureList())) {
CookieHelper::set($measureKey, $data['measure'], ['httponly' => false]);
}
} else {
CookieHelper::set(CookieKeysConstant::MEASURE, 'm', ['httponly' => false]);
}
}
private function checkIfThisIsOrderThenChangeCountryForDelivery(array $data, ?string $reqLastUrl): void
{
$orderId = $this->getOrderIdInPrevUrl($reqLastUrl);
if (empty($orderId)) {
return;
}
try {
$country = $this->listCountryRepository->getCountry($data['country']);
} catch (NonUniqueResultException $_) {
return;
}
if (empty($country)) {
return;
}
try {
$order = $this->orderService->getOrderObj($orderId);
$token = UserHelper::getInstance()->getToken();
if ($this->forbiddenChangeThisOrder($order, $token)) {
return;
}
$order->setDeliveryCountry($country);
$address = $order->getAddressRecipient();
if ($address) {
$address->setCountry($country);
}
$this->buyOrderRepository->save($order);
$this->orderAddressRepository->save($address);
} catch (NonUniqueResultException|NoResultException $_) {
// да и фиг с ним
}
}
private function getOrderIdInPrevUrl(?string $lastUrl): ?string
{
if (null === $lastUrl) {
return null;
}
if (stripos($lastUrl, '/buy-order/') === false) {
return null;
}
preg_match('#/buy-order/(\w*\d*).*$#is', $lastUrl, $matches);
return $matches[1];
}
private function forbiddenChangeThisOrder(BuyOrder $order, string $token): bool
{
if ($order->getStatus() >= BuyOrderStatusEnum::PARTIALLY_PAID) {
return true;
}
if ($order->getToken() !== $token) {
return true;
}
return false;
}
}