Project

General

Profile

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 (version_compare(PHP_VERSION, '5.3.0', '<')) {
36
            $this->previous = $previous;
37
            parent::__construct('');
38
        } else {
39
            parent::__construct('', 0, $previous);
40
        }
41

    
42
        $this->lineno = $lineno;
43
        $this->filename = $filename;
44

    
45
        if (-1 === $this->lineno || null === $this->filename) {
46
            $this->guessTemplateInfo();
47
        }
48

    
49
        $this->rawMessage = $message;
50

    
51
        $this->updateRepr();
52
    }
53

    
54
    /**
55
     * Gets the raw message.
56
     *
57
     * @return string The raw message
58
     */
59
    public function getRawMessage()
60
    {
61
        return $this->rawMessage;
62
    }
63

    
64
    /**
65
     * Gets the filename where the error occurred.
66
     *
67
     * @return string The filename
68
     */
69
    public function getTemplateFile()
70
    {
71
        return $this->filename;
72
    }
73

    
74
    /**
75
     * Sets the filename where the error occurred.
76
     *
77
     * @param string $filename The filename
78
     */
79
    public function setTemplateFile($filename)
80
    {
81
        $this->filename = $filename;
82

    
83
        $this->updateRepr();
84
    }
85

    
86
    /**
87
     * Gets the template line where the error occurred.
88
     *
89
     * @return integer The template line
90
     */
91
    public function getTemplateLine()
92
    {
93
        return $this->lineno;
94
    }
95

    
96
    /**
97
     * Sets the template line where the error occurred.
98
     *
99
     * @param integer $lineno The template line
100
     */
101
    public function setTemplateLine($lineno)
102
    {
103
        $this->lineno = $lineno;
104

    
105
        $this->updateRepr();
106
    }
107

    
108
    /**
109
     * For PHP < 5.3.0, provides access to the getPrevious() method.
110
     *
111
     * @param  string $method    The method name
112
     * @param  array  $arguments The parameters to be passed to the method
113
     *
114
     * @return Exception The previous exception or null
115
     */
116
    public function __call($method, $arguments)
117
    {
118
        if ('getprevious' == strtolower($method)) {
119
            return $this->previous;
120
        }
121

    
122
        throw new BadMethodCallException(sprintf('Method "Twig_Error::%s()" does not exist.', $method));
123
    }
124

    
125
    protected function updateRepr()
126
    {
127
        $this->message = $this->rawMessage;
128

    
129
        $dot = false;
130
        if ('.' === substr($this->message, -1)) {
131
            $this->message = substr($this->message, 0, -1);
132
            $dot = true;
133
        }
134

    
135
        if (null !== $this->filename) {
136
            if (is_string($this->filename) || (is_object($this->filename) && method_exists($this->filename, '__toString'))) {
137
                $filename = sprintf('"%s"', $this->filename);
138
            } else {
139
                $filename = json_encode($this->filename);
140
            }
141
            $this->message .= sprintf(' in %s', $filename);
142
        }
143

    
144
        if ($this->lineno >= 0) {
145
            $this->message .= sprintf(' at line %d', $this->lineno);
146
        }
147

    
148
        if ($dot) {
149
            $this->message .= '.';
150
        }
151
    }
152

    
153
    protected function guessTemplateInfo()
154
    {
155
        $template = null;
156
        foreach (debug_backtrace() as $trace) {
157
            if (isset($trace['object']) && $trace['object'] instanceof Twig_Template && 'Twig_Template' !== get_class($trace['object'])) {
158
                $template = $trace['object'];
159

    
160
                // update template filename
161
                if (null === $this->filename) {
162
                    $this->filename = $template->getTemplateName();
163
                }
164
            }
165
        }
166

    
167
        if (null === $template || $this->lineno > -1) {
168
            return;
169
        }
170

    
171
        $r = new ReflectionObject($template);
172
        $file = $r->getFileName();
173

    
174
        $exceptions = array($e = $this);
175
        while (method_exists($e, 'getPrevious') && $e = $e->getPrevious()) {
176
            $exceptions[] = $e;
177
        }
178

    
179
        while ($e = array_pop($exceptions)) {
180
            $traces = $e->getTrace();
181
            while ($trace = array_shift($traces)) {
182
                if (!isset($trace['file']) || !isset($trace['line']) || $file != $trace['file']) {
183
                    continue;
184
                }
185

    
186
                foreach ($template->getDebugInfo() as $codeLine => $templateLine) {
187
                    if ($codeLine <= $trace['line']) {
188
                        // update template line
189
                        $this->lineno = $templateLine;
190

    
191
                        return;
192
                    }
193
                }
194
            }
195
        }
196
    }
197
}
(6-6/33)