AbstractFrontend.php 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. /**
  7. * Entity/Attribute/Model - attribute frontend abstract
  8. *
  9. * @author Magento Core Team <core@magentocommerce.com>
  10. */
  11. namespace Magento\Eav\Model\Entity\Attribute\Frontend;
  12. use Magento\Framework\App\CacheInterface;
  13. use Magento\Framework\Serialize\Serializer\Json as Serializer;
  14. use Magento\Store\Model\StoreManagerInterface;
  15. use Magento\Framework\App\ObjectManager;
  16. use Magento\Eav\Model\Cache\Type as CacheType;
  17. use Magento\Eav\Model\Entity\Attribute;
  18. use Magento\Eav\Model\Entity\Attribute\Source\BooleanFactory;
  19. /**
  20. * EAV entity attribute form renderer.
  21. *
  22. * @api
  23. * @since 100.0.2
  24. */
  25. abstract class AbstractFrontend implements \Magento\Eav\Model\Entity\Attribute\Frontend\FrontendInterface
  26. {
  27. /**
  28. * Default cache tags values
  29. * will be used if no values in the constructor provided
  30. * @var array
  31. */
  32. private static $defaultCacheTags = [CacheType::CACHE_TAG, Attribute::CACHE_TAG];
  33. /**
  34. * @var CacheInterface
  35. */
  36. private $cache;
  37. /**
  38. * @var StoreManagerInterface
  39. */
  40. private $storeManager;
  41. /**
  42. * @var Serializer
  43. */
  44. private $serializer;
  45. /**
  46. * @var array
  47. */
  48. private $cacheTags;
  49. /**
  50. * Reference to the attribute instance
  51. *
  52. * @var \Magento\Eav\Model\Entity\Attribute\AbstractAttribute
  53. */
  54. protected $_attribute;
  55. /**
  56. * @var BooleanFactory
  57. */
  58. protected $_attrBooleanFactory;
  59. /**
  60. * @param BooleanFactory $attrBooleanFactory
  61. * @param CacheInterface $cache
  62. * @param null $storeResolver @deprecated
  63. * @param array $cacheTags
  64. * @param StoreManagerInterface $storeManager
  65. * @param Serializer $serializer
  66. * @codeCoverageIgnore
  67. * @SuppressWarnings(PHPMD.UnusedFormalParameter)
  68. */
  69. public function __construct(
  70. BooleanFactory $attrBooleanFactory,
  71. CacheInterface $cache = null,
  72. $storeResolver = null,
  73. array $cacheTags = null,
  74. StoreManagerInterface $storeManager = null,
  75. Serializer $serializer = null
  76. ) {
  77. $this->_attrBooleanFactory = $attrBooleanFactory;
  78. $this->cache = $cache ?: ObjectManager::getInstance()->get(CacheInterface::class);
  79. $this->cacheTags = $cacheTags ?: self::$defaultCacheTags;
  80. $this->storeManager = $storeManager ?: ObjectManager::getInstance()->get(StoreManagerInterface::class);
  81. $this->serializer = $serializer ?: ObjectManager::getInstance()->get(Serializer::class);
  82. }
  83. /**
  84. * Set attribute instance
  85. *
  86. * @param \Magento\Eav\Model\Entity\Attribute\AbstractAttribute $attribute
  87. * @return $this
  88. * @codeCoverageIgnore
  89. */
  90. public function setAttribute($attribute)
  91. {
  92. $this->_attribute = $attribute;
  93. return $this;
  94. }
  95. /**
  96. * Get attribute instance
  97. *
  98. * @return \Magento\Eav\Model\Entity\Attribute\AbstractAttribute
  99. * @codeCoverageIgnore
  100. */
  101. public function getAttribute()
  102. {
  103. return $this->_attribute;
  104. }
  105. /**
  106. * Get attribute type for user interface form
  107. *
  108. * @return string
  109. * @codeCoverageIgnore
  110. */
  111. public function getInputType()
  112. {
  113. return $this->getAttribute()->getFrontendInput();
  114. }
  115. /**
  116. * Retrieve label
  117. *
  118. * @return string
  119. */
  120. public function getLabel()
  121. {
  122. $label = $this->getAttribute()->getFrontendLabel();
  123. if ($label === null || $label == '') {
  124. $label = $this->getAttribute()->getAttributeCode();
  125. }
  126. return $label;
  127. }
  128. /**
  129. * Retrieve localized label
  130. *
  131. * @return \Magento\Framework\Phrase
  132. */
  133. public function getLocalizedLabel()
  134. {
  135. return __($this->getLabel());
  136. }
  137. /**
  138. * Retrieve attribute value
  139. *
  140. * @param \Magento\Framework\DataObject $object
  141. * @return mixed
  142. */
  143. public function getValue(\Magento\Framework\DataObject $object)
  144. {
  145. $value = $object->getData($this->getAttribute()->getAttributeCode());
  146. if (in_array($this->getConfigField('input'), ['select', 'boolean'])) {
  147. $valueOption = $this->getOption($value);
  148. if (!$valueOption) {
  149. $opt = $this->_attrBooleanFactory->create();
  150. $options = $opt->getAllOptions();
  151. if ($options) {
  152. foreach ($options as $option) {
  153. if ($option['value'] === $value) {
  154. $valueOption = $option['label'];
  155. }
  156. }
  157. }
  158. }
  159. $value = $valueOption;
  160. } elseif ($this->getConfigField('input') == 'multiselect') {
  161. $value = $this->getOption($value);
  162. if (is_array($value)) {
  163. $value = implode(', ', $value);
  164. }
  165. }
  166. return $value;
  167. }
  168. /**
  169. * Checks if attribute is visible on frontend
  170. *
  171. * @return bool
  172. * @codeCoverageIgnore
  173. */
  174. public function isVisible()
  175. {
  176. return $this->getConfigField('frontend_visible');
  177. }
  178. /**
  179. * Retrieve frontend class
  180. *
  181. * @return string
  182. */
  183. public function getClass()
  184. {
  185. $out = [];
  186. $out[] = $this->getAttribute()->getFrontendClass();
  187. if ($this->getAttribute()->getIsRequired()) {
  188. $out[] = 'required-entry';
  189. }
  190. $inputRuleClass = $this->_getInputValidateClass();
  191. if ($inputRuleClass) {
  192. $out[] = $inputRuleClass;
  193. }
  194. $textLengthValidateClasses = $this->getTextLengthValidateClasses();
  195. if (!empty($textLengthValidateClasses)) {
  196. $out = array_merge($out, $textLengthValidateClasses);
  197. }
  198. $out = !empty($out) ? implode(' ', array_unique(array_filter($out))) : '';
  199. return $out;
  200. }
  201. /**
  202. * Return validate class by attribute input validation rule
  203. *
  204. * @return string|false
  205. */
  206. protected function _getInputValidateClass()
  207. {
  208. $class = false;
  209. $validateRules = $this->getAttribute()->getValidateRules();
  210. if (!empty($validateRules['input_validation'])) {
  211. switch ($validateRules['input_validation']) {
  212. case 'alphanumeric':
  213. $class = 'validate-alphanum';
  214. break;
  215. case 'alphanum-with-spaces':
  216. $class = 'validate-alphanum-with-spaces';
  217. break;
  218. case 'numeric':
  219. $class = 'validate-digits';
  220. break;
  221. case 'alpha':
  222. $class = 'validate-alpha';
  223. break;
  224. case 'email':
  225. $class = 'validate-email';
  226. break;
  227. case 'url':
  228. $class = 'validate-url';
  229. break;
  230. case 'length':
  231. $class = 'validate-length';
  232. break;
  233. default:
  234. $class = false;
  235. break;
  236. }
  237. }
  238. return $class;
  239. }
  240. /**
  241. * Retrieve validation classes by min_text_length and max_text_length rules
  242. *
  243. * @return array
  244. */
  245. private function getTextLengthValidateClasses()
  246. {
  247. $classes = [];
  248. if ($this->_getInputValidateClass()) {
  249. $validateRules = $this->getAttribute()->getValidateRules();
  250. if (!empty($validateRules['min_text_length'])) {
  251. $classes[] = 'minimum-length-' . $validateRules['min_text_length'];
  252. }
  253. if (!empty($validateRules['max_text_length'])) {
  254. $classes[] = 'maximum-length-' . $validateRules['max_text_length'];
  255. }
  256. if (!empty($classes)) {
  257. $classes[] = 'validate-length';
  258. }
  259. }
  260. return $classes;
  261. }
  262. /**
  263. * Retrieve config field
  264. *
  265. * @param string $fieldName
  266. * @return mixed
  267. * @codeCoverageIgnore
  268. */
  269. public function getConfigField($fieldName)
  270. {
  271. return $this->getAttribute()->getData('frontend_' . $fieldName);
  272. }
  273. /**
  274. * Get select options in case it's select box and options source is defined
  275. *
  276. * @return array
  277. */
  278. public function getSelectOptions()
  279. {
  280. $cacheKey = 'attribute-navigation-option-' .
  281. $this->getAttribute()->getAttributeCode() . '-' .
  282. $this->storeManager->getStore()->getId();
  283. $optionString = $this->cache->load($cacheKey);
  284. if (false === $optionString) {
  285. $options = $this->getAttribute()->getSource()->getAllOptions();
  286. $this->cache->save(
  287. $this->serializer->serialize($options),
  288. $cacheKey,
  289. $this->cacheTags
  290. );
  291. } else {
  292. $options = $this->serializer->unserialize($optionString);
  293. }
  294. return $options;
  295. }
  296. /**
  297. * Retrieve option by option id
  298. *
  299. * @param int $optionId
  300. * @return mixed|bool
  301. */
  302. public function getOption($optionId)
  303. {
  304. $source = $this->getAttribute()->getSource();
  305. if ($source) {
  306. return $source->getOptionText($optionId);
  307. }
  308. return false;
  309. }
  310. /**
  311. * Retrieve Input Renderer Class
  312. *
  313. * @return string|null
  314. * @codeCoverageIgnore
  315. */
  316. public function getInputRendererClass()
  317. {
  318. return $this->getAttribute()->getData('frontend_input_renderer');
  319. }
  320. }