BackendModelFactory.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Theme\Model\Design;
  7. use Magento\Framework\App\Config\Value;
  8. use Magento\Framework\App\Config\ValueFactory;
  9. use Magento\Framework\ObjectManagerInterface;
  10. use Magento\Theme\Model\Design\Config\MetadataProvider;
  11. use Magento\Theme\Model\ResourceModel\Design\Config\CollectionFactory;
  12. class BackendModelFactory extends ValueFactory
  13. {
  14. /**
  15. * @var array
  16. */
  17. protected $storedData = [];
  18. /**
  19. * @var array
  20. */
  21. protected $metadata = [];
  22. /**
  23. * @var MetadataProvider
  24. */
  25. protected $metadataProvider;
  26. /**
  27. * @var CollectionFactory
  28. */
  29. protected $collectionFactory;
  30. /**
  31. * @var array
  32. */
  33. protected $backendTypes = [];
  34. /**
  35. * @param ObjectManagerInterface $objectManager
  36. * @param MetadataProvider $metadataProvider
  37. * @param CollectionFactory $collectionFactory
  38. */
  39. public function __construct(
  40. ObjectManagerInterface $objectManager,
  41. MetadataProvider $metadataProvider,
  42. CollectionFactory $collectionFactory
  43. ) {
  44. $this->metadataProvider = $metadataProvider;
  45. $this->collectionFactory = $collectionFactory;
  46. parent::__construct($objectManager);
  47. }
  48. /**
  49. * @inheritDoc
  50. */
  51. public function create(array $data = [])
  52. {
  53. $backendModelData = array_replace_recursive(
  54. $this->getStoredData($data['scope'], $data['scopeId'], $data['config']['path']),
  55. [
  56. 'path' => $data['config']['path'],
  57. 'scope' => $data['scope'],
  58. 'scope_id' => $data['scopeId'],
  59. 'field_config' => $data['config'],
  60. ]
  61. );
  62. $backendType = isset($data['config']['backend_model'])
  63. ? $data['config']['backend_model']
  64. : $this->_instanceName;
  65. /** @var Value $backendModel */
  66. $backendModel = $this->getNewBackendModel($backendType, $backendModelData);
  67. $backendModel->setValue($data['value']);
  68. return $backendModel;
  69. }
  70. /**
  71. * Retrieve new empty backend model
  72. *
  73. * @param string $backendType
  74. * @param array $data
  75. * @return Value
  76. */
  77. protected function getNewBackendModel($backendType, array $data = [])
  78. {
  79. return $this->_objectManager->create($backendType, ['data' => $data]);
  80. }
  81. /**
  82. * Create backend model by config path
  83. *
  84. * @param string $path
  85. * @param array $data
  86. * @return Value
  87. */
  88. public function createByPath($path, array $data = [])
  89. {
  90. return $this->getNewBackendModel($this->getBackendTypeByPath($path), $data);
  91. }
  92. /**
  93. * Retrieve backend type by config path
  94. *
  95. * @param string $path
  96. * @return string
  97. */
  98. protected function getBackendTypeByPath($path)
  99. {
  100. if (!isset($this->backendTypes[$path])) {
  101. $metadata = $this->metadataProvider->get();
  102. $index = array_search($path, array_column($metadata, 'path'));
  103. $backendType = $this->_instanceName;
  104. if ($index !== false && isset(array_values($metadata)[$index]['backend_model'])) {
  105. $backendType = array_values($metadata)[$index]['backend_model'];
  106. }
  107. $this->backendTypes[$path] = $backendType;
  108. }
  109. return $this->backendTypes[$path];
  110. }
  111. /**
  112. * Get config data for path
  113. *
  114. * @param string $scope
  115. * @param string $scopeId
  116. * @param string $path
  117. * @return array
  118. */
  119. protected function getStoredData($scope, $scopeId, $path)
  120. {
  121. $storedData = $this->getScopeData($scope, $scopeId);
  122. $dataKey = array_search($path, array_column($storedData, 'path'));
  123. return $dataKey !== false ? $storedData[$dataKey] : [];
  124. }
  125. /**
  126. * Get stored data for scope and scope id
  127. *
  128. * @param string $scope
  129. * @param string $scopeId
  130. * @return array
  131. */
  132. protected function getScopeData($scope, $scopeId)
  133. {
  134. if (!isset($this->storedData[$scope][$scopeId])) {
  135. $collection = $this->collectionFactory->create();
  136. $collection->addPathsFilter($this->getMetadata());
  137. $collection->addFieldToFilter('scope', $scope);
  138. $collection->addScopeIdFilter($scopeId);
  139. $this->storedData[$scope][$scopeId] = $collection->getData();
  140. }
  141. return $this->storedData[$scope][$scopeId];
  142. }
  143. /**
  144. * Retrieve metadata
  145. *
  146. * @return array
  147. */
  148. protected function getMetadata()
  149. {
  150. if (!$this->metadata) {
  151. $this->metadata = $this->metadataProvider->get();
  152. array_walk($this->metadata, function (&$value) {
  153. $value = $value['path'];
  154. });
  155. }
  156. return $this->metadata;
  157. }
  158. }