<?php
namespace App\Service;
use App\Config\FaqRouteEnum;
use App\Entity\Customer;
use App\Entity\Extra;
use App\Entity\ExtraType;
use App\Entity\FileData;
use App\Entity\FrontPage;
use App\Entity\HotelXmlPrice;
use App\Entity\MenuItemFront;
use App\Repository\AgencyRepository;
use App\Repository\CityRepository;
use App\Repository\CurrencyExchangerateRepository;
use App\Repository\CustomerRepository;
use App\Repository\ExtraTypeRepository;
use App\Repository\FileDataRepository;
use App\Repository\FrontPageRepository;
use App\Repository\FrontSectionRepository;
use App\Repository\FrontThemeRepository;
use App\Repository\FrontZoneRepository;
use App\Repository\HotelXmlPriceRepository;
use App\Repository\HotelXmlRepository;
use App\Repository\MenuItemFrontRepository;
use App\Repository\ProductFeeRepository;
use App\Repository\SocialNetworkRepository;
use App\Repository\HubLocationRepository;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use App\Entity\FrontSection;
use App\Repository\ExtraRepository;
class FrontService
{
public function __construct(
private readonly MenuItemFrontRepository $menuItemFrontRepository,
private readonly FileDataRepository $fileDataRepository,
private readonly Helpers $helpers,
private readonly RequestStack $requestStack,
private readonly FrontZoneRepository $frontZoneRepository,
private readonly HotelXmlPriceRepository $hotelXmlPriceRepository,
private readonly CityRepository $cityRepository,
private readonly UrlGeneratorInterface $router,
private readonly CurrencyExchangerateRepository $currencyExchangerateRepository,
private readonly ParameterService $parameterService,
private readonly FrontPageRepository $frontPageRepository,
private readonly FrontSectionRepository $frontSectionRepository,
private readonly HotelXmlRepository $hotelXmlRepository,
private readonly SocialNetworkRepository $socialNetworkRepository,
private readonly AgencyRepository $agencyRepository,
private readonly CurrencyService $currencyService,
private readonly FrontThemeRepository $frontThemeRepository,
private readonly ProductFeeRepository $productFeeRepository,
private readonly HubLocationRepository $xmlApiDefaultRepository,
private readonly CustomerRepository $customerRepository,
private readonly ExtraTypeRepository $extraTypeRepository,
private readonly FaqService $faqService,
private readonly ExtraRepository $extraRepository,
)
{
}
function getFrontMenu(): array
{
$session = $this->requestStack->getSession();
$menu_front_items = $this->menuItemFrontRepository->findBy(['active' => true], ['displayOrder' => 'ASC']);
$menu_front_items_array = $this->helpers->convert_ObjectArray_to_2DArray($menu_front_items);
foreach ($menu_front_items as $menu_front_item) {
switch ($menu_front_item->getId()) {
case str_starts_with($menu_front_item->getId(), MenuItemFront::HOTEL_CONTRY_CODE):
//if the country is null doesn't need to continue
if (is_null($menu_front_item->getCountry())) break;
$cities = $this->cityRepository->findByCriteria([
'active' => true,
'country' => $menu_front_item->getCountry()
]);
foreach ($cities as $key_city => $city) {
$path = $this->router->generate('app_front_hotel_city', ['name' => $city->getName()]);
$menu_city = [
'id' => 'HOTEL_' . strtoupper($city->getName()),
'title' => ucwords(strtolower($city->getName())),
'route' => $path,
'displayOrder' => $key_city + 1,
'externalUrl' => null,
"parent" => $menu_front_item->getId()
];
$menu_front_items_array[] = $menu_city;
}
break;
case 'SERVICES':
$typeExtras = $this->extraTypeRepository->findAll();
foreach ($typeExtras as $key_extra => $typeExtra) {
$path = $this->router->generate('app_front_extra_by_type', ['id' => $typeExtra->getId(),
'name' => $typeExtra->getName()]);
$menu_Extra = [
'id' => 'EXTRA_' . strtoupper($typeExtra->getId()),
'title' => ucwords(strtolower($typeExtra->getName())),
'route' => $path,
'displayOrder' => $key_extra + 1,
'externalUrl' => null,
"parent" => $menu_front_item->getId()
];
$menu_front_items_array[] = $menu_Extra;
}
break;
}
}
$menu_as_tree = $this->helpers->buildTree($menu_front_items_array);
if (array_key_exists('FRONT', $menu_as_tree) && array_key_exists('children', $menu_as_tree['FRONT'])) {
$session->set('menu_front', $menu_as_tree['FRONT']['children']);
}
return $menu_as_tree;
}
public function getItemHotel(HotelXmlPrice $hotelXmlPrice): array
{
$currency_session = $this->currencyService->getSessionCurrency();
$hotel = $hotelXmlPrice->getHotelXml();
$hotel_direct = $hotel->getHotel();
$hotel_direct_is_active = $hotel_direct !== null && $hotel_direct->isActive();
return [
'type' => 'hotel',
'title' => $hotel_direct_is_active ? $hotel_direct->getName() : $hotel->getName(),
'link' => $this->router->generate('hotel_detail', [
'city_label' => $hotel->getCity(),
'country_label' => $hotel->getCountry(),
'hotel_label' => $hotel->getName(),
'id' => $hotel->getCode()
]),
'image' => $hotel_direct_is_active ? $hotel_direct->getPrimaryImageUrl() : $hotel->getImageUrl(),
'city' => $hotel->getCity(),
'country' => $hotel->getCountry(),
'stars' => $hotel_direct_is_active ? $hotel_direct->getStarRating() : $hotel->getStarRating(),
'promos' => $hotel_direct_is_active ? $hotel_direct->getPromos() : [],
'badges' => $hotel_direct_is_active ? $hotel_direct->getBadges() : [],
'price' => $this->currencyService->convert($hotelXmlPrice->getPrice(), $hotelXmlPrice->getCurrency(), $currency_session),
'currency' => $currency_session,
'board' => $hotelXmlPrice->getBoard(),
'hotelsCount' => '',
'description' => $hotel_direct_is_active ? $hotel_direct->getDescription() : $hotel->getDescription(),
];
}
private function getItemCity(array $city_data): array
{
return [
'title' => $city_data['name'],
'type' => 'city',
'link' => $this->router->generate('app_front_hotel_city', [
'name' => $city_data['name']
]),
'image' => $this->getCityImage($city_data['name']),
'city' => $city_data['name'],
'badges' => [],
'country' => $city_data['country'],
'hotelsCount' => $city_data['hotelsCount'],
];
}
private function getItemTheme(array $theme_data): array
{
return [
'title' => $theme_data['name'],
'type' => 'theme',
'link' => $this->router->generate('app_front_hotel_theme', [
'name' => $theme_data['name']
]),
'image' => $this->getThemeImage($theme_data['name']),
'city' => "",
'country' => "",
'badges' => [],
'hotelsCount' => $theme_data['hotelsCount'],
'description' => $theme_data['description'],
];
}
public function getItemExtra(array $extra_data): array
{
return [
'title' => $extra_data['name'],
'subTitle' => $extra_data['subTitle'],
'type' => 'extra',
'link' => !empty($extra_data['url'])
? $extra_data['url']
: $this->router->generate(
'extra_detail', [
'extra_label' => urlencode($extra_data['name']),
'id' => $extra_data['id']
]
),
'image' => $extra_data['image'],
'city' => "",
'badges' => [],
'country' => "",
'currency' =>$extra_data['currency'],
'price' => $extra_data['price'],
'hotelsCount' => "",
];
}
private function getItemExtraType(array $extra_type_data): array
{
return [
'title' => $extra_type_data['name'],
'type' => 'extra',
'link' => $this->router->generate('app_front_extra_by_type', ['id' => $extra_type_data['id'], 'name' => urlencode($extra_type_data['name'])]),
'image' => $extra_type_data['image'],
'city' => "",
'badges' => [],
'country' => "",
'price' => "",
'hotelsCount' => "",
];
}
public function getFrontZones(): array
{
$zones_data= [];
$zones = $this->frontZoneRepository->findBy(['active' => true]);
foreach ($zones as $zone) {
if (empty($zone->getQuery())) continue;
$zoneID = $zone->getId();
$zones_data[$zoneID] = [
'view' => $zone->getHtmlFileName(), # view 1, 2, 3, 4 ...
'title' => $zone->getTitle(),
'subTitle' => $zone->getSubtitle(),
'description' => $zone->getDescription(),
'active' => $zone->isActive(),
'backgroundColor' => $zone->getbackgroundColor(),
'backgroundImage' => $zone->getBackgroundImage() ? $zone->getBackgroundImage()->getUrl() : null,
'itemsCount' => $zone->getNbElementsToDisplay(),
'query' => $zone->getQuery(),
'items' => [],
];
switch ($zone->getQuery()) {
case 'hotel' :
{
$criterias = [];
foreach ($zone->getFrontZoneParamValues() as $paramValue) {
if ($paramValue->getValue()) {
$criterias[$paramValue->getParameter()][] = $paramValue->getValue();
}
}
$hotelXmlPrices = $this->hotelXmlPriceRepository->getHotelXmlPriceByCriterias($criterias, $zone->getNbElementsToDisplay());
foreach ($hotelXmlPrices as $hotelXmlPrice) {
$zones_data[$zoneID]['items'][] = $this->getItemHotel($hotelXmlPrice);
}
break;
}
case 'cities' :
{
$cityNames = [];
$frontZoneParamValues = $zone->getFrontZoneParamValues();
foreach ($frontZoneParamValues as $frontZoneParamValue) {
$cityNames[] = $frontZoneParamValue->getValue();
}
$cities = $this->hotelXmlRepository->getCities($cityNames);
foreach ($cities as $city_data) {
$zones_data[$zoneID]['items'][] = $this->getItemCity($city_data);
}
break;
}
case 'themes':
{
$themeNames = [];
$frontZoneParamValues = $zone->getFrontZoneParamValues();
foreach ($frontZoneParamValues as $frontZoneParamValue) {
$themeNames[] = $frontZoneParamValue->getValue();
}
$themes = $this->frontThemeRepository->getSelectedFrontTheme($themeNames);
foreach ($themes as $theme) {
$hotelsCount = $this->hotelXmlRepository->getThemeCount($theme);
$theme_data = [
"name" => $theme->getName(),
"description"=>$theme->getDescription(),
"hotelsCount" => $hotelsCount
];
$zones_data[$zoneID]['items'][] = $this->getItemTheme($theme_data);
}
break;
}
case 'extras':
{
$criteria = [];
foreach ($zone->getFrontZoneParamValues() as $paramValue) {
if ($paramValue->getValue()) {
$criteria[$paramValue->getParameter()][] = $paramValue->getValue();
}
}
$extras = $this->extraRepository->findByCriteria($criteria);
/** @var Extra $extra_entity */
foreach ($extras as $extra_entity) {
$firstImage = $extra_entity->getImages()->first();
$extra_data = [
"id" => $extra_entity->getId(),
"name" => $extra_entity->getName(),
"subTitle" => $extra_entity->getSubTitle(),
"image" => $firstImage ? $firstImage->getUrl() : null,
"url" => $extra_entity->getUrl(),
"currency" => $extra_entity->getProvider()->getCurrency(),
"price" => $extra_entity->getMinPrice(),
];
$zones_data[$zoneID]['items'][] = $this->getItemExtra($extra_data);
}
break;
}
case 'extraTypes':
{
$extra_types = [];
$frontZoneParamValues = $zone->getFrontZoneParamValues();
foreach ($frontZoneParamValues as $frontZoneParamValue) {
$extra_types[] = $frontZoneParamValue->getValue();
}
$extraTypes = $this->extraTypeRepository->getSelectedFrontExtraType($extra_types);
/** @var ExtraType $extra_entity */
foreach ($extraTypes as $extraType_entity) {
$extraType_data = [
"id" => $extraType_entity->getId(),
"name" => $extraType_entity->getName(),
"image" => $extraType_entity->getImage()?->getUrl(),
];
$zones_data[$zoneID]['items'][] = $this->getItemExtraType($extraType_data);
}
break;
}
case 'section':
{
$sections = $this->getSections();
foreach ($sections as $section) {
if($section instanceof FrontSection) {
$section_data = [
"id" => $section->getId(),
"type"=>'section',
"title" => $section->getTitle(),
"content"=>$section->getContent(),
"image"=>$section->getImage()
];
$zones_data[$zoneID]['items'][] = $section_data;
}
}
break;
}
}
}
return $zones_data;
}
public function getCityImage($cityName): string
{
$city = $this->cityRepository->findOneBy(['name' => $cityName]);
if (is_null($city)) return FileData::IMAGE_NOT_AVAILABLE_PATH;
$image = $city->getImage();
return $image ? $image->getUrl() : FileData::IMAGE_NOT_AVAILABLE_PATH;
}
public function getThemeImage($themeName): string
{
$theme = $this->frontThemeRepository->findOneBy(['name' => $themeName]);
if (is_null($theme)) return FileData::IMAGE_NOT_AVAILABLE_PATH;
$image = $theme->getImage();
return $image ? $image->getUrl() : FileData::IMAGE_NOT_AVAILABLE_PATH;
}
public function getExtraImage($themeName): string
{
$extra = $this->extraTypeRepository->findOneBy(['name' => $themeName]);
if (is_null($extra)) return FileData::IMAGE_NOT_AVAILABLE_PATH;
$extra = $extra->getImage();
return $extra ? $extra->getUrl() : FileData::IMAGE_NOT_AVAILABLE_PATH;
}
public function getSliderImages($type): array
{
return $this->fileDataRepository->findBy(['type' => $type, 'active' => true]);
}
public function getSeoInfo(string $slug): array
{
$seoStaticPage = $this->frontPageRepository->findOneBy(['slug' => $slug]);
return [
'homeSeoTitle' => $seoStaticPage->getSeoTitle(),
'homeSeoDescription' => $seoStaticPage->getSeoDescription(),
'socialMedias' => $this->getSocialNetworks()
];
}
public function getSocialNetworks(): array
{
return $this->socialNetworkRepository->findBy(['active' => 'true']);
}
public function getCurrencies($fromExchangeRates = false): array
{
$currencies = [];
if ($fromExchangeRates) {
$currencies_exchanges = $this->currencyExchangerateRepository->findAll();
foreach ($currencies_exchanges as $currencies_exchange) {
$currencies[] = $currencies_exchange->getCurrencyTo();
}
} else {
$customers_default = $this->customerRepository->findBy(['isDefault' => true, 'active' => true]);
foreach ($customers_default as $customer) {
$currencies[] = $customer->getCurrency();
}
}
return array_unique($currencies);
}
public function getAgencies(): array
{
return $this->agencyRepository->findby(['isDefault' => false]);
}
public function getHomePage(): FrontPage
{
return $this->frontPageRepository->findOneBy(['slug' => FrontPage::HOME_PAGE]);
}
public function getProductFee(string $product, Customer $customer): float|int
{
$productFee = $this->productFeeRepository->findOneBy(['product' => $product]);
if ($productFee) {
$exchangeRate = $this->currencyService->calculateExchangeRate(
$this->parameterService->getReferenceCurrency(), // referenceCurrency
$customer->getCurrency()
);
if ($customer->getClass() == 'CustomerMoral') {
return $productFee->getB2bAmount() * $exchangeRate;
} else {
return $productFee->getAmount() * $exchangeRate;
}
}
return 0;
}
public function getSuggestions($cookieName, $xmlApiType): array
{
$suggestions = [];
$resultSuggestions = $this->xmlApiDefaultRepository->findBy(['productType' => $xmlApiType]);
foreach ($resultSuggestions as $resultSuggestion) {
$suggestions[] = json_decode($resultSuggestion->getDataJson());
}
return $suggestions;
}
public function getSections(): array
{
$sections = $this->frontSectionRepository->findAll();
return $sections;
}
public function getSessionCustomer(): ?Customer
{
$session = $this->requestStack->getSession();
$customer_in_session = $session->get('backend_customer');
$defaultCustomerId = $customer_in_session?->getId();
$defaultCustomer = null;
if ($defaultCustomerId) {
$defaultCustomer = $this->customerRepository->find($defaultCustomerId);
}
return $defaultCustomer;
}
public function getTrackingTools() : array
{
$twig_parameters ['META_PIXEL_ID'] = $this->parameterService->getTrackerMetaId();
$twig_parameters ['GOOGLE_ANALYTICS_ID'] = $this->parameterService->getTrackerGoogleAnalyticsID();
$twig_parameters ['GOOGLE_ADS_ID'] = $this->parameterService->getTrackerGoogleADsID();
$twig_parameters ['GOOGLE_TAG_MANAGER_ID'] = $this->parameterService->getTrackerGoogleTagManagerID();
$twig_parameters ['FACEBOOK_DOMAIN_VERIFICATION_CODE'] = $this->parameterService->getTrackerFacebookDomainVerification();
$twig_parameters ['GOOGLE_SEARCH_VERIFICATION'] = $this->parameterService->getTrackerGoogleSearchVerification();
return $twig_parameters;
}
/**
* @return \App\Entity\Faq[]
*/
public function getFaqs(FaqRouteEnum $route, ?string $routeParameter = null): array
{
return $this->faqService->getFaqs($route, $routeParameter);
}
}