From 34ff3b4a76d19a6a3ad40ec010cf72276367df86 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 12 Apr 2011 09:12:05 +0200 Subject: [PATCH] tweaked error wrapping --- CHANGELOG | 2 +- lib/Twig/Error.php | 49 ++++++++++++++++++++++++++ lib/Twig/Error/Wrapped.php | 75 ----------------------------------------- lib/Twig/Template.php | 2 +- test/Twig/Tests/ErrorTest.php | 55 ++++++++++++++++++++++++++++++ 5 files changed, 106 insertions(+), 77 deletions(-) delete mode 100644 lib/Twig/Error/Wrapped.php create mode 100644 test/Twig/Tests/ErrorTest.php diff --git a/CHANGELOG b/CHANGELOG index bccaf16..673cbe5 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,7 +4,7 @@ Flush your cache after upgrading. Changes: - * wrapped all runtime exceptions (Twig_Error_Wrapped) to try to add the template name and the line when a problem occurs + * wrapped all runtime exceptions with Twig_Error_Runtime and added logic to guess the template name and line * moved display() method to Twig_Template (generated templates should now use doDisplay() instead) * 1.0.0 (2011-03-27) diff --git a/lib/Twig/Error.php b/lib/Twig/Error.php index e85c587..c291307 100644 --- a/lib/Twig/Error.php +++ b/lib/Twig/Error.php @@ -32,6 +32,10 @@ class Twig_Error extends Exception */ public function __construct($message, $lineno = -1, $filename = null, Exception $previous = null) { + if (-1 === $lineno || null === $filename) { + list($lineno, $filename) = $this->findTemplateInfo(null !== $previous ? $previous : $this); + } + $this->lineno = $lineno; $this->filename = $filename; $this->rawMessage = $message; @@ -119,4 +123,49 @@ class Twig_Error extends Exception $this->message .= sprintf(' at line %d', $this->lineno); } } + + protected function findTemplateInfo(Exception $e) + { + if (!function_exists('token_get_all')) { + return array(-1, null); + } + + $traces = $e->getTrace(); + foreach ($traces as $i => $trace) { + if (!isset($trace['class']) || !isset($trace['line']) || 'Twig_Template' === $trace['class']) { + continue; + } + + $r = new ReflectionClass($trace['class']); + if (!$r->implementsInterface('Twig_TemplateInterface')) { + continue; + } + + $trace = $traces[$i - 1]; + + if (!file_exists($r->getFilename())) { + // probably an eval()'d code + return array(-1, null); + } + + $tokens = token_get_all(file_get_contents($r->getFilename())); + $currentline = 0; + $templateline = -1; + $template = null; + while ($token = array_shift($tokens)) { + if (T_WHITESPACE === $token[0]) { + $currentline += substr_count($token[1], "\n"); + if ($currentline >= $trace['line']) { + return array($templateline, $template); + } + } elseif (T_COMMENT === $token[0] && null === $template && preg_match('#/\* +(.+) +\*/#', $token[1], $match)) { + $template = $match[1]; + } elseif (T_COMMENT === $token[0] && preg_match('#line (\d+)#', $token[1], $match)) { + $templateline = $match[1]; + } + } + } + + return array(-1, null); + } } diff --git a/lib/Twig/Error/Wrapped.php b/lib/Twig/Error/Wrapped.php deleted file mode 100644 index 54190fd..0000000 --- a/lib/Twig/Error/Wrapped.php +++ /dev/null @@ -1,75 +0,0 @@ - - */ -class Twig_Error_Wrapped extends Twig_Error_Runtime -{ - public function __construct(Exception $e) - { - if ($e instanceof Twig_Error && -1 !== $e->getTemplateLine() && null === $e->getTemplateFile()) { - parent::__construct($e->getMessage(), $e->getTemplateLine(), $e->getTemplateFile(), $e); - } else { - list($lineno, $filename) = $this->findTemplateInfo($e); - - parent::__construct($e->getMessage(), $lineno, $filename, $e); - } - } - - protected function findTemplateInfo(Exception $e) - { - if (!function_exists('token_get_all')) { - return array(-1, null); - } - - $traces = $e->getTrace(); - foreach ($traces as $i => $trace) { - if (!isset($trace['class']) || !isset($trace['line']) || 'Twig_Template' === $trace['class']) { - continue; - } - - $r = new ReflectionClass($trace['class']); - if (!$r->implementsInterface('Twig_TemplateInterface')) { - continue; - } - - $trace = $traces[$i - 1]; - - if (!file_exists($r->getFilename())) { - // probably an eval()'d code - return array(-1, null); - } - - $tokens = token_get_all(file_get_contents($r->getFilename())); - $currentline = 0; - $templateline = -1; - $template = null; - while ($token = array_shift($tokens)) { - if (T_WHITESPACE === $token[0]) { - $currentline += substr_count($token[1], "\n"); - if ($currentline >= $trace['line']) { - return array($templateline, $template); - } - } elseif (T_COMMENT === $token[0] && null === $template && preg_match('#/\* +(.+) +\*/#', $token[1], $match)) { - $template = $match[1]; - } elseif (T_COMMENT === $token[0] && preg_match('#line (\d+)#', $token[1], $match)) { - $templateline = $match[1]; - } - } - } - - return array(-1, null); - } -} diff --git a/lib/Twig/Template.php b/lib/Twig/Template.php index 6a6ff3b..34556c1 100644 --- a/lib/Twig/Template.php +++ b/lib/Twig/Template.php @@ -169,7 +169,7 @@ abstract class Twig_Template implements Twig_TemplateInterface } catch (Twig_Error $e) { throw $e; } catch (Exception $e) { - throw new Twig_Error_Wrapped($e); + throw new Twig_Error_Runtime($e->getMessage(), -1, null, $e); } } diff --git a/test/Twig/Tests/ErrorTest.php b/test/Twig/Tests/ErrorTest.php new file mode 100644 index 0000000..7af3036 --- /dev/null +++ b/test/Twig/Tests/ErrorTest.php @@ -0,0 +1,55 @@ + "\n\n{{ foo.bar }}")); + $twig = new Twig_Environment($loader, array('strict_variables' => true, 'debug' => true, 'cache' => $this->getTempDir())); + + $template = $twig->loadTemplate('index'); + + try { + $template->render(array()); + } catch (Twig_Error_Runtime $e) { + $this->assertEquals(3, $e->getTemplateLine()); + $this->assertEquals('index', $e->getTemplateFile()); + } + } +*/ + public function testRenderWrapsExceptions() + { + $loader = new Twig_Loader_Array(array('index' => "\n\n{{ foo.bar }}")); + $twig = new Twig_Environment($loader, array('strict_variables' => true, 'debug' => true, 'cache' => $this->getTempDir())); + + $template = $twig->loadTemplate('index'); + + try { + $template->render(array('foo' => new Twig_Tests_ErrorTest_Foo())); + } catch (Twig_Error_Runtime $e) { + $this->assertEquals('Runtime error... in "index" at line 3', $e->getMessage()); + $this->assertEquals(3, $e->getTemplateLine()); + $this->assertEquals('index', $e->getTemplateFile()); + } + } +} + +class Twig_Tests_ErrorTest_Foo +{ + public function bar() + { + throw new Exception('Runtime error...'); + } +} -- 1.7.2.5