vendor/sulu/sulu/src/Sulu/Bundle/PageBundle/Content/Structure/ExcerptStructureExtension.php line 213

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\PageBundle\Content\Structure;
  11. use PHPCR\NodeInterface;
  12. use Sulu\Bundle\ReferenceBundle\Application\Collector\ReferenceCollectorInterface;
  13. use Sulu\Bundle\ReferenceBundle\Infrastructure\Sulu\ContentType\ReferenceContentTypeInterface;
  14. use Sulu\Bundle\SearchBundle\Search\Factory;
  15. use Sulu\Component\Content\Compat\StructureInterface;
  16. use Sulu\Component\Content\Compat\StructureManagerInterface;
  17. use Sulu\Component\Content\ContentTypeExportInterface;
  18. use Sulu\Component\Content\ContentTypeManagerInterface;
  19. use Sulu\Component\Content\Extension\AbstractExtension;
  20. use Sulu\Component\Content\Extension\ExportExtensionInterface;
  21. use Sulu\Component\Content\Extension\ReferenceExtensionInterface;
  22. use Sulu\Component\Content\Mapper\Translation\TranslatedProperty;
  23. use Sulu\Component\Export\Manager\ExportManagerInterface;
  24. use Sulu\Component\Import\Manager\ImportManagerInterface;
  25. /**
  26. * extends structure with seo content.
  27. */
  28. class ExcerptStructureExtension extends AbstractExtension implements ExportExtensionInterface, ReferenceExtensionInterface
  29. {
  30. /**
  31. * name of structure extension.
  32. */
  33. public const EXCERPT_EXTENSION_NAME = 'excerpt';
  34. /**
  35. * will be filled with data in constructor
  36. * {@inheritdoc}
  37. */
  38. protected $properties = [];
  39. protected $name = self::EXCERPT_EXTENSION_NAME;
  40. protected $additionalPrefix = self::EXCERPT_EXTENSION_NAME;
  41. /**
  42. * @var ContentTypeManagerInterface
  43. */
  44. protected $contentTypeManager;
  45. /**
  46. * @var StructureManagerInterface
  47. */
  48. protected $structureManager;
  49. /**
  50. * @var ExportManagerInterface
  51. */
  52. protected $exportManager;
  53. /**
  54. * @var ImportManagerInterface
  55. */
  56. protected $importManager;
  57. /**
  58. * @var string
  59. */
  60. private $languageNamespace;
  61. /**
  62. * @var string
  63. */
  64. private $languageCode;
  65. /**
  66. * @var Factory
  67. */
  68. private $factory;
  69. public function __construct(
  70. StructureManagerInterface $structureManager,
  71. ContentTypeManagerInterface $contentTypeManager,
  72. ExportManagerInterface $exportManager,
  73. ImportManagerInterface $importManager,
  74. Factory $factory
  75. ) {
  76. $this->contentTypeManager = $contentTypeManager;
  77. $this->structureManager = $structureManager;
  78. $this->exportManager = $exportManager;
  79. $this->importManager = $importManager;
  80. $this->factory = $factory;
  81. }
  82. public function save(NodeInterface $node, $data, $webspaceKey, $languageCode)
  83. {
  84. $this->setLanguageCode($languageCode, 'i18n', null);
  85. $excerptStructure = $this->getExcerptStructure($languageCode);
  86. foreach ($excerptStructure->getProperties() as $property) {
  87. $contentType = $this->contentTypeManager->get($property->getContentTypeName());
  88. if (\array_key_exists($property->getName(), $data)) {
  89. $property->setValue($data[$property->getName()]);
  90. $contentType->write(
  91. $node,
  92. new TranslatedProperty(
  93. $property,
  94. $languageCode,
  95. $this->languageNamespace,
  96. $this->additionalPrefix
  97. ),
  98. null, // userid
  99. $webspaceKey,
  100. $languageCode,
  101. null // segmentkey
  102. );
  103. }
  104. }
  105. }
  106. public function load(NodeInterface $node, $webspaceKey, $languageCode)
  107. {
  108. $excerptStructure = $this->getExcerptStructure($languageCode);
  109. $data = [];
  110. foreach ($excerptStructure->getProperties() as $property) {
  111. $contentType = $this->contentTypeManager->get($property->getContentTypeName());
  112. $contentType->read(
  113. $node,
  114. new TranslatedProperty(
  115. $property,
  116. $languageCode,
  117. $this->languageNamespace,
  118. $this->additionalPrefix
  119. ),
  120. $webspaceKey,
  121. $languageCode,
  122. null // segmentkey
  123. );
  124. $data[$property->getName()] = $property->getValue();
  125. }
  126. return $data;
  127. }
  128. public function setLanguageCode($languageCode, $languageNamespace, $namespace)
  129. {
  130. // lazy load excerpt structure to avoid redeclaration of classes
  131. // should be done before parent::setLanguageCode because it uses the $thi<->properties
  132. // which will be set in initExcerptStructure
  133. $this->initProperties($languageCode);
  134. $this->languageCode = $languageCode;
  135. $this->languageNamespace = $languageNamespace;
  136. parent::setLanguageCode($languageCode, $languageNamespace, $namespace);
  137. }
  138. public function getContentData($container)
  139. {
  140. $container = new ExcerptValueContainer($container);
  141. $data = [];
  142. foreach ($this->getExcerptStructure()->getProperties() as $property) {
  143. if ($container->__isset($property->getName())) {
  144. $property->setValue($container->__get($property->getName()));
  145. $contentType = $this->contentTypeManager->get($property->getContentTypeName());
  146. $data[$property->getName()] = $contentType->getContentData($property);
  147. }
  148. }
  149. return $data;
  150. }
  151. public function getFieldMapping()
  152. {
  153. $mappings = parent::getFieldMapping();
  154. foreach ($this->getExcerptStructure()->getPropertiesByTagName('sulu.search.field') as $property) {
  155. $tag = $property->getTag('sulu.search.field');
  156. $tagAttributes = $tag->getAttributes();
  157. $mappings['excerpt' . \ucfirst($property->getName())] = [
  158. 'type' => isset($tagAttributes['type']) ? $tagAttributes['type'] : 'string',
  159. 'field' => $this->factory->createMetadataExpression(
  160. \sprintf('object.getExtensionsData()["excerpt"]["%s"]', $property->getName())
  161. ),
  162. ];
  163. }
  164. return $mappings;
  165. }
  166. /**
  167. * Returns and caches excerpt-structure.
  168. *
  169. * @param string $locale
  170. *
  171. * @return StructureInterface
  172. */
  173. private function getExcerptStructure($locale = null)
  174. {
  175. if (null === $locale) {
  176. $locale = $this->languageCode;
  177. }
  178. $excerptStructure = $this->structureManager->getStructure(self::EXCERPT_EXTENSION_NAME);
  179. $excerptStructure->setLanguageCode($locale);
  180. return $excerptStructure;
  181. }
  182. /**
  183. * Initiates structure and properties.
  184. *
  185. * @param string $locale
  186. */
  187. private function initProperties($locale)
  188. {
  189. // Reset the properties before new initialization.
  190. $this->properties = [];
  191. foreach ($this->getExcerptStructure($locale)->getProperties() as $property) {
  192. $this->properties[] = $property->getName();
  193. }
  194. }
  195. public function export($properties, $format = null)
  196. {
  197. $container = new ExcerptValueContainer($properties);
  198. $data = [];
  199. foreach ($this->getExcerptStructure()->getProperties() as $property) {
  200. if ($container->__isset($property->getName())) {
  201. $property->setValue($container->__get($property->getName()));
  202. $contentType = $this->contentTypeManager->get($property->getContentTypeName());
  203. if ($this->exportManager->hasExport($property->getContentTypeName(), $format)) {
  204. $options = $this->exportManager->getOptions($property->getContentTypeName(), $format);
  205. $data[$property->getName()] = [
  206. 'name' => $property->getName(),
  207. 'value' => $contentType->exportData($property->getValue()),
  208. 'type' => $property->getContentTypeName(),
  209. 'options' => $options,
  210. ];
  211. }
  212. }
  213. }
  214. return $data;
  215. }
  216. public function getImportPropertyNames()
  217. {
  218. $propertyNames = [];
  219. foreach ($this->getExcerptStructure()->getProperties() as $property) {
  220. $propertyNames[] = $property->getName();
  221. }
  222. return $propertyNames;
  223. }
  224. public function import(NodeInterface $node, $data, $webspaceKey, $languageCode, $format)
  225. {
  226. $this->setLanguageCode($languageCode, 'i18n', null);
  227. foreach ($this->getExcerptStructure()->getProperties() as $property) {
  228. $contentType = $this->contentTypeManager->get($property->getContentTypeName());
  229. if (isset($data[$property->getName()])
  230. && $this->importManager->hasImport($property->getContentTypeName(), $format)
  231. ) {
  232. /* @var ContentTypeExportInterface $contentType */
  233. $contentType->importData(
  234. $node,
  235. new TranslatedProperty(
  236. $property,
  237. $languageCode,
  238. $this->languageNamespace,
  239. $this->additionalPrefix
  240. ),
  241. $data[$property->getName()],
  242. null, // userid
  243. $webspaceKey,
  244. $languageCode,
  245. null // segmentkey
  246. );
  247. }
  248. }
  249. }
  250. public function getReferences(array $data, ReferenceCollectorInterface $referenceCollector, string $propertyPrefix = ''): void
  251. {
  252. foreach ($this->getExcerptStructure()->getProperties(true) as $property) {
  253. $contentType = $this->contentTypeManager->get($property->getContentTypeName());
  254. if (!$contentType instanceof ReferenceContentTypeInterface) {
  255. continue;
  256. }
  257. $property->setValue($data[$property->getName()] ?? null);
  258. $contentType->getReferences(
  259. $property,
  260. $referenceCollector,
  261. $propertyPrefix
  262. );
  263. }
  264. }
  265. }