Twig-1.3.0/lib/Twig/Error.php
changeset 4 9a001a04b634
equal deleted inserted replaced
3:6d109e3804ac 4:9a001a04b634
       
     1 <?php
       
     2 
       
     3 /*
       
     4  * This file is part of Twig.
       
     5  *
       
     6  * (c) 2009 Fabien Potencier
       
     7  *
       
     8  * For the full copyright and license information, please view the LICENSE
       
     9  * file that was distributed with this source code.
       
    10  */
       
    11 
       
    12 /**
       
    13  * Twig base exception.
       
    14  *
       
    15  * @package    twig
       
    16  * @author     Fabien Potencier <fabien@symfony.com>
       
    17  */
       
    18 class Twig_Error extends Exception
       
    19 {
       
    20     protected $lineno;
       
    21     protected $filename;
       
    22     protected $rawMessage;
       
    23     protected $previous;
       
    24 
       
    25     /**
       
    26      * Constructor.
       
    27      *
       
    28      * @param string    $message  The error message
       
    29      * @param integer   $lineno   The template line where the error occurred
       
    30      * @param string    $filename The template file name where the error occurred
       
    31      * @param Exception $previous The previous exception
       
    32      */
       
    33     public function __construct($message, $lineno = -1, $filename = null, Exception $previous = null)
       
    34     {
       
    35         if (-1 === $lineno || null === $filename) {
       
    36             list($lineno, $filename) = $this->findTemplateInfo(null !== $previous ? $previous : $this, $lineno, $filename);
       
    37         }
       
    38 
       
    39         $this->lineno = $lineno;
       
    40         $this->filename = $filename;
       
    41         $this->rawMessage = $message;
       
    42 
       
    43         $this->updateRepr();
       
    44 
       
    45         if (version_compare(PHP_VERSION, '5.3.0', '<')) {
       
    46             $this->previous = $previous;
       
    47             parent::__construct($this->message);
       
    48         } else {
       
    49             parent::__construct($this->message, 0, $previous);
       
    50         }
       
    51     }
       
    52 
       
    53     /**
       
    54      * Gets the raw message.
       
    55      *
       
    56      * @return string The raw message
       
    57      */
       
    58     public function getRawMessage()
       
    59     {
       
    60         return $this->rawMessage;
       
    61     }
       
    62 
       
    63     /**
       
    64      * Gets the filename where the error occurred.
       
    65      *
       
    66      * @return string The filename
       
    67      */
       
    68     public function getTemplateFile()
       
    69     {
       
    70         return $this->filename;
       
    71     }
       
    72 
       
    73     /**
       
    74      * Sets the filename where the error occurred.
       
    75      *
       
    76      * @param string $filename The filename
       
    77      */
       
    78     public function setTemplateFile($filename)
       
    79     {
       
    80         $this->filename = $filename;
       
    81 
       
    82         $this->updateRepr();
       
    83     }
       
    84 
       
    85     /**
       
    86      * Gets the template line where the error occurred.
       
    87      *
       
    88      * @return integer The template line
       
    89      */
       
    90     public function getTemplateLine()
       
    91     {
       
    92         return $this->lineno;
       
    93     }
       
    94 
       
    95     /**
       
    96      * Sets the template line where the error occurred.
       
    97      *
       
    98      * @param integer $lineno The template line
       
    99      */
       
   100     public function setTemplateLine($lineno)
       
   101     {
       
   102         $this->lineno = $lineno;
       
   103 
       
   104         $this->updateRepr();
       
   105     }
       
   106 
       
   107     /**
       
   108      * For PHP < 5.3.0, provides access to the getPrevious() method.
       
   109      *
       
   110      * @param  string $method    The method name
       
   111      * @param  array  $arguments The parameters to be passed to the method
       
   112      *
       
   113      * @return Exception The previous exception or null
       
   114      */
       
   115     public function __call($method, $arguments)
       
   116     {
       
   117         if ('getprevious' == strtolower($method)) {
       
   118             return $this->previous;
       
   119         }
       
   120 
       
   121         throw new BadMethodCallException(sprintf('Method "Twig_Error::%s()" does not exist.', $method));
       
   122     }
       
   123 
       
   124     protected function updateRepr()
       
   125     {
       
   126         $this->message = $this->rawMessage;
       
   127 
       
   128         $dot = false;
       
   129         if ('.' === substr($this->message, -1)) {
       
   130             $this->message = substr($this->message, 0, -1);
       
   131             $dot = true;
       
   132         }
       
   133 
       
   134         if (null !== $this->filename) {
       
   135             $this->message .= sprintf(' in %s', json_encode($this->filename));
       
   136         }
       
   137 
       
   138         if ($this->lineno >= 0) {
       
   139             $this->message .= sprintf(' at line %d', $this->lineno);
       
   140         }
       
   141 
       
   142         if ($dot) {
       
   143             $this->message .= '.';
       
   144         }
       
   145     }
       
   146 
       
   147     protected function findTemplateInfo(Exception $e, $currentLine, $currentFile)
       
   148     {
       
   149         if (!function_exists('token_get_all')) {
       
   150             return array($currentLine, $currentFile);
       
   151         }
       
   152 
       
   153         $traces = $e->getTrace();
       
   154         foreach ($traces as $i => $trace) {
       
   155             if (!isset($trace['class']) || 'Twig_Template' === $trace['class']) {
       
   156                 continue;
       
   157             }
       
   158 
       
   159             $r = new ReflectionClass($trace['class']);
       
   160             if (!$r->implementsInterface('Twig_TemplateInterface')) {
       
   161                 continue;
       
   162             }
       
   163 
       
   164             if (!is_file($r->getFilename())) {
       
   165                 // probably an eval()'d code
       
   166                 return array($currentLine, $currentFile);
       
   167             }
       
   168 
       
   169             if (0 === $i) {
       
   170                 $line = $e->getLine();
       
   171             } else {
       
   172                 $line = isset($traces[$i - 1]['line']) ? $traces[$i - 1]['line'] : -log(0);
       
   173             }
       
   174 
       
   175             $tokens = token_get_all(file_get_contents($r->getFilename()));
       
   176             $templateline = -1;
       
   177             $template = null;
       
   178             foreach ($tokens as $token) {
       
   179                 if (isset($token[2]) && $token[2] >= $line) {
       
   180                     return array($templateline, $template);
       
   181                 }
       
   182 
       
   183                 if (T_COMMENT === $token[0] && null === $template && preg_match('#/\* +(.+) +\*/#', $token[1], $match)) {
       
   184                     $template = $match[1];
       
   185                 } elseif (T_COMMENT === $token[0] && preg_match('#^//\s*line (\d+)\s*$#', $token[1], $match)) {
       
   186                     $templateline = $match[1];
       
   187                 }
       
   188             }
       
   189 
       
   190             return array($currentLine, $template);
       
   191         }
       
   192 
       
   193         return array($currentLine, $currentFile);
       
   194     }
       
   195 }