Options.php 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. /**
  7. * Attribute add/edit form options tab
  8. *
  9. * @author Magento Core Team <core@magentocommerce.com>
  10. */
  11. namespace Magento\Eav\Block\Adminhtml\Attribute\Edit\Options;
  12. use Magento\Store\Model\ResourceModel\Store\Collection;
  13. /**
  14. * @api
  15. * @since 100.0.2
  16. */
  17. class Options extends \Magento\Backend\Block\Template
  18. {
  19. /**
  20. * @var \Magento\Framework\Registry
  21. */
  22. protected $_registry;
  23. /**
  24. * @var \Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\CollectionFactory
  25. */
  26. protected $_attrOptionCollectionFactory;
  27. /**
  28. * @var string
  29. */
  30. protected $_template = 'Magento_Catalog::catalog/product/attribute/options.phtml';
  31. /**
  32. * @var \Magento\Framework\Validator\UniversalFactory $universalFactory
  33. */
  34. protected $_universalFactory;
  35. /**
  36. * @param \Magento\Backend\Block\Template\Context $context
  37. * @param \Magento\Framework\Registry $registry
  38. * @param \Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\CollectionFactory $attrOptionCollectionFactory
  39. * @param \Magento\Framework\Validator\UniversalFactory $universalFactory
  40. * @param array $data
  41. */
  42. public function __construct(
  43. \Magento\Backend\Block\Template\Context $context,
  44. \Magento\Framework\Registry $registry,
  45. \Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\CollectionFactory $attrOptionCollectionFactory,
  46. \Magento\Framework\Validator\UniversalFactory $universalFactory,
  47. array $data = []
  48. ) {
  49. parent::__construct($context, $data);
  50. $this->_registry = $registry;
  51. $this->_attrOptionCollectionFactory = $attrOptionCollectionFactory;
  52. $this->_universalFactory = $universalFactory;
  53. }
  54. /**
  55. * Is true only for system attributes which use source model
  56. * Option labels and position for such attributes are kept in source model and thus cannot be overridden
  57. *
  58. * @return bool
  59. */
  60. public function canManageOptionDefaultOnly()
  61. {
  62. $attribute = $this->getAttributeObject();
  63. return !$attribute->getCanManageOptionLabels() &&
  64. !$attribute->getIsUserDefined() &&
  65. $attribute->getSourceModel();
  66. }
  67. /**
  68. * Retrieve stores collection with default store
  69. *
  70. * @return array
  71. */
  72. public function getStores()
  73. {
  74. if (!$this->hasStores()) {
  75. $this->setData('stores', $this->_storeManager->getStores(true));
  76. }
  77. return $this->_getData('stores');
  78. }
  79. /**
  80. * Returns stores sorted by Sort Order
  81. *
  82. * @return array
  83. * @since 100.1.0
  84. */
  85. public function getStoresSortedBySortOrder()
  86. {
  87. $stores = $this->getStores();
  88. if (is_array($stores)) {
  89. usort($stores, function ($storeA, $storeB) {
  90. if ($storeA->getSortOrder() == $storeB->getSortOrder()) {
  91. return $storeA->getId() < $storeB->getId() ? -1 : 1;
  92. }
  93. return ($storeA->getSortOrder() < $storeB->getSortOrder()) ? -1 : 1;
  94. });
  95. }
  96. return $stores;
  97. }
  98. /**
  99. * Retrieve attribute option values if attribute input type select or multiselect
  100. *
  101. * @return array
  102. */
  103. public function getOptionValues()
  104. {
  105. $values = $this->_getData('option_values');
  106. if ($values === null) {
  107. $values = [];
  108. $attribute = $this->getAttributeObject();
  109. $optionCollection = $this->_getOptionValuesCollection($attribute);
  110. if ($optionCollection) {
  111. $values = $this->_prepareOptionValues($attribute, $optionCollection);
  112. }
  113. $this->setData('option_values', $values);
  114. }
  115. return $values;
  116. }
  117. /**
  118. * @param \Magento\Eav\Model\Entity\Attribute\AbstractAttribute $attribute
  119. * @param array|\Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\Collection $optionCollection
  120. * @return array
  121. */
  122. protected function _prepareOptionValues(
  123. \Magento\Eav\Model\Entity\Attribute\AbstractAttribute $attribute,
  124. $optionCollection
  125. ) {
  126. $type = $attribute->getFrontendInput();
  127. if ($type === 'select' || $type === 'multiselect') {
  128. $defaultValues = explode(',', $attribute->getDefaultValue());
  129. $inputType = $type === 'select' ? 'radio' : 'checkbox';
  130. } else {
  131. $defaultValues = [];
  132. $inputType = '';
  133. }
  134. $values = [];
  135. $isSystemAttribute = is_array($optionCollection);
  136. foreach ($optionCollection as $option) {
  137. $bunch = $isSystemAttribute ? $this->_prepareSystemAttributeOptionValues(
  138. $option,
  139. $inputType,
  140. $defaultValues
  141. ) : $this->_prepareUserDefinedAttributeOptionValues(
  142. $option,
  143. $inputType,
  144. $defaultValues
  145. );
  146. foreach ($bunch as $value) {
  147. $values[] = new \Magento\Framework\DataObject($value);
  148. }
  149. }
  150. return $values;
  151. }
  152. /**
  153. * Retrieve option values collection
  154. * It is represented by an array in case of system attribute
  155. *
  156. * @param \Magento\Eav\Model\Entity\Attribute\AbstractAttribute $attribute
  157. * @return array|\Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\Collection
  158. */
  159. protected function _getOptionValuesCollection(\Magento\Eav\Model\Entity\Attribute\AbstractAttribute $attribute)
  160. {
  161. if ($this->canManageOptionDefaultOnly()) {
  162. $options = $this->_universalFactory->create(
  163. $attribute->getSourceModel()
  164. )->setAttribute(
  165. $attribute
  166. )->getAllOptions();
  167. return $options;
  168. } else {
  169. return $this->_attrOptionCollectionFactory->create()->setAttributeFilter(
  170. $attribute->getId()
  171. )->setPositionOrder(
  172. 'asc',
  173. true
  174. )->load();
  175. }
  176. }
  177. /**
  178. * Prepare option values of system attribute
  179. *
  180. * @param array|\Magento\Eav\Model\ResourceModel\Entity\Attribute\Option $option
  181. * @param string $inputType
  182. * @param array $defaultValues
  183. * @param string $valuePrefix
  184. * @return array
  185. */
  186. protected function _prepareSystemAttributeOptionValues($option, $inputType, $defaultValues, $valuePrefix = '')
  187. {
  188. if (is_array($option['value'])) {
  189. $values = [];
  190. foreach ($option['value'] as $subOption) {
  191. $bunch = $this->_prepareSystemAttributeOptionValues(
  192. $subOption,
  193. $inputType,
  194. $defaultValues,
  195. $option['label'] . ' / '
  196. );
  197. $values[] = $bunch[0];
  198. }
  199. return $values;
  200. }
  201. $value['checked'] = in_array($option['value'], $defaultValues) ? 'checked="checked"' : '';
  202. $value['intype'] = $inputType;
  203. $value['id'] = $option['value'];
  204. $value['sort_order'] = 0;
  205. foreach ($this->getStores() as $store) {
  206. $storeId = $store->getId();
  207. $value['store' . $storeId] = $storeId ==
  208. \Magento\Store\Model\Store::DEFAULT_STORE_ID ? $valuePrefix . $this->escapeHtml($option['label']) : '';
  209. }
  210. return [$value];
  211. }
  212. /**
  213. * Prepare option values of user defined attribute
  214. *
  215. * @param array|\Magento\Eav\Model\ResourceModel\Entity\Attribute\Option $option
  216. * @param string $inputType
  217. * @param array $defaultValues
  218. * @return array
  219. */
  220. protected function _prepareUserDefinedAttributeOptionValues($option, $inputType, $defaultValues)
  221. {
  222. $optionId = $option->getId();
  223. $value['checked'] = in_array($optionId, $defaultValues) ? 'checked="checked"' : '';
  224. $value['intype'] = $inputType;
  225. $value['id'] = $optionId;
  226. $value['sort_order'] = $option->getSortOrder();
  227. foreach ($this->getStores() as $store) {
  228. $storeId = $store->getId();
  229. $storeValues = $this->getStoreOptionValues($storeId);
  230. $value['store' . $storeId] = isset(
  231. $storeValues[$optionId]
  232. ) ? $this->escapeHtml(
  233. $storeValues[$optionId]
  234. ) : '';
  235. }
  236. return [$value];
  237. }
  238. /**
  239. * Retrieve attribute option values for given store id
  240. *
  241. * @param int $storeId
  242. * @return array
  243. */
  244. public function getStoreOptionValues($storeId)
  245. {
  246. $values = $this->getData('store_option_values_' . $storeId);
  247. if ($values === null) {
  248. $values = [];
  249. $valuesCollection = $this->_attrOptionCollectionFactory->create()->setAttributeFilter(
  250. $this->getAttributeObject()->getId()
  251. )->setStoreFilter(
  252. $storeId,
  253. false
  254. )->load();
  255. foreach ($valuesCollection as $item) {
  256. $values[$item->getId()] = $item->getValue();
  257. }
  258. $this->setData('store_option_values_' . $storeId, $values);
  259. }
  260. return $values;
  261. }
  262. /**
  263. * Retrieve attribute object from registry
  264. *
  265. * @return \Magento\Eav\Model\Entity\Attribute\AbstractAttribute
  266. * @codeCoverageIgnore
  267. */
  268. protected function getAttributeObject()
  269. {
  270. return $this->_registry->registry('entity_attribute');
  271. }
  272. }