UiComponent.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\View\Layout\Generator;
  7. use Magento\Framework\View\Element\BlockFactory;
  8. use Magento\Framework\View\Element\UiComponent\ContainerInterface;
  9. use Magento\Framework\View\Element\UiComponent\ContextFactory as UiComponentContextFactory;
  10. use Magento\Framework\View\Element\UiComponentFactory;
  11. use Magento\Framework\View\Element\UiComponentInterface;
  12. use Magento\Framework\View\Layout\Data\Structure as DataStructure;
  13. use Magento\Framework\View\Layout\Element;
  14. use Magento\Framework\View\Layout\Generator\Context as GeneratorContext;
  15. use Magento\Framework\View\Layout\GeneratorInterface;
  16. use Magento\Framework\View\Layout\Reader\Context as ReaderContext;
  17. use Magento\Framework\View\LayoutInterface;
  18. /**
  19. * Class UiComponent
  20. */
  21. class UiComponent implements GeneratorInterface
  22. {
  23. /**
  24. * Generator type
  25. */
  26. const TYPE = 'uiComponent';
  27. /**
  28. * Block container for components
  29. */
  30. const CONTAINER = \Magento\Framework\View\Element\UiComponent\ContainerInterface::class;
  31. /**
  32. * @var UiComponentFactory
  33. */
  34. protected $uiComponentFactory;
  35. /**
  36. * @var UiComponentContextFactory
  37. */
  38. protected $contextFactory;
  39. /**
  40. * @var BlockFactory
  41. */
  42. private $blockFactory;
  43. /**
  44. * Constructor
  45. *
  46. * @param UiComponentFactory $uiComponentFactory
  47. * @param BlockFactory $blockFactory
  48. * @param UiComponentContextFactory $contextFactory
  49. */
  50. public function __construct(
  51. UiComponentFactory $uiComponentFactory,
  52. BlockFactory $blockFactory,
  53. UiComponentContextFactory $contextFactory
  54. ) {
  55. $this->uiComponentFactory = $uiComponentFactory;
  56. $this->blockFactory = $blockFactory;
  57. $this->contextFactory = $contextFactory;
  58. }
  59. /**
  60. * {@inheritdoc}
  61. */
  62. public function getType()
  63. {
  64. return self::TYPE;
  65. }
  66. /**
  67. * Creates UI Component object based on scheduled data and add it to the layout
  68. *
  69. * @param ReaderContext $readerContext
  70. * @param GeneratorContext $generatorContext
  71. * @return $this
  72. */
  73. public function process(ReaderContext $readerContext, GeneratorContext $generatorContext)
  74. {
  75. $scheduledStructure = $readerContext->getScheduledStructure();
  76. $scheduledElements = $scheduledStructure->getElements();
  77. if (!$scheduledElements) {
  78. return $this;
  79. }
  80. $structure = $generatorContext->getStructure();
  81. $layout = $generatorContext->getLayout();
  82. // Instantiate blocks and collect all actions data
  83. /** @var $blocks \Magento\Framework\View\Element\AbstractBlock[] */
  84. $blocks = [];
  85. foreach ($scheduledElements as $elementName => $element) {
  86. list($elementType, $data) = $element;
  87. if ($elementType !== Element::TYPE_UI_COMPONENT) {
  88. continue;
  89. }
  90. $block = $this->generateComponent($structure, $elementName, $data, $layout);
  91. $blocks[$elementName] = $block;
  92. $layout->setBlock($elementName, $block);
  93. $scheduledStructure->unsetElement($elementName);
  94. }
  95. return $this;
  96. }
  97. /**
  98. * Create component object
  99. *
  100. * @param DataStructure $structure
  101. * @param string $elementName
  102. * @param string $data
  103. * @param LayoutInterface $layout
  104. * @return ContainerInterface
  105. */
  106. protected function generateComponent(DataStructure $structure, $elementName, $data, LayoutInterface $layout)
  107. {
  108. $attributes = $data['attributes'];
  109. if (!empty($attributes['group'])) {
  110. $structure->addToParentGroup($elementName, $attributes['group']);
  111. }
  112. $context = $this->contextFactory->create(
  113. [
  114. 'namespace' => $elementName,
  115. 'pageLayout' => $layout
  116. ]
  117. );
  118. /**
  119. * Structure is required for custom component factory like a 'htmlContent'
  120. */
  121. $component = $this->uiComponentFactory->create(
  122. $elementName,
  123. null,
  124. ['context' => $context, 'structure' => $structure]
  125. );
  126. $this->prepareComponent($component);
  127. /** @var ContainerInterface $blockContainer */
  128. $blockContainer = $this->blockFactory->createBlock(static::CONTAINER, ['component' => $component]);
  129. return $blockContainer;
  130. }
  131. /**
  132. * Call prepare method in the component UI
  133. *
  134. * @param UiComponentInterface $component
  135. * @return void
  136. */
  137. protected function prepareComponent(UiComponentInterface $component)
  138. {
  139. $childComponents = $component->getChildComponents();
  140. if (!empty($childComponents)) {
  141. foreach ($childComponents as $child) {
  142. $this->prepareComponent($child);
  143. }
  144. }
  145. $component->prepare();
  146. }
  147. }