Skip to content

Commit 453faf6

Browse files
committed
AC-8110: USPS Shipping Method Configuration Fix
1 parent 9e99eac commit 453faf6

File tree

4 files changed

+203
-0
lines changed

4 files changed

+203
-0
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\Usps\Model\Config\Backend;
10+
11+
use Magento\Framework\App\Cache\TypeListInterface;
12+
use Magento\Framework\App\Config\ScopeConfigInterface;
13+
use Magento\Framework\App\Config\Value;
14+
use Magento\Framework\Data\Collection\AbstractDb;
15+
use Magento\Framework\Exception\ValidatorException;
16+
use Magento\Framework\Model\Context;
17+
use Magento\Framework\Model\ResourceModel\AbstractResource;
18+
use Magento\Framework\Registry;
19+
use Magento\Framework\Validator\Url;
20+
21+
/**
22+
* Represents a config URL that may point to a USPS endpoint
23+
*
24+
* @SuppressWarnings(PHPMD.Superglobals)
25+
*/
26+
class UspsUrl extends Value
27+
{
28+
/**
29+
* @var Url
30+
*/
31+
private Url $url;
32+
33+
/**
34+
* @param Context $context
35+
* @param Registry $registry
36+
* @param ScopeConfigInterface $config
37+
* @param TypeListInterface $cacheTypeList
38+
* @param Url $url
39+
* @param AbstractResource|null $resource
40+
* @param AbstractDb|null $resourceCollection
41+
* @param array $data
42+
*/
43+
public function __construct(
44+
Context $context,
45+
Registry $registry,
46+
ScopeConfigInterface $config,
47+
TypeListInterface $cacheTypeList,
48+
Url $url,
49+
AbstractResource $resource = null,
50+
AbstractDb $resourceCollection = null,
51+
array $data = []
52+
) {
53+
$this->url = $url;
54+
parent::__construct($context, $registry, $config, $cacheTypeList, $resource, $resourceCollection, $data);
55+
}
56+
57+
/**
58+
* @inheritdoc
59+
*
60+
* @throws ValidatorException
61+
*/
62+
public function beforeSave()
63+
{
64+
$isValid = $this->url->isValid($this->getValue());
65+
if ($isValid) {
66+
// phpcs:ignore Magento2.Functions.DiscouragedFunction
67+
$host = parse_url((string)$this->getValue(), \PHP_URL_HOST);
68+
69+
if (!empty($host) && !preg_match("/(?:.+\.|^)usps|shippingapis\.com$/i", $host)) {
70+
throw new ValidatorException(__('USPS API endpoint URL\'s must use usps.com or shippingapis.com'));
71+
}
72+
}
73+
74+
return parent::beforeSave();
75+
}
76+
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\Usps\Test\Unit\Model\Config\Backend;
10+
11+
use Magento\Framework\App\Cache\TypeListInterface;
12+
use Magento\Framework\App\Config\ScopeConfigInterface;
13+
use Magento\Framework\Data\Collection\AbstractDb;
14+
use Magento\Framework\Event\ManagerInterface;
15+
use Magento\Framework\Exception\ValidatorException;
16+
use Magento\Framework\Model\Context;
17+
use Magento\Framework\Model\ResourceModel\AbstractResource;
18+
use Magento\Framework\Registry;
19+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
20+
use Magento\Framework\Validator\Url;
21+
use Magento\Usps\Model\Config\Backend\UspsUrl;
22+
use PHPUnit\Framework\TestCase;
23+
24+
/**
25+
* Verify behavior of UspsUrl backend type
26+
*
27+
* @SuppressWarnings(PHPMD.Superglobals)
28+
*/
29+
class UspsUrlTest extends TestCase
30+
{
31+
/**
32+
* @var UspsUrl
33+
*/
34+
private $urlConfig;
35+
36+
/**
37+
* @var Url
38+
*/
39+
private $url;
40+
41+
/**
42+
* @var Context
43+
*/
44+
private $contextMock;
45+
46+
protected function setUp(): void
47+
{
48+
$objectManager = new ObjectManager($this);
49+
50+
$this->contextMock = $this->createMock(Context::class);
51+
$registry = $this->createMock(Registry::class);
52+
$config = $this->createMock(ScopeConfigInterface::class);
53+
$cacheTypeList = $this->createMock(TypeListInterface::class);
54+
$this->url = $this->createMock(Url::class);
55+
$resource = $this->createMock(AbstractResource::class);
56+
$resourceCollection = $this->createMock(AbstractDb::class);
57+
$eventManagerMock = $this->getMockForAbstractClass(ManagerInterface::class);
58+
59+
$eventManagerMock->expects($this->any())->method('dispatch');
60+
$this->contextMock->expects($this->any())->method('getEventDispatcher')->willReturn($eventManagerMock);
61+
62+
$this->urlConfig = $objectManager->getObject(
63+
UspsUrl::class,
64+
[
65+
'url' => $this->url,
66+
'context' => $this->contextMock,
67+
'registry' => $registry,
68+
'config' => $config,
69+
'cacheTypeList' => $cacheTypeList,
70+
'resource' => $resource,
71+
'resourceCollection' => $resourceCollection,
72+
]
73+
);
74+
}
75+
76+
/**
77+
* @dataProvider validDataProvider
78+
* @param string $data The valid data
79+
* @throws ValidatorException
80+
*/
81+
public function testBeforeSave(string $data = ""): void
82+
{
83+
$this->url->expects($this->any())->method('isValid')->willReturn(true);
84+
$this->urlConfig->setValue($data);
85+
$this->urlConfig->beforeSave();
86+
$this->assertTrue($this->url->isValid($data));
87+
}
88+
89+
/**
90+
* @dataProvider invalidDataProvider
91+
* @param string $data The invalid data
92+
*/
93+
public function testBeforeSaveErrors(string $data): void
94+
{
95+
$this->url->expects($this->any())->method('isValid')->willReturn(true);
96+
$this->expectException('Magento\Framework\Exception\ValidatorException');
97+
$this->expectExceptionMessage('USPS API endpoint URL\'s must use usps.com or shippingapis.com');
98+
$this->urlConfig->setValue($data);
99+
$this->urlConfig->beforeSave();
100+
}
101+
102+
public function validDataProvider(): array
103+
{
104+
return [
105+
[],
106+
[''],
107+
['http://usps.com'],
108+
['https://foo.usps.com'],
109+
['http://foo.usps.com/foo/bar?baz=bash&fizz=buzz'],
110+
];
111+
}
112+
113+
/**
114+
* @return string[][]
115+
*/
116+
public function invalidDataProvider(): array
117+
{
118+
return [
119+
['https://shippingapis.com.fake.com'],
120+
['https://shippingapis.info'],
121+
['http://shippingapis.com.foo.com/foo/bar?baz=bash&fizz=buzz'],
122+
];
123+
}
124+
}

app/code/Magento/Usps/etc/adminhtml/system.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616
</field>
1717
<field id="gateway_url" translate="label" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" canRestore="1">
1818
<label>Gateway URL</label>
19+
<backend_model>Magento\Usps\Model\Config\Backend\UspsUrl</backend_model>
1920
</field>
2021
<field id="gateway_secure_url" translate="label" type="text" sortOrder="30" showInDefault="1" showInWebsite="1" canRestore="1">
2122
<label>Secure Gateway URL</label>
23+
<backend_model>Magento\Usps\Model\Config\Backend\UspsUrl</backend_model>
2224
</field>
2325
<field id="title" translate="label" type="text" sortOrder="40" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1">
2426
<label>Title</label>

app/code/Magento/Usps/i18n/en_US.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,4 @@ Machinable,Machinable
137137
Debug,Debug
138138
"Show Method if Not Applicable","Show Method if Not Applicable"
139139
"Sort Order","Sort Order"
140+
"USPS API endpoint URL\'s must use usps.com or shippingapis.com","USPS API endpoint URL\'s must use usps.com or shippingapis.com"

0 commit comments

Comments
 (0)