Exceptions.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Theme\Model\Design\Backend;
  7. use Magento\Config\Model\Config\Backend\Serialized\ArraySerialized;
  8. use Magento\Framework\Serialize\Serializer\Json;
  9. class Exceptions extends ArraySerialized
  10. {
  11. /**
  12. * Design package instance
  13. *
  14. * @var \Magento\Framework\View\DesignInterface
  15. */
  16. protected $_design = null;
  17. /**
  18. * Initialize dependencies
  19. *
  20. * @param \Magento\Framework\Model\Context $context
  21. * @param \Magento\Framework\Registry $registry
  22. * @param \Magento\Framework\App\Config\ScopeConfigInterface $config
  23. * @param \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList
  24. * @param \Magento\Framework\View\DesignInterface $design
  25. * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
  26. * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
  27. * @param array $data
  28. * @param Json|null $serializer
  29. */
  30. public function __construct(
  31. \Magento\Framework\Model\Context $context,
  32. \Magento\Framework\Registry $registry,
  33. \Magento\Framework\App\Config\ScopeConfigInterface $config,
  34. \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList,
  35. \Magento\Framework\View\DesignInterface $design,
  36. \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
  37. \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
  38. array $data = [],
  39. Json $serializer = null
  40. ) {
  41. $this->_design = $design;
  42. parent::__construct(
  43. $context,
  44. $registry,
  45. $config,
  46. $cacheTypeList,
  47. $resource,
  48. $resourceCollection,
  49. $data,
  50. $serializer
  51. );
  52. }
  53. /**
  54. * Validate value
  55. *
  56. * @return $this
  57. * @throws \Magento\Framework\Exception\LocalizedException
  58. * if there is no field value, search value is empty or regular expression is not valid
  59. */
  60. public function beforeSave()
  61. {
  62. $design = clone $this->_design;
  63. // For value validations
  64. $exceptions = $this->getValue();
  65. foreach ($exceptions as $rowKey => &$row) {
  66. unset($row['record_id']);
  67. // Validate that all values have come
  68. foreach (['search', 'value'] as $fieldName) {
  69. if (!isset($row[$fieldName])) {
  70. throw new \Magento\Framework\Exception\LocalizedException(
  71. __('%1 does not contain field \'%2\'', $this->getData('field_config/fieldset'), $fieldName)
  72. );
  73. }
  74. }
  75. // Empty string (match all) is not supported, because it means setting a default theme. Remove such entries.
  76. if (!strlen($row['search'])) {
  77. unset($exceptions[$rowKey]);
  78. continue;
  79. }
  80. // Validate the theme value
  81. $design->setDesignTheme($row['value'], \Magento\Framework\App\Area::AREA_FRONTEND);
  82. // Compose regular exception pattern
  83. $exceptions[$rowKey]['regexp'] = $this->_composeRegexp($row['search']);
  84. }
  85. $this->setValue($exceptions);
  86. return parent::beforeSave();
  87. }
  88. /**
  89. * Composes regexp by user entered value
  90. *
  91. * @param string $search
  92. * @return string
  93. * @throws \Magento\Framework\Exception\LocalizedException on invalid regular expression
  94. */
  95. protected function _composeRegexp($search)
  96. {
  97. // If valid regexp entered - do nothing
  98. if (@preg_match($search, '') !== false) {
  99. return $search;
  100. }
  101. // Find out - whether user wanted to enter regexp or normal string.
  102. if ($this->_isRegexp($search)) {
  103. throw new \Magento\Framework\Exception\LocalizedException(__('Invalid regular expression: "%1".', $search));
  104. }
  105. return '/' . preg_quote($search, '/') . '/i';
  106. }
  107. /**
  108. * Checks search string, whether it was intended to be a regexp or normal search string
  109. *
  110. * @param string $search
  111. * @return bool
  112. */
  113. protected function _isRegexp($search)
  114. {
  115. if (strlen($search) < 3) {
  116. return false;
  117. }
  118. $possibleDelimiters = '/#~%';
  119. // Limit delimiters to reduce possibility, that we miss string with regexp.
  120. // Starts with a delimiter
  121. if (strpos($possibleDelimiters, $search[0]) !== false) {
  122. return true;
  123. }
  124. // Ends with a delimiter and (possible) modifiers
  125. $pattern = '/[' . preg_quote($possibleDelimiters, '/') . '][imsxeADSUXJu]*$/';
  126. if (preg_match($pattern, $search)) {
  127. return true;
  128. }
  129. return false;
  130. }
  131. /**
  132. * @inheritDoc
  133. */
  134. public function afterLoad()
  135. {
  136. parent::afterLoad();
  137. $values = $this->getValue();
  138. foreach ($values as &$value) {
  139. if (isset($value['record_id'])) {
  140. unset($value['record_id']);
  141. }
  142. }
  143. $this->setValue($values);
  144. return $this;
  145. }
  146. /**
  147. * @return array
  148. */
  149. public function getValue()
  150. {
  151. return $this->getData('value') ?: [];
  152. }
  153. }