src/Util/Seo.php line 68

Open in your IDE?
  1. <?php
  2. namespace App\Util;
  3. use App\Annotations\Seo\Meta;
  4. use App\Entity\Asset;
  5. use App\Entity\MetaTemplates;
  6. use App\Entity\OgImage;
  7. use App\Entity\OpenGraphInterface;
  8. use App\Entity\Page;
  9. use App\Model\Seo\SerializationContext;
  10. use DateTimeInterface;
  11. use Doctrine\Common\Annotations\AnnotationReader;
  12. use Leogout\Bundle\SeoBundle\Provider\SeoGeneratorProvider;
  13. use Liip\ImagineBundle\Imagine\Cache\CacheManager;
  14. use ReflectionClass;
  15. use ReflectionException;
  16. use ReflectionProperty;
  17. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  18. use Symfony\Component\HttpFoundation\Request;
  19. use Symfony\Component\HttpFoundation\RequestStack;
  20. use Vich\UploaderBundle\Templating\Helper\UploaderHelper;
  21. class Seo
  22. {
  23.     /**
  24.      * @var SeoGeneratorProvider
  25.      */
  26.     protected $seoGenerator;
  27.     /**
  28.      * @var CacheManager
  29.      */
  30.     protected $cacheManager;
  31.     /**
  32.      * @var UploaderHelper
  33.      */
  34.     protected $uploaderHelper;
  35.     /**
  36.      * @var Request
  37.      */
  38.     protected $request;
  39.     /**
  40.      * @var ParameterBagInterface
  41.      */
  42.     private $parameterBag;
  43.     /**
  44.      * Seo constructor.
  45.      */
  46.     public function __construct(
  47.         SeoGeneratorProvider $seoGenerator,
  48.         CacheManager $cacheManager,
  49.         UploaderHelper $uploaderHelper,
  50.         RequestStack $requestStack,
  51.         ParameterBagInterface $parameterBag
  52.     ) {
  53.         $this->seoGenerator $seoGenerator;
  54.         $this->cacheManager $cacheManager;
  55.         $this->uploaderHelper $uploaderHelper;
  56.         $this->request $requestStack->getCurrentRequest();
  57.         $this->parameterBag $parameterBag;
  58.     }
  59.     public function setSeoInformationForPage(array $metaDataPage $page, ?OgImage $defaultOgImage): void
  60.     {
  61.         $pageTitle $metaData['metaTitle'] ?? null;
  62.         if (!$pageTitle) {
  63.             $pageTitle $page->getMetaTitle();
  64.         }
  65.         if (!$pageTitle) {
  66.             $pageTitle $page->getTitle();
  67.         }
  68.         // The metaData.ogImage must be invalid before Page.ogImage is allowed to be used
  69.         if (false === (
  70.             \array_key_exists('ogImage'$metaData)
  71.             && (\is_string($metaData['ogImage']) && '' !== $metaData['ogImage'])
  72.         )
  73.             && $page->getOgImage() instanceof OgImage
  74.         ) {
  75.             $pageOgImage $this->renderOgImage($page->getOgImage(), $page);
  76.             if ('' !== $pageOgImage) {
  77.                 $metaData['ogImage'] = $pageOgImage;
  78.             }
  79.         }
  80.         $ogImage = !empty($metaData['ogImage']) ? $metaData['ogImage'] : null;
  81.         if (\is_object($ogImage) && (is_subclass_of($ogImageAsset::class) || Asset::class === \get_class($ogImage))) {
  82.             /** @var Asset $ogImageAsset */
  83.             $ogImageAsset $metaData['ogImage'];
  84.             $ogImageAssetPath $this->uploaderHelper->asset($ogImageAsset'assetFile');
  85.             if ($ogImageAssetPath) {
  86.                 $ogImage $this->cacheManager->getBrowserPath(
  87.                     $this->uploaderHelper->asset($ogImageAsset'assetFile'),
  88.                     'w1200'
  89.                 );
  90.             }
  91.         }
  92.         // If all other fallbacks fail, use the default og image
  93.         if (empty($ogImage)) {
  94.             if ($defaultOgImage instanceof OgImage &&
  95.                 $defaultOgImage->getImage() instanceof Asset &&
  96.                 null !== $defaultOgImage->getImage()->getFileName()) {
  97.                 $ogImage $this->cacheManager->getBrowserPath(
  98.                     $this->uploaderHelper->asset($defaultOgImage->getImage(), 'assetFile'),
  99.                     'w1200'
  100.                 );
  101.             }
  102.         }
  103.         $this->seoGenerator->get('gn_og')
  104.             ->setTitle(sprintf('%s | %s'$pageTitle$this->parameterBag->get('site_company_name')))
  105.             ->setDescription(
  106.                 strip_tags(!empty($metaData['metaDescription']) ? $metaData['metaDescription'] : $page->getMetaDescription())
  107.             )
  108.             ->setUrl($this->request->getUri())
  109.             ->setImageWithSize(\is_string($ogImage) ? $ogImage '')
  110.             ->setType('website')
  111.         ;
  112.     }
  113.     public function renderOgImage(OgImage $ogImage, ?object $object): string
  114.     {
  115.         if (null === $ogImage->getImage() || null === $ogImage->getImage()->getFileName()) {
  116.             return '';
  117.         }
  118.         $getter 'get'.$ogImage->getField();
  119.         if (!method_exists($object$getter)) {
  120.             return $this->cacheManager->getBrowserPath(
  121.                 $this->uploaderHelper
  122.                     ->asset($ogImage->getImage(), 'assetFile'),
  123.                 'w1200'
  124.             );
  125.         }
  126.         $options = [
  127.             'text' => $object->{$getter}(),
  128.         ];
  129.         if ($ogImage->getTextSize()) {
  130.             $options['text_size'] = $ogImage->getTextSize();
  131.         }
  132.         if ($ogImage->getTextColor()) {
  133.             $options['text_color'] = $ogImage->getTextColor();
  134.         }
  135.         if ($ogImage->getTextPosition()) {
  136.             $options['position'] = $ogImage->getTextPosition();
  137.         }
  138.         return $this->cacheManager->getBrowserPath(
  139.             $this->uploaderHelper
  140.                 ->asset($ogImage->getImage(), 'assetFile'),
  141.             'text_overlay',
  142.             ['text_overlay' => $options]
  143.         );
  144.     }
  145.     /**
  146.      * @param OpenGraphInterface $entity
  147.      *
  148.      * @return array
  149.      */
  150.     public function extractMetaData(MetaTemplates $templatesobject $entity)
  151.     {
  152.         $context = new SerializationContext();
  153.         if (null !== $templates->getDateFormat()) {
  154.             $context->dateFormat $templates->getDateFormat();
  155.         }
  156.         $values $this->calculateFieldValues(
  157.             $entity,
  158.             $context
  159.         );
  160.         $callback = function ($result) use ($values) {
  161.             if (isset($result[1])) {
  162.                 $key trim($result[1]);
  163.                 return !empty($values[$key]) ? $values[$key] : '';
  164.             }
  165.             return '';
  166.         };
  167.         $regex '/\{{([a-zA-Z0-9\s_-]+?)\}}/';
  168.         $metaTitle preg_replace_callback(
  169.             $regex,
  170.             $callback,
  171.             $templates->getTitleTemplate()
  172.         );
  173.         $metaDescription preg_replace_callback(
  174.             $regex,
  175.             $callback,
  176.             $templates->getDescriptionTemplate()
  177.         );
  178.         return [$metaTitle$metaDescription];
  179.     }
  180.     public function calculateFields(string $objectClass): array
  181.     {
  182.         $fields = [];
  183.         /** @var ReflectionProperty $reflectionProperty */
  184.         foreach ($this->getMetaProperties($objectClass) as $reflectionProperty) {
  185.             /** @var Meta $annotation */
  186.             $fieldName $reflectionProperty->getName();
  187.             if (!empty($annotation->name)) {
  188.                 $fieldName $annotation->name;
  189.             }
  190.             $fields[] = $fieldName;
  191.         }
  192.         return $fields;
  193.     }
  194.     private function calculateFieldValues(object $entitySerializationContext $context): array
  195.     {
  196.         $reader = new AnnotationReader();
  197.         $fields = [];
  198.         /** @var ReflectionProperty $metaProperty */
  199.         foreach ($this->getMetaProperties(\get_class($entity)) as $metaProperty) {
  200.             /** @var Meta $annotation */
  201.             $annotation $reader->getPropertyAnnotation($metaPropertyMeta::class);
  202.             $propertyGetter 'get'.$metaProperty->getName();
  203.             if ($entity->$propertyGetter() instanceof DateTimeInterface) {
  204.                 $fields[$metaProperty->getName()] = $entity->$propertyGetter()->format($context->dateFormat);
  205.             } else {
  206.                 $fields[$metaProperty->getName()] = (string) $entity->$propertyGetter();
  207.             }
  208.             if ($annotation->supersededBy) {
  209.                 $getter 'get'.$annotation->supersededBy;
  210.                 if (!method_exists($entity$getter)) {
  211.                     throw new \RuntimeException(sprintf('Function %s for superseding property %s must exist'$getter$annotation->supersededBy));
  212.                 }
  213.                 $supersededValue $entity->$getter();
  214.                 if (!empty($supersededValue)) {
  215.                     $fields[$metaProperty->getName()] = $supersededValue;
  216.                 }
  217.             }
  218.             if ($annotation->name) {
  219.                 $fields[$annotation->name] = $fields[$metaProperty->getName()];
  220.             }
  221.         }
  222.         return $fields;
  223.     }
  224.     private function getMetaProperties(string $objectClass): array
  225.     {
  226.         $reader = new AnnotationReader();
  227.         try {
  228.             $reflectionClass = new ReflectionClass($objectClass);
  229.         } catch (ReflectionException $e) {
  230.             return [];
  231.         }
  232.         $properties = [];
  233.         foreach ($reflectionClass->getProperties() as $reflectionProperty) {
  234.             $annotation $reader->getPropertyAnnotation($reflectionPropertyMeta::class);
  235.             if (!$annotation) {
  236.                 continue;
  237.             }
  238.             $properties[] = $reflectionProperty;
  239.         }
  240.         return $properties;
  241.     }
  242. }