magento2-docker/dev/tests/static/testsuite/Magento/Test/Integrity/Phrase/ArgumentsTest.php

131 lines
4.6 KiB
PHP
Executable File

<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Test\Integrity\Phrase;
use Magento\Framework\Component\ComponentRegistrar;
/**
* Scan source code for detects invocations of __() function or Phrase object, analyzes placeholders with arguments
* and see if they not equal
*/
class ArgumentsTest extends \Magento\Test\Integrity\Phrase\AbstractTestCase
{
/**
* @var \Magento\Setup\Module\I18n\Parser\Adapter\Php\Tokenizer\PhraseCollector
*/
protected $_phraseCollector;
/**
* List of files that must be omitted
*
* @todo remove blacklist related logic when all files correspond to the standard
* @var array
*/
protected $blackList;
protected function setUp(): void
{
$this->_phraseCollector = new \Magento\Setup\Module\I18n\Parser\Adapter\Php\Tokenizer\PhraseCollector(
new \Magento\Setup\Module\I18n\Parser\Adapter\Php\Tokenizer(),
true,
\Magento\Framework\Phrase::class
);
$componentRegistrar = new ComponentRegistrar();
$this->blackList = [
// the file below is the only file where strings are translated without corresponding arguments
$componentRegistrar->getPath(ComponentRegistrar::MODULE, 'Magento_Translation')
. '/Model/Js/DataProvider.php',
];
}
public function testArguments()
{
$incorrectNumberOfArgumentsErrors = [];
$missedPhraseErrors = [];
foreach ($this->_getFiles() as $file) {
if (in_array($file, $this->blackList)) {
continue;
}
$this->_phraseCollector->parse($file);
foreach ($this->_phraseCollector->getPhrases() as $phrase) {
$this->checkEmptyPhrases($phrase, $missedPhraseErrors);
$this->checkArgumentMismatch($phrase, $incorrectNumberOfArgumentsErrors);
}
}
$this->assertEmpty(
$missedPhraseErrors,
sprintf(
"\n%d missed phrases were discovered: \n%s",
count($missedPhraseErrors),
implode("\n\n", $missedPhraseErrors)
)
);
$this->assertEmpty(
$incorrectNumberOfArgumentsErrors,
sprintf(
"\n%d usages of inconsistency the number of arguments and placeholders were discovered: \n%s",
count($incorrectNumberOfArgumentsErrors),
implode("\n\n", $incorrectNumberOfArgumentsErrors)
)
);
}
/**
* Will check if phrase is empty
*
* @param $phrase
* @param $missedPhraseErrors
*/
private function checkEmptyPhrases($phrase, &$missedPhraseErrors)
{
if (empty(trim($phrase['phrase'], "'\"\t\n\r\0\x0B"))) {
$missedPhraseErrors[] = $this->_createMissedPhraseError($phrase);
}
}
/**
* Will check if the number of arguments does not match the number of placeholders
*
* @param $phrase
* @param $incorrectNumberOfArgumentsErrors
*/
private function checkArgumentMismatch($phrase, &$incorrectNumberOfArgumentsErrors)
{
if (preg_match_all('/%(\w+)/', $phrase['phrase'], $matches) || $phrase['arguments']) {
$placeholderCount = count(array_unique($matches[1]));
// count all occurrences of sprintf placeholders
preg_match_all('/%\b([sducoxXbgGeEfF])\b/', $phrase['phrase'], $sprintfMatches);
if (count($sprintfMatches[0]) > count(array_unique($sprintfMatches[0]))) {
$placeholderCount = $placeholderCount +
count($sprintfMatches[0]) - count(array_unique($sprintfMatches[0]));
}
// Check for zend placeholders %placeholder% and sprintf placeholders and remove from the count
if (preg_match_all(
'/%\b(([sducoxXbgGeEfF])\b|([A-Za-z]+)%)/',
$phrase['phrase'],
$placeHolders,
PREG_OFFSET_CAPTURE
)) {
foreach ($placeHolders[0] as $ph) {
// Check if char after placeholder is not a digit or letter
$charAfterPh = $phrase['phrase'][$ph[1] + strlen($ph[0])];
if (!preg_match('/[A-Za-z0-9]/', $charAfterPh)) {
$placeholderCount--;
}
}
}
if ($placeholderCount != $phrase['arguments']) {
$incorrectNumberOfArgumentsErrors[] = $this->_createPhraseError($phrase);
}
}
}
}