protected function getCSSRules($fileName, $fileContent) { // Remove comments $fileContent = preg_replace('#/\\*(?:.(?!/)|[^\\*](?=/)|(?<!\\*)/)*\\*/#s', '', $fileContent); #$fileContent = str_replace(array("\t", "\n"), ' ', $fileContent); $fileContent = preg_replace('!\\s+!', ' ', $fileContent) . ' '; $content = explode('} ', $fileContent); if (trim(array_pop($content)) !== '') { $this->output->addMessage(Output::FATAL, 'Stylesheet file structure is invalid (Output after last rule)', $fileName); } $cssRules = array(); foreach ($content as $section) { if (strpos($section, '{') === false) { $this->output->addMessage(Output::FATAL, 'Stylesheet file structure is invalid: ' . trim($section), $fileName); continue; } list($rule, $ruleContent) = explode(' {', $section, 2); $rule = trim($rule); $ruleContent = trim($ruleContent); if (strpos($ruleContent, '{') !== false) { $this->output->addMessage(Output::FATAL, 'CSS rule is invalid: ' . $rule, $fileName); continue; } if (!isset($cssRules[$rule])) { $cssRules[$rule] = ''; } $cssRules[$rule] .= $ruleContent; } return $cssRules; }
/** * Try to find the plural rule for the language * @return int */ protected function guessPluralRule() { if (file_exists($this->originPath . '/' . $this->originLanguagePath . 'common.php')) { include $this->originPath . '/' . $this->originLanguagePath . 'common.php'; if (!isset($lang['PLURAL_RULE'])) { $this->output->writelnIfDebug("<info>No plural rule set, falling back to plural rule #1</info>"); } } else { $this->output->writelnIfDebug("<info>Could not find common.php, falling back to plural rule #1</info>"); } return isset($lang['PLURAL_RULE']) ? $lang['PLURAL_RULE'] : 1; }
/** * Validates the html usage in a string * * Checks whether the used HTML tags are also used in the original language. * Omitting tags is okay, as long as both (start and end) are omitted. * * @param string $file File to validate * @param string $key Key to validate * @param string $sourceString Language string to validate against * @param string $originString Language string to validate * @return null */ public function validateHtml($file, $key, $sourceString, $originString) { if ($this->originLanguagePath . 'install.php' === $file && in_array($key, array('INSTALL_CONGRATS_EXPLAIN', 'INSTALL_INTRO_BODY', 'SUPPORT_BODY', 'UPDATE_INSTALLATION_EXPLAIN', 'OVERVIEW_BODY')) || $this->originLanguagePath . 'ucp.php' === $file && in_array($key, array('TERMS_OF_USE_CONTENT', 'PRIVACY_POLICY'))) { $sourceString = '<p>' . $sourceString . '</p>'; $originString = '<p>' . $originString . '</p>'; } $sourceHtml = $originHtml = $openTags = array(); preg_match_all('/\\<.+?\\>/', $sourceString, $sourceHtml); preg_match_all('/\\<.+?\\>/', $originString, $originHtml); if (empty($originHtml) || empty($originHtml[0])) { // Return when we have no HTML return; } $sourceHtml = isset($sourceHtml[0]) ? $sourceHtml[0] : array(); $failedUnclosed = false; foreach ($originHtml[0] as $possibleHtml) { $openingTag = $possibleHtml[1] !== '/'; $ignoreAdditional = false; // The closing tag contains a space if (!$openingTag && strpos($possibleHtml, ' ') !== false) { $this->output->addMessage(Output::FATAL, 'String is using invalid html: ' . $possibleHtml, $file, $key); $ignoreAdditional = true; } $tag = strpos($possibleHtml, ' ') !== false ? substr($possibleHtml, 1, strpos($possibleHtml, ' ') - 1) : substr($possibleHtml, 1, strpos($possibleHtml, '>') - 1); $tag = $openingTag ? $tag : substr($tag, 1); if ($openingTag) { if (in_array($tag, $openTags)) { if (!$failedUnclosed) { $this->output->addMessage(Output::FATAL, 'String is missing closing tag for html: ' . $tag, $file, $key); } $failedUnclosed = true; } else { if (substr($possibleHtml, -3) !== ' />') { $openTags[] = $tag; } } } else { if (empty($openTags)) { if (!$failedUnclosed) { $this->output->addMessage(Output::FATAL, sprintf('String is closing tag for html “%s” which was not opened before', $tag), $file, $key); } $failedUnclosed = true; } else { if (end($openTags) != $tag) { if (!$failedUnclosed) { $this->output->addMessage(Output::FATAL, 'String is missing closing tag for html: ' . end($openTags), $file, $key); } $failedUnclosed = true; } else { array_pop($openTags); } } } // HTML tag is not used in original language if (!$ignoreAdditional && !in_array($possibleHtml, $sourceHtml) && !isset($this->additionalHtmlFound[$file][$key][$possibleHtml])) { $this->additionalHtmlFound[$file][$key][$possibleHtml] = true; if (strpos($possibleHtml, '</') === 0) { // Do not add an additional entry for closing tags continue; } $level = $this->getErrorLevelForAdditionalHtml($possibleHtml); if (strpos($possibleHtml, '<a ') === 0) { if (in_array(str_replace('http://', 'https://', $possibleHtml), $sourceHtml)) { $level = Output::NOTICE; } else { if (in_array('</a>', $sourceHtml) || $this->originLanguagePath . 'common.php' === $file && $key === 'TRANSLATION_INFO' || $this->originLanguagePath . 'help_faq.php' === $file || $this->originLanguagePath . 'help_bbcode.php' === $file) { // Source contains a link aswell, mostly IST changed the link to better match the language // It's the translation info with the credit links of the translators // Or the help pages (faq and bbcode help), where links are not as bad as in other places. $level = Output::WARNING; } } } $this->output->addMessage($level, 'String is using additional html: ' . $possibleHtml, $file, $key); } } if (!empty($openTags) && !$failedUnclosed) { $this->output->addMessage(Output::FATAL, 'String is missing closing tag for html: ' . $openTags[0], $file, $key); } }
/** * Validates the directories * * Directories should not miss any files. * Directories must not contain additional php files. * Directories should not contain additional files. * * @return array List of files we can continue to validate. */ public function validate() { $sourceFiles = $this->getFileList($this->sourcePath); // License file is required but missing from en/, so we add it here $sourceFiles[] = $this->sourceLanguagePath . 'LICENSE'; $sourceFiles = array_unique($sourceFiles); $originFiles = $this->getFileList($this->originPath); $missingSubsilver2Files = $availableSubsilver2Files = array(); $validFiles = array(); foreach ($sourceFiles as $sourceFile) { $testOriginFile = str_replace('/' . $this->sourceIso . '/', '/' . $this->originIso . '/', $sourceFile); if (!in_array($testOriginFile, $originFiles)) { if ($this->phpbbVersion === '3.1' && strpos($testOriginFile, 'styles/subsilver2/') === 0) { $missingSubsilver2Files[] = $testOriginFile; } else { $this->output->addMessage(Output::FATAL, 'Missing required file', $testOriginFile); } } else { if (substr($sourceFile, -4) != '.gif' && substr($sourceFile, -12) != 'imageset.cfg') { if ($this->phpbbVersion === '3.1' && strpos($testOriginFile, 'styles/subsilver2/') === 0) { $availableSubsilver2Files[] = $testOriginFile; } $validFiles[$sourceFile] = $testOriginFile; } } } if ($this->phpbbVersion === '3.1' && !empty($availableSubsilver2Files) && !empty($missingSubsilver2Files)) { // Either subsilver2 has to be completly there, or not at all foreach ($missingSubsilver2Files as $testOriginFile) { $this->output->addMessage(Output::FATAL, 'Missing required file', $testOriginFile); } } else { if ($this->phpbbVersion === '3.1' && empty($availableSubsilver2Files) && !empty($missingSubsilver2Files)) { // If subsilver2 is not there at all, we throw a little warning $this->output->addMessage(Output::WARNING, 'Missing subsilver2 files'); } } foreach ($originFiles as $origin_file) { $testSourceFile = str_replace('/' . $this->originIso . '/', '/' . $this->sourceIso . '/', $origin_file); if (!in_array($testSourceFile, $sourceFiles)) { if (in_array($origin_file, array($this->originLanguagePath . 'AUTHORS', $this->originLanguagePath . 'CHANGELOG', $this->originLanguagePath . 'README', $this->originLanguagePath . 'VERSION'))) { $this->output->addMessage(Output::NOTICE, 'Found additional file', $origin_file); } else { if ($this->phpbbVersion == '3.1' && in_array($origin_file, array($this->originLanguagePath . 'AUTHORS.md', $this->originLanguagePath . 'CHANGELOG.md', $this->originLanguagePath . 'README.md', $this->originLanguagePath . 'VERSION.md'))) { $this->output->addMessage(Output::NOTICE, 'Found additional file', $origin_file); } else { if (substr($origin_file, -10) === '/index.htm' || $origin_file === 'index.htm') { $level = Output::NOTICE; } else { if ($this->phpbbVersion === '3.2' && strpos($origin_file, 'styles/subsilver2/') === 0) { $level = Output::FATAL; } else { $level = substr($origin_file, -3) !== '.md' ? Output::FATAL : Output::ERROR; } } $this->output->addMessage($level, 'Found additional file', $origin_file); } } } } return $validFiles; }