Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
UiComponentFactory.php
Go to the documentation of this file.
1 <?php
8 
10 use Magento\Framework\Config\DataInterfaceFactory;
21 
30 {
36  protected $objectManager;
37 
44 
48  protected $contextFactory;
49 
56  protected $componentManager;
57 
61  private $componentChildFactories;
62 
66  private $configFactory;
67 
71  private $definitionData;
72 
83  public function __construct(
88  array $data = [],
89  array $componentChildFactories = [],
90  DataInterface $definitionData = null,
91  DataInterfaceFactory $configFactory = null
92  ) {
93  $this->objectManager = $objectManager;
94  $this->componentManager = $componentManager;
95  $this->argumentInterpreter = $argumentInterpreter;
96  $this->contextFactory = $contextFactory;
97  $this->componentChildFactories = $componentChildFactories;
98  $this->configFactory = $configFactory ?: $this->objectManager->get(DataInterfaceFactory::class);
99  parent::__construct($data);
100  $this->definitionData = $definitionData ?:
101  $this->objectManager->get(DataInterface::class);
102  }
103 
113  protected function createChildComponent(
114  array &$bundleComponents,
115  ContextInterface $renderContext,
116  $identifier,
117  array $arguments = []
118  ) {
119  $componentArguments = &$bundleComponents['arguments'];
120  list($className, $componentArguments) = $this->argumentsResolver($identifier, $bundleComponents);
121  if (isset($componentArguments['data']['disabled']) && (int)$componentArguments['data']['disabled']) {
122  return null;
123  }
124 
128  $bundleComponents['components'] = [];
129  $components = &$bundleComponents['components'];
130 
131  if (isset($this->componentChildFactories[$className])) {
132  $factory = $this->componentChildFactories[$className];
133 
138  $factory->create($bundleComponents, $arguments);
139  } else {
140  foreach ($bundleComponents['children'] as $childrenIdentifier => $childrenData) {
142  $childrenData,
143  $renderContext,
144  $childrenIdentifier,
145  $arguments
146  );
147  $components[$childrenIdentifier] = $children;
148  }
149  }
150  $components = array_filter($components);
151  $componentArguments['components'] = $components;
152 
156  if (isset($componentArguments['block']) && !$componentArguments['block']) {
157  return null;
158  }
159 
160  if (!isset($componentArguments['context'])) {
161  $componentArguments['context'] = $renderContext;
162  }
163 
164  return $this->objectManager->create($className, $componentArguments);
165  }
166 
174  protected function argumentsResolver($identifier, array $componentData)
175  {
177  $className = $attributes['class'];
178  unset($attributes['class']);
180 
181  if (!isset($arguments['data'])) {
182  $arguments['data'] = [];
183  }
184 
185  unset($attributes['component']);
186  $arguments['data'] = array_merge($arguments['data'], ['name' => $identifier], $attributes);
187  return [$className, $arguments];
188  }
189 
200  public function create($identifier, $name = null, array $arguments = [])
201  {
202  if ($name === null) {
203  $componentData = $this->configFactory->create(['componentName' => $identifier])->get($identifier);
204  $bundleComponents = [$identifier => $componentData];
205 
206  list($className, $componentArguments) = $this->argumentsResolver(
207  $identifier,
208  $bundleComponents[$identifier]
209  );
210  $componentArguments = array_replace_recursive($componentArguments, $arguments);
211  if (!isset($componentArguments['context'])) {
212  $componentArguments['context'] = $this->contextFactory->create(
213  ['namespace' => $identifier]
214  );
215  }
216  $reverseMerge = isset($componentArguments['data']['reverseMetadataMerge'])
217  && $componentArguments['data']['reverseMetadataMerge'];
218  $bundleComponents = $this->mergeMetadata($identifier, $bundleComponents, $reverseMerge);
219  $children = $bundleComponents[$identifier]['children'];
220  } else {
221  $rawComponentData = $this->definitionData->get($name);
222  list($className, $componentArguments) = $this->argumentsResolver($identifier, $rawComponentData);
223  $componentArguments = array_replace_recursive($componentArguments, $arguments);
224  $children = isset($componentArguments['data']['config']['children']) ?
225  $componentArguments['data']['config']['children'] : [];
227  }
228 
229  $className = isset($componentArguments['config']['class']) ?
230  $componentArguments['config']['class'] : $className;
231  $components = [];
232 
233  foreach ($children as $childrenIdentifier => $childrenData) {
235  $childrenData,
236  $componentArguments['context'],
237  $childrenIdentifier,
238  $arguments
239  );
240  $components[$childrenIdentifier] = $children;
241  }
242 
243  $components = array_filter($components);
244  $componentArguments['components'] = $components;
245 
247  $component = $this->objectManager->create(
248  $className,
249  $componentArguments
250  );
251 
252  return $component;
253  }
254 
263  protected function getBundleChildren(array $children = [])
264  {
265  $bundleChildren = [];
266 
267  foreach ($children as $identifier => $config) {
268  if (!isset($config['componentType'])) {
269  throw new LocalizedException(new Phrase(
270  'The "componentType" configuration parameter is required for the "%1" component.',
271  $identifier
272  ));
273  }
274 
275  if (!isset($componentArguments['context'])) {
276  throw new LocalizedException(
277  new \Magento\Framework\Phrase(
278  'An error occurred with the UI component. Each component needs context. Verify and try again.'
279  )
280  );
281  }
282 
283  $rawComponentData = $this->definitionData->get($config['componentType']);
284  list(, $componentArguments) = $this->argumentsResolver($identifier, $rawComponentData);
285  $arguments = array_replace_recursive($componentArguments, ['data' => ['config' => $config]]);
287 
288  $bundleChildren[$identifier] = $rawComponentData;
289  $bundleChildren[$identifier]['children'] = [];
290 
291  if (isset($arguments['data']['config']['children'])) {
292  $bundleChildren[$identifier]['children'] = $this->getBundleChildren(
293  $arguments['data']['config']['children']
294  );
295  }
296  }
297 
298  return $bundleChildren;
299  }
300 
310  protected function mergeMetadata($identifier, array $bundleComponents, $reverseMerge = false)
311  {
312  $dataProvider = $this->getDataProvider($identifier, $bundleComponents);
313  if ($dataProvider instanceof DataProviderInterface) {
314  $metadata = [
315  $identifier => [
316  'children' => $dataProvider->getMeta(),
317  ],
318  ];
319  $bundleComponents = $this->mergeMetadataItem($bundleComponents, $metadata, $reverseMerge);
320  }
321 
322  return $bundleComponents;
323  }
324 
335  protected function mergeMetadataElement(array $bundleComponents, $name, array $data, $reverseMerge = false)
336  {
337  if (isset($bundleComponents[$name])) {
338  $bundleComponents[$name] = $reverseMerge
339  ? array_replace_recursive($data, $bundleComponents[$name])
340  : array_replace_recursive($bundleComponents[$name], $data);
341  return [$bundleComponents, true];
342  } else {
343  foreach ($bundleComponents as &$childData) {
344  if (isset($childData['attributes']['class'])
345  && is_a($childData['attributes']['class'], \Magento\Ui\Component\Container::class, true)
346  && isset($childData['children']) && is_array($childData['children'])
347  ) {
348  list($childData['children'], $isMerged) = $this->mergeMetadataElement(
349  $childData['children'],
350  $name,
351  $data,
352  $reverseMerge
353  );
354  if ($isMerged) {
355  return [$bundleComponents, true];
356  }
357  }
358  }
359  }
360  return [$bundleComponents, false];
361  }
362 
373  protected function mergeMetadataItem(array $bundleComponents, array $metadata, $reverseMerge = false)
374  {
375  foreach ($metadata as $name => $data) {
376  $selfData = $data;
377  if (isset($selfData['children'])) {
378  unset($selfData['children']);
379  }
380 
381  list($bundleComponents, $isMerged) = $this->mergeMetadataElement(
382  $bundleComponents,
383  $name,
384  $selfData,
385  $reverseMerge
386  );
387 
388  if (!$isMerged) {
389  if (!isset($data['arguments']['data']['config']['componentType'])) {
390  throw new LocalizedException(new Phrase(
391  'The "componentType" configuration parameter is required for the "%1" component.',
392  [$name]
393  ));
394  }
395  $rawComponentData = $this->definitionData->get(
396  $data['arguments']['data']['config']['componentType']
397  );
398  list(, $componentArguments) = $this->argumentsResolver($name, $rawComponentData);
399  $arguments = array_replace_recursive($componentArguments, $data['arguments']);
401 
402  $bundleComponents[$name] = $rawComponentData;
403  $bundleComponents[$name]['children'] = [];
404  }
405 
406  if (isset($data['children']) && is_array($data['children'])) {
407  $bundleComponents[$name]['children'] = $this->mergeMetadataItem(
408  $bundleComponents[$name]['children'],
409  $data['children'],
410  $reverseMerge
411  );
412  }
413  }
414 
415  return $bundleComponents;
416  }
417 
426  protected function getDataProvider($identifier, array $bundleComponents)
427  {
428  foreach ($bundleComponents[$identifier]['children'] as $childrenData) {
429  if (isset($childrenData['arguments']['dataProvider'])
430  && $childrenData['arguments']['dataProvider'] instanceof DataProviderInterface
431  ) {
432  return $childrenData['arguments']['dataProvider'];
433  }
434  }
435 
436  return null;
437  }
438 }
$config
Definition: fraud_order.php:17
__construct(ObjectManagerInterface $objectManager, ManagerInterface $componentManager, InterpreterInterface $argumentInterpreter, ContextFactory $contextFactory, array $data=[], array $componentChildFactories=[], DataInterface $definitionData=null, DataInterfaceFactory $configFactory=null)
$attributes
Definition: matrix.phtml:13
$arguments
$children
Definition: actions.phtml:11
mergeMetadata($identifier, array $bundleComponents, $reverseMerge=false)
getDataProvider($identifier, array $bundleComponents)
mergeMetadataElement(array $bundleComponents, $name, array $data, $reverseMerge=false)
createChildComponent(array &$bundleComponents, ContextInterface $renderContext, $identifier, array $arguments=[])
mergeMetadataItem(array $bundleComponents, array $metadata, $reverseMerge=false)
if($currentSelectedMethod==$_code) $className
Definition: form.phtml:31
argumentsResolver($identifier, array $componentData)
if(!isset($_GET['name'])) $name
Definition: log.php:14