summaryrefslogtreecommitdiff
path: root/lib/phptal/PHPTAL/Php/State.php
diff options
context:
space:
mode:
authoremkael <emkael@tlen.pl>2016-10-31 21:58:33 +0100
committeremkael <emkael@tlen.pl>2016-10-31 21:59:22 +0100
commitd216b3147bc3f37cf2337acab5767c6a4f74aa2e (patch)
tree6090989e5071db101a1112131e2b075a02dccbc4 /lib/phptal/PHPTAL/Php/State.php
parentb23bfbb17d1d5f6852a1690f246a84c2d38ae969 (diff)
* PHPTAL library
Diffstat (limited to 'lib/phptal/PHPTAL/Php/State.php')
-rw-r--r--lib/phptal/PHPTAL/Php/State.php254
1 files changed, 254 insertions, 0 deletions
diff --git a/lib/phptal/PHPTAL/Php/State.php b/lib/phptal/PHPTAL/Php/State.php
new file mode 100644
index 0000000..cc4f193
--- /dev/null
+++ b/lib/phptal/PHPTAL/Php/State.php
@@ -0,0 +1,254 @@
+<?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/
+ */
+
+
+/**
+ * @package PHPTAL
+ * @subpackage Php
+ */
+class PHPTAL_Php_State
+{
+ private $debug = false;
+ private $tales_mode = 'tales';
+ private $encoding;
+ private $output_mode;
+ private $phptal;
+
+ function __construct(PHPTAL $phptal)
+ {
+ $this->phptal = $phptal;
+ $this->encoding = $phptal->getEncoding();
+ $this->output_mode = $phptal->getOutputMode();
+ }
+
+ /**
+ * used by codewriter to get information for phptal:cache
+ */
+ public function getCacheFilesBaseName()
+ {
+ return $this->phptal->getCodePath();
+ }
+
+ /**
+ * true if PHPTAL has translator set
+ */
+ public function isTranslationOn()
+ {
+ return !!$this->phptal->getTranslator();
+ }
+
+ /**
+ * controlled by phptal:debug
+ */
+ public function setDebug($bool)
+ {
+ $old = $this->debug;
+ $this->debug = $bool;
+ return $old;
+ }
+
+ /**
+ * if true, add additional diagnostic information to generated code
+ */
+ public function isDebugOn()
+ {
+ return $this->debug;
+ }
+
+ /**
+ * Sets new and returns old TALES mode.
+ * Valid modes are 'tales' and 'php'
+ *
+ * @param string $mode
+ *
+ * @return string
+ */
+ public function setTalesMode($mode)
+ {
+ $old = $this->tales_mode;
+ $this->tales_mode = $mode;
+ return $old;
+ }
+
+ public function getTalesMode()
+ {
+ return $this->tales_mode;
+ }
+
+ /**
+ * encoding used for both template input and output
+ */
+ public function getEncoding()
+ {
+ return $this->encoding;
+ }
+
+ /**
+ * Syntax rules to follow in generated code
+ *
+ * @return one of PHPTAL::XHTML, PHPTAL::XML, PHPTAL::HTML5
+ */
+ public function getOutputMode()
+ {
+ return $this->output_mode;
+ }
+
+ /**
+ * Load prefilter
+ */
+ public function getPreFilterByName($name)
+ {
+ return $this->phptal->getPreFilterByName($name);
+ }
+
+ /**
+ * compile TALES expression according to current talesMode
+ * @return string with PHP code or array with expressions for TalesChainExecutor
+ */
+ public function evaluateExpression($expression)
+ {
+ if ($this->getTalesMode() === 'php') {
+ return PHPTAL_Php_TalesInternal::php($expression);
+ }
+ return PHPTAL_Php_TalesInternal::compileToPHPExpressions($expression, false);
+ }
+
+ /**
+ * compile TALES expression according to current talesMode
+ * @return string with PHP code
+ */
+ private function compileTalesToPHPExpression($expression)
+ {
+ if ($this->getTalesMode() === 'php') {
+ return PHPTAL_Php_TalesInternal::php($expression);
+ }
+ return PHPTAL_Php_TalesInternal::compileToPHPExpression($expression, false);
+ }
+
+ /**
+ * returns PHP code that generates given string, including dynamic replacements
+ *
+ * It's almost unused.
+ */
+ public function interpolateTalesVarsInString($string)
+ {
+ return PHPTAL_Php_TalesInternal::parseString($string, false, ($this->getTalesMode() === 'tales') ? '' : 'php:' );
+ }
+
+ /**
+ * replaces ${} in string, expecting HTML-encoded input and HTML-escapes output
+ */
+ public function interpolateTalesVarsInHTML($src)
+ {
+ return preg_replace_callback('/((?:\$\$)*)\$\{(structure |text )?(.*?)\}|((?:\$\$)+)\{/isS',
+ array($this,'_interpolateTalesVarsInHTMLCallback'), $src);
+ }
+
+ /**
+ * callback for interpolating TALES with HTML-escaping
+ */
+ private function _interpolateTalesVarsInHTMLCallback($matches)
+ {
+ return $this->_interpolateTalesVarsCallback($matches, 'html');
+ }
+
+ /**
+ * replaces ${} in string, expecting CDATA (basically unescaped) input,
+ * generates output protected against breaking out of CDATA in XML/HTML
+ * (depending on current output mode).
+ */
+ public function interpolateTalesVarsInCDATA($src)
+ {
+ return preg_replace_callback('/((?:\$\$)*)\$\{(structure |text )?(.*?)\}|((?:\$\$)+)\{/isS',
+ array($this,'_interpolateTalesVarsInCDATACallback'), $src);
+ }
+
+ /**
+ * callback for interpolating TALES with CDATA escaping
+ */
+ private function _interpolateTalesVarsInCDATACallback($matches)
+ {
+ return $this->_interpolateTalesVarsCallback($matches, 'cdata');
+ }
+
+ private function _interpolateTalesVarsCallback($matches, $format)
+ {
+ // replaces $${ with literal ${ (or $$$${ with $${ etc)
+ if (!empty($matches[4])) {
+ return substr($matches[4], strlen($matches[4])/2).'{';
+ }
+
+ // same replacement, but before executed expression
+ $dollars = substr($matches[1], strlen($matches[1])/2);
+
+ $code = $matches[3];
+ if ($format == 'html') {
+ $code = html_entity_decode($code, ENT_QUOTES, $this->getEncoding());
+ }
+
+ $code = $this->compileTalesToPHPExpression($code);
+
+ if (rtrim($matches[2]) == 'structure') { // regex captures a space there
+ return $dollars.'<?php echo '.$this->stringify($code)." ?>\n";
+ } else {
+ if ($format == 'html') {
+ return $dollars.'<?php echo '.$this->htmlchars($code)." ?>\n";
+ }
+ if ($format == 'cdata') {
+ // quite complex for an "unescaped" section, isn't it?
+ if ($this->getOutputMode() === PHPTAL::HTML5) {
+ return $dollars."<?php echo str_replace('</','<\\\\/', ".$this->stringify($code).") ?>\n";
+ } elseif ($this->getOutputMode() === PHPTAL::XHTML) {
+ // both XML and HMTL, because people will inevitably send it as text/html :(
+ return $dollars."<?php echo strtr(".$this->stringify($code)." ,array(']]>'=>']]]]><![CDATA[>','</'=>'<\\/')) ?>\n";
+ } else {
+ return $dollars."<?php echo str_replace(']]>',']]]]><![CDATA[>', ".$this->stringify($code).") ?>\n";
+ }
+ }
+ assert(0);
+ }
+ }
+
+ /**
+ * expects PHP code and returns PHP code that will generate escaped string
+ * Optimizes case when PHP string is given.
+ *
+ * @return php code
+ */
+ public function htmlchars($php)
+ {
+ // PHP strings can be escaped at compile time
+ if (preg_match('/^\'((?:[^\'{]+|\\\\.)*)\'$/s', $php, $m)) {
+ return "'".htmlspecialchars(str_replace('\\\'', "'", $m[1]), ENT_QUOTES, $this->encoding)."'";
+ }
+ return 'phptal_escape('.$php.', \''.$this->encoding.'\')';
+ }
+
+ /**
+ * allow proper printing of any object
+ * (without escaping - for use with structure keyword)
+ *
+ * @return php code
+ */
+ public function stringify($php)
+ {
+ // PHP strings don't need to be changed
+ if (preg_match('/^\'(?>[^\'\\\\]+|\\\\.)*\'$|^\s*"(?>[^"\\\\]+|\\\\.)*"\s*$/s', $php)) {
+ return $php;
+ }
+ return 'phptal_tostring('.$php.')';
+ }
+}
+