vendor/sulu/sulu/src/Sulu/Component/Content/Metadata/Factory/StructureMetadataFactory.php line 90

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\Metadata\Factory;
  11. use Doctrine\Common\Inflector\Inflector;
  12. use Symfony\Component\Config\ConfigCache;
  13. use Symfony\Component\Config\FileLocator;
  14. use Symfony\Component\Config\Loader\LoaderInterface;
  15. use Symfony\Component\Config\Resource\FileResource;
  16. /**
  17.  * Create new (mapped) structures using the provided loader.
  18.  */
  19. class StructureMetadataFactory implements StructureMetadataFactoryInterface
  20. {
  21.     /**
  22.      * @var array
  23.      */
  24.     private $typePaths = [];
  25.     /**
  26.      * @var string
  27.      */
  28.     private $cachePath;
  29.     /**
  30.      * @var LoaderInterface
  31.      */
  32.     private $loader;
  33.     /**
  34.      * @var bool
  35.      */
  36.     private $debug;
  37.     /**
  38.      * @var array
  39.      */
  40.     private $defaultTypes;
  41.     /**
  42.      * @var array
  43.      */
  44.     private $cache = [];
  45.     public function __construct(
  46.         LoaderInterface $loader,
  47.         array $typePaths,
  48.         array $defaultTypes,
  49.         $cachePath,
  50.         $debug false
  51.     ) {
  52.         $this->typePaths $typePaths;
  53.         $this->cachePath $cachePath;
  54.         $this->loader $loader;
  55.         $this->debug $debug;
  56.         $this->defaultTypes $defaultTypes;
  57.     }
  58.     public function getStructureMetadata($type$structureType null)
  59.     {
  60.         $cacheKey $type $structureType;
  61.         if (isset($this->cache[$cacheKey])) {
  62.             return $this->cache[$cacheKey];
  63.         }
  64.         $this->assertExists($type);
  65.         if (!$structureType) {
  66.             $structureType $this->getDefaultStructureType($type);
  67.         }
  68.         if (!$structureType) {
  69.             return;
  70.         }
  71.         $cachePath sprintf(
  72.             '%s%s%s%s',
  73.             $this->cachePath,
  74.             DIRECTORY_SEPARATOR,
  75.             Inflector::camelize($type),
  76.             Inflector::camelize($structureType)
  77.         );
  78.         $cache = new ConfigCache($cachePath$this->debug);
  79.         if ($this->debug || !$cache->isFresh()) {
  80.             $paths $this->getPaths($type);
  81.             // reverse paths, so that the last path overrides previous ones
  82.             $fileLocator = new FileLocator(array_reverse($paths));
  83.             try {
  84.                 $filePath $fileLocator->locate(sprintf('%s.xml'$structureType));
  85.             } catch (\InvalidArgumentException $e) {
  86.                 throw new Exception\StructureTypeNotFoundException(
  87.                     sprintf(
  88.                         'Could not load structure type "%s" for document type "%s", looked in "%s"',
  89.                         $structureType,
  90.                         $type,
  91.                         implode('", "'$paths)
  92.                     ), null$e
  93.                 );
  94.             }
  95.             $metadata $this->loader->load($filePath$type);
  96.             $resources = [new FileResource($filePath)];
  97.             $cache->write(
  98.                 serialize($metadata),
  99.                 $resources
  100.             );
  101.         }
  102.         $structure unserialize(file_get_contents($cachePath));
  103.         $this->cache[$cacheKey] = $structure;
  104.         return $structure;
  105.     }
  106.     public function getStructures($type)
  107.     {
  108.         $structureNames $this->getStructureNames($type);
  109.         $structures = [];
  110.         foreach ($structureNames as $structureName) {
  111.             $structures[] = $this->getStructureMetadata($type$structureName);
  112.         }
  113.         return $structures;
  114.     }
  115.     public function getStructureTypes(): array
  116.     {
  117.         return array_keys($this->typePaths);
  118.     }
  119.     public function hasStructuresFor($type)
  120.     {
  121.         return isset($this->typePaths[$type]);
  122.     }
  123.     /**
  124.      * Return the structure names for the given type
  125.      * (not necessarily valid).
  126.      *
  127.      * @param string $type
  128.      *
  129.      * @return string[]
  130.      */
  131.     private function getStructureNames($type)
  132.     {
  133.         $this->assertExists($type);
  134.         $structureNames = [];
  135.         foreach ($this->typePaths[$type] as $pathConfig) {
  136.             $structurePath $pathConfig['path'];
  137.             // Ignore not-existing paths
  138.             if (!file_exists($structurePath)) {
  139.                 continue;
  140.             }
  141.             $iterator = new \DirectoryIterator($structurePath);
  142.             foreach ($iterator as $file) {
  143.                 $ext $file->getExtension();
  144.                 if ('xml' !== $ext) {
  145.                     continue;
  146.                 }
  147.                 $structureNames[] = $file->getBasename('.' $ext);
  148.             }
  149.         }
  150.         return $structureNames;
  151.     }
  152.     /**
  153.      * Assert type exists.
  154.      *
  155.      * @param string $type
  156.      */
  157.     private function assertExists($type)
  158.     {
  159.         if (!isset($this->typePaths[$type])) {
  160.             throw new Exception\DocumentTypeNotFoundException(
  161.                 sprintf(
  162.                     'Structure path for document type "%s" is not mapped. Mapped structure types: "%s"',
  163.                     $type,
  164.                     implode('", "'array_keys($this->typePaths))
  165.                 )
  166.             );
  167.         }
  168.     }
  169.     /**
  170.      * Get the paths from the type path configuration.
  171.      *
  172.      * @param string $type
  173.      *
  174.      * @return array
  175.      */
  176.     private function getPaths($type)
  177.     {
  178.         $typeConfigs $this->typePaths[$type];
  179.         $paths = [];
  180.         foreach ($typeConfigs as $typeConfig) {
  181.             $paths[] = $typeConfig['path'];
  182.         }
  183.         return $paths;
  184.     }
  185.     /**
  186.      * Return the default structure type for the the given document type.
  187.      *
  188.      * @param string $type
  189.      *
  190.      * @return string|null
  191.      */
  192.     private function getDefaultStructureType($type)
  193.     {
  194.         if (!isset($this->defaultTypes[$type])) {
  195.             return;
  196.         }
  197.         return $this->defaultTypes[$type];
  198.     }
  199. }