diff --git a/app/code/Magento/Customer/Model/Address/AbstractAddress.php b/app/code/Magento/Customer/Model/Address/AbstractAddress.php
index 51999970d2fbe..47aaabbf4aa31 100644
--- a/app/code/Magento/Customer/Model/Address/AbstractAddress.php
+++ b/app/code/Magento/Customer/Model/Address/AbstractAddress.php
@@ -1,7 +1,7 @@
_directoryData = $directoryData;
$data = $this->_implodeArrayField($data);
@@ -206,6 +211,8 @@ public function __construct(
->get(CountryModelsCache::class);
$this->regionModelsCache = $regionModelsCache ?: ObjectManager::getInstance()
->get(RegionModelsCache::class);
+ $this->compositeSanitizer = $compositeSanitizer ?: ObjectManager::getInstance()
+ ->get(CompositeSanitizer::class);
parent::__construct(
$context,
$registry,
@@ -680,6 +687,17 @@ public function validate()
return $errors;
}
+ /**
+ * Sanitize address attribute values.
+ *
+ * @return $this
+ */
+ public function sanitize(): self
+ {
+ $this->compositeSanitizer->sanitize($this);
+ return $this;
+ }
+
/**
* Create region instance
*
diff --git a/app/code/Magento/Customer/Model/Address/CompositeSanitizer.php b/app/code/Magento/Customer/Model/Address/CompositeSanitizer.php
new file mode 100644
index 0000000000000..8e7e8bdb944b9
--- /dev/null
+++ b/app/code/Magento/Customer/Model/Address/CompositeSanitizer.php
@@ -0,0 +1,40 @@
+sanitizers = $sanitizers;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function sanitize(AbstractAddress $address): AbstractAddress
+ {
+ foreach ($this->sanitizers as $sanitizer) {
+ $sanitizer->sanitize($address);
+ }
+
+ return $address;
+ }
+}
diff --git a/app/code/Magento/Customer/Model/Address/Sanitizer/TemplateVars.php b/app/code/Magento/Customer/Model/Address/Sanitizer/TemplateVars.php
new file mode 100644
index 0000000000000..026168cdfdde4
--- /dev/null
+++ b/app/code/Magento/Customer/Model/Address/Sanitizer/TemplateVars.php
@@ -0,0 +1,76 @@
+attributesToSanitize as $attributeCode) {
+ $attributeValue = $address->getData($attributeCode);
+ preg_match_all($this->templateVarsPattern, (string)$attributeValue, $matches);
+ if (!empty($matches[0])) {
+ $sanitizedAttributeValue = $this->sanitizeTemplateVars($attributeValue);
+ $address->setData($attributeCode, $sanitizedAttributeValue);
+ }
+ }
+
+ return $address;
+ }
+
+ /**
+ * Sanitize string for template vars in address attributes.
+ *
+ * @param string $value
+ * @return string
+ */
+ private function sanitizeTemplateVars(string $value): string
+ {
+ if (!empty($value)) {
+ return str_replace(['{', '}'], ['{', '}'], $value);
+ }
+ return $value;
+ }
+}
diff --git a/app/code/Magento/Customer/Model/Address/SanitizerInterface.php b/app/code/Magento/Customer/Model/Address/SanitizerInterface.php
new file mode 100644
index 0000000000000..6bd409fac3768
--- /dev/null
+++ b/app/code/Magento/Customer/Model/Address/SanitizerInterface.php
@@ -0,0 +1,20 @@
+setStoreId($customerModel->getStoreId());
}
+ $addressModel = $addressModel->sanitize();
$errors = $addressModel->validate();
if ($errors !== true) {
$inputException = new InputException();
diff --git a/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/AddressRepositoryTest.php b/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/AddressRepositoryTest.php
index 704537ce28fef..b8397d305a2d4 100644
--- a/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/AddressRepositoryTest.php
+++ b/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/AddressRepositoryTest.php
@@ -1,7 +1,7 @@
address->expects($this->once())
->method('setCustomer')
->with($this->customer);
+ $this->address->expects($this->once())
+ ->method('sanitize')
+ ->willReturn($this->address);
$this->address->expects($this->once())
->method('validate')
->willReturn(true);
@@ -280,6 +284,9 @@ public function testSaveWithConfigCustomerAccountShareScopeWebsite()
->willReturn(true);
$this->address->expects($this->once())
->method('setStoreId');
+ $this->address->expects($this->once())
+ ->method('sanitize')
+ ->willReturn($this->address);
$this->address->expects($this->once())
->method('validate')
->willReturn(true);
@@ -350,6 +357,9 @@ public function testSaveWithConfigCustomerAccountShareScopeGlobal()
->willReturn(false);
$this->address->expects($this->never())
->method('setStoreId');
+ $this->address->expects($this->once())
+ ->method('sanitize')
+ ->willReturn($this->address);
$this->address->expects($this->once())
->method('validate')
->willReturn(true);
@@ -404,6 +414,9 @@ public function testSaveWithException()
$this->address->expects($this->once())
->method('updateData')
->with($customerAddress);
+ $this->address->expects($this->once())
+ ->method('sanitize')
+ ->willReturn($this->address);
$this->address->expects($this->once())
->method('validate')
->willReturn($errors);
@@ -446,6 +459,9 @@ public function testSaveWithInvalidRegion()
$this->address->expects($this->never())
->method('getRegionId')
->willReturn(null);
+ $this->address->expects($this->once())
+ ->method('sanitize')
+ ->willReturn($this->address);
$this->address->expects($this->once())
->method('validate')
->willReturn($errors);
@@ -487,6 +503,9 @@ public function testSaveWithInvalidRegionId()
$this->address->expects($this->never())
->method('getRegion')
->willReturn('');
+ $this->address->expects($this->once())
+ ->method('sanitize')
+ ->willReturn($this->address);
$this->address->expects($this->once())
->method('validate')
->willReturn($errors);
diff --git a/app/code/Magento/Customer/etc/di.xml b/app/code/Magento/Customer/etc/di.xml
index 00a8597d8c364..87011bf7398eb 100644
--- a/app/code/Magento/Customer/etc/di.xml
+++ b/app/code/Magento/Customer/etc/di.xml
@@ -472,6 +472,13 @@
+
+
+
+ - Magento\Customer\Model\Address\Sanitizer\TemplateVars
+
+
+
customer_group