Skip to content

Commit 33724b1

Browse files
Merge pull request #4023 from magento-qwerty/2.3-bugfixes-080419
Fixed issues: - MC-10870: Invalid company ID in web API - MC-14893: Fixed incorrect behavior of email templates - MC-15556: Processing of AJAX header
2 parents 3fe42cb + 6a81f74 commit 33724b1

File tree

14 files changed

+277
-116
lines changed

14 files changed

+277
-116
lines changed

app/code/Magento/Webapi/Controller/Rest/ParamsOverrider.php

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
namespace Magento\Webapi\Controller\Rest;
88

9+
use Magento\Framework\App\ObjectManager;
910
use Magento\Framework\Webapi\Rest\Request\ParamOverriderInterface;
1011
use Magento\Webapi\Model\Config\Converter;
1112
use Magento\Framework\Reflection\MethodsMap;
@@ -26,15 +27,24 @@ class ParamsOverrider
2627
*/
2728
private $methodsMap;
2829

30+
/**
31+
* @var SimpleDataObjectConverter
32+
*/
33+
private $dataObjectConverter;
34+
2935
/**
3036
* Initialize dependencies
3137
*
3238
* @param ParamOverriderInterface[] $paramOverriders
39+
* @param SimpleDataObjectConverter|null $dataObjectConverter
3340
*/
3441
public function __construct(
35-
array $paramOverriders = []
42+
array $paramOverriders = [],
43+
SimpleDataObjectConverter $dataObjectConverter = null
3644
) {
3745
$this->paramOverriders = $paramOverriders;
46+
$this->dataObjectConverter = $dataObjectConverter
47+
?? ObjectManager::getInstance()->get(SimpleDataObjectConverter::class);
3848
}
3949

4050
/**
@@ -64,15 +74,17 @@ public function override(array $inputData, array $parameters)
6474
/**
6575
* Determine if a nested array value is set.
6676
*
67-
* @param array &$nestedArray
77+
* @param array $nestedArray
6878
* @param string[] $arrayKeys
6979
* @return bool true if array value is set
7080
*/
71-
protected function isNestedArrayValueSet(&$nestedArray, $arrayKeys)
81+
protected function isNestedArrayValueSet($nestedArray, $arrayKeys)
7282
{
73-
$currentArray = &$nestedArray;
83+
//Converting input data to camelCase in order to process both snake and camel style data equally.
84+
$currentArray = $this->dataObjectConverter->convertKeysToCamelCase($nestedArray);
7485

7586
foreach ($arrayKeys as $key) {
87+
$key = SimpleDataObjectConverter::snakeCaseToCamelCase($key);
7688
if (!isset($currentArray[$key])) {
7789
return false;
7890
}
@@ -95,12 +107,22 @@ protected function setNestedArrayValue(&$nestedArray, $arrayKeys, $valueToSet)
95107
$lastKey = array_pop($arrayKeys);
96108

97109
foreach ($arrayKeys as $key) {
110+
if (!array_key_exists($key, $currentArray)) {
111+
//In case input data uses camelCase format
112+
$key = SimpleDataObjectConverter::snakeCaseToCamelCase($key);
113+
}
98114
if (!isset($currentArray[$key])) {
99115
$currentArray[$key] = [];
100116
}
101117
$currentArray = &$currentArray[$key];
102118
}
103119

120+
//In case input data uses camelCase format
121+
$camelCaseKey = SimpleDataObjectConverter::snakeCaseToCamelCase($lastKey);
122+
if (array_key_exists($camelCaseKey, $currentArray)) {
123+
$lastKey = $camelCaseKey;
124+
}
125+
104126
$currentArray[$lastKey] = $valueToSet;
105127
}
106128

app/code/Magento/Webapi/Model/Config/Reader.php

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -18,38 +18,6 @@ class Reader extends \Magento\Framework\Config\Reader\Filesystem
1818
protected $_idAttributes = [
1919
'/routes/route' => ['url', 'method'],
2020
'/routes/route/resources/resource' => 'ref',
21-
'/routes/route/data' => 'name',
21+
'/routes/route/data/parameter' => 'name',
2222
];
23-
24-
/**
25-
* @param \Magento\Framework\Config\FileResolverInterface $fileResolver
26-
* @param Converter $converter
27-
* @param SchemaLocator $schemaLocator
28-
* @param \Magento\Framework\Config\ValidationStateInterface $validationState
29-
* @param string $fileName
30-
* @param array $idAttributes
31-
* @param string $domDocumentClass
32-
* @param string $defaultScope
33-
*/
34-
public function __construct(
35-
\Magento\Framework\Config\FileResolverInterface $fileResolver,
36-
Converter $converter,
37-
SchemaLocator $schemaLocator,
38-
\Magento\Framework\Config\ValidationStateInterface $validationState,
39-
$fileName = 'webapi.xml',
40-
$idAttributes = [],
41-
$domDocumentClass = \Magento\Framework\Config\Dom::class,
42-
$defaultScope = 'global'
43-
) {
44-
parent::__construct(
45-
$fileResolver,
46-
$converter,
47-
$schemaLocator,
48-
$validationState,
49-
$fileName,
50-
$idAttributes,
51-
$domDocumentClass,
52-
$defaultScope
53-
);
54-
}
5523
}

app/code/Magento/Webapi/Model/Config/SchemaLocator.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ class SchemaLocator implements \Magento\Framework\Config\SchemaLocatorInterface
3131
*/
3232
public function __construct(\Magento\Framework\Module\Dir\Reader $moduleReader)
3333
{
34-
$this->_schema = $moduleReader->getModuleDir(Dir::MODULE_ETC_DIR, 'Magento_Webapi') . '/webapi.xsd';
34+
$this->_schema = $moduleReader->getModuleDir(Dir::MODULE_ETC_DIR, 'Magento_Webapi') . '/webapi_merged.xsd';
35+
$this->_perFileSchema = $moduleReader->getModuleDir(Dir::MODULE_ETC_DIR, 'Magento_Webapi') . '/webapi.xsd';
3536
}
3637

3738
/**

app/code/Magento/Webapi/Test/Unit/Controller/Rest/ParamsOverriderTest.php

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
namespace Magento\Webapi\Test\Unit\Controller\Rest;
88

99
use \Magento\Authorization\Model\UserContextInterface;
10+
use Magento\Framework\Api\SimpleDataObjectConverter;
11+
use Magento\Webapi\Controller\Rest\ParamsOverrider;
12+
use PHPUnit\Framework\MockObject\MockObject;
1013

1114
/**
1215
* Test Magento\Webapi\Controller\Rest\ParamsOverrider
@@ -36,10 +39,31 @@ public function testOverrideParams($requestData, $parameters, $expectedOverridde
3639
['userContext' => $userContextMock]
3740
);
3841

39-
/** @var \Magento\Webapi\Controller\Rest\ParamsOverrider $paramsOverrider */
42+
/** @var MockObject $objectConverter */
43+
$objectConverter = $this->getMockBuilder(SimpleDataObjectConverter::class)
44+
->disableOriginalConstructor()
45+
->setMethods(['convertKeysToCamelCase'])
46+
->getMock();
47+
$objectConverter->expects($this->any())
48+
->method('convertKeysToCamelCase')
49+
->willReturnCallback(
50+
function (array $array) {
51+
$converted = [];
52+
foreach ($array as $key => $value) {
53+
$converted[mb_strtolower($key)] = $value;
54+
}
55+
56+
return $converted;
57+
}
58+
);
59+
60+
/** @var ParamsOverrider $paramsOverrider */
4061
$paramsOverrider = $objectManager->getObject(
41-
\Magento\Webapi\Controller\Rest\ParamsOverrider::class,
42-
['paramOverriders' => ['%customer_id%' => $paramOverriderCustomerId ]]
62+
ParamsOverrider::class,
63+
[
64+
'paramOverriders' => ['%customer_id%' => $paramOverriderCustomerId ],
65+
'dataObjectConverter' => $objectConverter
66+
]
4367
);
4468

4569
$this->assertEquals($expectedOverriddenParams, $paramsOverrider->override($requestData, $parameters));

app/code/Magento/Webapi/etc/di.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,11 @@
5858
</argument>
5959
</arguments>
6060
</type>
61+
<type name="Magento\Webapi\Model\Config\Reader">
62+
<arguments>
63+
<argument name="converter" xsi:type="object">Magento\Webapi\Model\Config\Converter</argument>
64+
<argument name="schemaLocator" xsi:type="object">Magento\Webapi\Model\Config\SchemaLocator</argument>
65+
<argument name="fileName" xsi:type="string">webapi.xml</argument>
66+
</arguments>
67+
</type>
6168
</config>

app/code/Magento/Webapi/etc/webapi.xsd

Lines changed: 13 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -8,69 +8,17 @@
88
*/
99
-->
1010
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
11-
<xs:element name="routes" type="routesType"/>
12-
13-
<xs:complexType name="routesType">
14-
<xs:sequence>
15-
<xs:element name="route" type="routeType" minOccurs="0" maxOccurs="unbounded"/>
16-
</xs:sequence>
17-
</xs:complexType>
18-
19-
<xs:complexType name="routeType">
20-
<xs:sequence>
21-
<xs:element name="service" type="serviceType"/>
22-
<xs:element name="resources" type="resourcesType"/>
23-
<xs:element name="data" type="dataType" minOccurs="0"/>
24-
</xs:sequence>
25-
<xs:attribute name="method" use="required">
26-
<xs:simpleType>
27-
<xs:restriction base="xs:string">
28-
<xs:enumeration value="GET"/>
29-
<xs:enumeration value="PUT"/>
30-
<xs:enumeration value="POST"/>
31-
<xs:enumeration value="DELETE"/>
32-
</xs:restriction>
33-
</xs:simpleType>
34-
</xs:attribute>
35-
<xs:attribute name="url" type="xs:string" use="required"/>
36-
<xs:attribute name="secure" type="xs:boolean"/>
37-
<xs:attribute name="soapOperation" type="xs:string"/>
38-
</xs:complexType>
39-
40-
<xs:complexType name="serviceType">
41-
<xs:attribute name="class" type="xs:string" use="required"/>
42-
<xs:attribute name="method" type="xs:string" use="required"/>
43-
</xs:complexType>
44-
45-
<xs:complexType name="resourcesType" >
46-
<xs:sequence>
47-
<xs:element name="resource" type="resourceType" maxOccurs="unbounded"/>
48-
</xs:sequence>
49-
</xs:complexType>
50-
51-
<xs:complexType name="resourceType">
52-
<xs:attribute name="ref" use="required">
53-
<xs:simpleType>
54-
<xs:restriction base="xs:string">
55-
<xs:pattern value=".+(, ?.+)*"/>
56-
</xs:restriction>
57-
</xs:simpleType>
58-
</xs:attribute>
59-
</xs:complexType>
60-
61-
<xs:complexType name="dataType" >
62-
<xs:sequence>
63-
<xs:element name="parameter" type="parameterType" maxOccurs="unbounded"/>
64-
</xs:sequence>
65-
</xs:complexType>
66-
67-
<xs:complexType name="parameterType">
68-
<xs:simpleContent>
69-
<xs:extension base="xs:string">
70-
<xs:attribute name="name" type="xs:string" use="required"/>
71-
<xs:attribute name="force" type="xs:boolean"/>
72-
</xs:extension>
73-
</xs:simpleContent>
74-
</xs:complexType>
75-
11+
<xs:redefine schemaLocation="urn:magento:module:Magento_Webapi:etc/webapi_base.xsd">
12+
<xs:complexType name="routeType">
13+
<xs:complexContent>
14+
<xs:extension base="routeType">
15+
<xs:sequence>
16+
<xs:element name="service" type="serviceType" minOccurs="0"/>
17+
<xs:element name="resources" type="resourcesType" minOccurs="0"/>
18+
<xs:element name="data" type="dataType" minOccurs="0"/>
19+
</xs:sequence>
20+
</xs:extension>
21+
</xs:complexContent>
22+
</xs:complexType>
23+
</xs:redefine>
7624
</xs:schema>
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Structure description for webapi.xml configuration files.
5+
*
6+
* Copyright © Magento, Inc. All rights reserved.
7+
* See COPYING.txt for license details.
8+
*/
9+
-->
10+
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
11+
<xs:element name="routes" type="routesType"/>
12+
13+
<xs:complexType name="routesType">
14+
<xs:sequence>
15+
<xs:element name="route" type="routeType" minOccurs="0" maxOccurs="unbounded"/>
16+
</xs:sequence>
17+
</xs:complexType>
18+
19+
<xs:complexType name="routeType">
20+
<xs:attribute name="method" use="required">
21+
<xs:simpleType>
22+
<xs:restriction base="xs:string">
23+
<xs:enumeration value="GET"/>
24+
<xs:enumeration value="PUT"/>
25+
<xs:enumeration value="POST"/>
26+
<xs:enumeration value="DELETE"/>
27+
</xs:restriction>
28+
</xs:simpleType>
29+
</xs:attribute>
30+
<xs:attribute name="url" type="xs:string" use="required"/>
31+
<xs:attribute name="secure" type="xs:boolean"/>
32+
<xs:attribute name="soapOperation" type="xs:string"/>
33+
</xs:complexType>
34+
35+
<xs:complexType name="serviceType">
36+
<xs:attribute name="class" type="xs:string" use="required"/>
37+
<xs:attribute name="method" type="xs:string" use="required"/>
38+
</xs:complexType>
39+
40+
<xs:complexType name="resourcesType" >
41+
<xs:sequence>
42+
<xs:element name="resource" type="resourceType" maxOccurs="unbounded"/>
43+
</xs:sequence>
44+
</xs:complexType>
45+
46+
<xs:complexType name="resourceType">
47+
<xs:attribute name="ref" use="required">
48+
<xs:simpleType>
49+
<xs:restriction base="xs:string">
50+
<xs:pattern value=".+(, ?.+)*"/>
51+
</xs:restriction>
52+
</xs:simpleType>
53+
</xs:attribute>
54+
</xs:complexType>
55+
56+
<xs:complexType name="dataType" >
57+
<xs:sequence>
58+
<xs:element name="parameter" type="parameterType" maxOccurs="unbounded"/>
59+
</xs:sequence>
60+
</xs:complexType>
61+
62+
<xs:complexType name="parameterType">
63+
<xs:simpleContent>
64+
<xs:extension base="xs:string">
65+
<xs:attribute name="name" type="xs:string" use="required"/>
66+
<xs:attribute name="force" type="xs:boolean"/>
67+
</xs:extension>
68+
</xs:simpleContent>
69+
</xs:complexType>
70+
71+
</xs:schema>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Structure description for webapi.xml configuration files.
5+
*
6+
* Copyright © Magento, Inc. All rights reserved.
7+
* See COPYING.txt for license details.
8+
*/
9+
-->
10+
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
11+
<xs:redefine schemaLocation="urn:magento:module:Magento_Webapi:etc/webapi_base.xsd">
12+
<xs:complexType name="routeType">
13+
<xs:complexContent>
14+
<xs:extension base="routeType">
15+
<xs:sequence>
16+
<xs:element name="service" type="serviceType"/>
17+
<xs:element name="resources" type="resourcesType"/>
18+
<xs:element name="data" type="dataType" minOccurs="0"/>
19+
</xs:sequence>
20+
</xs:extension>
21+
</xs:complexContent>
22+
</xs:complexType>
23+
</xs:redefine>
24+
</xs:schema>

0 commit comments

Comments
 (0)