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