summaryrefslogtreecommitdiff
path: root/lib/phptal/PHPTAL/TemplateException.php
diff options
context:
space:
mode:
Diffstat (limited to 'lib/phptal/PHPTAL/TemplateException.php')
-rw-r--r--lib/phptal/PHPTAL/TemplateException.php160
1 files changed, 160 insertions, 0 deletions
diff --git a/lib/phptal/PHPTAL/TemplateException.php b/lib/phptal/PHPTAL/TemplateException.php
new file mode 100644
index 0000000..ce72b6b
--- /dev/null
+++ b/lib/phptal/PHPTAL/TemplateException.php
@@ -0,0 +1,160 @@
+<?php
+/**
+ * PHPTAL templating engine
+ *
+ * PHP Version 5
+ *
+ * @category HTML
+ * @package PHPTAL
+ * @author Laurent Bedubourg <lbedubourg@motion-twin.com>
+ * @author Kornel LesiƄski <kornel@aardvarkmedia.co.uk>
+ * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License
+ * @version SVN: $Id$
+ * @link http://phptal.org/
+ */
+
+/**
+ * Exception that is related to location within a template.
+ * You can check srcFile and srcLine to find source of the error.
+ *
+ * @package PHPTAL
+ * @subpackage Exception
+ */
+class PHPTAL_TemplateException extends PHPTAL_Exception
+{
+ public $srcFile;
+ public $srcLine;
+ private $is_src_accurate;
+
+ public function __construct($msg, $srcFile='', $srcLine=0)
+ {
+ parent::__construct($msg);
+
+ if ($srcFile && $srcLine) {
+ $this->srcFile = $srcFile;
+ $this->srcLine = $srcLine;
+ $this->is_src_accurate = true;
+ } else {
+ $this->is_src_accurate = $this->setTemplateSource();
+ }
+
+ if ($this->is_src_accurate) {
+ $this->file = $this->srcFile;
+ $this->line = (int)$this->srcLine;
+ }
+ }
+
+ public function __toString()
+ {
+ if (!$this->srcFile || $this->is_src_accurate) return parent::__toString();
+ return "From {$this->srcFile} around line {$this->srcLine}\n".parent::__toString();
+ }
+
+ /**
+ * Set new TAL source file/line if it isn't known already
+ */
+ public function hintSrcPosition($srcFile, $srcLine)
+ {
+ if ($srcFile && $srcLine) {
+ if (!$this->is_src_accurate) {
+ $this->srcFile = $srcFile;
+ $this->srcLine = $srcLine;
+ $this->is_src_accurate = true;
+ } else if ($this->srcLine <= 1 && $this->srcFile === $srcFile) {
+ $this->srcLine = $srcLine;
+ }
+ }
+
+ if ($this->is_src_accurate) {
+ $this->file = $this->srcFile;
+ $this->line = (int)$this->srcLine;
+ }
+ }
+
+ private function isTemplatePath($path)
+ {
+ return preg_match('/[\\\\\/]tpl_[0-9a-f]{8}_[^\\\\]+$/', $path);
+ }
+
+ private function findFileAndLine()
+ {
+ if ($this->isTemplatePath($this->file)) {
+ return array($this->file, $this->line);
+ }
+
+ $eval_line = 0;
+ $eval_path = NULL;
+
+ // searches backtrace to find template file
+ foreach($this->getTrace() as $tr) {
+ if (!isset($tr['file'],$tr['line'])) continue;
+
+ if ($this->isTemplatePath($tr['file'])) {
+ return array($tr['file'], $tr['line']);
+ }
+
+ // PHPTAL.php uses eval() on first run to catch fatal errors. This makes template path invisible.
+ // However, function name matches template path and eval() is visible in backtrace.
+ if (false !== strpos($tr['file'], 'eval()')) {
+ $eval_line = $tr['line'];
+ }
+ else if ($eval_line && isset($tr['function'],$tr['args'],$tr['args'][0]) &&
+ $this->isTemplatePath("/".$tr['function'].".php") && $tr['args'][0] instanceof PHPTAL) {
+ return array($tr['args'][0]->getCodePath(), $eval_line);
+ }
+ }
+
+ return array(NULL,NULL);
+ }
+
+ /**
+ * sets srcLine and srcFile to template path and source line
+ * by checking error backtrace and scanning PHP code file
+ *
+ * @return bool true if found accurate data
+ */
+ private function setTemplateSource()
+ {
+ // not accurate, but better than null
+ $this->srcFile = $this->file;
+ $this->srcLine = $this->line;
+
+ list($file,$line) = $this->findFileAndLine();
+
+ if (NULL === $file) {
+ return false;
+ }
+
+ // this is not accurate yet, hopefully will be overwritten later
+ $this->srcFile = $file;
+ $this->srcLine = $line;
+
+ $lines = @file($file);
+ if (!$lines) {
+ return false;
+ }
+
+ $found_line=false;
+ $found_file=false;
+
+ // scan lines backwards looking for "from line" comments
+ $end = min(count($lines), $line)-1;
+ for($i=$end; $i >= 0; $i--) {
+ if (preg_match('/tag "[^"]*" from line (\d+)/', $lines[$i], $m)) {
+ $this->srcLine = intval($m[1]);
+ $found_line=true;
+ break;
+ }
+ }
+
+ foreach(preg_grep('/Generated by PHPTAL from/',$lines) as $line) {
+ if (preg_match('/Generated by PHPTAL from (.*) \(/', $line, $m)) {
+ $this->srcFile = $m[1];
+ $found_file=true;
+ break;
+ }
+ }
+
+ return $found_line && $found_file;
+ }
+}