diff --git a/libraries/joomla/language/language.php b/libraries/joomla/language/language.php index 35e57b901d1cc..968bb15c56728 100644 --- a/libraries/joomla/language/language.php +++ b/libraries/joomla/language/language.php @@ -851,85 +851,112 @@ protected function parse($filename) // Restore error tracking to what it was before. ini_set('track_errors', $track_errors); - // Initialise variables for manually parsing the file for common errors. - $blacklist = array('YES', 'NO', 'NULL', 'FALSE', 'ON', 'OFF', 'NONE', 'TRUE'); - $this->debug = false; - $errors = array(); + $this->debugFile($filename); + } - // Open the file as a stream. - $file = new SplFileObject($filename); + return $strings; + } - foreach ($file as $lineNumber => $line) - { - // Avoid BOM error as BOM is OK when using parse_ini. - if ($lineNumber == 0) - { - $line = str_replace("\xEF\xBB\xBF", '', $line); - } + /** + * Debugs a language file + * + * @param string $filename Absolute path to the file to debug + * + * @return integer A count of the number of parsing errors + * + * @since __DEPLOY_VERSION__ + * @throws InvalidArgumentException + */ + public function debugFile($filename) + { + // Make sure our file actually exists + if (!file_exists($filename)) + { + throw new InvalidArgumentException( + sprintf('Unable to locate file "%s" for debugging', $filename) + ); + } - $line = trim($line); + // Initialise variables for manually parsing the file for common errors. + $blacklist = array('YES', 'NO', 'NULL', 'FALSE', 'ON', 'OFF', 'NONE', 'TRUE'); + $debug = $this->getDebug(); + $this->debug = false; + $errors = array(); + $php_errormsg = null; - // Ignore comment lines. - if (!strlen($line) || $line['0'] == ';') - { - continue; - } + // Open the file as a stream. + $file = new SplFileObject($filename); - // Ignore grouping tag lines, like: [group] - if (preg_match('#^\[[^\]]*\](\s*;.*)?$#', $line)) - { - continue; - } + foreach ($file as $lineNumber => $line) + { + // Avoid BOM error as BOM is OK when using parse_ini. + if ($lineNumber == 0) + { + $line = str_replace("\xEF\xBB\xBF", '', $line); + } - // Remove the "_QQ_" from the equation - $line = str_replace('"_QQ_"', '', $line); - $realNumber = $lineNumber + 1; + $line = trim($line); - // Check for any incorrect uses of _QQ_. - if (strpos($line, '_QQ_') !== false) - { - $errors[] = $realNumber; - continue; - } + // Ignore comment lines. + if (!strlen($line) || $line['0'] == ';') + { + continue; + } - // Check for odd number of double quotes. - if (substr_count($line, '"') % 2 != 0) - { - $errors[] = $realNumber; - continue; - } + // Ignore grouping tag lines, like: [group] + if (preg_match('#^\[[^\]]*\](\s*;.*)?$#', $line)) + { + continue; + } - // Check that the line passes the necessary format. - if (!preg_match('#^[A-Z][A-Z0-9_\*\-\.]*\s*=\s*".*"(\s*;.*)?$#', $line)) - { - $errors[] = $realNumber; - continue; - } + // Remove the "_QQ_" from the equation + $line = str_replace('"_QQ_"', '', $line); + $realNumber = $lineNumber + 1; - // Check that the key is not in the blacklist. - $key = strtoupper(trim(substr($line, 0, strpos($line, '=')))); + // Check for any incorrect uses of _QQ_. + if (strpos($line, '_QQ_') !== false) + { + $errors[] = $realNumber; + continue; + } - if (in_array($key, $blacklist)) - { - $errors[] = $realNumber; - } + // Check for odd number of double quotes. + if (substr_count($line, '"') % 2 != 0) + { + $errors[] = $realNumber; + continue; } - // Check if we encountered any errors. - if (count($errors)) + // Check that the line passes the necessary format. + if (!preg_match('#^[A-Z][A-Z0-9_\*\-\.]*\s*=\s*".*"(\s*;.*)?$#', $line)) { - $this->errorfiles[$filename] = $filename . ' : error(s) in line(s) ' . implode(', ', $errors); + $errors[] = $realNumber; + continue; } - elseif ($php_errormsg) + + // Check that the key is not in the blacklist. + $key = strtoupper(trim(substr($line, 0, strpos($line, '=')))); + + if (in_array($key, $blacklist)) { - // We didn't find any errors but there's probably a parse notice. - $this->errorfiles['PHP' . $filename] = 'PHP parser errors :' . $php_errormsg; + $errors[] = $realNumber; } + } - $this->debug = true; + // Check if we encountered any errors. + if (count($errors)) + { + $this->errorfiles[$filename] = $filename . ' : error(s) in line(s) ' . implode(', ', $errors); + } + elseif ($php_errormsg) + { + // We didn't find any errors but there's probably a parse notice. + $this->errorfiles['PHP' . $filename] = 'PHP parser errors :' . $php_errormsg; } - return $strings; + $this->debug = $debug; + + return count($errors); } /** diff --git a/tests/unit/suites/libraries/joomla/language/JLanguageTest.php b/tests/unit/suites/libraries/joomla/language/JLanguageTest.php index a1307712f805a..0586983c83950 100644 --- a/tests/unit/suites/libraries/joomla/language/JLanguageTest.php +++ b/tests/unit/suites/libraries/joomla/language/JLanguageTest.php @@ -780,6 +780,38 @@ public function testParse() ); } + /** + * Test debugFile reports no errors on a good file + * + * @return void + */ + public function testVerifyDebugFileFindsNoErrorsInAGoodFile() + { + $this->assertSame(0, $this->object->debugFile(__DIR__ . '/data/good.ini')); + } + + /** + * Test debugFile reports errors on a bad file + * + * @return void + */ + public function testVerifyDebugFileFindsErrorsInABadFile() + { + $this->assertGreaterThan(0, $this->object->debugFile(__DIR__ . '/data/bad.ini')); + } + + /** + * Test debugFile throws an Exception when the file does not exist + * + * @expectedException InvalidArgumentException + * + * @return void + */ + public function testVerifyDebugFileThrowsAnExceptionWhenTheFileDoesNotExist() + { + $this->object->debugFile(__DIR__ . '/data/not-existing.ini'); + } + /** * Test... *