src/Services/Tours/TourService.php line 438

Open in your IDE?
  1. <?php
  2. /**
  3.  * Created by PhpStorm.
  4.  * User: lskalytska
  5.  * Date: 11/11/19
  6.  * Time: 6:25 PM
  7.  */
  8. namespace App\Services\Tours;
  9. use App\Entity\Otpusk\Country;
  10. use App\Entity\Otpusk\City;
  11. use App\Entity\Otpusk\GeoCategoryValues;
  12. use App\Entity\Otpusk\HotelServices;
  13. use App\Entity\Otpusk\HotelsRCache;
  14. use App\Entity\Otpusk\Chain;
  15. use App\Entity\Otpusk\PriceIndex;
  16. use App\Entity\Otpusk\Rubric;
  17. use App\Entity\Otpusk\Selection;
  18. use App\Services\OtpuskApiService;
  19. use Doctrine\Common\Collections\ArrayCollection;
  20. use Doctrine\ORM\EntityManagerInterface;
  21. use Symfony\Component\Cache\Adapter\MemcachedAdapter;
  22. use Symfony\Component\HttpFoundation\RequestStack;
  23. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  24. use Symfony\Contracts\HttpClient\HttpClientInterface;
  25. class TourService
  26. {
  27.     private EntityManagerInterface $repository;
  28.     private RequestStack $requestStack;
  29.     private HttpClientInterface $httpClient;
  30.     private OtpuskApiService $apiService;
  31.     private $cache;
  32.     private $accessToken '4b26a-e5237-9b0fa-bcc36-67732';
  33.     private $seasonsPeriod = array(
  34.         'win'   => array('begin' => '12''end' => '02'),
  35.         'spr'   => array('begin' => '03''end' => '05'),
  36.         'sum'   => array('begin' => '06''end' => '08'),
  37.         'aut'   => array('begin' => '09''end' => '11'),
  38.         'winter'   => array('begin' => '12''end' => '02'),
  39.         'spring'   => array('begin' => '03''end' => '05'),
  40.         'summer'   => array('begin' => '06''end' => '08'),
  41.         'autumn'   => array('begin' => '09''end' => '11'),
  42.         'january'   => array('begin' => '01''end' => '01'),
  43.         'february'  => array('begin' => '02''end' => '02'),
  44.         'march'     => array('begin' => '03''end' => '03'),
  45.         'april'     => array('begin' => '04''end' => '04'),
  46.         'may'       => array('begin' => '05''end' => '05'),
  47.         'june'      => array('begin' => '06''end' => '06'),
  48.         'july'      => array('begin' => '07''end' => '07'),
  49.         'august'    => array('begin' => '08''end' => '08'),
  50.         'september' => array('begin' => '09''end' => '09'),
  51.         'october'   => array('begin' => '10''end' => '10'),
  52.         'november'  => array('begin' => '11''end' => '11'),
  53.         'december'  => array('begin' => '12''end' => '12'),
  54.         '1'         => array('begin' => '01''end' => '01'),
  55.         '2'         => array('begin' => '02''end' => '02'),
  56.         '3'         => array('begin' => '03''end' => '03'),
  57.         '4'         => array('begin' => '04''end' => '04'),
  58.         '5'         => array('begin' => '05''end' => '05'),
  59.         '6'         => array('begin' => '06''end' => '06'),
  60.         '7'         => array('begin' => '07''end' => '07'),
  61.         '8'         => array('begin' => '08''end' => '08'),
  62.         '9'         => array('begin' => '09''end' => '09'),
  63.         '10'        => array('begin' => '10''end' => '10'),
  64.         '11'        => array('begin' => '11''end' => '11'),
  65.         '12'        => array('begin' => '12''end' => '12'),
  66.     );
  67.     private $months = [
  68.         1  => 'january',
  69.         2  => 'february',
  70.         3  => 'march',
  71.         4  => 'april',
  72.         5  => 'may',
  73.         6  => 'june',
  74.         7  => 'july',
  75.         8  => 'august',
  76.         9  => 'september',
  77.         10 => 'october',
  78.         11 => 'november',
  79.         12 => 'december'
  80.     ];
  81.     /**
  82.      * Dates for start and ending tours searching
  83.      */
  84.     const _ADD_START_DAY        7;    // +7 days from now
  85.     const _ADD_END_DAY          21;   // +21 day from start
  86.     const _ADD_START_DAY_HOT    2;    // +2 days from now for hot tours
  87.     const _ADD_END_DAY_HOT      12;   // +12 day from start for hot tours
  88.     const _ADD_START_DAY_MIN    2;    // +2 days from now for min tours
  89.     const _ADD_END_DAY_MIN      118;   // +118 day from start for min tours
  90.     public function __construct(EntityManagerInterface $repositoryRequestStack $requestStackHttpClientInterface $httpClientOtpuskApiService $apiService)
  91.     {
  92.         $this->repository $repository;
  93.         $this->requestStack $requestStack;
  94.         $this->httpClient $httpClient;
  95.         $this->apiService $apiService;
  96.         $option = array(
  97.             \Memcached::OPT_PREFIX_KEY => (getenv('MEMCACHED_PREFIX')?getenv('MEMCACHED_PREFIX'):($_ENV['MEMCACHED_PREFIX']??'')),
  98.         );
  99.         $this->cache MemcachedAdapter::createConnection(getenv('MEMCACHED_SERV')?getenv('MEMCACHED_SERV'):$_ENV['MEMCACHED_SERV'], $option);
  100.     }
  101.     /**
  102.      * @param int|null $countryId
  103.      * @param int|null $cityId
  104.      * @param string|null $season
  105.      * @param string|null $month
  106.      * @param int|null $budget
  107.      * @param string|null $currency
  108.      * @param int $cityFrom
  109.      * @return ArrayCollection
  110.      * @throws \ErrorException
  111.      */
  112.     public function getGeneralToursPage($market$dbNormalizerint $countryId nullint $cityId nullstring $season nullint $month nullint $budget nullstring $currency nullint $cityFrom$locale 'ru'$isDeparture false$isRubric false)
  113.     {
  114.         $key 'mainpage_' $market['id'] . '_' $countryId '_' $cityId '_' $season '_' $month '_' $budget '_' $currency '_' $currency'_' $locale'_' . (int)$isDeparture'_' $cityFrom'_' . (int)$isRubric;
  115.         if (($tours $this->cache->get($key)) !== false) return $tours;
  116.         $tours = new ArrayCollection();
  117.         $tours $this->getMainInfo($market$dbNormalizer$tours$countryId$cityId$locale$isDeparture$cityFrom$season$month$isRubric);
  118.         $tours $this->getTours($market$dbNormalizer$tours$countryId$cityId$season$month$budget$currencyfalsenull$cityFrom$locale$isDeparture);
  119.         if(isset($season) && property_exists($tours'info'))
  120.             $tours->info['season'] = $season;
  121.         $this->cache->set($key$tours30 60);
  122.         return $tours;
  123.     }
  124.     public function getSelectionPage(string $marketCodeint $selectionId$locale 'ru')
  125.     {
  126.         $tours $this->cache->get('selection_'.$marketCode.'_'.$selectionId.'_'.$locale);
  127.         return $tours;
  128.     }
  129.     public function getSelectionsForGeoById(string $marketCodeint $geoId)
  130.     {
  131.         $key 'selections_page_'.$marketCode.'_by_geo_id_'.$geoId;
  132.         if (($results $this->cache->get($key)) !== false) return $results;
  133.         $results = [];
  134.         $selectionIds $this->cache->get('selections_'.$marketCode.'_by_geo_id_'.$geoId);
  135.         if ($selectionIds) {
  136.             $results $this->repository->getRepository(Selection::class)->findByIds($selectionIds);
  137.         }
  138.         $this->cache->set($key$results60);
  139.         return $results;
  140.     }
  141.     public function getPageCountries($market$dbNormalizer$locale 'ru')
  142.     {
  143.         $key 'countries_' $market['id'] . '_'.$locale;
  144.         if (($results $this->cache->get($key)) !== false) return $results;
  145.         $results = new ArrayCollection();
  146.         $results->popularNow $this->repository->getRepository(Country::class, 'otpusk')->getByCategory($market'countries-popular-now'$locale);
  147.         $results->popularNow $this->repository->getRepository(PriceIndex::class, 'otpusk')->getPriceCountries($market$results->popularNow);
  148.         $results->natureAndMountains $this->repository->getRepository(Country::class, 'otpusk')->getByCategory($market'countries-nature-and-mountains'$locale);
  149.         $results->natureAndMountains $this->repository->getRepository(PriceIndex::class, 'otpusk')->getPriceCountries($market$results->natureAndMountains);
  150.         $results->earlyBooking $this->repository->getRepository(Country::class, 'otpusk')->getByCategory($market'countries-early-booking'$locale);
  151.         $results->earlyBooking $this->repository->getRepository(PriceIndex::class, 'otpusk')->getPriceCountries($market$results->earlyBooking);
  152.         $results->citiesAndLandmarks $this->repository->getRepository(Country::class, 'otpusk')->getByCategory($market'countries-cities-and-landmarks'$locale);
  153.         $results->citiesAndLandmarks $this->repository->getRepository(PriceIndex::class, 'otpusk')->getPriceCountries($market$results->citiesAndLandmarks);
  154.         $results->exoticCountries $this->repository->getRepository(Country::class, 'otpusk')->getByCategory($market'countries-exotic-countries'$locale);
  155.         $results->exoticCountries $this->repository->getRepository(PriceIndex::class, 'otpusk')->getPriceCountries($market$results->exoticCountries);
  156.         $results->cities $this->repository->getRepository(City::class, 'otpusk')->getGuidCitiesByIds($market$localenull$dbNormalizer);
  157.         $results->cities $this->repository->getRepository(PriceIndex::class, 'otpusk')->getPriceCities($market$results->cities);
  158.         $results->excursions $this->repository->getRepository(Country::class, 'otpusk')->getExcursions();
  159.         $this->cache->set($key$results30 60);
  160.         return $results;
  161.     }
  162.     public function getRubrics($dbNormalizer$countryObj$rubricObj null$locale 'ru'$citiesStatus false)
  163.     {
  164.         $key = (is_null($rubricObj))
  165.             ? 'country_' $countryObj->getId(). '_rubrics_' $locale
  166.             'country_' $countryObj->getId(). '_rubric_' $rubricObj->getId(). '_' $locale
  167.         ;
  168.         if (($rubrics $this->cache->get($key)) !== false) return $rubrics;
  169.         $rubrics $this->repository->getRepository(Rubric::class)->findByCountry($countryObj$rubricObj$citiesStatus);
  170.         foreach ($rubrics as $k => $rubric) {
  171.             $rubrics[$k]->setCitiesOutput($this->repository->getRepository(City::class, 'otpusk')->getCitiesByIds($dbNormalizer$locale$rubric->getCities()));
  172.         }
  173.         $this->cache->set($key$rubrics30 60);
  174.         return $rubrics;
  175.     }
  176.     /**
  177.      * @param ArrayCollection $tours
  178.      * @param int|null $countryId
  179.      * @param int|null $cityId
  180.      * @param bool $guide
  181.      * @return ArrayCollection
  182.      * @throws \ErrorException
  183.      */
  184.     public function getMainInfo($market$dbNormalizerArrayCollection $toursint $countryId nullint $cityId null$locale 'ru'$isDeparture false$cityFromstring $season nullint $month null$isRubric false)
  185.     {
  186.         $date = new \DateTime();
  187.         $date->add(new \DateInterval('P' self::_ADD_START_DAY 'D'));
  188.         if ($countryId && is_null($cityId)) {
  189.             $tours->info                $this->getCountryInfo($countryId$locale$dbNormalizer);
  190.             $tours->faq                 $this->getCountryFaq($countryId'Часто задаваемые вопросы'$locale$dbNormalizer);
  191.             $tours->cities              $this->getPopCities($countryId$cityId$locale$isDeparture$cityFrom$dbNormalizer);
  192.             $tours->similarCountries    $this->repository->getRepository(Country::class, 'otpusk')->getSimilarById($countryId$locale$dbNormalizer);
  193.             if (!empty($tours->similarCountries)) {
  194. //                $tours->similarCountries = $this->repository->getRepository(PriceIndex::class, 'otpusk')->getPriceForCountryPage($market, $tours->similarCountries);
  195.                 foreach ($tours->similarCountries as $k => $similarCountry) {
  196.                     $key 'similar_country_price_' $market['id'] . '_'.$similarCountry['id'];
  197.                     if (($similarCountryPrice $this->cache->get($key)) !== false) {
  198.                         $tours->similarCountries[$k]['price'] = $similarCountryPrice;
  199.                     } else {
  200.                         $similarCountryPrice $this->repository->getRepository(PriceIndex::class, 'otpusk')->getPriceForCountryPageByCountryId($market$similarCountry['id']);
  201.                         $tours->similarCountries[$k]['price'] = $similarCountryPrice;
  202.                         $this->cache->set($key$similarCountryPrice30 60);
  203.                     }
  204.                 }
  205.                 $tours->similarCountries $this->repository->getRepository(Country::class, 'otpusk')->getCountriesDescription($tours->similarCountries'Описание для посадочных страниц'$locale$dbNormalizer);
  206.             }
  207.             $tours->monthly             $this->getCountryMonthly($market$countryId);
  208.             $tours->description         null;
  209.             if (!$isDeparture && is_null($season) && is_null($month)) {
  210.                 $tours->description     $this->getCountryFaq($countryId'Туры в страну'$locale$dbNormalizer);
  211.             }
  212.             $tours->descriptionNew      $this->getCountryFaqNew($countryId$locale$season, (!is_null($month)?$this->months[$month]:null), $isDeparture$cityFrom$isRubric$dbNormalizer);
  213.         } elseif ($cityId) {
  214.             $tours->info                $this->getCityInfo($cityId$locale$dbNormalizer);
  215.             $tours->faq                 $this->getCityFaq($cityId'Часто задаваемые вопросы'$locale$dbNormalizer);
  216.             $tours->weather             $this->getWeather($cityId$dbNormalizer['temperatures']['language'][$locale]);
  217.             $tours->cities              $this->getPopCities(null$cityId$locale$isDeparture$cityFrom$dbNormalizer);
  218.             $tours->similarCities       $this->repository->getRepository(City::class, 'otpusk')->getGuidCitiesByIds($market$locale$cityId$dbNormalizer);
  219. //            $tours->similarCities       = $this->repository->getRepository(PriceIndex::class, 'otpusk')->getPriceCities($market, $tours->similarCities);
  220.             foreach ($tours->similarCities as $k => $similarCity) {
  221.                 $key 'similar_city_price_' $market['id'] . '_'.$similarCity['id'];
  222.                 if (($similarCityPrice $this->cache->get($key)) !== false) {
  223.                     $tours->similarCities[$k]['price'] = $similarCityPrice;
  224.                 } else {
  225.                     $similarCityPrice $this->repository->getRepository(PriceIndex::class, 'otpusk')->getPriceCitiesByCityId($market$similarCity['id']);
  226.                     $tours->similarCities[$k]['price'] = $similarCityPrice;
  227.                     $this->cache->set($key$similarCityPrice30 60);
  228.                 }
  229.             }
  230.             $tours->monthly             $this->getCityMonthly($market$cityId);
  231.             $tours->description         null;
  232.             if (!$isDeparture && is_null($season) && is_null($month)) {
  233.                 $tours->description     $this->getCityFaq($cityId'Туры в страну'$locale$dbNormalizer);
  234.             }
  235.             $tours->descriptionNew      $this->getCityFaqNew($cityId$locale$season, (!is_null($month)?$this->months[$month]:null), $isDeparture$cityFrom$dbNormalizer);
  236.         }
  237.         return $tours;
  238.     }
  239.     private function _getCalendarDate($id)
  240.     {
  241.         if (empty($id) || $id<|| $id>5000) return '';
  242.         $token getenv('OTPUSK_API_TOKEN') ? getenv('OTPUSK_API_TOKEN') : $_ENV['OTPUSK_API_TOKEN'];
  243.         $ch curl_init();
  244.         curl_setopt($chCURLOPT_URL'https://api.otpusk.com/api/2.4/tours/dates?to='.$id.'&access_token='.$token);
  245.         curl_setopt($chCURLOPT_RETURNTRANSFERtrue);
  246.         curl_setopt($chCURLOPT_HEADERfalse);
  247.         curl_setopt($chCURLOPT_SSL_VERIFYHOSTfalse);
  248.         curl_setopt($chCURLOPT_SSL_VERIFYPEERfalse);
  249.         curl_setopt($chCURLOPT_USERPWD'dev:dev');
  250.         curl_setopt($chCURLOPT_USERAGENT'web.otpusk.com getCalendarDate');
  251.         curl_setopt($chCURLOPT_TIMEOUT1);
  252.         $response curl_exec($ch);
  253.         $err curl_error($ch);
  254.         curl_close($ch);
  255.         if ($err) {
  256.             return '';
  257.         } else {
  258.             $response = @json_decode($response,1);
  259.             if (empty($response)) return '';
  260.             if (empty($response['dates'])) return '';
  261.             $dates array_keys($response['dates']);
  262.             if (empty($dates)) return '';
  263.             return $dates[0];
  264.         }
  265.     }
  266.     /**
  267.      * @param ArrayCollection $tours
  268.      * @param int|null $countryId
  269.      * @param int|null $cityId
  270.      * @param string|null $season
  271.      * @param int|null $month
  272.      * @param int|null $budget
  273.      * @param string|null $currency
  274.      * @param bool $hot
  275.      * @param string|null $order
  276.      * @param int $cityFrom
  277.      * @return ArrayCollection
  278.      * @throws \Exception
  279.      */
  280.     public function getTours($market$dbNormalizerArrayCollection $toursint $countryId nullint $cityId nullstring $season nullint $month nullint $budget nullstring $currency nullbool $hot falsestring $order nullint $cityFrom$locale 'ru'$isDeparture false)
  281.     {
  282.         $date = new \DateTime($this->_getCalendarDate(max($countryId,$cityId))??'now');
  283.         $period $this->checkPeriod($season$month$date$hot);
  284.         if(isset($order) && $order == 'quality')
  285.             $order true;
  286.         else
  287.             $order false;
  288.         $tours->qualityPrice  $this->getBestQualityTours($market$dbNormalizer$localenullnull$countryId$cityId$cityFrom$period$budget$currency$isDeparture);
  289.         if(is_null($month) && is_null($season) && !$hot){
  290.             $hotPeriod $this->checkPeriod(nullnull, new \DateTime(), true);
  291.             $tours->hot $this->getCheapestTours($market$dbNormalizer$locale'hot'$countryId$cityId$cityFrom$hotPeriod$budget$currencyfalse$isDeparture);
  292.             $tours->hotLux $this->getCheapestTours($market$dbNormalizer$localenull$countryId$cityId$cityFrom$hotPeriod$budget$currencytrue$isDeparture);
  293.         }
  294.         $dateCheapest = new \DateTime($this->_getCalendarDate(max($countryId,$cityId))??'now');
  295.         $periodCheapest = array(
  296.             'dateBeg' => $dateCheapest
  297.                 ->add(new \DateInterval('P' self::_ADD_START_DAY_MIN 'D'))
  298.                 ->format('Y-m-d'),
  299.             'dateEnd' => $dateCheapest
  300.                 ->add(new \DateInterval('P' self::_ADD_END_DAY_MIN 'D'))
  301.                 ->format('Y-m-d')
  302.         );
  303.         $tours->cheapest      $this->getCheapestTours($market$dbNormalizer$localenull$countryId$cityId$cityFrom$periodCheapest$budget$currencyfalse$isDeparture);
  304.         if(is_null($month) && is_null($season) && !$hot){
  305.             $tours->hotBudget $tours->cheapest;
  306.         }
  307.         $tours->friendsBudget   $this->getTypeTours($market$dbNormalizer$locale'friends',  $countryId$cityId$cityFrom$period$budget$currency$ordertruefalse$isDeparture);
  308.         $tours->friends         $this->getTypeTours($market$dbNormalizer$locale'friends',  $countryId$cityId$cityFrom$period$budget$currency$orderfalsefalse$isDeparture);
  309.         $tours->friendsLux      $this->getTypeTours($market$dbNormalizer$locale'friends',  $countryId$cityId$cityFrom$period$budget$currency$ordertruetrue$isDeparture);
  310.         $tours->romanticBudget  $this->getTypeTours($market$dbNormalizer$locale'romantic'$countryId$cityId$cityFrom$period$budget$currency$ordertruefalse$isDeparture);
  311.         $tours->romantic        $this->getTypeTours($market$dbNormalizer$locale'romantic'$countryId$cityId$cityFrom$period$budget$currency$orderfalsefalse$isDeparture);
  312.         $tours->romanticLux     $this->getTypeTours($market$dbNormalizer$locale'romantic'$countryId$cityId$cityFrom$period$budget$currency$ordertruetrue$isDeparture);
  313.         $tours->familyBudget    $this->getTypeTours($market$dbNormalizer$locale'family',   $countryId$cityId$cityFrom$period$budget$currency$ordertruefalse$isDeparture);
  314.         $tours->family          $this->getTypeTours($market$dbNormalizer$locale'family',   $countryId$cityId$cityFrom$period$budget$currency$orderfalsefalse$isDeparture);
  315.         $tours->familyLux       $this->getTypeTours($market$dbNormalizer$locale'family',   $countryId$cityId$cityFrom$period$budget$currency$ordertruetrue$isDeparture);
  316.         $tours->peacefulBudget  $this->getTypeTours($market$dbNormalizer$locale'peaceful'$countryId$cityId$cityFrom$period$budget$currency$ordertruefalse$isDeparture);
  317.         $tours->peaceful        $this->getTypeTours($market$dbNormalizer$locale'peaceful'$countryId$cityId$cityFrom$period$budget$currency$orderfalsefalse$isDeparture);
  318.         $tours->peacefulLux     $this->getTypeTours($market$dbNormalizer$locale'peaceful'$countryId$cityId$cityFrom$period$budget$currency$ordertruetrue$isDeparture);
  319.         $tours->hotelsChains  $this->getHotelsChains($countryId$cityId);
  320.         $tours->bestHotels    = array(
  321.             => $this->getBestHotelsTours($market$dbNormalizer$localenull5$countryId$cityId$cityFrom$period$budget$currency$isDeparture),
  322.             => $this->getBestHotelsTours($market$dbNormalizer$localenull4$countryId$cityId$cityFrom$period$budget$currency$isDeparture),
  323.             => $this->getBestHotelsTours($market$dbNormalizer$localenull3$countryId$cityId$cityFrom$period$budget$currency$isDeparture),
  324.             => $this->getBestHotelsTours($market$dbNormalizer$localenull2$countryId$cityId$cityFrom$period$budget$currency$isDeparture),
  325.         );
  326.         $tours->sport $this->getServicesCount($date->format('Y-m-d'), $countryId$cityId$period);
  327.         $tours->hotelServices $this->getHotelServcies($dbNormalizer$locale);
  328.         $tours->catalogue     = new ArrayCollection();
  329.         $tours->catalogue->friends count($tours->friends) >= 0;
  330.         $tours->catalogue->romantic count($tours->romantic) >= 0;
  331.         $tours->catalogue->family count($tours->family) >= 0;
  332.         $tours->catalogue->peaceful count($tours->peaceful) >= 0;
  333.         $tours->catalogue->aquapark = (int)$tours->sport[0]['aquapark'];
  334.         $tours->catalogue->spa = (int)$tours->sport[0]['spa'];
  335.         $tours->departureCities $this->getDepartureCities($market$dbNormalizer$locale$countryId);
  336.         $tours->departureCity $this->getDepartureCity($market$tours->departureCities);
  337.         return $tours;
  338.     }
  339.     public function getDepartureCities($market$dbNormalizer$locale$countryId)
  340.     {
  341.         $key 'departureCities_' $market['id'] . '_' $countryId '_' $locale;
  342.         if (($cities $this->cache->get($key)) !== false) return $cities;
  343.         $fromCities $this->apiService->getInfo($market['apiToken'], 'cities'$countryId);
  344.         $uniqueIds = (count($fromCities) > 0) ? '\''.implode('\',\''array_values($fromCities)).'\'' null;
  345.         $cities = (!is_null($uniqueIds)) ? $this->repository->getRepository(City::class)->getDepartureCitiesForCountrySearchPage($uniqueIds$locale$dbNormalizer) : [];
  346.         $this->cache->set($key$cities60 60);
  347.         return $cities;
  348.     }
  349.     public function getDepartureCity($market$departureCities)
  350.     {
  351.         $marketCities = [];
  352.         foreach ($market['mainCities'] as $marketCity) {
  353.             if (!is_null($marketCity['id'])) {
  354.                 $marketCities[] = $marketCity['id'];
  355.             }
  356.         }
  357.         $marketCities array_unique($marketCities);
  358.         $departureCityIds = [];
  359.         foreach ($departureCities as $departureCityItem) {
  360.             $departureCityIds[] = $departureCityItem['id'];
  361.         }
  362.         $departureCitiesIntersect array_intersect($marketCities$departureCityIds);
  363.         if (count($departureCitiesIntersect) > 0) {
  364.             $departureCity array_shift($departureCitiesIntersect);
  365.         } elseif (count($departureCityIds) > 0) {
  366.             $departureCity array_shift($departureCityIds);
  367.         } else {
  368.             $departureCity null;
  369.         }
  370.         return $departureCity;
  371.     }
  372.     public function getPopCities($countryId$cityId$locale 'ru'$isDeparture false$cityFrom$dbNormalizer)
  373.     {
  374.         $key 'popCities_' $countryId '_' $cityId'_' $locale'_' . (int)$isDeparture'_' $cityFrom;
  375.         if (($cities $this->cache->get($key)) !== false) return $cities;
  376.         $cities $this->repository
  377.             ->getRepository(City::class, 'otpusk')
  378.             ->getPopCities($countryId$cityId$locale$isDeparture$cityFrom$dbNormalizer);
  379.         $this->cache->set($key$cities60 60);
  380.         return $cities;
  381.     }
  382.     public function getBestQualityTours($market$dbNormalizer$locale$type null$stars null$countryId null$cityId null$cityFrom$period null$budget null$currency null$isDeparture false)
  383.     {
  384.         $tours $this->repository
  385.             ->getRepository(HotelsRCache::class, 'otpusk')
  386.             ->getBestQualityTours($market$dbNormalizer$locale$type$stars$countryId$cityId$cityFrom$period$budget$currency$isDeparture);
  387.         return $tours;
  388.     }
  389.     public function getCheapestTours($market$dbNormalizer$locale$type null$countryId null$cityId null$cityFrom$period null$budget null$currency null$vipStatus false$isDeparture false)
  390.     {
  391.         $tours $this->repository
  392.             ->getRepository(HotelsRCache::class, 'otpusk')
  393.             ->getCheapestTours($market$dbNormalizer$locale$type$countryId$cityId$cityFrom$period$budget$currency$vipStatus$isDeparture);
  394.         return $tours;
  395.     }
  396.     public function getBestHotelsTours($market$dbNormalizer$locale$type null$stars null$countryId null$cityId null$cityFrom$period null$budget null$currency null$isDeparture false)
  397.     {
  398.         $tours $this->repository
  399.             ->getRepository(HotelsRCache::class, 'otpusk')
  400.             ->getBestHotelsTours($market$dbNormalizer$locale$type$stars$countryId$cityId$cityFrom$period$budget$currency$isDeparture);
  401.         return $tours;
  402.     }
  403.     public function getTypeTours($market$dbNormalizer$locale$type null$countryId null$cityId null$cityFrom$period null$budget null$currency null$order false$withoutRating false$vipStatus false$isDeparture false)
  404.     {
  405.         $tours $this->repository
  406.             ->getRepository(HotelsRCache::class, 'otpusk')
  407.             ->getTypeTours($market$dbNormalizer$locale$type$countryId$cityId$cityFrom$period$budget$currency$order$withoutRating$vipStatus$isDeparture);
  408.         return $tours;
  409.     }
  410.     public function getHotelsChains($countryId null$cityId null)
  411.     {
  412.         $chains $this->repository
  413.             ->getRepositoryChain::class, 'otpusk')
  414.             ->getChainsByCount($countryId$cityId);
  415.         return $chains;
  416.     }
  417.     public function getServicesCount($date$countryId null$cityId null$period null)
  418.     {
  419.         $services $this->repository
  420.             ->getRepositoryHotelsRCache::class, 'otpusk')
  421.             ->getServicesCount($date$countryId$cityId$period);
  422.         return $services;
  423.     }
  424.     public function getHotelServcies($dbNormalizer$locale)
  425.     {
  426.         $services $this->repository
  427.             ->getRepositoryHotelServices::class, 'otpusk')
  428.             ->getHotelServcies($dbNormalizer$locale);
  429.         return $services;
  430.     }
  431.     private function getMonthsArray(){
  432.         return array(
  433.             array('price' => null'currency' => null'uah' => null'date' => null'monthName' => 'Jan''weather' => null'water' => null),
  434.             array('price' => null'currency' => null'uah' => null'date' => null'monthName' => 'Feb''weather' => null'water' => null),
  435.             array('price' => null'currency' => null'uah' => null'date' => null'monthName' => 'Mar''weather' => null'water' => null),
  436.             array('price' => null'currency' => null'uah' => null'date' => null'monthName' => 'Apr''weather' => null'water' => null),
  437.             array('price' => null'currency' => null'uah' => null'date' => null'monthName' => 'May''weather' => null'water' => null),
  438.             array('price' => null'currency' => null'uah' => null'date' => null'monthName' => 'Jun''weather' => null'water' => null),
  439.             array('price' => null'currency' => null'uah' => null'date' => null'monthName' => 'Jul''weather' => null'water' => null),
  440.             array('price' => null'currency' => null'uah' => null'date' => null'monthName' => 'Aug''weather' => null'water' => null),
  441.             array('price' => null'currency' => null'uah' => null'date' => null'monthName' => 'Sep''weather' => null'water' => null),
  442.             array('price' => null'currency' => null'uah' => null'date' => null'monthName' => 'Oct''weather' => null'water' => null),
  443.             array('price' => null'currency' => null'uah' => null'date' => null'monthName' => 'Nov''weather' => null'water' => null),
  444.             array('price' => null'currency' => null'uah' => null'date' => null'monthName' => 'Dec''weather' => null'water' => null),
  445.         );
  446.     }
  447.     public function getCountryMonthly($market$countryId null)
  448.     {
  449.         $months $this->getMonthsArray();
  450.         if(isset($countryId)){
  451.             $res $this->repository
  452.                 ->getRepositoryHotelsRCache::class, 'otpusk')
  453.                 ->getMonthlyInfo($market$countryId'countryId');
  454.             $temps $this->repository
  455.                 ->getRepository(Country::class, 'otpusk')
  456.                 ->getTemperaturesByCountry($countryId);
  457.             foreach ($months as &$month) {
  458.                 foreach ($res as $item) {
  459.                     $date = new \DateTime($item['date']);
  460.                     if($month['monthName'] == $date->format('M')){
  461.                         foreach ($item as $index => $value) {
  462.                             $month[$index] = $value;
  463.                         }
  464.                         if(is_array($temps) && count($temps) > 0){
  465.                             foreach ($temps AS $temp){
  466.                                 $month[$temp['type']] = array_key_exists($month['monthName'], $temp) ? round($temp[$month['monthName']]) : null;
  467.                             }
  468.                         }
  469.                         continue;
  470.                     }
  471.                 }
  472.                 if(is_array($temps) && count($temps) > 0){
  473.                     foreach ($temps AS $temp){
  474.                         $month[$temp['type']] = array_key_exists($month['monthName'], $temp) ? round($temp[$month['monthName']]) : null;
  475.                     }
  476.                 }
  477.             }
  478.         }
  479.         return $months;
  480.     }
  481.     public function getCityMonthly($market$cityId null)
  482.     {
  483.         $months $this->getMonthsArray();
  484.         if(isset($cityId)){
  485.             $res $this->repository
  486.                 ->getRepositoryHotelsRCache::class, 'otpusk')
  487.                 ->getMonthlyInfo($market$cityId'cityId');
  488.             $temps $this->repository
  489.                 ->getRepository(City::class, 'otpusk')
  490.                 ->getTemperaturesByCity($cityId);
  491.             foreach ($months as &$month) {
  492.                 foreach ($res as $item) {
  493.                     $date = new \DateTime($item['date']);
  494.                     if($month['monthName'] == $date->format('M')){
  495.                         foreach ($item as $index => $value) {
  496.                             $month[$index] = $value;
  497.                         }
  498.                         if(is_array($temps) && count($temps) > 0){
  499.                             foreach ($temps AS $temp){
  500.                                 $month[$temp['type']] = array_key_exists($month['monthName'], $temp) ? (int)$temp[$month['monthName']] : null;
  501.                             }
  502.                         }
  503.                         continue;
  504.                     }
  505.                 }
  506.                 if(is_array($temps) && count($temps) > 0){
  507.                     foreach ($temps AS $temp){
  508.                         $month[$temp['type']] = array_key_exists($month['monthName'], $temp) ? (int)$temp[$month['monthName']] : null;
  509.                     }
  510.                 }
  511.             }
  512.         }
  513.         return $months;
  514.     }
  515.     /**
  516.      * @param $season
  517.      * @param $month
  518.      * @param $date
  519.      * @param bool $hot
  520.      * @return array|null
  521.      * @throws \Exception
  522.      */
  523.     public function checkPeriod($season$month$date$hot false)
  524.     {
  525.         // general period
  526.         if (is_null($season) && is_null($month) && !$hot)
  527.             return array(
  528.                 'dateBeg' => $date
  529.                     ->add(new \DateInterval('P' self::_ADD_START_DAY 'D'))
  530.                     ->format('Y-m-d'),
  531.                 'dateEnd' => $date
  532.                     ->add(new \DateInterval('P' self::_ADD_END_DAY 'D'))
  533.                     ->format('Y-m-d')
  534.             );
  535.         // period for hot tours
  536.         elseif (is_null($season) && is_null($month) && $hot)
  537.             return array(
  538.                 'dateBeg' => $date
  539.                     ->add(new \DateInterval('P' self::_ADD_START_DAY_HOT 'D'))
  540.                     ->format('Y-m-d'),
  541.                 'dateEnd' => $date
  542.                     ->add(new \DateInterval('P' self::_ADD_END_DAY_HOT 'D'))
  543.                     ->format('Y-m-d')
  544.             );
  545.         // period for months period
  546.         if (isset($month) && ($month >= || $month <= 12)) {
  547.             if ((int)$date->format('m') > $month) {
  548.                 $year $date->format('Y') + 1;
  549.                 return array(
  550.                     'dateBeg' => $year '-' $this->seasonsPeriod[$month]['begin'] . '-01',
  551.                     'dateEnd' => $year '-' $this->seasonsPeriod[$month]['begin'] . '-31'
  552.                 );
  553.             } elseif ((int)$date->format('m') == $month) {
  554.                 return array(
  555.                     'dateBeg' => $date->format('Y-n-d'),
  556.                     'dateEnd' => $date->format('Y-n') . '-31'
  557.                 );
  558.             } else {
  559.                 return array(
  560.                     'dateBeg' => $date->format('Y') . '-' $this->seasonsPeriod[$month]['begin'] . '-01',
  561.                     'dateEnd' => $date->format('Y') . '-' $this->seasonsPeriod[$month]['begin'] . '-31'
  562.                 );
  563.             }
  564.         } // period for season
  565.         elseif (isset($season) && array_key_exists($season$this->seasonsPeriod)) {
  566.             if ($season == 'win' || $season == 'winter') {
  567.                 $year $date->format('Y') + 1;
  568.                 return array(
  569.                     'dateBeg' => $date->format('Y') . '-' $this->seasonsPeriod[$season]['begin'] . '-01',
  570.                     'dateEnd' => $year '-' $this->seasonsPeriod[$season]['end'] . '-31'
  571.                 );
  572.             } elseif ((int)$date->format('m') > (int)$this->seasonsPeriod[$season]['begin']) {
  573.                 $year $date->format('Y') + 1;
  574.                 return array(
  575.                     'dateBeg' => $year '-' $this->seasonsPeriod[$season]['begin'] . '-01',
  576.                     'dateEnd' => $year '-' $this->seasonsPeriod[$season]['end'] . '-31'
  577.                 );
  578.             } elseif ((int)$date->format('m') >= (int)$this->seasonsPeriod[$season]['begin'] && (int)$date->format('m') <= (int)$this->seasonsPeriod[$season]['end']) {
  579.                 return array(
  580.                     'dateBeg' => $date->format('Y-n-d'),
  581.                     'dateEnd' => $date->format('Y') . '-' $this->seasonsPeriod[$season]['end'] . '-31'
  582.                 );
  583.             } else {
  584.                 return array(
  585.                     'dateBeg' => $date->format('Y') . '-' $this->seasonsPeriod[$season]['begin'] . '-01',
  586.                     'dateEnd' => $date->format('Y') . '-' $this->seasonsPeriod[$season]['end'] . '-31'
  587.                 );
  588.             }
  589.         }
  590.         return null;
  591.     }
  592.     /**
  593.      * @param $countryId
  594.      * @return mixed
  595.      */
  596.     public function getCountryInfo($countryId$locale 'ru'$dbNormalizer)
  597.     {
  598.         return $this->repository
  599.             ->getRepository(Country::class, 'otpusk')
  600.             ->getCountryInfo($countryId$locale$dbNormalizer);
  601.     }
  602.     /**
  603.      * @param $countryId
  604.      * @return mixed
  605.      */
  606.     public function getCityInfo($cityId$locale 'ru'$dbNormalizer)
  607.     {
  608.         return $this->repository
  609.             ->getRepository(City::class, 'otpusk')
  610.             ->getCityInfo($cityId$locale$dbNormalizer);
  611.     }
  612.     /**
  613.      * @param $countryAlias
  614.      * @param $cityAlias
  615.      * @return mixed
  616.      */
  617.     public function getIdByAlias($countryAlias$cityAlias)
  618.     {
  619.         $teritory $this->repository
  620.             ->getRepository(Country::class, 'otpusk')
  621.             ->getIdByAlias($countryAlias$cityAlias);
  622.         if(is_null($teritory) || !array_key_exists('countryId'$teritory))
  623.             throw new NotFoundHttpException("Can't find country or city");
  624.         elseif(isset($cityAlias) && !array_key_exists('cityId'$teritory))
  625.             throw new NotFoundHttpException("Can't find city");
  626.         elseif(is_null($cityAlias))
  627.             $teritory['cityId'] = null;
  628.         return $teritory;
  629.     }
  630.     public function getCountryFaq($countryId$type$locale 'ru'$dbNormalizer)
  631.     {
  632.         return $this->repository
  633.             ->getRepository(Country::class, 'otpusk')
  634.             ->getCountryFaq($countryId$type$locale$dbNormalizer);
  635.     }
  636.     public function getCountryFaqNew($countryId$locale 'ru'$season null$month null$isDeparture false$cityFrom$isRubric false$dbNormalizer)
  637.     {
  638.         return $this->repository
  639.             ->getRepository(Country::class, 'otpusk')
  640.             ->getCountryFaqNew($countryId$locale$season$month$isDeparture$cityFrom$isRubric$dbNormalizer);
  641.     }
  642.     public function getCityFaq($cityId$type$locale 'ru'$dbNormalizer)
  643.     {
  644.         return $this->repository
  645.             ->getRepository(City::class, 'otpusk')
  646.             ->getCityFaq($cityId$type$locale$dbNormalizer);
  647.     }
  648.     public function getCityFaqNew($cityId$locale 'ru'$season null$month null$isDeparture false$cityFrom$dbNormalizer)
  649.     {
  650.         return $this->repository
  651.             ->getRepository(City::class, 'otpusk')
  652.             ->getCityFaqNew($cityId$locale$season$month$isDeparture$cityFrom$dbNormalizer);
  653.     }
  654.     public function getWeather($cityId$lang)
  655.     {
  656.         return $this->repository
  657.             ->getRepository(City::class, 'otpusk')
  658.             ->getWeather($cityId$lang);
  659.     }
  660.     public function fetchOfferDetails(string $offerIdstring $lang 'uk'string $currency 'uah'): ?array
  661.     {
  662.         $request $this->requestStack->getCurrentRequest();
  663.         $host str_replace(['web','www'],'api'$request->getSchemeAndHttpHost());
  664.         $url sprintf(
  665.             'https://api.otpusk.com/api/2.4/tours/offer?offerId=%s&access_token=%s&lang=%s&currencyLocal=%s',
  666.             $offerId,
  667.             $this->accessToken,
  668.             $lang,
  669.             $currency
  670.         );
  671.         $response $this->httpClient->request('GET'$url);
  672.         if ($response->getStatusCode() === 200) {
  673.             return $response->toArray();
  674.         }
  675.         return null;
  676.     }
  677.     public function fetchHotelsDetails(string $hotelIdstring $lang 'uk')
  678.     {
  679.         $request $this->requestStack->getCurrentRequest();
  680.         $host str_replace(['web','www'],'api'$request->getSchemeAndHttpHost());
  681.         $url sprintf(
  682.             'https://api.otpusk.com/api/2.4/tours/hotels?hotelId=%s&access_token=%s&lang=%s',
  683.             $hotelId,
  684.             $this->accessToken,
  685.             $lang,
  686.         );
  687.         $response $this->httpClient->request('GET'$url);
  688.         if ($response->getStatusCode() === 200) {
  689.             return $response->toArray();
  690.         }
  691.         return null;
  692.     }
  693.     public function fetchHotelDetails(string $hotelIdstring $lang 'uk')
  694.     {
  695.         $request $this->requestStack->getCurrentRequest();
  696.         $host str_replace(['web','www'],'api'$request->getSchemeAndHttpHost());
  697.         $url sprintf(
  698.             'https://api.otpusk.com/api/2.4/tours/hotel?hotelId=%s&access_token=%s&lang=%s',
  699.             $hotelId,
  700.             $this->accessToken,
  701.             $lang,
  702.         );
  703.         $response $this->httpClient->request('GET'$url);
  704.         if ($response->getStatusCode() === 200) {
  705.             return $response->toArray();
  706.         }
  707.         return null;
  708.     }
  709. }