<?php
namespace App\Repository\Otpusk;
use App\Entity\Otpusk\City;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\Persistence\ManagerRegistry;
use GeoIp2\Database\Reader;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use function Doctrine\ORM\QueryBuilder;
class CityRepository extends ServiceEntityRepository
{
private $imgUrl = 'https://www.otpusk.com/';
private $dbNormalizer;
public function __construct(ManagerRegistry $registry, ParameterBagInterface $config)
{
parent::__construct($registry, City::class);
$this->dbNormalizer = $config->get('db_normalizer');
}
public function checkDepartureCity($city, $locale = 'ru')
{
$name = $this->dbNormalizer['city']['name'][$locale];
return $this->createQueryBuilder('c')
->select('c.id AS id, c.'.$name.'Rd AS nameRd, c.fNameTr AS nameTr')
->andWhere('c.fNameTr = :city')
->setParameter('city', $city)
->getQuery()
->getOneOrNullResult()
;
}
public function getDepartureCitiesForCountrySearchPage($citiesIds, $locale = 'ru', $dbNormalizer)
{
$name = $dbNormalizer['city']['name'][$locale];
$qb = $this->createQueryBuilder('c');
$qb = $qb
->select('c.id, c.'.$name.'Rd AS name, c.fNameTr AS nameTr')
->where('c.id IN ('.$citiesIds.')')
->getQuery()
;
return $qb->execute();
}
public function getTourCitiesForPages($countryId, $cityId = null, $locale = 'ru', $dbNormalizer)
{
$name = $dbNormalizer['city']['name'][$locale];
$qb = $this->createQueryBuilder('c')
->select('c.id AS id, c.'.$name.' AS name, c.fNameTr AS nameTr, c.'.$name.'Rd AS nameInGenitiveCase')
->leftJoin('c.priceIndex', 'pi');
if(isset($cityId)){
$qb->innerJoin('App\Entity\Otpusk\City', 't', \Doctrine\ORM\Query\Expr\Join::WITH, 'c.fCountryID = t.fCountryID')
->where('t.id = :city')
->setParameter('city', $cityId);
} else {
$qb->where('c.fCountryID = :country')
->setParameter('country', $countryId);
}
$qb->andWhere('pi.id IS NOT NULL')
->andWhere('pi.date > :now')
->setParameter('now', new \DateTime())
->groupBy('c.id')
->orderBy('c.fName', 'ASC')
->having('COUNT(pi.id) > 0');
$result = $qb->getQuery()->getArrayResult();
if (count($result) == 0) {
$qb = $this->createQueryBuilder('c')
->select('c.id AS id, c.'.$name.' AS name, c.fNameTr AS nameTr, c.'.$name.'Rd AS nameInGenitiveCase');
if(isset($cityId)){
$qb->innerJoin('App\Entity\Otpusk\City', 't', \Doctrine\ORM\Query\Expr\Join::WITH, 'c.fCountryID = t.fCountryID')
->where('t.id = :city')
->setParameter('city', $cityId);
} else {
$qb->where('c.fCountryID = :country')
->setParameter('country', $countryId);
}
$qb->groupBy('c.id')
->orderBy('c.fName', 'ASC');
$result = $qb->getQuery()->getArrayResult();
}
return $result;
}
public function getPopCities($countryId, $cityId = null, $locale = 'ru', $isDeparture = false, $cityFrom, $dbNormalizer)
{
$name = $dbNormalizer['city']['name'][$locale];
$params = array(
'baseUrl' => $this->imgUrl,
);
$conn = $this->getEntityManager()
->getConnection();
$sql = 'SELECT c.rec_id AS id, c.'.$name.' AS name, c.fNameTr AS nameTr, c.'.$name.'Rd AS nameInGenitiveCase, CONCAT(:baseUrl, "media/city/", LPAD(FLOOR(m.media_id / 100000) + 1, 4, 0), "/", LPAD(FLOOR((m.media_id - (FLOOR(m.media_id / 100000) * 100000))/ 1000) + 1, 2, 0), "/thumb_", m.media_id, "_city_desktop_gallery_2.jpeg") as desktop_gallery, CONCAT(:baseUrl, "media/city/", LPAD(FLOOR(m.media_id / 100000) + 1, 4, 0), "/", LPAD(FLOOR((m.media_id - (FLOOR(m.media_id / 100000) * 100000))/ 1000) + 1, 2, 0), "/thumb_", m.media_id, "_city_mobile_card.jpeg") as mobile_card
FROM otpusk.tCities AS c
LEFT JOIN otp_tours.media__gallery_media m ON c.gallery_id = m.gallery_id';
if(isset($cityId)){
$sql .= ' LEFT JOIN otpusk.tCities AS t ON c.fCountryID = t.fCountryID';
}
if ($isDeparture) {
$sql .= ' '.($isDeparture?'INNER':'LEFT'). ' JOIN otpusk.priceIndex pi ON c.rec_id = pi.cityId';
}
if(isset($cityId)){
$sql .= ' WHERE t.rec_id = :city';
$params['city'] = $cityId;
} else {
$sql .= " WHERE c.fCountryID = :country";
$params['country'] = $countryId;
}
$sql .= " AND c.cityWeight > 0 AND m.position = 1";
if ($isDeparture) {
$sql .= " AND c.fPriority = 2 AND pi.fromCityId = :fromCityId";
$params['fromCityId'] = $cityFrom;
}
$sql .= " GROUP BY c.rec_id";
if (FALSE && $isDeparture) {
$sql .= " HAVING COUNT(pi.rec_id) > 0";
}
$sql .= " ORDER BY c.cityWeight DESC, c.fName LIMIT 6";
$stmt = $conn->prepare($sql);
foreach ($params as $index => $param) {
$stmt->bindValue($index, $param);
}
return $stmt->execute()->fetchAll();
}
public function getByCategory($market, $category, $locale = 'ru')
{
$sql = $this->createQueryBuilder('c')
->join('c.cityCategoryValues', 'cv')
->leftJoin('cv.category', 'cat')
->where('cat.name = :category')
->andWhere('cv.market = :marketId')
->setParameter('category', $category)
->setParameter('marketId', $market['id'])
->orderBy('cv.position')
;
return $sql->getQuery()->getResult();
}
public function getSimilarById($cityId)
{
$params = array(
'cityId' => $cityId,
);
$conn = $this->getEntityManager()->getConnection();
$sql = 'SELECT city_similar_in_id as id FROM CitiesSimilar cs WHERE cs.city_similar_id = :cityId ORDER BY cs.priority DESC';
$stmt = $conn->prepare($sql);
foreach ($params as $index => $param) {
$stmt->bindValue($index, $param);
}
return $stmt->execute()->fetchAll();
}
public function getGuidCitiesByIds($market, $locale = 'ru', $cityId = null, $dbNormalizer)
{
$date = new \DateTime();
$date->add(new \DateInterval('P7D'));
$nameCity = $dbNormalizer['city']['name'][$locale];
$cities = (is_null($cityId)) ? $this->getByCategory($market, 'cities-popular-cities') : $this->getSimilarById($cityId);
$cityIds = [];
foreach ($cities as $city) {
$cityIds[] = (is_null($cityId)) ? $city->getId() : $city['id'];
}
foreach ($cityIds as $k => $v) {
if (empty($v)) unset($cityIds[$k]);
}
if ($cityIds) {
$params = array(
'baseUrl' => $this->imgUrl,
'date' => $date->format('n'),
'lang' => $dbNormalizer['tRefs']['language'][$locale],
);
$conn = $this->getEntityManager()
->getConnection();
$month = strtolower($date->format('M'));
if ($month == 'dec') $month = 'decm';
$sql = 'SELECT c.rec_id AS id, c.' . $nameCity . ' AS name, c.fNameTr AS nameTr, co.fNameTr AS countryNameTr, c.' . $nameCity . 'Rd AS nameInGenitiveCase, cw.weight AS seasonWeight, t. ' . $month . ' AS weather, tw. ' . $month . ' AS water, r.fBrief AS text,
CONCAT(:baseUrl, "media/city/", LPAD(FLOOR(m.media_id / 100000) + 1, 4, 0), "/", LPAD(FLOOR((m.media_id - (FLOOR(m.media_id / 100000) * 100000))/ 1000) + 1, 2, 0), "/thumb_", m.media_id, "_city_desktop_gallery_2.jpeg") as desktop_gallery, CONCAT(:baseUrl, "media/city/", LPAD(FLOOR(m.media_id / 100000) + 1, 4, 0), "/", LPAD(FLOOR((m.media_id - (FLOOR(m.media_id / 100000) * 100000))/ 1000) + 1, 2, 0), "/thumb_", m.media_id, "_city_mobile_card.jpeg") as mobile_card
FROM otpusk.tCities AS c
LEFT JOIN otp_tours.media__gallery_media m ON c.gallery_id = m.gallery_id
LEFT JOIN otpusk.citiesWeight cw ON (c.rec_id = cw.cityId AND cw.month = :date)
LEFT JOIN otpusk.tCountries co ON (c.fCountryID = co.rec_id)
LEFT JOIN otp_misc.temperatures t ON (c.rec_id = t.cityId AND t.temperatureType = "weather")
LEFT JOIN otp_misc.temperatures tw ON (c.rec_id = tw.cityId AND tw.temperatureType = "water")
LEFT JOIN otpusk.tRefs r ON (c.rec_id = r.fBindID AND r.fRefTypeID = 94 AND r.fLang = :lang)
WHERE c.rec_id IN (' . implode(',', $cityIds) . ')
GROUP BY c.rec_id
ORDER BY FIELD(c.rec_id, ' . implode(',', $cityIds) . ')';
$stmt = $conn->prepare($sql);
foreach ($params as $index => $param) {
$stmt->bindValue($index, $param);
}
return $stmt->execute()->fetchAll();
}
return [];
}
public function getCitiesByIds($dbNormalizer, $locale = 'ru', $cityIdsObject = null)
{
$name = $dbNormalizer['city']['name'][$locale];
$cityIds = [];
foreach ($cityIdsObject as $city) {
$cityIds[] = $city->getCity()->getId();
}
if ($cityIds) {
$params = array(
'baseUrl' => $this->imgUrl,
);
$conn = $this->getEntityManager()
->getConnection();
$sql = 'SELECT c.rec_id AS id, c.' . $name . ' AS name,
CONCAT(:baseUrl, "media/city/", LPAD(FLOOR(m.media_id / 100000) + 1, 4, 0), "/", LPAD(FLOOR((m.media_id - (FLOOR(m.media_id / 100000) * 100000))/ 1000) + 1, 2, 0), "/thumb_", m.media_id, "_city_desktop_gallery_2.jpeg") as desktop_gallery, CONCAT(:baseUrl, "media/city/", LPAD(FLOOR(m.media_id / 100000) + 1, 4, 0), "/", LPAD(FLOOR((m.media_id - (FLOOR(m.media_id / 100000) * 100000))/ 1000) + 1, 2, 0), "/thumb_", m.media_id, "_city_mobile_card.jpeg") as mobile_card
FROM otpusk.tCities AS c
LEFT JOIN otp_tours.media__gallery_media m ON c.gallery_id = m.gallery_id
WHERE c.rec_id IN (' . implode(',', $cityIds) . ')
GROUP BY c.rec_id
ORDER BY FIELD(c.rec_id, ' . implode(',', $cityIds) . ')';
$stmt = $conn->prepare($sql);
foreach ($params as $index => $param) {
$stmt->bindValue($index, $param);
}
$cities = $stmt->execute()->fetchAll();
$results = [];
foreach ($cities as $city) {
$results[$city['id']] = $city;
}
return $results;
}
return [];
}
public function getByCityAliases($dbNormalizer, $locale, string $cityAlias)
{
$name = $dbNormalizer['city']['name'][$locale];
$city = $this->createQueryBuilder('city')
->select('city.'.$name.'Rd as name')
->where('city.fNameTr = :cityAlias')
->orWhere('city.fNameTr = :cityAliasChanged')
->orWhere('city.fNameTr = :cityAliasChangedA')
->setParameter('cityAlias', $cityAlias)
->setParameter('cityAliasChanged', $cityAlias)
->setParameter('cityAliasChangedA', str_replace('_', ' ', $cityAlias))
->getQuery()
->getOneOrNullResult();
return $city;
}
public function getCityInfo($cityId, $locale = 'ru', $dbNormalizer)
{
$nameCountry = $dbNormalizer['country']['name'][$locale];
$nameCase = $dbNormalizer['country']['case'][$locale];
$nameCity = $dbNormalizer['city']['name'][$locale];
$nameCurrency = $dbNormalizer['country']['currency'][$locale];
$nameLanguage = $dbNormalizer['country']['language'][$locale];
$sql = $this->createQueryBuilder('c')
->select('c.id AS id, c.'.$nameCity.' AS name, c.'.$nameCity.'Rd AS nameRd, c.'.$nameCity.'Vn AS nameVn, c.'.$nameCity.'Pr AS namePr, c.'.$nameCity.'Dt AS nameDt, c.fNameTr AS nameTr, country.fNameTr AS countryTr, country.'.$nameCountry.' AS countryName, country.'.$nameCase.'Vn AS countryNameVn, country.foodCost as foodCostCountry, country.coffeeCost as coffeeCostCountry, c.foodCost, c.coffeeCost, country.'.$nameCurrency.' as currencyName, country.'.$nameLanguage.' as language, c.timeLocal, c.timeZone, country.timeLocal as timeLocalCounty, country.timeZone as timeZoneCounty, c.flightTime, country.flightTime as flightTimeCountry')
->leftJoin('c.country', 'country', Join::WITH, 'country.id = c.fCountryID')
->where('c.id = :city')
->setParameter('city', $cityId)
->getQuery();
return $sql->getOneOrNullResult();
}
public function getCityFaq($cityId, $type, $locale = 'ru', $dbNormalizer)
{
$sql = $this->createQueryBuilder('c')
->select('f.fTitle AS title, f.fText AS text, f.fLang AS lang')
->leftJoin('c.faqText', 'f')
->leftJoin('f.fRefTypeID', 'fb')
->where('c.id = :city')
->andWhere('f.fLang = :lang')
->andWhere('fb.fName = :type')
->andWhere('fb.fBindType = :bind')
->setParameters(array('city' => $cityId, 'type' => $type, 'bind' => 'city', 'lang' => $dbNormalizer['tRefs']['language'][$locale]))
->orderBy('f.fSort', 'DESC')
;
return $sql->getQuery()->getArrayResult();
}
public function getCityFaqNew($cityId, $locale = 'ru', $season = null, $month = null, $isDeparture = false, $cityFrom, $dbNormalizer)
{
$code = 'citytours';
if ($isDeparture) $code .= 'departurecity';
if (!is_null($season)) $code .= $season;
if (!is_null($month)) $code .= $month;
$sql = $this->createQueryBuilder('c')
->select('f.fTitle AS title, f.fText AS text')
->leftJoin('c.faqText', 'f')
->leftJoin('f.fRefTypeID', 'fb')
->where('c.id = :city')
->andWhere('f.fLang = :lang')
->andWhere('fb.fCode = :code');
if ($isDeparture) {
$sql
->andWhere('f.fFromCityId = :cityFrom')
->setParameter('cityFrom', $cityFrom);
}
$sql
->setParameter('city', $cityId)
->setParameter('code', $code)
->setParameter('lang', $dbNormalizer['tRefs']['language'][$locale])
->orderBy('f.fSort', 'DESC');
$result = $sql->getQuery()->getOneOrNullResult();
if (!is_null($result) && is_resource($result['text'])) {
rewind($result['text']);
$result['text'] = stream_get_contents($result['text']);
}
return $result;
}
public function getWeather($cityId, $lang = 'rus')
{
$params = array(
'city' => $cityId,
'lang' => $lang,
);
$conn = $this->getEntityManager()
->getConnection();
$sql = 'SELECT t.temperatureType AS lang, t.jan AS january, t.feb AS february, t.mar AS march, t.apr AS april, t.may AS may, t.jun AS june, t.jul AS july, t.aug AS august, t.sep AS september, t.oct AS october, t.nov AS november, t.decm AS december
FROM otp_misc.temperatures t
WHERE t.cityId = :city AND t.temperatureType = :lang';
$stmt = $conn->prepare($sql);
foreach ($params as $index => $param) {
$stmt->bindValue($index, $param);
}
return $stmt->execute()->fetchAll();
}
/**
* @param int|null $cityId
* @param string $type
* @return array
*/
public function getTemperaturesByCity($cityId)
{
$params = array(
'cityId' => $cityId,
);
$conn = $this->getEntityManager()
->getConnection();
$sql = 'SELECT t.temperatureType as type, t.jan as Jan, t.feb as Feb, t.mar as Mar, t.apr as Apr, t.may as May, t.jun as Jun, t.jul as Jul, t.aug as Aug, t.sep as Sep, t.oct as Oct, t.nov as Nov, t.decm as "Dec"
FROM otp_misc.temperatures t
WHERE t.cityId = :cityId';
$stmt = $conn->prepare($sql);
foreach ($params as $index => $param) {
$stmt->bindValue($index, $param);
}
return $stmt->execute()->fetchAll();
}
public function getCityNames($market)
{
$conn = $this->getEntityManager()
->getConnection();
$topIds = [];
foreach ($market['mainCities'] as $mainCity) {
if (!is_null($mainCity['id'])) $topIds[] = $mainCity['id'];
}
$sql = 'select d.fDeptCity as id, c.fName as name, c.fNameRd as nameRd
from otp_tours.tOpDeptHotel d
left join otpusk.tCities c ON d.fDeptCity=c.rec_id
where c.fCountryID in ('.implode(',', $market['mainCountries']).')
group by d.fDeptCity';
$stmt = $conn->prepare($sql);
$data = $stmt->execute()->fetchAll();
$results = [];
foreach ($data as $one) {
$results[$one['id']] = array(
'name' => !empty($one['name']) ? $one['name'] : 'любой город',
'nameRd' => !empty($one['nameRd']) ? $one['nameRd'] : 'любого города',
'priority' => (in_array($one['id'], $topIds) ? true : false)
);
}
return $results;
}
public function getCityByIp($ip = null)
{
if (empty($ip)){
$ip = $_SERVER['REMOTE_ADDR'];
}
$project_dir = dirname($_SERVER['DOCUMENT_ROOT']);
if (!is_dir($project_dir)) $project_dir = '/app';
$reader = new Reader($project_dir.'/public/upload/GeoLite2/GeoLite2-City/GeoLite2-City.mmdb');
$record = $reader->city($ip);
$subdivisions = [];
foreach ($record->subdivisions AS $subdivision) $subdivisions[] = [$subdivision->names['ru'],$subdivision->names['en'],$subdivision->isoCode];
$this->res = [
$record->location->latitude, $record->location->longitude,
[$record->continent->names['ru'],$record->continent->names['en'], $record->continent->code],
[$record->country->names['ru'], $record->country->names['en'], $record->country->isoCode],
$subdivisions,
[$record->city->names['ru'], $record->city->names['en']]
];
return $this->getIdByCityName(
$record->city->names['ru'],
$record->city->names['en'],
$record->location->latitude,
$record->location->longitude
);
}
public function getIdByCityName($name, $nameEng, $lat, $long)
{
$sql = $this->createQueryBuilder('c')
->select('c.id AS cityId')
->where('c.fNameEng = :name')
->orWhere('c.fName = :nameEng')
->orWhere('c.fSouthWest >= :latStart AND c.fSouthWest <= :latEnd AND c.fNorthEast >= :longStart AND c.fNorthEast <= :longEnd')
->setParameter('name', $name)
->setParameter('nameEng', $nameEng)
->setParameter('latStart', $lat-0.1)
->setParameter('latEnd', $lat+0.1)
->setParameter('longStart', $long-0.1)
->setParameter('longEnd', $long+0.1)
;
$result = $sql->getQuery()->getResult();
return isset($result[0]['cityId'])?$result[0]['cityId']:null;
}
public function getRes(){
return $this->res;
}
}