-
-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #69 from kasimi/validate-lang
Test for missing language files and keys
- Loading branch information
Showing
7 changed files
with
288 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
<?php | ||
|
||
/** | ||
* | ||
* EPV :: The phpBB Forum Extension Pre Validator. | ||
* | ||
* @copyright (c) 2017 phpBB Limited <https://www.phpbb.com> | ||
* @license GNU General Public License, version 2 (GPL-2.0) | ||
* | ||
*/ | ||
|
||
namespace Phpbb\Epv\Tests\Tests; | ||
|
||
use Phpbb\Epv\Output\OutputInterface; | ||
use Phpbb\Epv\Tests\BaseTest; | ||
use PhpParser\Error; | ||
use PhpParser\Node\Expr\Array_; | ||
use PhpParser\Node\Expr\ArrayItem; | ||
use PhpParser\Node\Expr\Assign; | ||
use PhpParser\Node\Expr\FuncCall; | ||
use PhpParser\Node\Scalar\String_; | ||
use PhpParser\Parser; | ||
use PhpParser\ParserFactory; | ||
|
||
class epv_test_validate_languages extends BaseTest | ||
{ | ||
/** | ||
* @var Parser | ||
*/ | ||
private $parser; | ||
|
||
/** | ||
* @param bool $debug if debug is enabled | ||
* @param OutputInterface $output | ||
* @param string $basedir | ||
* @param string $namespace | ||
* @param boolean $titania | ||
* @param string $opendir | ||
*/ | ||
public function __construct($debug, OutputInterface $output, $basedir, $namespace, $titania, $opendir) | ||
{ | ||
parent::__construct($debug, $output, $basedir, $namespace, $titania, $opendir); | ||
|
||
$this->directory = true; | ||
$this->parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7); | ||
} | ||
|
||
/** | ||
* @param array $files | ||
* | ||
* @return void | ||
*/ | ||
public function validateDirectory(array $files) | ||
{ | ||
$langs = []; | ||
$expected_keys = []; | ||
$expected_files = []; | ||
|
||
foreach ($files as $file) | ||
{ | ||
if (preg_match('#^' . $this->basedir . 'language/([a-z_]+?)/(.+\.php)$#', $file, $matches) === 1) | ||
{ | ||
$language = $matches[1]; // language, e.g. "en" | ||
$relative_filename = $matches[2]; // file name relative to language's base dir, e.g. "info_acp_ext.php" | ||
$expected_files[$relative_filename] = $relative_filename; | ||
|
||
try | ||
{ | ||
$keys = $this->load_language_keys($file); | ||
$langs[$language][$relative_filename] = $keys; | ||
|
||
$lang_keys = isset($expected_keys[$relative_filename]) ? $expected_keys[$relative_filename] : []; | ||
$expected_keys[$relative_filename] = array_unique(array_merge($lang_keys, $keys)); | ||
} | ||
catch (Error $e) | ||
{ | ||
$this->output->addMessage(OutputInterface::FATAL, 'PHP parse error in file ' . $file->getSaveFilename() . '. Message: ' . $e->getMessage()); | ||
} | ||
} | ||
} | ||
|
||
foreach ($langs as $lang_name => $file_contents) | ||
{ | ||
// Check for missing language files | ||
foreach (array_diff($expected_files, array_keys($file_contents)) as $missing_file) | ||
{ | ||
$this->output->addMessage(OutputInterface::NOTICE, sprintf("Language %s is missing the language file %s", $lang_name, $missing_file)); | ||
} | ||
|
||
// Check for missing language keys | ||
foreach ($file_contents as $relative_filename => $present_keys) | ||
{ | ||
foreach (array_diff($expected_keys[$relative_filename], $present_keys) as $missing_key) | ||
{ | ||
$this->output->addMessage(OutputInterface::WARNING, sprintf("Language file %s/%s is missing the language key %s", $lang_name, $relative_filename, $missing_key)); | ||
} | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* This method scans through all global-scoped calls to array_merge | ||
* and extracts all string keys of all array arguments. | ||
* | ||
* @param string $filename File name to a phpBB language file | ||
* @return array | ||
* @throws Error | ||
*/ | ||
protected function load_language_keys($filename) | ||
{ | ||
$contents = @file_get_contents($filename); | ||
|
||
$keys = []; | ||
|
||
$nodes = $this->parser->parse($contents); | ||
|
||
foreach ($nodes as $node) | ||
{ | ||
if ($node instanceof Assign && $node->expr instanceof FuncCall) | ||
{ | ||
/** @var FuncCall $expr */ | ||
$expr = $node->expr; | ||
|
||
if ($expr->name->getFirst() === 'array_merge') | ||
{ | ||
for ($i = 1; $i < sizeof($expr->args); $i++) | ||
{ | ||
/** @var Array_ $array */ | ||
$array = $expr->args[$i]->value; | ||
|
||
if (!($array instanceof Array_)) | ||
{ | ||
throw new Error(sprintf('Expected argument %d of array_merge() to be %s, got %s', $i + 1, Array_::class, get_class($array)), $array->getLine()); | ||
} | ||
|
||
foreach ($array->items as $item) | ||
{ | ||
/** @var ArrayItem $item */ | ||
if ($item->key instanceof String_) | ||
{ | ||
$keys[] = $item->key->value; | ||
} | ||
else | ||
{ | ||
$this->output->addMessage(OutputInterface::NOTICE, 'Language key is not a string value in ' . substr($filename, strlen($this->basedir)) . ' on line ' . $item->key->getLine()); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
return $keys; | ||
} | ||
|
||
/** | ||
* | ||
* @return String | ||
*/ | ||
public function testName() | ||
{ | ||
return 'Test languages'; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<?php | ||
|
||
if (!defined('IN_PHPBB')) | ||
{ | ||
exit; | ||
} | ||
|
||
if (empty($lang) || !is_array($lang)) | ||
{ | ||
$lang = array(); | ||
} | ||
|
||
$lang = array_merge($lang, array( | ||
'C' => 'Third language string', | ||
)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<?php | ||
|
||
if (!defined('IN_PHPBB')) | ||
{ | ||
exit; | ||
} | ||
|
||
if (empty($lang) || !is_array($lang)) | ||
{ | ||
$lang = array(); | ||
} | ||
|
||
$lang = array_merge($lang, array( | ||
'A' => 'First language string', | ||
'B' => 'Second language string', | ||
)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<?php | ||
|
||
if (!defined('IN_PHPBB')) | ||
{ | ||
exit; | ||
} | ||
|
||
if (empty($lang) || !is_array($lang)) | ||
{ | ||
$lang = array(); | ||
} | ||
|
||
$lang = array_merge($lang, array(), array( | ||
'C' => 'Third language string', | ||
)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<?php | ||
|
||
if (!defined('IN_PHPBB')) | ||
{ | ||
exit; | ||
} | ||
|
||
if (empty($lang) || !is_array($lang)) | ||
{ | ||
$lang = array(); | ||
} | ||
|
||
$lang = array_merge($lang, array( | ||
'A' => 'First language string', | ||
)); | ||
|
||
$lang = array_merge($lang, array( | ||
'B' => 'Second language string', | ||
)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<?php | ||
|
||
if (!defined('IN_PHPBB')) | ||
{ | ||
exit; | ||
} | ||
|
||
if (empty($lang) || !is_array($lang)) | ||
{ | ||
$lang = array(); | ||
} | ||
|
||
$lang = array_merge($lang, array( | ||
'A' => 'First language string', | ||
)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
<?php | ||
|
||
/** | ||
* | ||
* EPV :: The phpBB Forum Extension Pre Validator. | ||
* | ||
* @copyright (c) 2017 phpBB Limited <https://www.phpbb.com> | ||
* @license GNU General Public License, version 2 (GPL-2.0) | ||
* | ||
*/ | ||
|
||
use Phpbb\Epv\Output\OutputInterface; | ||
use Phpbb\Epv\Tests\Tests\epv_test_validate_languages; | ||
|
||
class validate_languages_test extends PHPUnit_Framework_TestCase | ||
{ | ||
public static function setUpBeforeClass() | ||
{ | ||
require_once('./tests/Mock/Output.php'); | ||
} | ||
|
||
public function test_languages() { | ||
/** @var OutputInterface|PHPUnit_Framework_MockObject_MockObject $output */ | ||
$output = $this->getMock('Phpbb\Epv\Output\OutputInterface'); | ||
|
||
$output | ||
->expects($this->exactly(2)) | ||
->method('addMessage') | ||
->withConsecutive( | ||
[OutputInterface::NOTICE, 'Language en_incomplete is missing the language file additional.php'], | ||
[OutputInterface::WARNING, 'Language file en_incomplete/common.php is missing the language key B'] | ||
) | ||
; | ||
|
||
$tester = new epv_test_validate_languages(false, $output, 'tests/testFiles/', 'epv/test', false, 'tests/testFiles/'); | ||
$tester->validateDirectory([ | ||
'tests/testFiles/language/en/common.php', | ||
'tests/testFiles/language/en/additional.php', | ||
'tests/testFiles/language/en_complete/common.php', | ||
'tests/testFiles/language/en_complete/additional.php', | ||
'tests/testFiles/language/en_incomplete/common.php', | ||
]); | ||
} | ||
} |