fixed template line number in some exceptions
authorFabien Potencier <fabien.potencier@gmail.com>
Sat, 21 Apr 2012 20:21:04 +0000 (22:21 +0200)
committerFabien Potencier <fabien.potencier@gmail.com>
Sat, 21 Apr 2012 20:21:37 +0000 (22:21 +0200)
CHANGELOG
lib/Twig/Error.php

index 920205e..51bd451 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,6 @@
 * 1.7.0 (2012-XX-XX)
 
+ * fixed template line number in some exceptions
  * added an iterable test
  * added an error when defining two blocks with the same name in a template
  * added the preserves_safety option for filters
index a19aca6..a2ffd35 100644 (file)
@@ -32,30 +32,23 @@ class Twig_Error extends Exception
      */
     public function __construct($message, $lineno = -1, $filename = null, Exception $previous = null)
     {
-        if (-1 === $lineno || null === $filename) {
-            if ($trace = $this->getTemplateTrace()) {
-                if (-1 === $lineno) {
-                    $lineno = $this->guessTemplateLine($trace);
-                }
-
-                if (null === $filename) {
-                    $filename = $trace['object']->getTemplateName();
-                }
-            }
+        if (version_compare(PHP_VERSION, '5.3.0', '<')) {
+            $this->previous = $previous;
+            parent::__construct('');
+        } else {
+            parent::__construct('', 0, $previous);
         }
 
         $this->lineno = $lineno;
         $this->filename = $filename;
+
+        if (-1 === $this->lineno || null === $this->filename) {
+            $this->guessTemplateInfo();
+        }
+
         $this->rawMessage = $message;
 
         $this->updateRepr();
-
-        if (version_compare(PHP_VERSION, '5.3.0', '<')) {
-            $this->previous = $previous;
-            parent::__construct($this->message);
-        } else {
-            parent::__construct($this->message, 0, $previous);
-        }
     }
 
     /**
@@ -157,25 +150,48 @@ class Twig_Error extends Exception
         }
     }
 
-    protected function getTemplateTrace()
+    protected function guessTemplateInfo()
     {
+        $template = null;
         foreach (debug_backtrace() as $trace) {
-            if (isset($trace['object']) && $trace['object'] instanceof Twig_Template) {
-                return $trace;
+            if (isset($trace['object']) && $trace['object'] instanceof Twig_Template && 'Twig_Template' !== get_class($trace['object'])) {
+                $template = $trace['object'];
+
+                // update template filename
+                if (null === $this->filename) {
+                    $this->filename = $template->getTemplateName();
+                }
             }
         }
-    }
 
-    protected function guessTemplateLine($trace)
-    {
-        if (isset($trace['line'])) {
-            foreach ($trace['object']->getDebugInfo() as $codeLine => $templateLine) {
-                if ($codeLine <= $trace['line']) {
-                    return $templateLine;
+        if (null === $template || $this->lineno > -1) {
+            return;
+        }
+
+        $r = new ReflectionObject($template);
+        $file = $r->getFileName();
+
+        $exceptions = array($e = $this);
+        while ($e = $e->getPrevious()) {
+            $exceptions[] = $e;
+        }
+
+        while ($e = array_pop($exceptions)) {
+            $traces = $e->getTrace();
+            while ($trace = array_shift($traces)) {
+                if (!isset($trace['file']) || !isset($trace['line']) || $file != $trace['file']) {
+                    continue;
+                }
+
+                foreach ($template->getDebugInfo() as $codeLine => $templateLine) {
+                    if ($codeLine <= $trace['line']) {
+                        // update template line
+                        $this->lineno = $templateLine;
+
+                        return;
+                    }
                 }
             }
         }
-
-        return -1;
     }
 }