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

  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.     /**
  33.      * @var ?string
  34.      */
  35.     private $providerAttribute;
  36.     public function __construct(
  37.         LinkProviderPoolInterface $linkProviderPool,
  38.         bool $isPreview false,
  39.         UrlHelper $urlHelper null,
  40.         ?string $providerAttribute null
  41.     ) {
  42.         $this->linkProviderPool $linkProviderPool;
  43.         $this->isPreview $isPreview;
  44.         $this->urlHelper $urlHelper;
  45.         $this->providerAttribute $providerAttribute;
  46.         if (null === $this->urlHelper) {
  47.             @\trigger_error(
  48.                 'Instantiating the LinkTag class without the $urlHelper argument is deprecated.',
  49.                 \E_USER_DEPRECATED
  50.             );
  51.         }
  52.     }
  53.     public function parseAll(array $attributesByTag$locale)
  54.     {
  55.         $contents $this->preload($attributesByTag$locale);
  56.         $result = [];
  57.         foreach ($attributesByTag as $tag => $attributes) {
  58.             $provider $this->getValue($attributes'provider'self::DEFAULT_PROVIDER);
  59.             $validationState $attributes['sulu-validation-state'] ?? null;
  60.             $hrefParts $this->getPartsFromHref($attributes['href'] ?? null);
  61.             $uuid $hrefParts['uuid'];
  62.             $anchor $hrefParts['anchor'];
  63.             $query $hrefParts['query'];
  64.             if ($uuid && \array_key_exists($provider '-' $uuid$contents)) {
  65.                 $item $contents[$provider '-' $uuid];
  66.                 $url $item->getUrl();
  67.                 if ($this->urlHelper) {
  68.                     $url $this->urlHelper->getAbsoluteUrl($url);
  69.                 }
  70.                 if ($query) {
  71.                     $url .= '?' $query;
  72.                 }
  73.                 if ($anchor) {
  74.                     $url .= '#' $anchor;
  75.                 }
  76.                 $title $item->getTitle();
  77.                 $attributes['href'] = $url;
  78.             } elseif ($this->isPreview && self::VALIDATE_UNPUBLISHED === $validationState) {
  79.                 // render anchor without href to keep styling even if target is not published in preview
  80.                 $title $this->getContent($attributes);
  81.                 $attributes['href'] = null;
  82.             } else {
  83.                 // only render text instead of anchor to prevent dead links on website
  84.                 $result[$tag] = $this->getContent($attributes);
  85.                 continue;
  86.             }
  87.             $htmlAttributes \array_map(
  88.                 function($value$name) use ($attributes) {
  89.                     if (empty($value) || \in_array($name, ['content''sulu-validation-state'])) {
  90.                         return null;
  91.                     }
  92.                     if ('provider' === $name) {
  93.                         if (null === $this->providerAttribute || \array_key_exists($this->providerAttribute$attributes)) {
  94.                             return null;
  95.                         }
  96.                         return \sprintf('%s="%s"'$this->providerAttribute$value);
  97.                     }
  98.                     return \sprintf('%s="%s"'$name$value);
  99.                 },
  100.                 $attributes,
  101.                 \array_keys($attributes)
  102.             );
  103.             $result[$tag] = \sprintf(
  104.                 '<a %s>%s</a>',
  105.                 \implode(' '\array_filter($htmlAttributes)),
  106.                 $this->getValue($attributes'content'$title)
  107.             );
  108.         }
  109.         return $result;
  110.     }
  111.     public function validateAll(array $attributesByTag$locale)
  112.     {
  113.         $items $this->preload($attributesByTag$localefalse);
  114.         $result = [];
  115.         foreach ($attributesByTag as $tag => $attributes) {
  116.             $provider $this->getValue($attributes'provider'self::DEFAULT_PROVIDER);
  117.             $uuid $this->getPartsFromHref($attributes['href'] ?? null)['uuid'];
  118.             if (!$uuid || !\array_key_exists($provider '-' $uuid$items)) {
  119.                 $result[$tag] = self::VALIDATE_REMOVED;
  120.             } elseif (!$items[$provider '-' $uuid]->isPublished()) {
  121.                 $result[$tag] = self::VALIDATE_UNPUBLISHED;
  122.             }
  123.         }
  124.         return $result;
  125.     }
  126.     /**
  127.      * Return items for given attributes.
  128.      *
  129.      * @param array $attributesByTag
  130.      * @param string $locale
  131.      * @param bool $published
  132.      *
  133.      * @return LinkItem[]
  134.      */
  135.     private function preload($attributesByTag$locale$published true)
  136.     {
  137.         $uuidsByType = [];
  138.         foreach ($attributesByTag as $attributes) {
  139.             $provider $this->getValue($attributes'provider'self::DEFAULT_PROVIDER);
  140.             if (!\array_key_exists($provider$uuidsByType)) {
  141.                 $uuidsByType[$provider] = [];
  142.             }
  143.             $uuid $this->getPartsFromHref($attributes['href'] ?? null)['uuid'];
  144.             if ($uuid) {
  145.                 $uuidsByType[$provider][] = $uuid;
  146.             }
  147.         }
  148.         $result = [];
  149.         foreach ($uuidsByType as $provider => $uuids) {
  150.             $items $this->linkProviderPool->getProvider($provider)->preload(
  151.                 \array_unique($uuids),
  152.                 $locale,
  153.                 $published
  154.             );
  155.             foreach ($items as $item) {
  156.                 $result[$provider '-' $item->getId()] = $item;
  157.             }
  158.         }
  159.         return $result;
  160.     }
  161.     /**
  162.      * Returns attribute identified by name or default if not exists.
  163.      *
  164.      * @param string $name
  165.      */
  166.     private function getValue(array $attributes$name$default null)
  167.     {
  168.         if (\array_key_exists($name$attributes) && !empty($attributes[$name])) {
  169.             return $attributes[$name];
  170.         }
  171.         return $default;
  172.     }
  173.     /**
  174.      * Returns content or title of given attributes.
  175.      *
  176.      * @return string
  177.      */
  178.     private function getContent(array $attributes)
  179.     {
  180.         if (\array_key_exists('content'$attributes)) {
  181.             return $attributes['content'];
  182.         }
  183.         return $this->getValue($attributes'title''');
  184.     }
  185.     /**
  186.      * @param mixed $href
  187.      *
  188.      * @return array{uuid: string|null, query: string|null, anchor: string|null}
  189.      */
  190.     private function getPartsFromHref($href): array
  191.     {
  192.         $href = (string) $href ?: null;
  193.         /** @var string[] $hrefParts */
  194.         $hrefParts $href \explode('#'$href2) : [];
  195.         $anchor $hrefParts[1] ?? null;
  196.         $hrefParts $hrefParts \explode('?'$hrefParts[0], 2) : [];
  197.         $uuid $hrefParts[0] ?? null;
  198.         $query $hrefParts[1] ?? null;
  199.         return [
  200.             'uuid' => $uuid,
  201.             'anchor' => $anchor,
  202.             'query' => $query,
  203.         ];
  204.     }
  205. }