vendor/sulu/sulu/src/Sulu/Component/Content/Types/ResourceLocator/Strategy/ResourceLocatorStrategy.php line 207

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\Component\Content\Types\ResourceLocator\Strategy;
  11. use Sulu\Bundle\DocumentManagerBundle\Bridge\DocumentInspector;
  12. use Sulu\Component\Content\Compat\StructureManagerInterface;
  13. use Sulu\Component\Content\ContentTypeManagerInterface;
  14. use Sulu\Component\Content\Document\Behavior\ResourceSegmentBehavior;
  15. use Sulu\Component\Content\Exception\ResourceLocatorAlreadyExistsException;
  16. use Sulu\Component\Content\Exception\ResourceLocatorGeneratorException;
  17. use Sulu\Component\Content\Exception\ResourceLocatorNotFoundException;
  18. use Sulu\Component\Content\Exception\ResourceLocatorNotValidException;
  19. use Sulu\Component\Content\Types\ResourceLocator\Mapper\ResourceLocatorMapperInterface;
  20. use Sulu\Component\DocumentManager\Behavior\Mapping\ParentBehavior;
  21. use Sulu\Component\DocumentManager\DocumentManagerInterface;
  22. use Sulu\Component\PHPCR\PathCleanupInterface;
  23. use Sulu\Component\Util\SuluNodeHelper;
  24. /**
  25.  * Basic implementation for resource-locator-strategies.
  26.  */
  27. abstract class ResourceLocatorStrategy implements ResourceLocatorStrategyInterface
  28. {
  29.     /**
  30.      * @var ResourceLocatorMapperInterface
  31.      */
  32.     protected $mapper;
  33.     /**
  34.      * @var PathCleanupInterface
  35.      */
  36.     protected $cleaner;
  37.     /**
  38.      * @var StructureManagerInterface
  39.      */
  40.     protected $structureManager;
  41.     /**
  42.      * @var ContentTypeManagerInterface
  43.      */
  44.     protected $contentTypeManager;
  45.     /**
  46.      * @var SuluNodeHelper
  47.      */
  48.     protected $nodeHelper;
  49.     /**
  50.      * @var DocumentInspector
  51.      */
  52.     protected $documentInspector;
  53.     /**
  54.      * @var DocumentManagerInterface
  55.      */
  56.     protected $documentManager;
  57.     /**
  58.      * @var ResourceLocatorGeneratorInterface
  59.      */
  60.     private $resourceLocatorGenerator;
  61.     public function __construct(
  62.         ResourceLocatorMapperInterface $mapper,
  63.         PathCleanupInterface $cleaner,
  64.         StructureManagerInterface $structureManager,
  65.         ContentTypeManagerInterface $contentTypeManager,
  66.         SuluNodeHelper $nodeHelper,
  67.         DocumentInspector $documentInspector,
  68.         DocumentManagerInterface $documentManager,
  69.         ResourceLocatorGeneratorInterface $resourceLocatorGenerator
  70.     ) {
  71.         $this->mapper $mapper;
  72.         $this->cleaner $cleaner;
  73.         $this->structureManager $structureManager;
  74.         $this->contentTypeManager $contentTypeManager;
  75.         $this->nodeHelper $nodeHelper;
  76.         $this->documentInspector $documentInspector;
  77.         $this->documentManager $documentManager;
  78.         $this->resourceLocatorGenerator $resourceLocatorGenerator;
  79.     }
  80.     public function generate($title$parentUuid$webspaceKey$languageCode$segmentKey null)
  81.     {
  82.         // title should not have a slash
  83.         $title str_replace('/''-'$title);
  84.         $parentPath $this->getClosestResourceLocator($parentUuid$webspaceKey$languageCode);
  85.         // get generated path from childClass
  86.         $path $this->resourceLocatorGenerator->generate($title$parentPath);
  87.         // cleanup path
  88.         $path $this->cleaner->cleanup($path$languageCode);
  89.         // if no path was added throw an except that no url could be generated for the given title
  90.         if (substr($path0, -1) === $parentPath) {
  91.             throw new ResourceLocatorGeneratorException($title$parentPath);
  92.         }
  93.         // get unique path
  94.         $path $this->mapper->getUniquePath($path$webspaceKey$languageCode$segmentKey);
  95.         return $path;
  96.     }
  97.     /**
  98.      * Returns the closes resourcelocator possible. Skips pages without URLs as internal/external links or unpublished
  99.      * pages.
  100.      *
  101.      * @param string $uuid
  102.      * @param string $webspaceKey
  103.      * @param string $languageCode
  104.      *
  105.      * @return null|string
  106.      */
  107.     private function getClosestResourceLocator($uuid$webspaceKey$languageCode)
  108.     {
  109.         if (!$uuid) {
  110.             return null;
  111.         }
  112.         $document $this->documentManager->find($uuid$languageCode, ['load_ghost_content' => false]);
  113.         do {
  114.             try {
  115.                 return $this->loadByContentUuid($this->documentInspector->getUuid($document), $webspaceKey$languageCode);
  116.             } catch (ResourceLocatorNotFoundException $e) {
  117.                 $document $document->getParent();
  118.             }
  119.         } while ($document instanceof ParentBehavior);
  120.     }
  121.     public function save(ResourceSegmentBehavior $document$userId)
  122.     {
  123.         $path $document->getResourceSegment();
  124.         $webspaceKey $this->documentInspector->getWebspace($document);
  125.         $languageCode $this->documentInspector->getOriginalLocale($document);
  126.         try {
  127.             $treeValue $this->loadByContent($document);
  128.         } catch (ResourceLocatorNotFoundException $e) {
  129.             $treeValue null;
  130.         }
  131.         if ($treeValue === $path) {
  132.             return false;
  133.         }
  134.         if (!$this->isValid($path$webspaceKey$languageCode)) {
  135.             throw new ResourceLocatorNotValidException($path);
  136.         }
  137.         if (!$this->mapper->unique($path$webspaceKey$languageCode)) {
  138.             try {
  139.                 $treeContent $this->loadByResourceLocator($path$webspaceKey$languageCode);
  140.                 // FIXME Required because jackalope-doctrine-dbal does not return references which only exist in the current
  141.                 // session. If it would loadByContent would already return some value, which would make this check obsolete.
  142.                 if ($treeContent === $this->documentInspector->getUuid($document)) {
  143.                     return false;
  144.                 }
  145.                 throw new ResourceLocatorAlreadyExistsException($path$treeContent);
  146.             } catch (ResourceLocatorNotFoundException $exception) {
  147.                 // a node exists but is not a resource-locator.
  148.             }
  149.         }
  150.         $this->mapper->save($document);
  151.     }
  152.     public function loadByContent(ResourceSegmentBehavior $document)
  153.     {
  154.         // delegate to mapper
  155.         return $this->mapper->loadByContent(
  156.             $this->documentInspector->getNode($document),
  157.             $this->documentInspector->getWebspace($document),
  158.             $this->documentInspector->getOriginalLocale($document),
  159.             null
  160.         );
  161.     }
  162.     public function loadByContentUuid($uuid$webspaceKey$languageCode$segmentKey null)
  163.     {
  164.         // delegate to mapper
  165.         return $this->mapper->loadByContentUuid($uuid$webspaceKey$languageCode$segmentKey);
  166.     }
  167.     public function loadHistoryByContentUuid($uuid$webspaceKey$languageCode$segmentKey null)
  168.     {
  169.         return $this->mapper->loadHistoryByContentUuid($uuid$webspaceKey$languageCode$segmentKey);
  170.     }
  171.     public function loadByResourceLocator($resourceLocator$webspaceKey$languageCode$segmentKey null)
  172.     {
  173.         // delegate to mapper
  174.         return $this->mapper->loadByResourceLocator($resourceLocator$webspaceKey$languageCode$segmentKey);
  175.     }
  176.     public function isValid($path$webspaceKey$languageCode$segmentKey null)
  177.     {
  178.         return '/' !== $path && $this->cleaner->validate($path);
  179.     }
  180.     public function deleteById($id$languageCode$segmentKey null)
  181.     {
  182.         $this->mapper->deleteById($id$languageCode$segmentKey);
  183.     }
  184. }