AbstractComponent.php 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Ui\Component;
  7. use Magento\Framework\DataObject;
  8. use Magento\Framework\Exception\LocalizedException;
  9. use Magento\Framework\View\Element\UiComponentFactory;
  10. use Magento\Framework\View\Element\UiComponentInterface;
  11. use Magento\Framework\View\Element\UiComponent\ContextInterface;
  12. use Magento\Framework\View\Element\UiComponent\DataSourceInterface;
  13. use Magento\Framework\View\Element\UiComponent\ObserverInterface;
  14. use Magento\Framework\Data\ValueSourceInterface;
  15. /**
  16. * Abstract class AbstractComponent
  17. *
  18. * @api
  19. * @SuppressWarnings(PHPMD.NumberOfChildren)
  20. * @since 100.0.2
  21. */
  22. abstract class AbstractComponent extends DataObject implements UiComponentInterface
  23. {
  24. /**
  25. * Render context
  26. *
  27. * @var ContextInterface
  28. */
  29. protected $context;
  30. /**
  31. * @var UiComponentInterface[]
  32. */
  33. protected $components;
  34. /**
  35. * @var array
  36. */
  37. protected $componentData = [];
  38. /**
  39. * @var DataSourceInterface[]
  40. */
  41. protected $dataSources = [];
  42. /**
  43. * Constructor
  44. *
  45. * @param ContextInterface $context
  46. * @param UiComponentInterface[] $components
  47. * @param array $data
  48. */
  49. public function __construct(
  50. ContextInterface $context,
  51. array $components = [],
  52. array $data = []
  53. ) {
  54. $this->context = $context;
  55. $this->components = $components;
  56. $this->_data = array_replace_recursive($this->_data, $data);
  57. $this->initObservers($this->_data);
  58. }
  59. /**
  60. * Get component context
  61. *
  62. * @return ContextInterface
  63. */
  64. public function getContext()
  65. {
  66. return $this->context;
  67. }
  68. /**
  69. * Get component name
  70. *
  71. * @return string
  72. */
  73. public function getName()
  74. {
  75. return $this->getData('name');
  76. }
  77. /**
  78. * Prepare component configuration
  79. *
  80. * @return void
  81. */
  82. public function prepare()
  83. {
  84. $config = $this->getData('config');
  85. if (isset($config['value']) && $config['value'] instanceof ValueSourceInterface) {
  86. $config['value'] = $config['value']->getValue($this->getName());
  87. }
  88. $this->setData('config', (array)$config);
  89. $jsConfig = $this->getJsConfig($this);
  90. if (isset($jsConfig['provider'])) {
  91. unset($jsConfig['extends']);
  92. $this->getContext()->addComponentDefinition($this->getName(), $jsConfig);
  93. } else {
  94. $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig);
  95. }
  96. if ($this->hasData('actions')) {
  97. $this->getContext()->addActions($this->getData('actions'), $this);
  98. }
  99. if ($this->hasData('html_blocks')) {
  100. $this->getContext()->addHtmlBlocks($this->getData('html_blocks'), $this);
  101. }
  102. if ($this->hasData('buttons')) {
  103. $this->getContext()->addButtons($this->getData('buttons'), $this);
  104. }
  105. $this->context->getProcessor()->register($this);
  106. $this->getContext()->getProcessor()->notify($this->getComponentName());
  107. }
  108. /**
  109. * Call prepare method in the component UI
  110. *
  111. * @param UiComponentInterface $component
  112. * @return $this
  113. * @since 100.1.0
  114. */
  115. protected function prepareChildComponent(UiComponentInterface $component)
  116. {
  117. $childComponents = $component->getChildComponents();
  118. if (!empty($childComponents)) {
  119. foreach ($childComponents as $child) {
  120. $this->prepareChildComponent($child);
  121. }
  122. }
  123. $component->prepare();
  124. return $this;
  125. }
  126. /**
  127. * Produce and return block's html output
  128. *
  129. * @return string
  130. */
  131. public function toHtml()
  132. {
  133. $this->render();
  134. }
  135. /**
  136. * Render component
  137. *
  138. * @return string
  139. */
  140. public function render()
  141. {
  142. $result = $this->getContext()->getRenderEngine()->render($this, $this->getTemplate());
  143. return $result;
  144. }
  145. /**
  146. * Add component
  147. *
  148. * @param string $name
  149. * @param UiComponentInterface $component
  150. * @return void
  151. */
  152. public function addComponent($name, UiComponentInterface $component)
  153. {
  154. $this->components[$name] = $component;
  155. }
  156. /**
  157. * @param string $name
  158. * @return UiComponentInterface
  159. */
  160. public function getComponent($name)
  161. {
  162. return isset($this->components[$name]) ? $this->components[$name] : null;
  163. }
  164. /**
  165. * Get components
  166. *
  167. * @return UiComponentInterface[]
  168. */
  169. public function getChildComponents()
  170. {
  171. return $this->components;
  172. }
  173. /**
  174. * Render child component
  175. *
  176. * @param string $name
  177. * @return string
  178. */
  179. public function renderChildComponent($name)
  180. {
  181. $result = null;
  182. if (isset($this->components[$name])) {
  183. $result = $this->components[$name]->render();
  184. }
  185. return $result;
  186. }
  187. /**
  188. * Get template
  189. *
  190. * @return string
  191. */
  192. public function getTemplate()
  193. {
  194. return $this->getData('template') . '.xhtml';
  195. }
  196. /**
  197. * Get component configuration
  198. *
  199. * @return array
  200. */
  201. public function getConfiguration()
  202. {
  203. return (array)$this->getData('config');
  204. }
  205. /**
  206. * Get configuration of related JavaScript Component
  207. * (force extending the root component if component does not extend other component)
  208. *
  209. * @param UiComponentInterface $component
  210. * @return array
  211. */
  212. public function getJsConfig(UiComponentInterface $component)
  213. {
  214. $jsConfig = (array)$component->getData('js_config');
  215. if (!isset($jsConfig['extends'])) {
  216. $jsConfig['extends'] = $component->getContext()->getNamespace();
  217. }
  218. return $jsConfig;
  219. }
  220. /**
  221. * Component data setter
  222. *
  223. * @param string|array $key
  224. * @param mixed $value
  225. * @return void
  226. */
  227. public function setData($key, $value = null)
  228. {
  229. parent::setData($key, $value);
  230. }
  231. /**
  232. * Component data getter
  233. *
  234. * @param string $key
  235. * @param string|int $index
  236. * @return mixed
  237. */
  238. public function getData($key = '', $index = null)
  239. {
  240. return parent::getData($key, $index);
  241. }
  242. /**
  243. * Prepare Data Source
  244. *
  245. * @param array $dataSource
  246. * @return array
  247. */
  248. public function prepareDataSource(array $dataSource)
  249. {
  250. return $dataSource;
  251. }
  252. /**
  253. * {@inheritdoc}
  254. */
  255. public function getDataSourceData()
  256. {
  257. return [];
  258. }
  259. /**
  260. * Initiate observers
  261. *
  262. * @param array $data
  263. * @return void
  264. */
  265. protected function initObservers(array & $data = [])
  266. {
  267. if (isset($data['observers']) && is_array($data['observers'])) {
  268. foreach ($data['observers'] as $observerType => $observer) {
  269. if (!is_object($observer)) {
  270. $observer = $this;
  271. }
  272. if ($observer instanceof ObserverInterface) {
  273. $this->getContext()->getProcessor()->attach($observerType, $observer);
  274. }
  275. unset($data['observers']);
  276. }
  277. }
  278. }
  279. }