Skip to content

Commit 51c58e0

Browse files
committed
Add FileValidator-Function for composer.json
1 parent aae50bd commit 51c58e0

2 files changed

Lines changed: 163 additions & 41 deletions

File tree

src/Phpbb/TranslationValidator/Command/ValidateCommand.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ protected function configure()
2525
->setName('validate')
2626
->setDescription('Run the validator on your language pack.')
2727
->addArgument('origin-iso', InputArgument::REQUIRED, 'The ISO of the language to validate')
28-
->addOption('phpbb-version', null, InputOption::VALUE_OPTIONAL, 'The phpBB Version to validate against', '3.3')
28+
->addOption('phpbb-version', null, InputOption::VALUE_OPTIONAL, 'The phpBB Version to validate against', '4.0')
2929
->addOption('source-iso', null, InputOption::VALUE_OPTIONAL, 'The ISO of the language to validate against', 'en')
3030
->addOption('package-dir', null, InputOption::VALUE_OPTIONAL, 'The path to the directory with the language packages', null)
3131
->addOption('language-dir', null, InputOption::VALUE_OPTIONAL, 'The path to the directory with the language folders', null)
@@ -52,9 +52,9 @@ protected function execute(InputInterface $input, OutputInterface $output)
5252
$displayNotices = $input->getOption('display-notices');
5353
$safeMode = $input->getOption('safe-mode');
5454

55-
if (!in_array($phpbbVersion, array('3.2', '3.3')))
55+
if ($phpbbVersion != '4.0')
5656
{
57-
throw new \RuntimeException('Invalid phpbb-version, allowed versions: 3.2 and 3.3');
57+
throw new \RuntimeException('Invalid phpbb-version, allowed versions: 4.0');
5858
}
5959

6060
$output = new Output($output, $debug);

src/Phpbb/TranslationValidator/Validator/FileValidator.php

Lines changed: 160 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,47 @@ class FileValidator
119119
'', // Allow empty strings
120120
];
121121

122+
/** @var array List from https://developers.cloudflare.com/turnstile/reference/supported-languages/ */
123+
private $reTurnstilesLanguages = [
124+
'ar',
125+
'bg',
126+
'zh',
127+
'hr',
128+
'cs',
129+
'da',
130+
'nl',
131+
'en',
132+
'fa',
133+
'fi',
134+
'fr',
135+
'de',
136+
'el',
137+
'he',
138+
'hi',
139+
'hu',
140+
'id',
141+
'it',
142+
'ja',
143+
'ko',
144+
'lt',
145+
'ms',
146+
'nb',
147+
'pl',
148+
'pt',
149+
'ro',
150+
'ru',
151+
'sr',
152+
'sk',
153+
'sl',
154+
'es',
155+
'sv',
156+
'tl',
157+
'th',
158+
'tr',
159+
'uk',
160+
'vi',
161+
'', // Allow empty strings
162+
];
122163
/**
123164
* @param InputInterface $input
124165
* @param OutputInterface $output
@@ -260,9 +301,9 @@ public function validate($sourceFile, $originFile)
260301
{
261302
$this->validateLicenseFile($originFile);
262303
}
263-
else if ($originFile === $this->originLanguagePath . 'iso.txt')
304+
else if ($originFile === $this->originLanguagePath . 'composer.json')
264305
{
265-
$this->validateIsoFile($originFile);
306+
$this->validateJsonFile($originFile);
266307
}
267308
else if (substr($originFile, -4) === '.css')
268309
{
@@ -361,32 +402,10 @@ public function validateLangFile($sourceFile, $originFile)
361402
$this->output->addMessage(Output::FATAL, 'Must not contain key: ' . $validateLangKey, $originFile);
362403
}
363404
}
364-
365-
// Check reCaptcha file
366-
if ($originFile === $this->originLanguagePath . 'captcha_recaptcha.php')
367-
{
368-
$this->validateReCaptchaValue($originFile, $validate);
369-
}
370-
}
371-
372-
/**
373-
* Check that the reCaptcha key provided is allowed
374-
* @param $originFile
375-
* @param array $validate
376-
*/
377-
public function validateReCaptchaValue($originFile, $validate)
378-
{
379-
// The key 'RECAPTCHA_LANG' must match the list provided by Google, or be left empty
380-
// If any other key is used, we will show an error
381-
if (array_key_exists('RECAPTCHA_LANG', $validate) && !in_array($validate['RECAPTCHA_LANG'], $this->reCaptchaLanguages))
382-
{
383-
// The supplied value doesn't match the allowed values
384-
$this->output->addMessage(Output::ERROR, 'reCaptcha must match a language/country code on https://developers.google.com/recaptcha/docs/language - if no code exists for your language you can use "en" or leave the string empty', $originFile, 'RECAPTCHA_LANG');
385-
}
386405
}
387406

388407
/**
389-
* Validates a email .txt file
408+
* Validates an email .txt file
390409
*
391410
* Emails must have a subject when the source file has one, otherwise must not have one.
392411
* Emails must have a signature when the source file has one, otherwise must not have one.
@@ -521,26 +540,129 @@ public function validateIndexFile($originFile)
521540
}
522541

523542
/**
524-
* Validates the iso.txt file
543+
* Validates the composer.json file
525544
*
526-
* Should only contain 3 lines:
527-
* 1. English name of the language
528-
* 2. Native name of the language
529-
* 3. Line with information about the author
545+
* Should be valid and contain the necessary information:
546+
* Mandatory:
547+
* name, description, type, version, homepage, license
548+
* Authors: name (optional: email and homepage)
549+
* Extra: language-iso, english-name, local-name,
550+
* phpbb-version, direction, user-lang, plural-rule,
551+
* recaptcha-lang, turnstile-lang
552+
* Optional:
553+
* Support: urls to: forum, wiki, issues etc
530554
*
531555
* @param string $originFile File to validate
532556
* @return null
533557
*/
534-
public function validateIsoFile($originFile)
558+
public function validateJsonFile($originFile)
535559
{
536560
$fileContents = (string) file_get_contents($this->originPath . '/' . $originFile);
537-
$isoFile = explode("\n", $fileContents);
538-
539-
if (sizeof($isoFile) != 3)
540-
{
541-
$this->output->addMessage(Output::FATAL, 'Must contain exactly 3 lines: 1. English name, 2. Native name, 3. Author information', $originFile);
542-
}
543-
}
561+
$jsonContent = json_decode($fileContents, true);
562+
563+
if (!$jsonContent['name'] == (substr($originFile, 21) === 'phpbb/phpbb-language-'))
564+
{
565+
$this->output->addMessage(Output::FATAL, 'File must have name value which starts with phpbb/phpbb-language- following by the language iso code', $originFile);
566+
}
567+
568+
if (!array_key_exists('description', $jsonContent))
569+
{
570+
$this->output->addMessage(Output::FATAL, 'File must contain a description value', $originFile);
571+
}
572+
// Check if the type is correctly defined
573+
if (!$jsonContent['type'] == 'phpbb-language')
574+
{
575+
$this->output->addMessage(Output::FATAL, 'File must contain a type with the value "phpbb-language"', $originFile);
576+
}
577+
// Check if there is a valid version definition
578+
if (!array_key_exists('version', $jsonContent))
579+
{
580+
$this->output->addMessage(Output::FATAL, 'Language pack needs a version definition.', $originFile);
581+
}
582+
elseif ($jsonContent['version'] == '')
583+
{
584+
$this->output->addMessage(Output::FATAL, 'The defined version should not be empty.', $originFile);
585+
}
586+
elseif (preg_match('^(\d+\.)?(\d+\.)?(\*|\d+)$', $jsonContent['version']))
587+
{
588+
$this->output->addMessage(Output::FATAL, 'The defined version is in the wrong format.', $originFile);
589+
}
590+
// Homepage should be at least an empty string
591+
if (!array_key_exists('homepage', $jsonContent))
592+
{
593+
$this->output->addMessage(Output::FATAL, 'The homepage value is missing, can be an empty string.', $originFile);
594+
}
595+
// Check for the correct license value
596+
if (!$jsonContent['license'] == 'GPL-2.0')
597+
{
598+
$this->output->addMessage(Output::FATAL, 'The license value has to be "GPL-2.0"', $originFile);
599+
}
600+
// Check for the authors
601+
if (!array_key_exists('authors', $jsonContent))
602+
{
603+
$this->output->addMessage(Output::FATAL, 'The authors value is missing.', $originFile);
604+
}
605+
// Check for support, authors should at least give one contact option!
606+
if (!array_key_exists('support', $jsonContent))
607+
{
608+
$this->output->addMessage(Output::FATAL, 'The support value is missing.', $originFile);
609+
}
610+
elseif (count ($jsonContent['support']) < 1)
611+
{
612+
$this->output->addMessage(Output::FATAL, 'The support value has not sub values. Please provide at least one contact option e.g. forum, email.', $originFile);
613+
}
614+
// Check for the extra-section
615+
if (!array_key_exists('extra', $jsonContent))
616+
{
617+
$this->output->addMessage(Output::FATAL, 'The extra section is missing.', $originFile);
618+
}
619+
// language-iso must be valid
620+
if (preg_match('^(?:[a-z]*_?){0,2}[a-z]*$', $jsonContent['extra']['language-iso']))
621+
{
622+
$this->output->addMessage(Output::FATAL, 'The language-iso should only contain small letters from a to z or maximum two underscores.', $originFile);
623+
}
624+
// Check for english name
625+
if ($jsonContent['extra']['english-name'] == '' || preg_match('^[a-zA-Z\s]+$', $jsonContent['extra']['english-name']))
626+
{
627+
$this->output->addMessage(Output::ERROR, 'The english-name value should only contain letters aA-zZ and spaces.', $originFile);
628+
}
629+
// Check for local name
630+
if ($jsonContent['extra']['local-name'] == '')
631+
{
632+
$this->output->addMessage(Output::ERROR, 'The local-name value should not be empty.', $originFile);
633+
}
634+
// Check for valid phpBB-Version, we accept: 4.0.0, 4.0.0-a1 or 4.0.0-b1 or 4.0.0-RC1
635+
if (!preg_match('^\d+\.\d+\.\d+(-(?:a|b|RC)\d+)?$', $jsonContent['extra']['phpbb-version']) || $jsonContent['extra']['phpbb-version'] == '' )
636+
{
637+
$this->output->addMessage(Output::FATAL, 'The phpbb-version value should not be empty and contain a valid version number.', $originFile);
638+
}
639+
// Check for valid direction
640+
$direction = $jsonContent['extra']['phpbb-direction'];
641+
if (!in_array($direction, array('ltr', 'rtl')))
642+
{
643+
$this->output->addMessage(Output::FATAL, 'The direction can only be rtl or ltr.', $originFile);
644+
}
645+
// Check for user-lang: en-gb
646+
if (!isset($jsonContent['extra']['user-lang']) || $jsonContent['extra']['user-lang'] == '')
647+
{
648+
$this->output->addMessage(Output::FATAL, 'The user-lang must be defined.', $originFile);
649+
}
650+
// Check for plural-rule
651+
if (!preg_match('^(?:[0-9]|1[0-5])$', $jsonContent['extra']['plural-rule']))
652+
{
653+
$this->output->addMessage(Output::FATAL, 'Plural rules does not have a valid value.', $originFile);
654+
}
655+
// Check for valid recaptcha-lang: en-GB
656+
if (!in_array($jsonContent['extra']['recaptcha-lang'], $this->reCaptchaLanguages))
657+
{
658+
$this->output->addMessage(Output::ERROR, 'reCaptcha must match a language/country code on https://developers.google.com/recaptcha/docs/language - if no code exists for your language you can use "en" or leave the string empty', $originFile);
659+
}
660+
// Check for valid turnstile-lang: en (should be in: https://developers.cloudflare.com/turnstile/reference/supported-languages/ )
661+
if (!in_array($jsonContent['extra']['turnstile-lang'], $this->reTurnstilesLanguages))
662+
{
663+
$this->output->addMessage(Output::ERROR, 'Turnstile must match a 2-digit-language code from https://developers.cloudflare.com/turnstile/reference/supported-languages/ ', $originFile);
664+
}
665+
}
544666

545667
/**
546668
* Validates whether a file checks for the IN_PHPBB constant

0 commit comments

Comments
 (0)