vendor/sulu/sulu/src/Sulu/Bundle/MarkupBundle/Markup/LinkTag.php line 61

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of Sulu.
  4.  *
  5.  * (c) Sulu GmbH
  6.  *
  7.  * This source file is subject to the MIT license that is bundled
  8.  * with this source code in the file LICENSE.
  9.  */
  10. namespace Sulu\Bundle\MarkupBundle\Markup;
  11. use Sulu\Bundle\MarkupBundle\Markup\Link\LinkItem;
  12. use Sulu\Bundle\MarkupBundle\Markup\Link\LinkProviderPoolInterface;
  13. use Sulu\Bundle\MarkupBundle\Tag\TagInterface;
  14. use Symfony\Component\HttpFoundation\UrlHelper;
  15. class LinkTag implements TagInterface
  16. {
  17.     public const VALIDATE_UNPUBLISHED 'unpublished';
  18.     public const VALIDATE_REMOVED 'removed';
  19.     public const DEFAULT_PROVIDER 'page';
  20.     /**
  21.      * @var LinkProviderPoolInterface
  22.      */
  23.     private $linkProviderPool;
  24.     /**
  25.      * @var bool
  26.      */
  27.     private $isPreview;
  28.     /**
  29.      * @var UrlHelper
  30.      */
  31.     private $urlHelper;
  32.     public function __construct(
  33.         LinkProviderPoolInterface $linkProviderPool,
  34.         bool $isPreview false,
  35.         UrlHelper $urlHelper null
  36.     ) {
  37.         $this->linkProviderPool $linkProviderPool;
  38.         $this->isPreview $isPreview;
  39.         $this->urlHelper $urlHelper;
  40.         if (null === $this->urlHelper) {
  41.             @\trigger_error(
  42.                 'Instantiating the LinkTag class without the $urlHelper argument is deprecated.',
  43.                 \E_USER_DEPRECATED
  44.             );
  45.         }
  46.     }
  47.     public function parseAll(array $attributesByTag$locale)
  48.     {
  49.         $contents $this->preload($attributesByTag$locale);
  50.         $result = [];
  51.         foreach ($attributesByTag as $tag => $attributes) {
  52.             $provider $this->getValue($attributes'provider'self::DEFAULT_PROVIDER);
  53.             $validationState $attributes['sulu-validation-state'] ?? null;
  54.             $hrefParts $this->getUuidAndAnchorFromHref($attributes['href'] ?? null);
  55.             $uuid $hrefParts['uuid'];
  56.             $anchor $hrefParts['anchor'];
  57.             if ($uuid && \array_key_exists($provider '-' $uuid$contents)) {
  58.                 $item $contents[$provider '-' $uuid];
  59.                 $url $item->getUrl();
  60.                 if ($this->urlHelper) {
  61.                     $url $this->urlHelper->getAbsoluteUrl($url);
  62.                 }
  63.                 if ($anchor) {
  64.                     $url .= '#' $anchor;
  65.                 }
  66.                 $title $item->getTitle();
  67.                 $attributes['href'] = $url;
  68.                 $attributes['title'] = $this->getValue($attributes'title'$title);
  69.             } elseif ($this->isPreview && self::VALIDATE_UNPUBLISHED === $validationState) {
  70.                 // render anchor without href to keep styling even if target is not published in preview
  71.                 $title $this->getContent($attributes);
  72.                 $attributes['href'] = null;
  73.                 $attributes['title'] = $this->getValue($attributes'title');
  74.             } else {
  75.                 // only render text instead of anchor to prevent dead links on website
  76.                 $result[$tag] = $this->getContent($attributes);
  77.                 continue;
  78.             }
  79.             $htmlAttributes \array_map(
  80.                 function($value$name) {
  81.                     if (\in_array($name, ['provider''content''sulu-validation-state']) || empty($value)) {
  82.                         return null;
  83.                     }
  84.                     return \sprintf('%s="%s"'$name$value);
  85.                 },
  86.                 $attributes,
  87.                 \array_keys($attributes)
  88.             );
  89.             $result[$tag] = \sprintf(
  90.                 '<a %s>%s</a>',
  91.                 \implode(' '\array_filter($htmlAttributes)),
  92.                 $this->getValue($attributes'content'$title)
  93.             );
  94.         }
  95.         return $result;
  96.     }
  97.     public function validateAll(array $attributesByTag$locale)
  98.     {
  99.         $items $this->preload($attributesByTag$localefalse);
  100.         $result = [];
  101.         foreach ($attributesByTag as $tag => $attributes) {
  102.             $provider $this->getValue($attributes'provider'self::DEFAULT_PROVIDER);
  103.             $uuid $this->getUuidAndAnchorFromHref($attributes['href'] ?? null)['uuid'];
  104.             if (!$uuid || !\array_key_exists($provider '-' $uuid$items)) {
  105.                 $result[$tag] = self::VALIDATE_REMOVED;
  106.             } elseif (!$items[$provider '-' $uuid]->isPublished()) {
  107.                 $result[$tag] = self::VALIDATE_UNPUBLISHED;
  108.             }
  109.         }
  110.         return $result;
  111.     }
  112.     /**
  113.      * Return items for given attributes.
  114.      *
  115.      * @param array $attributesByTag
  116.      * @param string $locale
  117.      * @param bool $published
  118.      *
  119.      * @return LinkItem[]
  120.      */
  121.     private function preload($attributesByTag$locale$published true)
  122.     {
  123.         $uuidsByType = [];
  124.         foreach ($attributesByTag as $attributes) {
  125.             $provider $this->getValue($attributes'provider'self::DEFAULT_PROVIDER);
  126.             if (!\array_key_exists($provider$uuidsByType)) {
  127.                 $uuidsByType[$provider] = [];
  128.             }
  129.             $uuid $this->getUuidAndAnchorFromHref($attributes['href'] ?? null)['uuid'];
  130.             if ($uuid) {
  131.                 $uuidsByType[$provider][] = $uuid;
  132.             }
  133.         }
  134.         $result = [];
  135.         foreach ($uuidsByType as $provider => $uuids) {
  136.             $items $this->linkProviderPool->getProvider($provider)->preload(
  137.                 \array_unique($uuids),
  138.                 $locale,
  139.                 $published
  140.             );
  141.             foreach ($items as $item) {
  142.                 $result[$provider '-' $item->getId()] = $item;
  143.             }
  144.         }
  145.         return $result;
  146.     }
  147.     /**
  148.      * Returns attribute identified by name or default if not exists.
  149.      *
  150.      * @param string $name
  151.      */
  152.     private function getValue(array $attributes$name$default null)
  153.     {
  154.         if (\array_key_exists($name$attributes) && !empty($attributes[$name])) {
  155.             return $attributes[$name];
  156.         }
  157.         return $default;
  158.     }
  159.     /**
  160.      * Returns content or title of given attributes.
  161.      *
  162.      * @return string
  163.      */
  164.     private function getContent(array $attributes)
  165.     {
  166.         if (\array_key_exists('content'$attributes)) {
  167.             return $attributes['content'];
  168.         }
  169.         return $this->getValue($attributes'title''');
  170.     }
  171.     /**
  172.      * @param mixed $href
  173.      *
  174.      * @return array{uuid: string|null, anchor: string|null}
  175.      */
  176.     private function getUuidAndAnchorFromHref($href): array
  177.     {
  178.         $href = (string) $href ?: null;
  179.         /** @var string[] $hrefParts */
  180.         $hrefParts $href \explode('#'$href2) : [];
  181.         $uuid $hrefParts[0] ?? null;
  182.         $anchor $hrefParts[1] ?? null;
  183.         return [
  184.             'uuid' => $uuid,
  185.             'anchor' => $anchor,
  186.         ];
  187.     }
  188. }