Skip to content

Backport of MAGETWO-71545 for Magento 2.1: Added 'application/json' C… #13548

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions app/code/Magento/Ui/Controller/Adminhtml/Index/Render.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,32 @@
use Magento\Ui\Controller\Adminhtml\AbstractAction;
use Magento\Framework\View\Element\UiComponentFactory;
use Magento\Framework\View\Element\UiComponentInterface;
use Magento\Ui\Model\UiComponentTypeResolver;

/**
* Class Render
*/
class Render extends AbstractAction
{
/**
* @var \Magento\Ui\Model\UiComponentTypeResolver
*/
private $contentTypeResolver;

/**
* @param Context $context
* @param UiComponentFactory $factory
* @param UiComponentTypeResolver $contentTypeResolver
*/
public function __construct(
Context $context,
UiComponentFactory $factory,
UiComponentTypeResolver $contentTypeResolver
) {
parent::__construct($context, $factory);
$this->contentTypeResolver = $contentTypeResolver;
}

/**
* Action for AJAX request
*
Expand All @@ -27,7 +47,7 @@ public function execute()
return;
}

$component = $this->factory->create($this->_request->getParam('namespace'));
$component = $this->factory->create($this->getRequest()->getParam('namespace'));

$aclResource = $component->getData('acl');

Expand All @@ -37,7 +57,10 @@ public function execute()
}

$this->prepareComponent($component);
$this->_response->appendBody((string) $component->render());
$this->getResponse()->appendBody((string) $component->render());

$contentType = $this->contentTypeResolver->resolve($component->getContext());
$this->getResponse()->setHeader('Content-Type', $contentType, true);
}

/**
Expand Down
48 changes: 48 additions & 0 deletions app/code/Magento/Ui/Model/UiComponentTypeResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Ui\Model;

use Magento\Framework\View\Element\UiComponent\ContextInterface as UiComponentContext;

/**
* Provides correct Content-Type header value for the Ui Component renderer based on the Accept Type of
* the Component Context. Additional types may be added to the type map via di.xml configuration for this resolver.
*
* This is a workaround for the lacking Content-Type processing in
* \Magento\Framework\View\Element\UiComponent\ContentType\ContentTypeInterface
*/
class UiComponentTypeResolver
{
/**
* @var string
*/
const DEFAULT_CONTENT_TYPE = 'text/html';

/**
* @var array
*/
private $uiComponentTypeMap = [];

/**
* @param array $uiComponentTypeMap
*/
public function __construct(array $uiComponentTypeMap)
{
$this->uiComponentTypeMap = $uiComponentTypeMap;
}

/**
* @param UiComponentContext $componentContext
* @return string
*/
public function resolve(UiComponentContext $componentContext)
{
$acceptType = $componentContext->getAcceptType();
return isset($this->uiComponentTypeMap[$acceptType])
? $this->uiComponentTypeMap[$acceptType]
: static::DEFAULT_CONTENT_TYPE;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
*/
namespace Magento\Ui\Test\Unit\Controller\Adminhtml\Index;

use \Magento\Ui\Controller\Adminhtml\Index\Render;
use Magento\Ui\Controller\Adminhtml\Index\Render;
use Magento\Ui\Model\UiComponentTypeResolver;
use Magento\Framework\View\Element\UiComponent\ContextInterface;

/**
* Class RenderTest
Expand Down Expand Up @@ -57,6 +59,11 @@ class RenderTest extends \PHPUnit_Framework_TestCase
*/
private $helperMock;

/**
* @var \PHPUnit_Framework_MockObject_MockObject|UiComponentTypeResolver
*/
private $uiComponentTypeResolverMock;

protected function setUp()
{
$this->requestMock = $this->getMockBuilder('Magento\Framework\App\Request\Http')
Expand Down Expand Up @@ -102,7 +109,10 @@ protected function setUp()
->method('getHelper')
->willReturn($this->helperMock);

$this->render = new Render($this->contextMock, $this->uiFactoryMock);
$this->uiComponentTypeResolverMock = $this->getMockBuilder(UiComponentTypeResolver::class)
->disableOriginalConstructor()
->getMock();
$this->render = new Render($this->contextMock, $this->uiFactoryMock, $this->uiComponentTypeResolverMock);
}

public function testExecuteAjaxRequest()
Expand Down Expand Up @@ -133,15 +143,22 @@ public function testExecuteAjaxRequest()
true,
['render']
);
$contextMock = $this->getMock(ContextInterface::class);

$viewMock->expects($this->once())
->method('render')
->willReturn($renderedData);
$viewMock->expects($this->once())
->method('getChildComponents')
->willReturn([]);
$viewMock->expects($this->atLeastOnce())->method('getContext')->willReturn($contextMock);
$this->uiFactoryMock->expects($this->once())
->method('create')
->willReturn($viewMock);
$this->uiComponentTypeResolverMock->expects($this->once())->method('resolve')->with($contextMock)
->willReturn('application/json');
$this->responseMock->expects($this->once())->method('setHeader')
->with('Content-Type', 'application/json', true);

$this->render->executeAjaxRequest();
}
Expand Down Expand Up @@ -180,6 +197,8 @@ public function testExecuteAjaxRequestWithoutPermissions($acl, $isAllowed)
true,
['render']
);
$contextMock = $this->getMock(ContextInterface::class);

$componentMock->expects($this->any())
->method('render')
->willReturn($renderedData);
Expand All @@ -190,6 +209,9 @@ public function testExecuteAjaxRequestWithoutPermissions($acl, $isAllowed)
->method('getData')
->with('acl')
->willReturn($acl);
$componentMock->expects($this->any())
->method('getContext')
->willReturn($contextMock);
$this->uiFactoryMock->expects($this->once())
->method('create')
->willReturn($componentMock);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Ui\Test\Unit\Model;

use Magento\Ui\Model\UiComponentTypeResolver;
use Magento\Framework\View\Element\UiComponent\ContextInterface;

class UiComponentTypeResolverTest extends \PHPUnit_Framework_TestCase
{
/**
* @var UiComponentTypeResolver
*/
private $model;

/**
* @var array
*/
private $contentTypeMap = [];

protected function setUp()
{
$this->contentTypeMap = [
'xml' => 'application/xml',
'json' => 'application/json',
'html' => 'text/html'
];
$this->model = new UiComponentTypeResolver($this->contentTypeMap);
}

/**
* @param string $acceptType
* @param string $contentType
* @dataProvider resolveDataProvider
*/
public function testResolve($acceptType, $contentType)
{
$uiComponentContextMock = $this->getMock(ContextInterface::class);
$uiComponentContextMock->expects($this->atLeastOnce())->method('getAcceptType')->willReturn($acceptType);

$this->assertEquals($contentType, $this->model->resolve($uiComponentContextMock));
}

/**
* @return array
*/
public function resolveDataProvider()
{
return [
['json', 'application/json'],
['xml', 'application/xml'],
['html', 'text/html'],
['undefined', UiComponentTypeResolver::DEFAULT_CONTENT_TYPE]
];
}
}
9 changes: 9 additions & 0 deletions app/code/Magento/Ui/etc/di.xml
Original file line number Diff line number Diff line change
Expand Up @@ -282,4 +282,13 @@
<argument name="subject" xsi:type="object">uiComponentAggregatedSourceOverrideThemeFiltered</argument>
</arguments>
</virtualType>
<type name="Magento\Ui\Model\UiComponentTypeResolver">
<arguments>
<argument name="uiComponentTypeMap" xsi:type="array">
<item name="html" xsi:type="string">text/html</item>
<item name="json" xsi:type="string">application/json</item>
<item name="xml" xsi:type="string">application/xml</item>
</argument>
</arguments>
</type>
</config>