diff --git a/systems/translationwizard/translationwizard/TranslationWizard.php b/systems/translationwizard/translationwizard/TranslationWizard.php index 994053e..e016792 100644 --- a/systems/translationwizard/translationwizard/TranslationWizard.php +++ b/systems/translationwizard/translationwizard/TranslationWizard.php @@ -2,6 +2,15 @@ declare(strict_types=1); class TranslationWizard { + /** + * Parse a PHP file and return all translatable strings. + * + * @param string $filepath Path to the file being scanned + * @param bool $debug Output debug information when true + * @param string|false $standard_tlschema Default tlschema if not auto-detected + * + * @return array Array of ['text' => string, 'schema' => string] entries + */ public static function scanFile(string $filepath, bool $debug=false, $standard_tlschema=false) { if(!is_file($filepath)) { throw new RuntimeException("Fatal Error: Could not find file at path: " . $filepath); @@ -284,6 +293,15 @@ public static function scanFile(string $filepath, bool $debug=false, $standard_t return $return; } + /** + * Insert untranslated strings into the database. + * + * @param array|string $delrows Strings or rows to insert + * @param string $languageschema Target language schema + * @param bool $serialized Whether input rows are serialized + * + * @return void + */ public static function insertFile($delrows, $languageschema, $serialized=false) { if(is_array($delrows)) { $insertrows = $delrows; @@ -300,6 +318,15 @@ public static function insertFile($delrows, $languageschema, $serialized=false) } } + /** + * Advance the pointer past PHP comments while scanning a file. + * + * @param string $str Entire file contents + * @param int &$i Current index in the string (modified) + * @param int &$line Current line counter (modified) + * + * @return void + */ protected static function skipCommentary($str, &$i, &$line) { while($str[$i] == "/" && $str[$i] != "") { if($str[($i+1)] == "/") { @@ -320,6 +347,15 @@ protected static function skipCommentary($str, &$i, &$line) { } } + /** + * Check if a translation entry already exists in the given array. + * + * @param array $array Current collection of entries + * @param string $text Text string to compare + * @param string $schema Associated schema + * + * @return bool True if an identical entry exists + */ protected static function alreadyInArray($array, $text, $schema) { foreach($array as $entry) { if($entry['text'] == $text && $entry['schema'] == $schema) { @@ -329,6 +365,16 @@ protected static function alreadyInArray($array, $text, $schema) { return false; } + /** + * Display or return a list of scannable files. + * + * @param bool $dosubmit When true, change events submit the form + * @param int $onlymodules 0 = all, 1 = modules folder, 2 = only modules + * @param bool $showselectbox Whether to output a <select> element + * @param bool $mainmodulecheck If true, onChange uses modulecheck() + * + * @return array Array of valid file paths + */ public static function showValidFiles($dosubmit=true, $onlymodules=0, $showselectbox=true, $mainmodulecheck=false) { global $coding; require_once("lib/errorhandling.php"); @@ -418,6 +464,13 @@ public static function showValidFiles($dosubmit=true, $onlymodules=0, $showselec return $outputfiles; } + /** + * Recursively gather subdirectories below a given base path. + * + * @param string $base Base directory + * + * @return array List of directory paths + */ protected static function tree($base) { $d = dir("$base"); $back=array(); diff --git a/systems/translationwizard/translationwizard/WizardService.php b/systems/translationwizard/translationwizard/WizardService.php index 046669c..38f99dc 100644 --- a/systems/translationwizard/translationwizard/WizardService.php +++ b/systems/translationwizard/translationwizard/WizardService.php @@ -2,6 +2,13 @@ declare(strict_types=1); class WizardService { + /** + * Normalize input into an array. + * + * @param mixed $value Scalar or array value to wrap + * + * @return array The provided value as an array + */ public static function ensureArray($value): array { if (is_array($value)) { return $value; @@ -9,6 +16,21 @@ public static function ensureArray($value): array { return ($value !== null && $value !== '') ? array($value) : array(); } + /** + * Insert a translation row. + * + * Values are manually escaped because the db_query helper has no + * parameterized query support. + * + * @param string $language Target language code + * @param string $namespace Namespace/URI of the text + * @param string $intext Original text + * @param string $outtext Translated text + * @param string $author Saving author + * @param string $version Game version + * + * @return resource|bool Result of db_query() + */ public static function createTranslation(string $language, string $namespace, string $intext, string $outtext, string $author, string $version) { // db_query() has no support for parameterized queries, so manually escape values $language = addslashes($language); @@ -22,6 +44,18 @@ public static function createTranslation(string $language, string $namespace, st return db_query($sql); } + /** + * Remove a row from the untranslated table. + * + * Values are manually escaped because parameterized queries are not + * available. + * + * @param string $language Target language code + * @param string $namespace Namespace/URI of the text + * @param string $intext Original untranslated text + * + * @return resource|bool Result of db_query() + */ public static function deleteUntranslated(string $language, string $namespace, string $intext) { // Inputs may originate from user data; escape to prevent SQL injection // due to lack of parameterized query support @@ -32,6 +66,21 @@ public static function deleteUntranslated(string $language, string $namespace, s return db_query($sql); } + /** + * Convenience wrapper to insert a translation and remove the untranslated row. + * + * Manual escaping occurs inside the called methods since no parameterized + * queries are available. + * + * @param string $language Target language code + * @param string $namespace Namespace/URI of the text + * @param string $intext Original text + * @param string $outtext Translated text + * @param string $author Saving author + * @param string $version Game version + * + * @return bool True on success + */ public static function saveTranslation(string $language, string $namespace, string $intext, string $outtext, string $author, string $version): bool { $insert = self::createTranslation($language, $namespace, $intext, $outtext, $author, $version); $delete = self::deleteUntranslated($language, $namespace, $intext); @@ -42,6 +91,9 @@ public static function saveTranslation(string $language, string $namespace, stri /** * Copy untranslated texts directly to the translation table. * + * Manual escaping is performed before issuing SQL statements because no + * parameterized query mechanism is available. + * * @param string $language Target language * @param string $namespace Namespace of the texts * @param array $texts Array of untranslated texts (URL encoded) @@ -67,6 +119,9 @@ public static function copyCheckedTranslations(string $language, string $namespa /** * Save multiple translations at once. * + * Manual escaping of values is required for the generated SQL queries + * because the project lacks support for parameterized statements. + * * @param string $language Target language * @param string $namespace Default namespace if none is supplied per row * @param array $inTexts Texts to translate