Skip to content

Commit 72524c4

Browse files
committed
#10521: Set correct Content-Type header for ajax responses in the Magento_UI module
1 parent c10abf0 commit 72524c4

File tree

4 files changed

+138
-26
lines changed

4 files changed

+138
-26
lines changed

app/code/Magento/Ui/Controller/Adminhtml/Index/Render.php

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,32 @@
99
use Magento\Ui\Controller\Adminhtml\AbstractAction;
1010
use Magento\Framework\View\Element\UiComponentFactory;
1111
use Magento\Framework\View\Element\UiComponentInterface;
12-
use Magento\Framework\View\Element\UiComponent\ContentType;
12+
use Magento\Ui\Model\UiComponentTypeResolver;
1313

1414
/**
1515
* Class Render
1616
*/
1717
class Render extends AbstractAction
1818
{
19+
/**
20+
* @var \Magento\Ui\Model\UiComponentTypeResolver
21+
*/
22+
private $contentTypeResolver;
23+
24+
/**
25+
* @param Context $context
26+
* @param UiComponentFactory $factory
27+
* @param UiComponentTypeResolver $contentTypeResolver
28+
*/
29+
public function __construct(
30+
Context $context,
31+
UiComponentFactory $factory,
32+
UiComponentTypeResolver $contentTypeResolver
33+
) {
34+
parent::__construct($context, $factory);
35+
$this->contentTypeResolver = $contentTypeResolver;
36+
}
37+
1938
/**
2039
* Action for AJAX request
2140
*
@@ -28,10 +47,12 @@ public function execute()
2847
return;
2948
}
3049

31-
$component = $this->factory->create($this->_request->getParam('namespace'));
50+
$component = $this->factory->create($this->getRequest()->getParam('namespace'));
3251
$this->prepareComponent($component);
33-
$this->_response->appendBody((string) $component->render());
34-
$this->setResponseContentTypeHeader($component);
52+
$this->getResponse()->appendBody((string) $component->render());
53+
54+
$contentType = $this->contentTypeResolver->resolve($component->getContext());
55+
$this->getResponse()->setHeader('Content-Type', $contentType, true);
3556
}
3657

3758
/**
@@ -47,26 +68,4 @@ protected function prepareComponent(UiComponentInterface $component)
4768
}
4869
$component->prepare();
4970
}
50-
51-
/**
52-
* Set the response 'Content-Type' header based on the component's render engine
53-
*
54-
* @param UiComponentInterface $component
55-
* @return void
56-
*/
57-
private function setResponseContentTypeHeader(UiComponentInterface $component)
58-
{
59-
$contentType = 'text/html';
60-
61-
if ($component->getContext()) {
62-
$renderEngine = $component->getContext()->getRenderEngine();
63-
if ($renderEngine instanceof ContentType\Json) {
64-
$contentType = 'application/json';
65-
} elseif ($renderEngine instanceof ContentType\Xml) {
66-
$contentType = 'application/xml';
67-
}
68-
}
69-
70-
$this->_response->setHeader('Content-Type', $contentType, true);
71-
}
7271
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Ui\Model;
7+
8+
use Magento\Framework\View\Element\UiComponent\ContextInterface as UiComponentContext;
9+
10+
/**
11+
* Provides correct Content-Type header value for the Ui Component renderer based on the Accept Type of
12+
* the Component Context. Additional types may be added to the type map via di.xml configuration for this resolver.
13+
*
14+
* This is a workaround for the lacking Content-Type processing in
15+
* \Magento\Framework\View\Element\UiComponent\ContentType\ContentTypeInterface
16+
*/
17+
class UiComponentTypeResolver
18+
{
19+
/**
20+
* @var string
21+
*/
22+
const DEFAULT_CONTENT_TYPE = 'text/html';
23+
24+
/**
25+
* @var array
26+
*/
27+
private $uiComponentTypeMap = [];
28+
29+
/**
30+
* @param array $uiComponentTypeMap
31+
*/
32+
public function __construct(array $uiComponentTypeMap)
33+
{
34+
$this->uiComponentTypeMap = $uiComponentTypeMap;
35+
}
36+
37+
/**
38+
* @param UiComponentContext $componentContext
39+
* @return string
40+
*/
41+
public function resolve(UiComponentContext $componentContext): string
42+
{
43+
$acceptType = $componentContext->getAcceptType();
44+
return $this->uiComponentTypeMap[$acceptType] ?? static::DEFAULT_CONTENT_TYPE;
45+
}
46+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Ui\Test\Unit\Model;
7+
8+
use Magento\Ui\Model\UiComponentTypeResolver;
9+
use Magento\Framework\View\Element\UiComponent\ContextInterface;
10+
11+
class UiComponentTypeResolverTest extends \PHPUnit\Framework\TestCase
12+
{
13+
/**
14+
* @var UiComponentTypeResolver
15+
*/
16+
private $model;
17+
18+
/**
19+
* @var array
20+
*/
21+
private $contentTypeMap = [];
22+
23+
protected function setUp()
24+
{
25+
$this->contentTypeMap = [
26+
'xml' => 'application/xml',
27+
'json' => 'application/json',
28+
'html' => 'text/html'
29+
];
30+
$this->model = new UiComponentTypeResolver($this->contentTypeMap);
31+
}
32+
33+
/**
34+
* @param string $acceptType
35+
* @param string $contentType
36+
* @dataProvider resolveDataProvider
37+
*/
38+
public function testResolve(string $acceptType, string $contentType)
39+
{
40+
$uiComponentContextMock = $this->createMock(ContextInterface::class);
41+
$uiComponentContextMock->expects($this->atLeastOnce())->method('getAcceptType')->willReturn($acceptType);
42+
43+
$this->assertEquals($contentType, $this->model->resolve($uiComponentContextMock));
44+
}
45+
46+
/**
47+
* @return array
48+
*/
49+
public function resolveDataProvider(): array
50+
{
51+
return [
52+
['json', 'application/json'],
53+
['xml', 'application/xml'],
54+
['html', 'text/html'],
55+
['undefined', UiComponentTypeResolver::DEFAULT_CONTENT_TYPE]
56+
];
57+
}
58+
}

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,4 +426,13 @@
426426
</argument>
427427
</arguments>
428428
</type>
429+
<type name="Magento\Ui\Model\UiComponentTypeResolver">
430+
<arguments>
431+
<argument name="uiComponentTypeMap" xsi:type="array">
432+
<item name="html" xsi:type="string">text/html</item>
433+
<item name="json" xsi:type="string">application/json</item>
434+
<item name="xml" xsi:type="string">application/xml</item>
435+
</argument>
436+
</arguments>
437+
</type>
429438
</config>

0 commit comments

Comments
 (0)