src/Twig/SeoExtension.php line 61

Open in your IDE?
  1. <?php
  2. /**
  3.  * Created by simpson <simpsonwork@gmail.com>
  4.  * Date: 2019-03-28
  5.  * Time: 16:32
  6.  */
  7. namespace App\Twig;
  8. use App\Entity\SEO\PageMetadata;
  9. use App\Entity\Location\City;
  10. use App\Entity\Profile\BodyTypes;
  11. use App\Entity\Profile\HairColors;
  12. use App\Service\CanonicalUrlGenerator;
  13. use App\Service\PageMetadataGenerator;
  14. use Symfony\Contracts\Translation\TranslatorInterface;
  15. use Symfony\Component\HttpFoundation\RequestStack;
  16. use Twig\Extension\AbstractExtension;
  17. use Twig\TwigFilter;
  18. use Twig\TwigFunction;
  19. class SeoExtension extends AbstractExtension
  20. {
  21.     public function __construct(
  22.         protected PageMetadataGenerator $metadataGenerator,
  23.         protected RequestStack $requestStack,
  24.         protected CanonicalUrlGenerator $canonicalUrlGenerator,
  25.         protected TranslatorInterface $translator
  26.     ) {}
  27.     public function getFunctions()
  28.     {
  29.         return [
  30.             new TwigFunction('canonical_url', [$this, 'canonicalUrl']),
  31.             new TwigFunction('city_profiles_canonical_url', [$this, 'cityProfilesCanonicalUrl']),
  32.             new TwigFunction('seo_title', [$this, 'metaTitle']),
  33.             new TwigFunction('_seo_title_fallback', [$this, 'metaTitleFallback']),
  34.             new TwigFunction('seo_description', [$this, 'metaDescription']),
  35.             new TwigFunction('_seo_description_fallback', [$this, 'metaDescriptionFallback']),
  36.             new TwigFunction('seo_keywords', [$this, 'metaKeywords']),
  37.             new TwigFunction('_seo_keywords_fallback', [$this, 'metaKeywordsFallback']),
  38.             new TwigFunction('seo_heading', [$this, 'pageHeading'], ['is_safe' => ['html']]),
  39.             new TwigFunction('_seo_heading_fallback', [$this, 'pageHeadingFallback'], ['is_safe' => ['html']]),
  40.             new TwigFunction('seo_heading_profile', [$this, 'profileHeadingGenerator']),
  41.             new TwigFunction('seo_top', [$this, 'topHtml'], ['is_safe' => ['html']]),
  42.             new TwigFunction('seo_footer', [$this, 'bottomHtml'], ['is_safe' => ['html']]),
  43.         ];
  44.     }
  45.     public function getFilters()
  46.     {
  47.         return [
  48.             new TwigFilter('seo_morphing', [$this, 'morphing']),
  49.         ];
  50.     }
  51.     public function canonicalUrl(string $host = null): string
  52.     {
  53.         return $this->canonicalUrlGenerator->generate($host);
  54.     }
  55.     public function cityProfilesCanonicalUrl(City $city, string $host = null): string
  56.     {
  57.         return $this->canonicalUrlGenerator->generateCityProfiles($city, $host);
  58.     }
  59.     public function morphing($variants, int $index): string
  60.     {
  61.         if (empty($variants)) {
  62.             return '';
  63.         }
  64.         if (!is_array($variants)) {
  65.             if (!is_string($variants)) {
  66.                 throw new \InvalidArgumentException(sprintf('Unexpected type %s for morphing variants.', gettype($variants)));
  67.             }
  68.             $variants = explode('|', $variants);
  69.         }
  70.         return $variants[$index % count($variants)];
  71.     }
  72.     public function topHtml(): ?string
  73.     {
  74.         $page = $this->getPage();
  75.         if ($page) {
  76.             $text = $this->processRawText($page->getTopHtml());
  77.             if (!empty($text)) {
  78.                 return $text;
  79.             }
  80.         }
  81.         return $this->metadataGenerator->topHtml();
  82.     }
  83.     public function bottomHtml(): ?string
  84.     {
  85.         $page = $this->getPage();
  86.         if ($page) {
  87.             $text = $this->processRawText($page->getBottomHtml());
  88.             if (!empty($text)) {
  89.                 return $text;
  90.             }
  91.         }
  92.         return $this->metadataGenerator->bottomHtml();
  93.     }
  94.     public function metaTitleFallback(): ?string
  95.     {
  96.         $page = $this->getFallbackPage();
  97.         if (!$page) {
  98.             return null;
  99.         }
  100.         $text = $this->processRawText($page->getMetaTitle());
  101.         if (empty($text)) {
  102.             return null;
  103.         }
  104.         return $text;
  105.     }
  106.     public function metaTitle(): ?string
  107.     {
  108.         $page = $this->getPage();
  109.         if ($page) {
  110.             $text = $this->processRawText($page->getMetaTitle());
  111.             if (!empty($text)) {
  112.                 return $text;
  113.             }
  114.         }
  115.         return $this->metadataGenerator->metaTitle();
  116.     }
  117.     public function metaDescriptionFallback(): ?string
  118.     {
  119.         $page = $this->getFallbackPage();
  120.         if (!$page) {
  121.             return null;
  122.         }
  123.         $text = $this->processRawText($page->getMetaDescription());
  124.         if (empty($text)) {
  125.             return null;
  126.         }
  127.         return $text;
  128.     }
  129.     public function metaDescription(): ?string
  130.     {
  131.         $page = $this->getPage();
  132.         if ($page) {
  133.             $text = $this->processRawText($page->getMetaDescription());
  134.             if (!empty($text)) {
  135.                 return $text;
  136.             }
  137.         }
  138.         return $this->metadataGenerator->metaDescription();
  139.     }
  140.     public function metaKeywordsFallback(): ?string
  141.     {
  142.         $page = $this->getFallbackPage();
  143.         if (!$page) {
  144.             return null;
  145.         }
  146.         $text = $this->processRawText($page->getMetaKeywords());
  147.         if (empty($text)) {
  148.             return null;
  149.         }
  150.         return $text;
  151.     }
  152.     public function metaKeywords(): ?string
  153.     {
  154.         $page = $this->getPage();
  155.         if ($page) {
  156.             $text = $this->processRawText($page->getMetaKeywords());
  157.             if (!empty($text)) {
  158.                 return $text;
  159.             }
  160.         }
  161.         return $this->metadataGenerator->metaKeywords();
  162.     }
  163.     public function pageHeadingFallback(): ?string
  164.     {
  165.         $page = $this->getFallbackPage();
  166.         if (!$page) {
  167.             return null;
  168.         }
  169.         $text = $this->processRawText($page->getPageHeading());
  170.         if (empty($text)) {
  171.             return null;
  172.         }
  173.         return $text;
  174.     }
  175.     public function pageHeading(): ?string
  176.     {
  177.         $page = $this->getPage();
  178.         if ($page) {
  179.             $text = $this->processRawText($page->getPageHeading());
  180.             if (!empty($text)) {
  181.                 return $text;
  182.             }
  183.         }
  184.         return $this->metadataGenerator->pageHeading();
  185.     }
  186.     /**
  187.      * Функция генератор заголовков H1 для страницы Профиля модели
  188.      *
  189.      * Функция получает объект profile(данные модели)
  190.      * На выход отдаёт строку для H1
  191.      *
  192.      * таск https://redminez.net/issues/27126#note-2
  193.      */
  194.     public function profileHeadingGenerator($model): string
  195.     {
  196.         if (empty($model)) {
  197.             return '';
  198.         }
  199.         $LOW_TRIGGER_PRICE = 1500;
  200.         $HIGH_TRIGGER_PRICE = 5000;
  201.         $title = $this->translator->trans($model->isMasseur() ? 'массажистка' : 'проститутка', [], 'seo_heading');
  202.         $age = $model->getPersonParameters()->getAge();
  203.         $bodyType = BodyTypes::getLabel($model->getPersonParameters()->getBodyType()); // 1.худая 2стройная 3спорт 4плотная 5толстая
  204.         $hairColor = HairColors::getLabel($model->getPersonParameters()->getHairColor()); // 1брюнетка,5блонд
  205.         $priceTakeOut = $model->getTakeOutPricing()->getOneHourPrice();
  206.         $priceApart = $model->getApartmentsPricing()->getOneHourPrice();
  207.         $prefix = null;
  208.         if ( $priceApart >= $HIGH_TRIGGER_PRICE and !is_null($priceApart) ){
  209.             $prefix = 'VIP';
  210.         }
  211.         else if ( $priceTakeOut >= $HIGH_TRIGGER_PRICE and !is_null($priceTakeOut)  ){
  212.             $prefix = 'VIP';
  213.         }
  214.         else if ( $priceApart <= $LOW_TRIGGER_PRICE and !is_null($priceApart)  ){
  215.             $prefix = $this->translator->trans('Дешевая', [], 'seo_heading');
  216.         }
  217.         else if ( $priceTakeOut <= $LOW_TRIGGER_PRICE and !is_null($priceTakeOut)  ){
  218.             $prefix = $this->translator->trans('Дешевая', [], 'seo_heading');
  219.         }
  220.         else if ( $bodyType == 2 and ($hairColor == 'BLONDE' or $hairColor == 'BRUNETTE') ){
  221.             $prefix = $this->translator->trans('Красивая', [], 'seo_heading');
  222.         }
  223.         else if ( $age < 20 ){
  224.             $prefix = $this->translator->trans('Молодая', [], 'seo_heading');
  225.         }
  226.         else if ( $age > 35 ){
  227.             $prefix = $this->translator->trans('Взрослая', [], 'seo_heading');
  228.         }
  229.         else if ( $bodyType ){
  230.             $prefix = $this->translator->trans($bodyType, [], 'body_types');
  231.         }
  232.         $translationParameters = [
  233.             'prefix' => $prefix,
  234.             'title' => $title,
  235.         ];
  236.         $translation = $this->translator->trans($prefix ? 'complex_name_prefix' : 'name_prefix', $translationParameters, 'profile');
  237.         return ucfirst($translation);
  238.     }
  239.     private function getPage(): ?PageMetadata
  240.     {
  241.         $request = $this->requestStack->getMasterRequest();
  242.         if (!$request) {
  243.             return null;
  244.         }
  245.         return $request->attributes->get(PageMetadata::PAGE_REQUEST_ATTRIBUTE);
  246.     }
  247.     private function getFallbackPage(): ?PageMetadata
  248.     {
  249.         $request = $this->requestStack->getMasterRequest();
  250.         if (!$request) {
  251.             return null;
  252.         }
  253.         return $request->attributes->get(PageMetadata::FALLBACK_REQUEST_ATTRIBUTE);
  254.     }
  255.     private function replaceDateVariables(string $text): string
  256.     {
  257.         static $variables = [];
  258.         if (empty($variables)) {
  259.             [$year, $month, $day, $weekday] = explode('-', date('Y-m-d-l'));
  260.             $variables = [
  261.                 'current_year' => $year,
  262.                 'current_month' => $month,
  263.                 'current_day' => $day,
  264.                 'current_weekday' => $weekday,
  265.             ];
  266.         }
  267.         return preg_replace_callback('#\{\{\s*([a-z_]+)\s*}}#i', static function ($match) use ($variables) {
  268.             return $variables[$match[1]] ?? $match[0];
  269.         }, $text);
  270.     }
  271.     private function processRawText(string $rawText): ?string
  272.     {
  273.         $text = $this->replaceDateVariables($rawText);
  274.         return $this->translator->trans($text);
  275.     }
  276. }