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)
*/
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;
$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);
+ }
}
+++ /dev/null
-<?php
-
-/*
- * This file is part of Twig.
- *
- * (c) 2011 Fabien Potencier
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Twig base exception.
- *
- * @package twig
- * @author Fabien Potencier <fabien.potencier@symfony-project.com>
- */
-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);
- }
-}
} 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);
}
}
--- /dev/null
+<?php
+
+require_once dirname(__FILE__).'/TestCase.php';
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+class Twig_Tests_ErrorTest extends Twig_Tests_TestCase
+{
+ /*
+ public function testTwigExceptionAddsFileAndLineWhenMissing()
+ {
+ $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());
+ } 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...');
+ }
+}