<?php
namespace App\EventListener;
use App\Entity\MetaTemplates;
use App\Event\PageEvent;
use App\Service\ParameterService;
use App\Util\Seo;
use Doctrine\ORM\EntityManagerInterface;
use Leogout\Bundle\SeoBundle\Seo\Basic\BasicSeoGenerator;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
class PageSeoEventListener
{
protected BasicSeoGenerator $basicSeoGenerator;
protected Seo $seoUtil;
protected EntityManagerInterface $entityManager;
protected ParameterBagInterface $parameterBag;
/**
* PageSeoEventListener constructor.
*/
public function __construct(
BasicSeoGenerator $basicSeoGenerator,
Seo $seoUtil,
EntityManagerInterface $entityManager,
ParameterBagInterface $parameterBag,
private readonly ParameterService $parameterService,
) {
$this->basicSeoGenerator = $basicSeoGenerator;
$this->seoUtil = $seoUtil;
$this->entityManager = $entityManager;
$this->parameterBag = $parameterBag;
}
public function onPagePreBuild(PageEvent $event)
{
if (!$page = $event->getPage()) {
return;
}
$locale = $event->getRequest()->getLocale();
$titleSuffixes = $this->parameterService->toArray('site_title_suffix');
if (!empty($titleSuffixes[$locale])) {
$titleSuffix = $titleSuffixes[$locale];
}
if (empty($titleSuffix)) {
$titleSuffix = $this->parameterBag->get('site_company_name');
}
$lastResortFallbackTitle = sprintf(
'%s | %s',
$page->getTitle(),
$titleSuffix
);
$metaTitle = null;
if ($page->getMetaTitle()) {
// Sprintf for backwards compatibility from App\Util\Seo
$metaTitle = sprintf(
'%s | %s',
$page->getMetaTitle(),
$titleSuffix
);
}
$metaDescription = $page->getMetaDescription();
// When the event has no entity or the entity does not implement OpenGraphInterface
// or the entity has no function to get the identifier, we cannot proceed
// the page's meta title and description are used
if (
null === $event->getEntity() ||
!method_exists($event->getEntity(), 'getMetaTitle') ||
!method_exists($event->getEntity(), 'getId')
) {
if (!empty($event->getMetadata()['metaTitle'])) {
$metaTitle = sprintf(
'%s | %s',
$event->getMetadata()['metaTitle'],
$titleSuffix
);
}
if (!empty($event->getMetadata()['metaDescription'])) {
$metaDescription = sprintf(
'%s | %s',
$event->getMetadata()['metaDescription'],
$titleSuffix
);
}
$this->basicSeoGenerator
->setTitle($metaTitle ?? $lastResortFallbackTitle)
->setDescription(strip_tags($metaDescription))
;
return;
}
$entity = $event->getEntity();
$entityMetaTitle = null;
if ($entity->getMetaTitle()) {
// Sprintf for backwards compatibility from App\Util\Seo
$entityMetaTitle = sprintf(
'%s | %s',
$entity->getMetaTitle(),
$titleSuffix
);
}
$entityMetaDescription = null;
if (method_exists($event->getEntity(), 'getMetaDescription')) {
$entityMetaDescription = $entity->getMetaDescription();
}
if (!$templates = $this->entityManager->getRepository(MetaTemplates::class)
->findOneBy(['objectClass' => \get_class($entity), 'foreignKey' => $entity->getId()])) {
$templates = $this->entityManager->getRepository(MetaTemplates::class)
->findTemplatesForObjectClass(\get_class($entity));
}
if (!$templates) {
$title = $this->getFallbackValue([
$entityMetaTitle,
$metaTitle,
]);
$description = $this->getFallbackValue([
$entityMetaDescription,
$metaDescription,
]);
$this->basicSeoGenerator
->setTitle($title ?? $lastResortFallbackTitle)
->setDescription($description ? strip_tags($description) : '')
;
return;
}
// Do not do sprintf's with company name, this can easily be managed in the templates
[$renderedMetaTitle, $renderedMetaDescription] = $this->seoUtil->extractMetaData($templates, $entity);
$title = $this->getFallbackValue([
$entityMetaTitle,
$renderedMetaTitle,
$metaTitle,
]);
$description = $this->getFallbackValue([
$entityMetaDescription,
$renderedMetaDescription,
$metaDescription,
]);
$this->basicSeoGenerator
->setTitle($title ?? $lastResortFallbackTitle)
->setDescription($description ? strip_tags($description) : '')
;
}
/**
* @param string[] $values
*/
private function getFallbackValue(array $values): ?string
{
$values = array_filter($values);
if (empty($values)) {
return null;
}
return reset($values);
}
}