<?php
/**
* Created by simpson <simpsonwork@gmail.com>
* Date: 2019-04-18
* Time: 11:17
*/
namespace App\EventSubscriber;
use App\Entity\Location\City;
use App\Entity\Profile\BodyTypes;
use App\Entity\Profile\HairColors;
use App\Entity\Profile\Nationalities;
use App\Entity\Profile\PrivateHaircuts;
use App\Entity\Profile\Profile;
use App\Entity\Service;
use App\Entity\TakeOutLocations;
use App\Entity\Saloon\Saloon;
use App\Repository\CityRepository;
use App\Repository\ProfileRepository;
use App\Repository\SaloonRepository;
use App\Repository\ServiceRepository;
use App\Service\Features;
use Carbon\Carbon;
use Doctrine\Persistence\ManagerRegistry;
use Presta\SitemapBundle\Event\SitemapPopulateEvent;
use Presta\SitemapBundle\Service\UrlContainerInterface;
use Presta\SitemapBundle\Sitemap\Url\UrlConcrete;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
class SitemapSubscriber implements EventSubscriberInterface
{
protected CityRepository $cityRepository;
protected ProfileRepository $profileRepository;
protected SaloonRepository $saloonRepository;
protected ServiceRepository $serviceRepository;
protected string $defaultCity;
private ?array $routeLocales;
public function __construct(
protected UrlGeneratorInterface $urlGenerator,
private Features $features,
ManagerRegistry $registry,
ParameterBagInterface $parameterBag
)
{
$this->defaultCity = $parameterBag->get('default_city');
$this->cityRepository = $registry->getManagerForClass(City::class)->getRepository(City::class);
$this->profileRepository = $registry->getManagerForClass(Profile::class)->getRepository(Profile::class);
$this->saloonRepository = $registry->getManagerForClass(Saloon::class)->getRepository(Saloon::class);
$this->serviceRepository = $registry->getManagerForClass(Service::class)->getRepository(Service::class);
if ($this->features->has_translations()) {
$this->routeLocales = $this->features->sitemap_multiple_locales()
? ['ru', 'en']
: ['ru'];
} else {
$this->routeLocales = null;
}
}
/**
* @inheritDoc
*/
public static function getSubscribedEvents()
{
return [
SitemapPopulateEvent::ON_SITEMAP_POPULATE => 'populate',
];
}
public function populate(SitemapPopulateEvent $event): void
{
$urlContainer = $event->getUrlContainer();
$this->registerCityUrls($urlContainer, UrlConcrete::CHANGEFREQ_DAILY, 0.8);
$this->registerProfileUrls($urlContainer, UrlConcrete::CHANGEFREQ_DAILY, 0.6);
if ($this->features->has_saloons()) {
$this->registerSaloonUrls($urlContainer, UrlConcrete::CHANGEFREQ_DAILY, 0.2);
}
}
private function dateMutable(?\DateTimeImmutable $dateImmutable): ?\DateTime
{
if (null === $dateImmutable) {
return Carbon::now();
}
return Carbon::createFromTimestampUTC($dateImmutable->getTimestamp());
}
private function normalizeUriIdentity(string $value): string
{
$normalized = strtolower(str_replace('_', '-', $value));
return $normalized;
}
private function generateLocalizedUrls(string $canonicalRoute, array $routeParameters)
{
if (null === $this->routeLocales) {
yield $this->urlGenerator->generate($canonicalRoute, $routeParameters, UrlGeneratorInterface::ABSOLUTE_URL);
} else {
foreach ($this->routeLocales as $routeLocale) {
yield $this->urlGenerator->generate("$canonicalRoute.$routeLocale", $routeParameters, UrlGeneratorInterface::ABSOLUTE_URL);
}
}
}
protected function registerCityUrls(UrlContainerInterface $urlContainer, string $changeFrequency, $priority)
{
$lastModified = Carbon::now();
$homepageAsCityList = $this->features->homepage_as_city_list();
foreach ($this->cityRepository->iterateAll() as $city) {
/** @var City $city */
// Если включена фича вывода списка городов на главной странице, добавляем в sitemap для всех городов (в том числе и для дефолтного) страницу фильтра по городу;
// Если фича выключена, то для дефолтного города не добавляем страницу фильтра анкет по городу - она уже будет добавлена как роут "homepage".
if ($homepageAsCityList || !$city->equals($this->defaultCity)) {
foreach ($this->generateLocalizedUrls('profile_list.list_by_city', ['city' => $city->getUriIdentity()]) as $url) {
$urlContainer->addUrl(new UrlConcrete(
$url, $lastModified, $changeFrequency, $priority
), 'cities');
}
}
$this->registerCityLocationUrls($urlContainer, $city, $changeFrequency, 0.6);
$this->registerCityStaticUrls($urlContainer, $city, $changeFrequency, 0.4);
}
}
protected function registerCityLocationUrls(UrlContainerInterface $urlContainer, City $city, string $changeFrequency, $priority)
{
$lastModified = Carbon::now();
foreach ($city->getCounties() as $county) {
foreach ($this->generateLocalizedUrls('profile_list.list_by_county', ['city' => $city->getUriIdentity(), 'county' => $county->getUriIdentity()]) as $url) {
$urlContainer->addUrl(new UrlConcrete(
$url, $lastModified, $changeFrequency, $priority
), 'cities');
}
}
foreach ($city->getDistricts() as $district) {
foreach ($this->generateLocalizedUrls('profile_list.list_by_district', ['city' => $city->getUriIdentity(), 'district' => $district->getUriIdentity()]) as $url) {
$urlContainer->addUrl(new UrlConcrete(
$url, $lastModified, $changeFrequency, $priority
), 'cities');
}
}
foreach ($city->getStations() as $station) {
foreach ($this->generateLocalizedUrls('profile_list.list_by_station', ['city' => $city->getUriIdentity(), 'station' => $station->getUriIdentity()]) as $url) {
$urlContainer->addUrl(new UrlConcrete(
$url, $lastModified, $changeFrequency, $priority
), 'cities');
}
}
foreach ($this->generateLocalizedUrls('map.page', ['city' => $city->getUriIdentity()]) as $url) {
$urlContainer->addUrl(new UrlConcrete(
$url, $lastModified, $changeFrequency, $priority
), 'cities');
}
}
protected function registerCityStaticUrls(UrlContainerInterface $urlContainer, City $city, string $changeFrequency, $priority)
{
$lastModified = Carbon::now();
if ($this->features->has_masseurs()) {
foreach ($this->generateLocalizedUrls('masseur_list.page', ['city' => $city->getUriIdentity()]) as $url) {
$urlContainer->addUrl(new UrlConcrete(
$url, $lastModified, $changeFrequency, $priority
), 'profiles');
}
}
if ($this->features->has_saloons()) {
foreach ($this->generateLocalizedUrls('saloon_list.list_by_city', ['city' => $city->getUriIdentity()]) as $url) {
$urlContainer->addUrl(new UrlConcrete(
$url, $lastModified, $changeFrequency, $priority
), 'profiles');
}
}
if ($this->features->has_archive_page()) {
foreach ($this->generateLocalizedUrls('profile_list.list_archived', ['city' => $city->getUriIdentity()]) as $url) {
$urlContainer->addUrl(new UrlConcrete(
$url, $lastModified, $changeFrequency, $priority
), 'profiles');
}
}
foreach ($this->serviceRepository->iterateAll() as $service) {
/** @var \App\Entity\Service $service */
foreach ($this->generateLocalizedUrls('profile_list.list_by_provided_service', ['city' => $city->getUriIdentity(), 'service' => $service->getUriIdentity()]) as $url) {
$urlContainer->addUrl(new UrlConcrete(
$url, $lastModified, $changeFrequency, $priority
), 'profiles');
}
}
}
protected function registerProfileUrls(UrlContainerInterface $urlContainer, string $changeFrequency, $priority)
{
foreach ($this->profileRepository->sitemapItemsIterator() as $profile) {
foreach ($this->generateLocalizedUrls('profile_preview.page', ['city' => $profile['city_uri'], 'profile' => $profile['uri']]) as $url) {
$urlContainer->addUrl(new UrlConcrete(
$url, $this->dateMutable($profile['updatedAt']), $changeFrequency, $priority
), 'profiles');
}
}
}
protected function registerSaloonUrls(UrlContainerInterface $urlContainer, string $changeFrequency, $priority)
{
foreach ($this->saloonRepository->sitemapItemsIterator() as $saloon) {
foreach ($this->generateLocalizedUrls('saloon_preview.page', ['city' => $saloon['city_uri'], 'saloon' => $saloon['uri']]) as $url) {
$urlContainer->addUrl(new UrlConcrete(
$url, $this->dateMutable($saloon['updatedAt']), $changeFrequency, $priority
), 'saloons');
}
}
}
}