Skip to content
This repository was archived by the owner on Apr 29, 2019. It is now read-only.

Commit 96885cb

Browse files
committed
Merge remote-tracking branch 'mainline/2.3-develop' into RE-develop-pr
2 parents 536a796 + 0339078 commit 96885cb

File tree

20 files changed

+475
-13
lines changed

20 files changed

+475
-13
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<services xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
9+
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_WebapiAsync:etc/webapi_async.xsd">
10+
<route url="async/bulk/V1/products/bySku" method="PUT" alias="async/bulk/V1/products"/>
11+
</services>

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class Config
2121
const HTTP_METHOD_DELETE = 'DELETE';
2222
const HTTP_METHOD_PUT = 'PUT';
2323
const HTTP_METHOD_POST = 'POST';
24+
const HTTP_METHOD_PATCH = 'PATCH';
2425
/**#@-*/
2526

2627
/**#@+

app/code/Magento/WebapiAsync/Model/ServiceConfig.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
*/
2121
class ServiceConfig
2222
{
23-
const CACHE_ID = 'webapi_async_config';
23+
const CACHE_ID = 'webapi_async_service_config';
2424

2525
/**
2626
* @var WebapiCache
@@ -71,7 +71,7 @@ public function getServices()
7171
if ($services && is_string($services)) {
7272
$this->services = $this->serializer->unserialize($services);
7373
} else {
74-
$this->services = $this->configReader->read()[Converter::KEY_SERVICES] ?? [];
74+
$this->services = $this->configReader->read();
7575
$this->cache->save($this->serializer->serialize($this->services), self::CACHE_ID);
7676
}
7777
}

app/code/Magento/WebapiAsync/Model/ServiceConfig/Converter.php

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,17 @@ class Converter implements \Magento\Framework\Config\ConverterInterface
2020
const KEY_METHOD = 'method';
2121
const KEY_METHODS = 'methods';
2222
const KEY_SYNCHRONOUS_INVOCATION_ONLY = 'synchronousInvocationOnly';
23+
const KEY_ROUTES = 'routes';
2324
/**#@-*/
2425

26+
private $allowedRouteMethods = [
27+
\Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
28+
\Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST,
29+
\Magento\Webapi\Model\Rest\Config::HTTP_METHOD_PUT,
30+
\Magento\Webapi\Model\Rest\Config::HTTP_METHOD_DELETE,
31+
\Magento\Webapi\Model\Rest\Config::HTTP_METHOD_PATCH
32+
];
33+
2534
/**
2635
* {@inheritdoc}
2736
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
@@ -44,6 +53,7 @@ public function convert($source)
4453
$this->initServiceMethodsKey($result, $serviceClass, $serviceMethod);
4554
$this->mergeSynchronousInvocationMethodsData($service, $result, $serviceClass, $serviceMethod);
4655
}
56+
$result[self::KEY_ROUTES] = $this->convertRouteCustomizations($source);
4757

4858
return $result;
4959
}
@@ -158,4 +168,68 @@ private function isSynchronousInvocationOnlyTrue(\DOMElement $synchronousInvocat
158168

159169
return filter_var($synchronousInvocationOnlyNode->nodeValue, FILTER_VALIDATE_BOOLEAN);
160170
}
171+
172+
/**
173+
* Convert and merge "route" nodes, which represent route customizations
174+
* @param \DOMDocument $source
175+
* @return array
176+
*/
177+
private function convertRouteCustomizations($source)
178+
{
179+
$customRoutes = [];
180+
$routes = $source->getElementsByTagName('route');
181+
/** @var \DOMElement $route */
182+
foreach ($routes as $route) {
183+
$routeUrl = $this->getRouteUrl($route);
184+
$routeMethod = $this->getRouteMethod($route);
185+
$routeAlias = $this->getRouteAlias($route);
186+
if ($routeUrl && $routeMethod && $routeAlias) {
187+
if (!isset($customRoutes[$routeAlias])) {
188+
$customRoutes[$routeAlias] = [];
189+
}
190+
$customRoutes[$routeAlias][$routeMethod] = $routeUrl;
191+
}
192+
}
193+
return $customRoutes;
194+
}
195+
196+
/**
197+
* @param \DOMElement $route
198+
* @return null|string
199+
*/
200+
private function getRouteUrl($route)
201+
{
202+
$url = $route->attributes->getNamedItem('url')->nodeValue;
203+
return mb_strlen((string) $url) === 0 ? null : $url;
204+
}
205+
206+
/**
207+
* @param \DOMElement $route
208+
* @return null|string
209+
*/
210+
private function getRouteAlias($route)
211+
{
212+
$alias = $route->attributes->getNamedItem('alias')->nodeValue;
213+
return mb_strlen((string) $alias) === 0 ? null : ltrim($alias, '/');
214+
}
215+
216+
/**
217+
* @param \DOMElement $route
218+
* @return null|string
219+
*/
220+
private function getRouteMethod($route)
221+
{
222+
$method = $route->attributes->getNamedItem('method')->nodeValue;
223+
$method = mb_strlen((string) $method) === 0 ? null : $method;
224+
return ($this->validateRouteMethod($method)) ? $method : null;
225+
}
226+
227+
/**
228+
* @param string $method
229+
* @return bool
230+
*/
231+
private function validateRouteMethod($method)
232+
{
233+
return in_array($method, $this->allowedRouteMethods);
234+
}
161235
}

app/code/Magento/WebapiAsync/Model/ServiceConfig/Reader.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class Reader extends \Magento\Framework\Config\Reader\Filesystem
2020
*/
2121
protected $_idAttributes = [
2222
'/services/service' => ['class', 'method'],
23+
'/services/route' => ['url', 'method']
2324
];
2425

2526
/**
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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\WebapiAsync\Plugin;
10+
11+
use Magento\WebapiAsync\Model\ServiceConfig;
12+
use Magento\Webapi\Controller\PathProcessor;
13+
use Magento\Framework\App\RequestInterface;
14+
use Magento\WebapiAsync\Model\ServiceConfig\Converter;
15+
16+
class ControllerRest
17+
{
18+
/**
19+
* @var ServiceConfig
20+
*/
21+
private $serviceConfig;
22+
23+
/**
24+
* @var PathProcessor
25+
*/
26+
private $pathProcessor;
27+
28+
/**
29+
* ControllerRest constructor.
30+
*
31+
* @param ServiceConfig $serviceConfig
32+
* @param PathProcessor $pathProcessor
33+
*/
34+
public function __construct(
35+
ServiceConfig $serviceConfig,
36+
PathProcessor $pathProcessor
37+
) {
38+
$this->serviceConfig = $serviceConfig;
39+
$this->pathProcessor = $pathProcessor;
40+
}
41+
42+
/**
43+
* Apply route customization.
44+
* @param \Magento\Webapi\Controller\Rest $subject
45+
* @param RequestInterface $request
46+
* @return array
47+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
48+
*/
49+
public function beforeDispatch(\Magento\Webapi\Controller\Rest $subject, RequestInterface $request)
50+
{
51+
$routeCustomizations = $this->serviceConfig->getServices()[Converter::KEY_ROUTES] ?? [];
52+
if ($routeCustomizations) {
53+
$originPath = $request->getPathInfo();
54+
$requestMethod = $request->getMethod();
55+
$routePath = ltrim($this->pathProcessor->process($originPath), '/');
56+
if (array_key_exists($routePath, $routeCustomizations)) {
57+
if (isset($routeCustomizations[$routePath][$requestMethod])) {
58+
$path = ltrim($routeCustomizations[$routePath][$requestMethod], '/');
59+
$request->setPathInfo(str_replace($routePath, $path, $originPath));
60+
}
61+
}
62+
}
63+
return [$request];
64+
}
65+
}

app/code/Magento/WebapiAsync/Plugin/ServiceMetadata.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,8 @@ private function getServiceVersions(string $serviceName)
129129
private function getSynchronousOnlyServiceMethods(\Magento\Webapi\Model\ServiceMetadata $serviceMetadata)
130130
{
131131
$synchronousOnlyServiceMethods = [];
132-
foreach ($this->serviceConfig->getServices() as $service => $serviceData) {
132+
$services = $this->serviceConfig->getServices()[Converter::KEY_SERVICES] ?? [];
133+
foreach ($services as $service => $serviceData) {
133134
if (!isset($serviceData[Converter::KEY_METHODS])) {
134135
continue;
135136
}

app/code/Magento/WebapiAsync/Test/Unit/Model/ServiceConfig/_files/Converter/webapi_async.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,9 @@
2222
],
2323
],
2424
],
25+
'routes' => [
26+
'asyncProducts' => ['POST' => 'async/V1/products'],
27+
'asyncBulkCmsBlocks' => ['POST' => 'async/bulk/V1/cmsBlock'],
28+
'asyncCustomers' => ['POST' => 'async/V1/customers']
29+
]
2530
];

app/code/Magento/WebapiAsync/Test/Unit/Model/ServiceConfig/_files/Converter/webapi_async.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,8 @@
1616
</service>
1717

1818
<service class="Magento\Customer\Api\CustomerRepositoryInterface" method="get" />
19+
20+
<route url="async/V1/products" method="POST" alias="asyncProducts"/>
21+
<route url="async/bulk/V1/cmsBlock" method="POST" alias="asyncBulkCmsBlocks"/>
22+
<route url="async/V1/customers" method="POST" alias="asyncCustomers"/>
1923
</services>

app/code/Magento/WebapiAsync/Test/Unit/Model/ServiceConfig/_files/Reader/webapi_async.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,9 @@
2222
],
2323
],
2424
],
25+
'routes' => [
26+
'asyncProducts' => ['POST' => 'async/bulk/V1/products'],
27+
'asyncBulkCmsPages' => ['POST' => 'async/bulk/V1/cmsPage'],
28+
'asyncCustomers' => ['POST' => 'async/V1/customers']
29+
]
2530
];

app/code/Magento/WebapiAsync/Test/Unit/Model/ServiceConfig/_files/Reader/webapi_async_1.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,7 @@
1515
<synchronousInvocationOnly />
1616
</service>
1717

18+
<route url="async/V1/products" method="POST" alias="asyncProducts"/>
19+
<route url="async/bulk/V1/cmsPage" method="POST" alias="asyncBulkCmsPages"/>
20+
<route url="async/V1/customers" method="POST" alias="/asyncCustomers"/>
1821
</services>

app/code/Magento/WebapiAsync/Test/Unit/Model/ServiceConfig/_files/Reader/webapi_async_2.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@
88
<services xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
99
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_WebapiAsync:etc/webapi_async.xsd">
1010
<service class="Magento\Customer\Api\CustomerRepositoryInterface" method="get" />
11-
11+
<route url="async/bulk/V1/products" method="POST" alias="asyncProducts"/>
1212
</services>

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,7 @@
4242
<argument name="processorPath" xsi:type="const">Magento\WebapiAsync\Controller\Rest\AsynchronousSchemaRequestProcessor::BULK_PROCESSOR_PATH</argument>
4343
</arguments>
4444
</virtualType>
45+
<type name="Magento\Webapi\Controller\Rest">
46+
<plugin name="webapiContorllerRestAsync" type="Magento\WebapiAsync\Plugin\ControllerRest" />
47+
</type>
4548
</config>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<services xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
9+
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_WebapiAsync:etc/webapi_async.xsd">
10+
<route url="async/V1/products" method="POST" alias="asyncProducts" />
11+
</services>

app/code/Magento/WebapiAsync/etc/webapi_async.xsd

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,14 @@
88
*/
99
-->
1010
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
11-
<xs:element name="services" type="servicesType"/>
11+
<xs:element name="services">
12+
<xs:complexType>
13+
<xs:choice maxOccurs="unbounded">
14+
<xs:element name="service" type="serviceType" minOccurs="0" maxOccurs="unbounded"/>
15+
<xs:element name="route" type="routeType" minOccurs="0" maxOccurs="unbounded"/>
16+
</xs:choice>
17+
</xs:complexType>
18+
</xs:element>
1219

1320
<xs:complexType name="serviceType">
1421
<xs:sequence>
@@ -18,10 +25,19 @@
1825
<xs:attribute name="method" type="xs:string" use="required"/>
1926
</xs:complexType>
2027

21-
<xs:complexType name="servicesType">
22-
<xs:sequence>
23-
<xs:element name="service" type="servicesType" minOccurs="0" maxOccurs="unbounded"/>
24-
</xs:sequence>
28+
<xs:complexType name="routeType">
29+
<xs:attribute name="url" type="xs:string" use="required"/>
30+
<xs:attribute name="method" use="required">
31+
<xs:simpleType>
32+
<xs:restriction base="xs:string">
33+
<xs:enumeration value="GET"/>
34+
<xs:enumeration value="PUT"/>
35+
<xs:enumeration value="POST"/>
36+
<xs:enumeration value="DELETE"/>
37+
</xs:restriction>
38+
</xs:simpleType>
39+
</xs:attribute>
40+
<xs:attribute name="alias" type="xs:string" use="required"/>
2541
</xs:complexType>
2642

2743
</xs:schema>

dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/SearchAndMultiselectActionGroup.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@
1010
xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd">
1111
<actionGroup name="searchAndMultiSelectActionGroup">
1212
<arguments>
13-
<argument name="dropDownSelector"/>
14-
<argument name="options"/>
13+
<argument name="dropDownSelector" />
14+
<argument name="options" type="string"/>
1515
</arguments>
1616
<waitForPageLoad stepKey="waitForPageLoad"/>
1717
<waitForElementVisible selector="{{dropDownSelector}} .action-select.admin__action-multiselect" stepKey="waitForDropdown"/>
1818
<click selector="{{dropDownSelector}} .action-select.admin__action-multiselect" stepKey="clickDropdown"/>
19-
<selectMultipleOptions filterSelector="{{dropDownSelector}} .admin__action-multiselect-search-wrap>input[data-role='advanced-select-text']" optionSelector="{{dropDownSelector}} .admin__action-multiselect-label>span" stepKey="selectSpecifiedOptions">
19+
<selectMultipleOptions filterSelector="{{dropDownSelector}} .admin__action-multiselect-search-wrap>input" optionSelector="{{dropDownSelector}} .admin__action-multiselect-label>span" stepKey="selectSpecifiedOptions">
2020
<array>[{{options}}]</array>
2121
</selectMultipleOptions>
2222
</actionGroup>

dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Customer/Data/CustomerGroupData.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,9 @@
1313
<data key="tax_class_id">3</data>
1414
<data key="tax_class_name">Retail Customer</data>
1515
</entity>
16+
<entity name="DefaultCustomerGroup" type="customerGroup">
17+
<array key="group_names">
18+
<item>General</item>
19+
</array>
20+
</entity>
1621
</entities>

dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Customer/Section/AdminCustomerAccountInformationSection.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@
1313
<element name="firstName" type="input" selector="input[name='customer[firstname]']"/>
1414
<element name="lastName" type="input" selector="input[name='customer[lastname]']"/>
1515
<element name="email" type="input" selector="input[name='customer[email]']"/>
16+
<element name="group" type="select" selector="[name='customer[group_id]']"/>
1617
</section>
1718
</sections>

dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Customer/Test/AdminCreateCustomerTest.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
<testCaseId value="MAGETWO-72095"/>
1919
<group value="customer"/>
2020
<group value="create"/>
21-
<group value="skip"/>
2221
</annotations>
2322
<after>
2423
<amOnPage url="admin/admin/auth/logout/" stepKey="amOnLogoutPage"/>

0 commit comments

Comments
 (0)