<?php
namespace Aqarmap\Bundle\MainBundle\EventListener;
use Aqarmap\Bundle\DiscussionBundle\Constant\DiscussionStatus;
use Aqarmap\Bundle\ListingBundle\Entity\Listing;
use Aqarmap\Bundle\MainBundle\Service\Setting;
use Aqarmap\Bundle\MainBundle\Service\SiteMapService;
use Doctrine\ORM\EntityManagerInterface;
use Presta\SitemapBundle\Event\SitemapPopulateEvent;
use Presta\SitemapBundle\Sitemap\Url\UrlConcrete;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* Sitemap Listener.
*/
class SiteMapListener implements EventSubscriberInterface
{
/** @var RouterInterface */
private $router;
/** @var EntityManagerInterface */
private $em;
/** @var array */
private $locales;
/** @var SiteMapService */
private $siteMapService;
/**
* @throws \Exception
* @throws \Throwable
*/
public function __construct(
EntityManagerInterface $em,
RouterInterface $router,
TranslatorInterface $translator,
SiteMapService $siteMapService,
Setting $settingService,
ParameterBagInterface $parameterBag
) {
$this->router = $router;
$this->em = $em;
$this->siteMapService = $siteMapService;
$this->locales = $parameterBag->get('locales');
}
public static function getSubscribedEvents()
{
return [
SitemapPopulateEvent::class => 'populate',
];
}
public function populate(SitemapPopulateEvent $event): void
{
$section = $event->getSection() ?: 'default';
if (\in_array($section, ['default', 'neighborhood'])) {
echo 'Generating Neighborhoods Links'.\PHP_EOL;
$this->generateNeighborhoodsLinks($event);
}
if (\in_array($section, ['default', 'latest-listings'])) {
echo 'Generating Latest Listings Links'.\PHP_EOL;
$this->generateLatestListingsLinks($event);
}
if (\in_array($section, ['default', 'search-results', 'search-results-listing-only'])) {
echo 'Generating Search Results Links without locations'.\PHP_EOL;
$this->generateSearchResultLinks($event);
}
if (\in_array($section, ['default', 'search-results-locations', 'search-results-location-listing-only'])) {
echo 'Generating Search Results Links with locations'.\PHP_EOL;
$this->generateSearchResultLocationLinks($event);
}
if (\in_array($section, ['default', 'projects-luxury'])) {
echo 'Generating Luxury Projects Links'.\PHP_EOL;
$this->generateProjectsLuxuryLinks($event);
}
if (\in_array($section, ['default', 'compounds'])) {
echo 'Generating Compounds Links'.\PHP_EOL;
$this->generateCompoundsLinks($event);
}
if (\in_array($section, ['default', 'ask-neighbors'])) {
echo 'Generating Discussions Links'.\PHP_EOL;
$this->generateDiscussionsLinks($event);
}
}
public function generateNeighborhoodsLinks(SitemapPopulateEvent $event): void
{
$neighborhoods = $this->em
->getRepository(\Aqarmap\Bundle\ListingBundle\Entity\Location::class)->getNeighbourhoodLocations();
foreach ($this->locales as $locale) {
foreach ($neighborhoods as $location) {
$url = $this->router->generate(
'neighborhood_main_page',
['location_slug' => $location->getSlug(), '_locale' => $locale],
UrlGeneratorInterface::ABSOLUTE_URL
);
// add homepage url to the urlset named default
$event->getUrlContainer()->addUrl(
new UrlConcrete(
$url,
new \DateTime(),
UrlConcrete::CHANGEFREQ_HOURLY,
0.8
),
'neighborhood'
);
}
}
}
public function generateCompoundsLinks(SitemapPopulateEvent $event): void
{
$compounds = $this
->em
->getRepository(\Aqarmap\Bundle\ListingBundle\Entity\CompoundLocation::class)
->getAllEnabled()
;
foreach ($this->locales as $locale) {
foreach ($compounds as $location) {
$url = $this->router->generate(
'compound_search_with_location',
['location' => $location->getSlug(), '_locale' => $locale],
UrlGeneratorInterface::ABSOLUTE_URL
);
// add homepage url to the urlset named default
$event->getUrlContainer()->addUrl(
new UrlConcrete(
$url,
new \DateTime(),
UrlConcrete::CHANGEFREQ_HOURLY,
0.4
),
'compounds'
);
}
}
}
public function generateLatestListingsLinks(SitemapPopulateEvent $event): void
{
$listings = $this->em
->getRepository(Listing::class)->getLatestListings(100)->getQuery()->getResult();
foreach ($this->locales as $locale) {
foreach ($listings as $listing) {
if (!$listing->getSlug() || empty($listing->getSlug())) {
continue;
}
$url = $this->router->generate(
'listing_slug',
['id' => $listing->getId(), 'slug' => $listing->getSlug(), '_locale' => $locale],
UrlGeneratorInterface::ABSOLUTE_URL
);
// add homepage url to the urlset named default
$event->getUrlContainer()->addUrl(
new UrlConcrete(
$url,
new \DateTime(),
UrlConcrete::CHANGEFREQ_DAILY,
0.5
),
'latest-listings'
);
}
}
}
public function generateSearchResultLocationLinks(SitemapPopulateEvent $event): void
{
foreach ($this->siteMapService->generateSearchResultLocationLinks()->iterate() as $searchResults) {
$searchResults = current($searchResults);
foreach ($this->locales as $locale) {
$url = $this->router->generate(
'search',
['section_slug' => $searchResults['sectionSlug'],
'property_type_slug' => $searchResults['propertyTypeSlug'],
'location_slug' => $searchResults['locationSlug'],
'_locale' => $locale,
],
UrlGeneratorInterface::ABSOLUTE_URL
);
// Set priority based on location level field
$locationPriority = [
/* Cities */
0 => 1,
/* Neighborhoods */
1 => 0.9,
/* Sub Locations */
2 => 0.8,
/* Sub-sub Locations */
3 => 0.7,
/* Sub-sub-sub Locations */
4 => 0.6,
/* Sub-sub-sub-sub Locations */
5 => 0.5,
];
$level = $searchResults['locationLevel'];
// add homepage url to the urlset named default
$event->getUrlContainer()->addUrl(
new UrlConcrete(
$url,
new \DateTime(),
UrlConcrete::CHANGEFREQ_HOURLY,
$locationPriority[$level] ?: 1
),
'search-results-locations'
);
}
}
}
public function generateSearchResultLinks(SitemapPopulateEvent $event): void
{
$sections = $this->em
->getRepository(\Aqarmap\Bundle\ListingBundle\Entity\Section::class)->getSearchableSection();
$propertyTypes = $this->em
->getRepository(\Aqarmap\Bundle\ListingBundle\Entity\PropertyType::class)->getPropertyTypesList();
foreach ($this->locales as $locale) {
foreach ($sections as $section) {
foreach ($propertyTypes as $propertyType) {
$url = $this->router->generate(
'property_type_search',
['section_slug' => $section->getSlug(),
'property_type_slug' => $propertyType->getSlug(),
'_locale' => $locale,
],
UrlGeneratorInterface::ABSOLUTE_URL
);
// add homepage url to the urlset named default
$event->getUrlContainer()->addUrl(
new UrlConcrete(
$url,
new \DateTime(),
UrlConcrete::CHANGEFREQ_HOURLY,
1
),
'search-results'
);
}
$url = $this->router->generate(
'homepage',
['_locale' => $locale],
UrlGeneratorInterface::ABSOLUTE_URL
);
// add homepage url to the urlset named default
$event->getUrlContainer()->addUrl(
new UrlConcrete(
$url,
new \DateTime(),
UrlConcrete::CHANGEFREQ_HOURLY,
1
),
'search-results'
);
$url = $this->router->generate(
'homepage',
['_locale' => $locale],
UrlGeneratorInterface::ABSOLUTE_URL
);
// add homepage url to the urlset named default
$event->getUrlContainer()->addUrl(
new UrlConcrete(
$url,
new \DateTime(),
UrlConcrete::CHANGEFREQ_HOURLY,
1
),
'search-results'
);
}
}
}
public function generateProjectsLuxuryLinks(SitemapPopulateEvent $event): void
{
$sections = $this->em
->getRepository(\Aqarmap\Bundle\ListingBundle\Entity\Section::class)->getNonSearchableSection();
foreach ($this->locales as $locale) {
foreach ($sections as $section) {
$listings = $this->em
->getRepository(Listing::class)->search(['section' => $section])->getQuery()->getResult();
$listings = array_column($listings, 'listing');
foreach ($listings as $listing) {
if ($listing->getSlug()) {
$url = $this->router->generate(
'listing_slug',
[
'id' => $listing->getId(),
'slug' => $listing->getSlug(),
'_locale' => $locale,
],
UrlGeneratorInterface::ABSOLUTE_URL
);
// add homepage url to the urlset named default
$event->getUrlContainer()->addUrl(
new UrlConcrete(
$url,
new \DateTime(),
UrlConcrete::CHANGEFREQ_HOURLY,
1
),
'projects-luxury'
);
}
}
}
}
}
public function generateDiscussionsLinks(SitemapPopulateEvent $event): void
{
$discussions = $this
->em
->getRepository('AqarmapDiscussionBundle:Discussion')
->filter([
'status' => DiscussionStatus::APPROVED,
])
;
foreach ($this->locales as $locale) {
foreach ($discussions as $discussion) {
$url = $this->router->generate(
'neighborhood_discussion_comments',
['discussion' => $discussion->getId(), '_locale' => $locale],
UrlGeneratorInterface::ABSOLUTE_URL
);
$event->getUrlContainer()->addUrl(
new UrlConcrete(
$url,
new \DateTime(),
UrlConcrete::CHANGEFREQ_HOURLY,
0.8
),
'ask-neighbors'
);
}
}
}
public function generateListingsLinks(SitemapPopulateEvent $event): void
{
$listingRepository = $this->em->getRepository(Listing::class);
$count = $listingRepository->countAllLiveListings();
echo 'We have '.$count.' Live Listings'.\PHP_EOL;
$limit = 400;
$chunk = floor($count / $limit);
echo 'We have '.$chunk.' Number of Chunks'.\PHP_EOL;
$locales = $this->locales;
for ($i = 0; $i <= $chunk; ++$i) {
$listings = $listingRepository->getSiteMapListings($limit, $i * $limit)->iterate();
foreach ($listings as $listing) {
/** @var Listing $listing */
$listing = $listing[0];
foreach ($locales as $locale) {
if (!$listing->getSlug() || empty($listing->getSlug())) {
continue;
}
$url = $this->router->generate(
'listing_slug',
[
'id' => $listing->getId(),
'slug' => $listing->getSlug(),
'_locale' => $locale,
],
UrlGeneratorInterface::ABSOLUTE_URL
);
// add homepage url to the urlset named default
$event->getUrlContainer()->addUrl(
new UrlConcrete(
$url,
new \DateTime(),
UrlConcrete::CHANGEFREQ_HOURLY,
0.5
),
'lisitngs-'.$i
);
}
$this->em->detach($listing);
}
echo 'Done with Chunk number '.$i.\PHP_EOL;
}
}
}