diff options
author | emkael <emkael@tlen.pl> | 2016-10-31 21:58:33 +0100 |
---|---|---|
committer | emkael <emkael@tlen.pl> | 2016-10-31 21:59:22 +0100 |
commit | d216b3147bc3f37cf2337acab5767c6a4f74aa2e (patch) | |
tree | 6090989e5071db101a1112131e2b075a02dccbc4 /lib/phptal/PHPTAL/Php/State.php | |
parent | b23bfbb17d1d5f6852a1690f246a84c2d38ae969 (diff) |
* PHPTAL library
Diffstat (limited to 'lib/phptal/PHPTAL/Php/State.php')
-rw-r--r-- | lib/phptal/PHPTAL/Php/State.php | 254 |
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.')'; + } +} + |