Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/imported-magento-magento2-32002'…
Browse files Browse the repository at this point in the history
… into 2.4-develop-pr127
  • Loading branch information
zakdma committed Feb 24, 2021
2 parents 64d3e2e + 6341225 commit 159197c
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 14 deletions.
2 changes: 1 addition & 1 deletion app/code/Magento/Translation/Model/Inline/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ private function _prepareTagAttributesForContent(&$content)
} else {
$trAttr = ' ' . $this->_getHtmlAttribute(
self::DATA_TRANSLATE,
'[' . str_replace("\"", "'", join(',', $trArr)) . ']'
'[' . str_replace("\"", """, join(',', $trArr)) . ']'
);
}
$trAttr = $this->_addTranslateAttribute($trAttr);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,12 @@ public function testProcessResponseBodyStringProcessingAttributesCorrectly()
{
$testContent = file_get_contents(__DIR__ . '/_files/datatranslate_fixture.html');
$processedAttributes = [
"data-translate=\"[{'shown':'* Required Fields','translated':'* Required Fields',"
. "'original':'* Required Fields','location':'Tag attribute (ALT, TITLE, etc.)'}]\"",
"data-translate=\"[{'shown':'Email','translated':'Email','original':'Email',"
. "'location':'Tag attribute (ALT, TITLE, etc.)'}]\"",
"data-translate=\"[{'shown':'Password','translated':'Password','original':'Password',"
. "'location':'Tag attribute (ALT, TITLE, etc.)'}]\""
"data-translate=\"[{"shown":"* Required Fields","translated":"* Required Fields","
. ""original":"* Required Fields","location":"Tag attribute (ALT, TITLE, etc.)"}]\"",
"data-translate=\"[{"shown":"Email","translated":"Email","original":"Email","
. ""location":"Tag attribute (ALT, TITLE, etc.)"}]\"",
"data-translate=\"[{"shown":"Password","translated":"Password","original":"Password","
. ""location":"Tag attribute (ALT, TITLE, etc.)"}]\""
];
$this->translateInlineMock->method('getAdditionalHtmlAttribute')->willReturn(null);

Expand Down
45 changes: 43 additions & 2 deletions lib/internal/Magento/Framework/Escaper.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\Framework;

Expand Down Expand Up @@ -257,10 +258,17 @@ private function escapeAttributeValue($name, $value)
*/
public function escapeHtmlAttr($string, $escapeSingleQuote = true)
{
$string = (string)$string;

if ($escapeSingleQuote) {
return $this->getEscaper()->escapeHtmlAttr((string) $string);
$translateInline = $this->getTranslateInline();

return $translateInline->isAllowed()
? $this->inlineSensitiveEscapeHthmlAttr($string)
: $this->getEscaper()->escapeHtmlAttr($string);
}
return htmlspecialchars((string)$string, $this->htmlSpecialCharsFlag, 'UTF-8', false);

return htmlspecialchars($string, $this->htmlSpecialCharsFlag, 'UTF-8', false);
}

/**
Expand Down Expand Up @@ -476,4 +484,37 @@ private function getTranslateInline()

return $this->translateInline;
}

/**
* Inline sensitive escape attribute value.
*
* @param string $text
* @return string
*/
private function inlineSensitiveEscapeHthmlAttr(string $text): string
{
$escaper = $this->getEscaper();
$textLength = strlen($text);

if ($textLength < 6) {
return $escaper->escapeHtmlAttr($text);
}

$firstCharacters = substr($text, 0, 3);
$lastCharacters = substr($text, -3, 3);

if ($firstCharacters !== '{{{' || $lastCharacters !== '}}}') {
return $escaper->escapeHtmlAttr($text);
}

$text = substr($text, 3, $textLength - 6);
$strings = explode('}}{{', $text);
$escapedStrings = [];

foreach ($strings as $string) {
$escapedStrings[] = $escaper->escapeHtmlAttr($string);
}

return '{{{' . implode('}}{{', $escapedStrings) . '}}}';
}
}
68 changes: 63 additions & 5 deletions lib/internal/Magento/Framework/Test/Unit/EscaperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Magento\Framework\ZendEscaper;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use Magento\Framework\Translate\Inline\StateInterface;

/**
* \Magento\Framework\Escaper test case
Expand All @@ -24,6 +25,11 @@ class EscaperTest extends TestCase
*/
protected $escaper;

/**
* @var ObjectManager
*/
private $objectManagerHelper;

/**
* @var ZendEscaper
*/
Expand All @@ -44,14 +50,14 @@ class EscaperTest extends TestCase
*/
protected function setUp(): void
{
$objectManagerHelper = new ObjectManager($this);
$this->objectManagerHelper = new ObjectManager($this);
$this->escaper = new Escaper();
$this->zendEscaper = new ZendEscaper();
$this->translateInline = $objectManagerHelper->getObject(Inline::class);
$this->translateInline = $this->objectManagerHelper->getObject(Inline::class);
$this->loggerMock = $this->getMockForAbstractClass(LoggerInterface::class);
$objectManagerHelper->setBackwardCompatibleProperty($this->escaper, 'escaper', $this->zendEscaper);
$objectManagerHelper->setBackwardCompatibleProperty($this->escaper, 'logger', $this->loggerMock);
$objectManagerHelper->setBackwardCompatibleProperty(
$this->objectManagerHelper->setBackwardCompatibleProperty($this->escaper, 'escaper', $this->zendEscaper);
$this->objectManagerHelper->setBackwardCompatibleProperty($this->escaper, 'logger', $this->loggerMock);
$this->objectManagerHelper->setBackwardCompatibleProperty(
$this->escaper,
'translateInline',
$this->translateInline
Expand Down Expand Up @@ -169,6 +175,58 @@ public function testEscapeHtml($data, $expected, $allowedTags = [])
$this->assertEquals($expected, $actual);
}

/**
* Tests escapeHtmlAttr method when Inline translate is configured.
*
* @param string $input
* @param string $output
* @return void
* @dataProvider escapeHtmlAttributeWithInlineTranslateEnabledDataProvider
*/
public function testEscapeHtmlAttributeWithInlineTranslateEnabled(string $input, string $output): void
{
$this->objectManagerHelper->setBackwardCompatibleProperty(
$this->translateInline,
'isAllowed',
true
);
$stateMock = $this->createMock(StateInterface::class);
$stateMock->method('isEnabled')
->willReturn(true);
$this->objectManagerHelper->setBackwardCompatibleProperty(
$this->translateInline,
'state',
$stateMock
);


$actual = $this->escaper->escapeHtmlAttr($input);
$this->assertEquals($output, $actual);
}

/**
* Data provider for escapeHtmlAttrWithInline test.
*
* @return array
*/
public function escapeHtmlAttributeWithInlineTranslateEnabledDataProvider(): array
{
return [
[
'{{{Search entire store here...}}}',
'{{{Search&#x20;entire&#x20;store&#x20;here...}}}',
],
[
'{{{Product search}}{{Translated to language}}{{themeMagento/Luma}}}',
'{{{Product&#x20;search}}{{Translated&#x20;to&#x20;language}}{{themeMagento&#x2F;Luma}}}',
],
[
'Simple string',
'Simple&#x20;string',
],
];
}

/**
* @covers \Magento\Framework\Escaper::escapeHtml
* @dataProvider escapeHtmlInvalidDataProvider
Expand Down

0 comments on commit 159197c

Please sign in to comment.