Skip to content

Commit 2b27fc8

Browse files
authored
ENGCOM-7829: Issue 28656 inline translation rest api #28856
2 parents 41b7991 + 1b29b28 commit 2b27fc8

File tree

3 files changed

+350
-235
lines changed

3 files changed

+350
-235
lines changed

dev/tests/integration/testsuite/Magento/Translation/Model/InlineParserTest.php

Lines changed: 87 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,93 +3,134 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
7+
declare(strict_types=1);
8+
69
namespace Magento\Translation\Model;
710

8-
class InlineParserTest extends \PHPUnit\Framework\TestCase
11+
use Magento\Framework\App\Config\MutableScopeConfigInterface;
12+
use Magento\Framework\App\State;
13+
use Magento\Framework\Translate\Inline;
14+
use Magento\Framework\App\Area;
15+
use Magento\Store\Model\ScopeInterface;
16+
use Magento\TestFramework\Helper\Bootstrap;
17+
use Magento\Translation\Model\Inline\Parser;
18+
use PHPUnit\Framework\TestCase;
19+
use Psr\Log\LoggerInterface;
20+
21+
/**
22+
* Test for \Magento\Translation\Model\Inline\Parser.
23+
*/
24+
class InlineParserTest extends TestCase
925
{
26+
private const STUB_STORE = 'default';
27+
private const XML_PATH_TRANSLATE_INLINE_ACTIVE = 'dev/translate_inline/active';
28+
1029
/**
11-
* @var \Magento\Translation\Model\Inline\Parser
30+
* @var Parser
1231
*/
13-
protected $_inlineParser;
14-
15-
/** @var string */
16-
protected $_storeId = 'default';
32+
private $model;
1733

34+
/**
35+
* @inheritDoc
36+
*/
1837
protected function setUp(): void
1938
{
20-
/** @var $inline \Magento\Framework\Translate\Inline */
21-
$inline = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
22-
->create(\Magento\Framework\Translate\Inline::class);
23-
$this->_inlineParser = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
24-
\Magento\Translation\Model\Inline\Parser::class,
25-
['translateInline' => $inline]
26-
);
27-
/* Called getConfig as workaround for setConfig bug */
28-
\Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
29-
\Magento\Store\Model\StoreManagerInterface::class
30-
)->getStore(
31-
$this->_storeId
32-
)->getConfig(
33-
'dev/translate_inline/active'
34-
);
35-
\Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
36-
\Magento\Framework\App\Config\MutableScopeConfigInterface::class
37-
)->setValue(
38-
'dev/translate_inline/active',
39-
true,
40-
\Magento\Store\Model\ScopeInterface::SCOPE_STORE,
41-
$this->_storeId
42-
);
39+
$inline = Bootstrap::getObjectManager()->create(Inline::class);
40+
$this->model = Bootstrap::getObjectManager()->create(Parser::class, ['translateInline' => $inline]);
41+
Bootstrap::getObjectManager()->get(MutableScopeConfigInterface::class)
42+
->setValue(self::XML_PATH_TRANSLATE_INLINE_ACTIVE, true, ScopeInterface::SCOPE_STORE, self::STUB_STORE);
4343
}
4444

4545
/**
46+
* Process ajax post test
47+
*
4648
* @dataProvider processAjaxPostDataProvider
49+
*
50+
* @param string $originalText
51+
* @param string $translatedText
52+
* @param string $area
53+
* @param bool|null $isPerStore
54+
* @return void
4755
*/
48-
public function testProcessAjaxPost($originalText, $translatedText, $isPerStore = null)
49-
{
56+
public function testProcessAjaxPost(
57+
string $originalText,
58+
string $translatedText,
59+
string $area,
60+
?bool $isPerStore = null
61+
): void {
62+
Bootstrap::getObjectManager()->get(State::class)
63+
->setAreaCode($area);
64+
5065
$inputArray = [['original' => $originalText, 'custom' => $translatedText]];
5166
if ($isPerStore !== null) {
5267
$inputArray[0]['perstore'] = $isPerStore;
5368
}
54-
$this->_inlineParser->processAjaxPost($inputArray);
69+
$this->model->processAjaxPost($inputArray);
5570

56-
$model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
57-
\Magento\Translation\Model\StringUtils::class
58-
);
71+
$model = Bootstrap::getObjectManager()->create(StringUtils::class);
5972
$model->load($originalText);
73+
6074
try {
6175
$this->assertEquals($translatedText, $model->getTranslate());
6276
$model->delete();
6377
} catch (\Exception $e) {
6478
$model->delete();
65-
\Magento\TestFramework\Helper\Bootstrap::getObjectManager()
66-
->get(\Psr\Log\LoggerInterface::class)
79+
Bootstrap::getObjectManager()->get(LoggerInterface::class)
6780
->critical($e);
6881
}
6982
}
7083

7184
/**
85+
* Data provider for testProcessAjaxPost
86+
*
7287
* @return array
7388
*/
74-
public function processAjaxPostDataProvider()
89+
public function processAjaxPostDataProvider(): array
7590
{
7691
return [
77-
['original text 1', 'translated text 1'],
78-
['original text 2', 'translated text 2', true]
92+
['original text 1', 'translated text 1', Area::AREA_ADMINHTML],
93+
['original text 1', 'translated text 1', Area::AREA_FRONTEND],
94+
['original text 2', 'translated text 2', Area::AREA_ADMINHTML, true],
95+
['original text 2', 'translated text 2', Area::AREA_FRONTEND, true],
7996
];
8097
}
8198

82-
public function testSetGetIsJson()
99+
/**
100+
* Set get is json test
101+
*
102+
* @dataProvider allowedAreasDataProvider
103+
*
104+
* @param string $area
105+
* @return void
106+
*/
107+
public function testSetGetIsJson(string $area): void
83108
{
84-
$isJsonProperty = new \ReflectionProperty(get_class($this->_inlineParser), '_isJson');
109+
Bootstrap::getObjectManager()->get(State::class)
110+
->setAreaCode($area);
111+
112+
$isJsonProperty = new \ReflectionProperty(get_class($this->model), '_isJson');
85113
$isJsonProperty->setAccessible(true);
86114

87-
$this->assertFalse($isJsonProperty->getValue($this->_inlineParser));
115+
$this->assertFalse($isJsonProperty->getValue($this->model));
88116

89-
$setIsJsonMethod = new \ReflectionMethod($this->_inlineParser, 'setIsJson');
117+
$setIsJsonMethod = new \ReflectionMethod($this->model, 'setIsJson');
90118
$setIsJsonMethod->setAccessible(true);
91-
$setIsJsonMethod->invoke($this->_inlineParser, true);
119+
$setIsJsonMethod->invoke($this->model, true);
92120

93-
$this->assertTrue($isJsonProperty->getValue($this->_inlineParser));
121+
$this->assertTrue($isJsonProperty->getValue($this->model));
122+
}
123+
124+
/**
125+
* Data provider for testSetGetIsJson
126+
*
127+
* @return array
128+
*/
129+
public function allowedAreasDataProvider(): array
130+
{
131+
return [
132+
[Area::AREA_ADMINHTML],
133+
[Area::AREA_FRONTEND]
134+
];
94135
}
95136
}

lib/internal/Magento/Framework/Translate/Inline.php

Lines changed: 76 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,24 @@
88

99
namespace Magento\Framework\Translate;
1010

11-
class Inline implements \Magento\Framework\Translate\InlineInterface
11+
use Magento\Framework\App\Area;
12+
use Magento\Framework\App\ObjectManager;
13+
use Magento\Framework\App\ScopeInterface;
14+
use Magento\Framework\App\ScopeResolverInterface;
15+
use Magento\Framework\App\State;
16+
use Magento\Framework\Exception\LocalizedException;
17+
use Magento\Framework\Translate\Inline\ConfigInterface;
18+
use Magento\Framework\Translate\Inline\ParserInterface;
19+
use Magento\Framework\Translate\Inline\StateInterface;
20+
use Magento\Framework\UrlInterface;
21+
use Magento\Framework\View\Element\Template;
22+
use Magento\Framework\View\LayoutInterface;
23+
24+
/**
25+
* Translate Inline Class
26+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
27+
*/
28+
class Inline implements InlineInterface
1229
{
1330
/**
1431
* Indicator to hold state of whether inline translation is allowed
@@ -18,7 +35,7 @@ class Inline implements \Magento\Framework\Translate\InlineInterface
1835
protected $isAllowed;
1936

2037
/**
21-
* @var \Magento\Framework\Translate\Inline\ParserInterface
38+
* @var ParserInterface
2239
*/
2340
protected $parser;
2441

@@ -30,22 +47,22 @@ class Inline implements \Magento\Framework\Translate\InlineInterface
3047
protected $isScriptInserted = false;
3148

3249
/**
33-
* @var \Magento\Framework\UrlInterface
50+
* @var UrlInterface
3451
*/
3552
protected $url;
3653

3754
/**
38-
* @var \Magento\Framework\View\LayoutInterface
55+
* @var LayoutInterface
3956
*/
4057
protected $layout;
4158

4259
/**
43-
* @var \Magento\Framework\Translate\Inline\ConfigInterface
60+
* @var ConfigInterface
4461
*/
4562
protected $config;
4663

4764
/**
48-
* @var \Magento\Framework\App\ScopeResolverInterface
65+
* @var ScopeResolverInterface
4966
*/
5067
protected $scopeResolver;
5168

@@ -70,28 +87,39 @@ class Inline implements \Magento\Framework\Translate\InlineInterface
7087
protected $state;
7188

7289
/**
73-
* Initialize inline translation model
74-
*
75-
* @param \Magento\Framework\App\ScopeResolverInterface $scopeResolver
76-
* @param \Magento\Framework\UrlInterface $url
77-
* @param \Magento\Framework\View\LayoutInterface $layout
90+
* @var array
91+
*/
92+
private $allowedAreas = [Area::AREA_FRONTEND, Area::AREA_ADMINHTML];
93+
94+
/**
95+
* @var State
96+
*/
97+
private $appState;
98+
99+
/**
100+
* @param ScopeResolverInterface $scopeResolver
101+
* @param UrlInterface $url
102+
* @param LayoutInterface $layout
78103
* @param Inline\ConfigInterface $config
79104
* @param Inline\ParserInterface $parser
80105
* @param Inline\StateInterface $state
81106
* @param string $templateFileName
82107
* @param string $translatorRoute
83-
* @param null $scope
108+
* @param string|null $scope
109+
* @param State|null $appState
110+
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
84111
*/
85112
public function __construct(
86-
\Magento\Framework\App\ScopeResolverInterface $scopeResolver,
87-
\Magento\Framework\UrlInterface $url,
88-
\Magento\Framework\View\LayoutInterface $layout,
89-
\Magento\Framework\Translate\Inline\ConfigInterface $config,
90-
\Magento\Framework\Translate\Inline\ParserInterface $parser,
91-
\Magento\Framework\Translate\Inline\StateInterface $state,
113+
ScopeResolverInterface $scopeResolver,
114+
UrlInterface $url,
115+
LayoutInterface $layout,
116+
ConfigInterface $config,
117+
ParserInterface $parser,
118+
StateInterface $state,
92119
$templateFileName = '',
93120
$translatorRoute = '',
94-
$scope = null
121+
$scope = null,
122+
?State $appState = null
95123
) {
96124
$this->scopeResolver = $scopeResolver;
97125
$this->url = $url;
@@ -102,6 +130,7 @@ public function __construct(
102130
$this->templateFileName = $templateFileName;
103131
$this->translatorRoute = $translatorRoute;
104132
$this->scope = $scope;
133+
$this->appState = $appState ?: ObjectManager::getInstance()->get(State::class);
105134
}
106135

107136
/**
@@ -112,12 +141,13 @@ public function __construct(
112141
public function isAllowed()
113142
{
114143
if ($this->isAllowed === null) {
115-
if (!$this->scope instanceof \Magento\Framework\App\ScopeInterface) {
116-
$scope = $this->scopeResolver->getScope($this->scope);
117-
}
144+
$scope = $this->scope instanceof ScopeInterface ? null : $this->scopeResolver->getScope($this->scope);
145+
118146
$this->isAllowed = $this->config->isActive($scope)
119-
&& $this->config->isDevAllowed($scope);
147+
&& $this->config->isDevAllowed($scope)
148+
&& $this->isAreaAllowed();
120149
}
150+
121151
return $this->state->isEnabled() && $this->isAllowed;
122152
}
123153

@@ -134,7 +164,7 @@ public function getParser()
134164
/**
135165
* Replace translation templates with HTML fragments
136166
*
137-
* @param array|string &$body
167+
* @param array|string $body
138168
* @param bool $isJson
139169
* @return $this
140170
*/
@@ -189,7 +219,9 @@ protected function addInlineScript()
189219
return;
190220
}
191221
if (!$this->isScriptInserted) {
192-
$this->getParser()->setContent(str_ireplace('</body>', $this->getInlineScript() . '</body>', $content));
222+
$this->getParser()->setContent(
223+
str_ireplace('</body>', $this->getInlineScript() . '</body>', $content)
224+
);
193225
$this->isScriptInserted = true;
194226
}
195227
}
@@ -204,8 +236,8 @@ protected function addInlineScript()
204236
*/
205237
protected function getInlineScript()
206238
{
207-
/** @var $block \Magento\Framework\View\Element\Template */
208-
$block = $this->layout->createBlock(\Magento\Framework\View\Element\Template::class);
239+
/** @var $block Template */
240+
$block = $this->layout->createBlock(Template::class);
209241

210242
$block->setAjaxUrl($this->getAjaxUrl());
211243
$block->setTemplate($this->templateFileName);
@@ -238,15 +270,24 @@ protected function stripInlineTranslations(&$body)
238270
foreach ($body as &$part) {
239271
$this->stripInlineTranslations($part);
240272
}
241-
} else {
242-
if (is_string($body)) {
243-
$body = preg_replace(
244-
'#' . \Magento\Framework\Translate\Inline\ParserInterface::REGEXP_TOKEN . '#',
245-
'$1',
246-
$body
247-
);
248-
}
273+
} elseif (is_string($body)) {
274+
$body = preg_replace('#' . ParserInterface::REGEXP_TOKEN . '#', '$1', $body);
249275
}
276+
250277
return $this;
251278
}
279+
280+
/**
281+
* Indicates whether the current area is valid for inline translation
282+
*
283+
* @return bool
284+
*/
285+
private function isAreaAllowed(): bool
286+
{
287+
try {
288+
return in_array($this->appState->getAreaCode(), $this->allowedAreas, true);
289+
} catch (LocalizedException $e) {
290+
return false;
291+
}
292+
}
252293
}

0 commit comments

Comments
 (0)