diff --git a/app/code/Magento/Customer/Model/Address.php b/app/code/Magento/Customer/Model/Address.php index 191e9ab3fac..0dd2864a41e 100644 --- a/app/code/Magento/Customer/Model/Address.php +++ b/app/code/Magento/Customer/Model/Address.php @@ -13,6 +13,7 @@ use Magento\Customer\Model\Address\AbstractAddress\RegionModelsCache; use Magento\Customer\Model\Address\CompositeValidator; use Magento\Framework\Indexer\StateInterface; +use Magento\Customer\Helper\Address as AddressHelper; /** * Customer address model @@ -80,6 +81,7 @@ class Address extends \Magento\Customer\Model\Address\AbstractAddress * @param CompositeValidator|null $compositeValidator * @param CountryModelsCache|null $countryModelsCache * @param RegionModelsCache|null $regionModelsCache + * @param AddressHelper|null $addressHelper * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -106,6 +108,7 @@ public function __construct( ?CompositeValidator $compositeValidator = null, ?CountryModelsCache $countryModelsCache = null, ?RegionModelsCache $regionModelsCache = null, + ?AddressHelper $addressHelper = null ) { $this->dataProcessor = $dataProcessor; $this->_customerFactory = $customerFactory; @@ -130,6 +133,7 @@ public function __construct( $compositeValidator, $countryModelsCache, $regionModelsCache, + $addressHelper ); } diff --git a/app/code/Magento/Customer/Model/Address/AbstractAddress.php b/app/code/Magento/Customer/Model/Address/AbstractAddress.php index 51999970d2f..966e306e176 100644 --- a/app/code/Magento/Customer/Model/Address/AbstractAddress.php +++ b/app/code/Magento/Customer/Model/Address/AbstractAddress.php @@ -17,6 +17,7 @@ use Magento\Framework\App\ObjectManager; use Magento\Framework\Model\AbstractExtensibleModel; use Magento\Framework\ObjectManager\ResetAfterRequestInterface; +use Magento\Customer\Helper\Address as AddressHelper; /** * Address abstract model @@ -146,6 +147,11 @@ class AbstractAddress extends AbstractExtensibleModel implements AddressModelInt */ private array $regionIdCountry = []; + /** + * @var AddressHelper|null + */ + protected ?AddressHelper $addressHelper; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -166,6 +172,7 @@ class AbstractAddress extends AbstractExtensibleModel implements AddressModelInt * @param CompositeValidator $compositeValidator * @param CountryModelsCache|null $countryModelsCache * @param RegionModelsCache|null $regionModelsCache + * @param AddressHelper|null $addressHelper * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -189,6 +196,7 @@ public function __construct( ?CompositeValidator $compositeValidator = null, ?CountryModelsCache $countryModelsCache = null, ?RegionModelsCache $regionModelsCache = null, + ?AddressHelper $addressHelper = null ) { $this->_directoryData = $directoryData; $data = $this->_implodeArrayField($data); @@ -206,6 +214,8 @@ public function __construct( ->get(CountryModelsCache::class); $this->regionModelsCache = $regionModelsCache ?: ObjectManager::getInstance() ->get(RegionModelsCache::class); + $this->addressHelper = $addressHelper ?: ObjectManager::getInstance() + ->get(AddressHelper::class); parent::__construct( $context, $registry, @@ -242,6 +252,8 @@ public function getName() /** * Retrieve street field of an address + * Honour current configured street lines, and convert + * legacy data to match * * @return string[] */ @@ -250,7 +262,11 @@ public function getStreet() if (is_array($this->getStreetFull())) { return $this->getStreetFull(); } - return explode("\n", $this->getStreetFull()); + $maxAllowedLineCount = $this->addressHelper->getStreetLines() ?? 2; + $lines = explode("\n", $this->getStreetFull()); + $lines = $this->addressHelper->convertStreetLines($lines, $maxAllowedLineCount); + $this->setStreetFull(implode("\n", $lines)); + return $lines; } /** diff --git a/app/code/Magento/Customer/Test/Unit/Model/Address/AbstractAddressTest.php b/app/code/Magento/Customer/Test/Unit/Model/Address/AbstractAddressTest.php index 7765634d73a..fe470812bbc 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Address/AbstractAddressTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Address/AbstractAddressTest.php @@ -70,6 +70,11 @@ class AbstractAddressTest extends TestCase /** @var CompositeValidator|MockObject */ private $compositeValidatorMock; + /** + * @var \Magento\Customer\Helper\Address|MockObject + */ + private $addressHelperMock; + protected function setUp(): void { $this->contextMock = $this->createMock(Context::class); @@ -491,6 +496,89 @@ function ($data) { ); } + public function testGetStreetWithTwoLines() + { + // Create a partial mock for AddressHelper + $this->addressHelperMock = $this->getMockBuilder(\Magento\Customer\Helper\Address::class) + ->disableOriginalConstructor() + ->onlyMethods(['getStreetLines']) // Mock only getStreetLines, keep the real convertStreetLines + ->getMock(); + + // Mock getStreetLines to return 2 by default + $this->addressHelperMock->method('getStreetLines')->willReturn(2); + + // Use reflection to inject the partial mock into the model + $reflection = new \ReflectionClass($this->model); + $property = $reflection->getProperty('addressHelper'); + $property->setAccessible(true); + $property->setValue($this->model, $this->addressHelperMock); + + $this->addressHelperMock->method('getStreetLines')->willReturn(2); + $streetData = ["Street Line 1", "Street Line 2", "Street Line 3", "Street Line 4"]; + $this->model->setData('street', $streetData); + + // Call getStreet() which should internally call convertStreetLines() + $result = $this->model->getStreet(); + + // Assert that empty and whitespace-only lines are removed by convertStreetLines + $this->assertEquals(["Street Line 1 Street Line 2", "Street Line 3 Street Line 4"], $result); + } + + public function testGetStreetWithThreeLines() + { + // Create a partial mock for AddressHelper + $this->addressHelperMock = $this->getMockBuilder(\Magento\Customer\Helper\Address::class) + ->disableOriginalConstructor() + ->onlyMethods(['getStreetLines']) // Mock only getStreetLines, keep the real convertStreetLines + ->getMock(); + + // Mock getStreetLines to return 2 by default + $this->addressHelperMock->method('getStreetLines')->willReturn(3); + + // Use reflection to inject the partial mock into the model + $reflection = new \ReflectionClass($this->model); + $property = $reflection->getProperty('addressHelper'); + $property->setAccessible(true); + $property->setValue($this->model, $this->addressHelperMock); + + $this->addressHelperMock->method('getStreetLines')->willReturn(3); + $streetData = ["Street Line 1", "Street Line 2", "Street Line 3", "Street Line 4"]; + $this->model->setData('street', $streetData); + + // Call getStreet() which should internally call convertStreetLines() + $result = $this->model->getStreet(); + + // Assert that empty and whitespace-only lines are removed by convertStreetLines + $this->assertEquals(["Street Line 1 Street Line 2","Street Line 3","Street Line 4"], $result); + } + + public function testGetStreetWithOneLine() + { + // Create a partial mock for AddressHelper + $this->addressHelperMock = $this->getMockBuilder(\Magento\Customer\Helper\Address::class) + ->disableOriginalConstructor() + ->onlyMethods(['getStreetLines']) // Mock only getStreetLines, keep the real convertStreetLines + ->getMock(); + + // Mock getStreetLines to return 2 by default + $this->addressHelperMock->method('getStreetLines')->willReturn(1); + + // Use reflection to inject the partial mock into the model + $reflection = new \ReflectionClass($this->model); + $property = $reflection->getProperty('addressHelper'); + $property->setAccessible(true); + $property->setValue($this->model, $this->addressHelperMock); + + $streetData = ["Street Line 1", "Street Line 2", "Street Line 3", "Street Line 4"]; + $this->model->setData('street', $streetData); + + // Call getStreet() which should internally call convertStreetLines() + $result = $this->model->getStreet(); + + // Assert that empty and whitespace-only lines are removed by convertStreetLines + $this->assertEquals(["Street Line 1 Street Line 2 Street Line 3 Street Line 4"], $result); + } + protected function tearDown(): void { $this->objectManager->setBackwardCompatibleProperty( diff --git a/app/code/Magento/Customer/etc/di.xml b/app/code/Magento/Customer/etc/di.xml index 04dee8d9f6b..db30197e76d 100644 --- a/app/code/Magento/Customer/etc/di.xml +++ b/app/code/Magento/Customer/etc/di.xml @@ -88,6 +88,7 @@ Magento\Customer\Model\Address\Config\Proxy + Magento\Customer\Helper\Address @@ -593,4 +594,9 @@ type="Magento\Customer\Plugin\AsyncRequestCustomerGroupAuthorization" /> + + + Magento\Customer\Helper\Address + + diff --git a/app/code/Magento/Quote/Model/Quote/Address.php b/app/code/Magento/Quote/Model/Quote/Address.php index 082404de261..beb9f270c2c 100644 --- a/app/code/Magento/Quote/Model/Quote/Address.php +++ b/app/code/Magento/Quote/Model/Quote/Address.php @@ -46,6 +46,7 @@ use Magento\Store\Api\Data\StoreInterface; use Magento\Store\Model\ScopeInterface; use Magento\Store\Model\StoreManagerInterface; +use Magento\Customer\Helper\Address as AddressHelper; /** * Sales Quote address model @@ -341,6 +342,7 @@ class Address extends AbstractAddress implements * @param CompositeValidator|null $compositeValidator * @param CountryModelsCache|null $countryModelsCache * @param RegionModelsCache|null $regionModelsCache + * @param AddressHelper|null $addressHelper * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -382,6 +384,7 @@ public function __construct( ?CompositeValidator $compositeValidator = null, ?CountryModelsCache $countryModelsCache = null, ?RegionModelsCache $regionModelsCache = null, + ?AddressHelper $addressHelper = null ) { $this->_scopeConfig = $scopeConfig; $this->_addressItemFactory = $addressItemFactory; @@ -422,6 +425,7 @@ public function __construct( $compositeValidator, $countryModelsCache, $regionModelsCache, + $addressHelper ); } diff --git a/app/code/Magento/Quote/etc/di.xml b/app/code/Magento/Quote/etc/di.xml index 7693cbdc2ff..6de73a11994 100644 --- a/app/code/Magento/Quote/etc/di.xml +++ b/app/code/Magento/Quote/etc/di.xml @@ -63,6 +63,7 @@ Magento\Customer\Model\Address\Config\Proxy + Magento\Customer\Helper\Address