diff --git a/Api/Data/CustomFieldsInterface.php b/Api/Data/CustomFieldsInterface.php
index 30b8fbd..34ee663 100644
--- a/Api/Data/CustomFieldsInterface.php
+++ b/Api/Data/CustomFieldsInterface.php
@@ -26,6 +26,14 @@ interface CustomFieldsInterface
const CHECKOUT_GOODS_MARK = 'checkout_goods_mark';
const CHECKOUT_COMMENT = 'checkout_comment';
+ const ATTRIBUTES = [
+ self::CHECKOUT_BUYER_EMAIL,
+ self::CHECKOUT_BUYER_NAME,
+ self::CHECKOUT_COMMENT,
+ self::CHECKOUT_GOODS_MARK,
+ self::CHECKOUT_PURCHASE_ORDER_NO,
+ ];
+
/**
* Get checkout buyer name
*
diff --git a/Helper/Config.php b/Helper/Config.php
new file mode 100644
index 0000000..3d38fce
--- /dev/null
+++ b/Helper/Config.php
@@ -0,0 +1,77 @@
+config = $config;
+ $this->storeManager = $storeManager;
+ $this->logger = $logger;
+ }
+
+ /**
+ * @return array
+ */
+ public function getEnabledFields()
+ {
+ return explode(',',
+ $this->config->getValue('bodak/checkout/enabled_fields',
+ ScopeInterface::SCOPE_STORE));
+ }
+
+ /**
+ * @param $attribute
+ *
+ * @return int
+ */
+ public function getAllowedLength($attribute)
+ {
+ $configPath = 'checkout/general/' . $attribute . '_limit';
+ try {
+ $allowedLength = $this->config->getValue($configPath, ScopeInterface::SCOPE_STORES,
+ $this->storeManager->getStore()->getId());
+ } catch (NoSuchEntityException $e) {
+ $this->logger->error('Cannot get allowed length for custom field. Falling back to default scope value.');
+ $this->logger->error($e->getMessage(), ['exception' => $e]);
+ $allowedLength = $this->config->getValue($configPath);
+ }
+
+ return (int)$allowedLength ?: self::LIMIT_NOT_SET;
+ }
+}
\ No newline at end of file
diff --git a/Model/Checkout/LayoutProcessor/Plugin.php b/Model/Checkout/LayoutProcessor/Plugin.php
index d15ff24..19e5dae 100644
--- a/Model/Checkout/LayoutProcessor/Plugin.php
+++ b/Model/Checkout/LayoutProcessor/Plugin.php
@@ -12,9 +12,18 @@
namespace Bodak\CheckoutCustomForm\Model\Checkout\LayoutProcessor;
use Bodak\CheckoutCustomForm\Api\Data\CustomFieldsInterface;
+use Bodak\CheckoutCustomForm\Helper\Config;
class Plugin
{
+ /**
+ * @var Config
+ */
+ private $config;
+
+ /**
+ * @var array
+ */
private $fields = [
[
'dataScopeName' => CustomFieldsInterface::CHECKOUT_BUYER_NAME,
@@ -28,8 +37,8 @@ class Plugin
],
'config' => [
'tooltip' => [
- 'description' => 'We will send an order confirmation to this email address'
- ]
+ 'description' => 'We will send an order confirmation to this email address',
+ ],
],
],
[
@@ -46,48 +55,45 @@ class Plugin
'config' => [
'cols' => 15,
'rows' => 2,
- 'maxlength' => 80,
+ 'maxlength' => null,
'elementTmpl' => 'Bodak_CheckoutCustomForm/form/element/textarea',
],
'showTitle' => false,
],
];
- /**
- * @var \Magento\Framework\App\Config\ScopeConfigInterface
- */
- protected $_scopeConfig;
-
/**
* LayoutProcessor constructor.
*
- * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
+ * @param Config $config
*/
- public function __construct(\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig)
+ public function __construct(Config $config)
{
- $this->_scopeConfig = $scopeConfig;
+ $this->config = $config;
}
/**
* @param \Magento\Checkout\Block\Checkout\LayoutProcessor $subject
* @param array $jsLayout
*
- * @see \Magento\Checkout\Block\Checkout\LayoutProcessor::process
* @return array
+ * @see \Magento\Checkout\Block\Checkout\LayoutProcessor::process
*/
public function afterProcess(
\Magento\Checkout\Block\Checkout\LayoutProcessor $subject,
array $jsLayout
) {
- $config = explode(',',
- $this->_scopeConfig->getValue('bodak/checkout/enabled_fields',
- \Magento\Store\Model\ScopeInterface::SCOPE_STORE));
+ $config = $this->config->getEnabledFields();
+
+ $this->applyLengthLimitToFields();
foreach ($this->fields as $sortOrder => $field) {
- if ( ! in_array($field['dataScopeName'], $config)) {
+ if (!in_array($field['dataScopeName'], $config)) {
continue;
}
- if(!isset($field['showTitle'])) $field['showTitle'] = true;
+ if (!isset($field['showTitle'])) {
+ $field['showTitle'] = true;
+ }
$formField = [
'component' => 'Magento_Ui/js/form/element/abstract',
@@ -112,10 +118,23 @@ public function afterProcess(
}
$jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']
- ['children']['shippingAddress']['children']['custom-checkout-form-container']
- ['children']['custom-checkout-form-fieldset']['children'][$field['dataScopeName']] = $formField;
+ ['children']['shippingAddress']['children']['custom-checkout-form-container']
+ ['children']['custom-checkout-form-fieldset']['children'][$field['dataScopeName']] = $formField;
}
return $jsLayout;
}
+
+ private function applyLengthLimitToFields()
+ {
+ foreach ($this->fields as $key => $field) {
+ $fieldName = $field['dataScopeName'];
+ $allowedLength = $this->config->getAllowedLength($fieldName);
+ if ($allowedLength === Config::LIMIT_NOT_SET) {
+ continue;
+ }
+ $this->fields[$key]['config']['maxlength'] = $allowedLength;
+ $this->fields[$key]['validation']['max_text_length'] = $allowedLength;
+ }
+ }
}
\ No newline at end of file
diff --git a/Model/CustomFields/Validator.php b/Model/CustomFields/Validator.php
new file mode 100644
index 0000000..671eab5
--- /dev/null
+++ b/Model/CustomFields/Validator.php
@@ -0,0 +1,99 @@
+config = $config;
+ $this->underscoreToCamelCase = $underscoreToCamelCase;
+ }
+
+ /**
+ * Returns true if and only if $value meets the validation requirements
+ *
+ * If $value fails validation, then this method returns false, and
+ * getMessages() will return an array of messages that explain why the
+ * validation failed.
+ *
+ * @param mixed $value
+ *
+ * @return boolean
+ * @throws Zend_Validate_Exception If validation of $value is impossible
+ */
+ public function isValid($value)
+ {
+ $valid = true;
+ if (!($value instanceof CustomFieldsInterface)) {
+ throw new Zend_Validate_Exception('Expected value to be instance of \Bodak\CheckoutCustomForm\Api\Data\CustomFieldsInterface');
+ }
+
+ $this->setValue($value);
+
+ foreach (CustomFieldsInterface::ATTRIBUTES as $attribute) {
+ if (!$this->lengthIsValid($attribute)) {
+ $valid = false;
+ $this->_addMessages([sprintf('Field %s is to long.', $attribute)]);
+ }
+ }
+
+ return $valid;
+ }
+
+ /**
+ * @param $value
+ */
+ private function setValue($value)
+ {
+ $this->value = $value;
+ }
+
+ /**
+ * @param $attribute
+ *
+ * @return bool
+ */
+ private function lengthIsValid($attribute)
+ {
+ $allowedLength = $this->config->getAllowedLength($attribute);
+
+ if ($allowedLength === Config::LIMIT_NOT_SET) {
+ return true;
+ }
+
+ $function = $this->underscoreToCamelCase->filter('get_' . $attribute);
+ $value = call_user_func([$this->value, $function]);
+
+ return mb_strlen($value) <= $allowedLength;
+ }
+}
\ No newline at end of file
diff --git a/Model/CustomFieldsRepository.php b/Model/CustomFieldsRepository.php
index df3763e..649ba05 100644
--- a/Model/CustomFieldsRepository.php
+++ b/Model/CustomFieldsRepository.php
@@ -10,6 +10,8 @@
namespace Bodak\CheckoutCustomForm\Model;
+use Bodak\CheckoutCustomForm\Model\CustomFields\Validator;
+use Magento\Framework\Exception\LocalizedException;
use Magento\Quote\Api\CartRepositoryInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Exception\NoSuchEntityException;
@@ -47,31 +49,42 @@ class CustomFieldsRepository implements CustomFieldsRepositoryInterface
*/
protected $customFields;
+ /**
+ * @var Validator
+ */
+ private $validator;
+
/**
* CustomFieldsRepository constructor.
*
* @param CartRepositoryInterface $cartRepository CartRepositoryInterface
- * @param ScopeConfigInterface $scopeConfig ScopeConfigInterface
- * @param CustomFieldsInterface $customFields CustomFieldsInterface
+ * @param ScopeConfigInterface $scopeConfig ScopeConfigInterface
+ * @param CustomFieldsInterface $customFields CustomFieldsInterface
+ * @param Validator $validator
*/
public function __construct(
CartRepositoryInterface $cartRepository,
ScopeConfigInterface $scopeConfig,
- CustomFieldsInterface $customFields
+ CustomFieldsInterface $customFields,
+ Validator $validator
) {
$this->cartRepository = $cartRepository;
$this->scopeConfig = $scopeConfig;
$this->customFields = $customFields;
+ $this->validator = $validator;
}
+
/**
* Save checkout custom fields
*
- * @param int $cartId Cart id
+ * @param int $cartId Cart id
* @param \Bodak\CheckoutCustomForm\Api\Data\CustomFieldsInterface $customFields Custom fields
*
- * @return \Bodak\CheckoutCustomForm\Api\Data\CustomFieldsInterface
+ * @return \Bodak\CheckoutCustomForm\Api\Data\CustomFieldsInterface|string
* @throws CouldNotSaveException
* @throws NoSuchEntityException
+ * @throws \Zend_Validate_Exception
+ * @throws LocalizedException
*/
public function saveCustomFields(
int $cartId,
@@ -82,6 +95,10 @@ public function saveCustomFields(
throw new NoSuchEntityException(__('Cart %1 is empty', $cartId));
}
+ if (!$this->validator->isValid($customFields)) {
+ throw new LocalizedException(__('Custom fields contain invalid values.'));
+ }
+
try {
$cart->setData(
CustomFieldsInterface::CHECKOUT_BUYER_NAME,
diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml
index cf571a6..ac6f36b 100644
--- a/etc/adminhtml/system.xml
+++ b/etc/adminhtml/system.xml
@@ -15,6 +15,26 @@
Bodak\CheckoutCustomForm\Model\Config\Source\Option
bodak/checkout/enabled_fields
+
+
+ Limit the character length. Leave empty for no limit.
+
+
+
+ Limit the character length. Leave empty for no limit.
+
+
+
+ Limit the character length. Leave empty for no limit.
+
+
+
+ Limit the character length. Leave empty for no limit.
+
+