diff --git a/i18n/i18nTextCollector.php b/i18n/i18nTextCollector.php index eb21c30f5..73b855598 100644 --- a/i18n/i18nTextCollector.php +++ b/i18n/i18nTextCollector.php @@ -634,6 +634,13 @@ class i18nTextCollector_Parser extends SSTemplateParser { private static $currentEntity = array(); + public function __construct($string) { + $this->string = $string; + $this->pos = 0; + $this->depth = 0; + $this->regexps = array(); + } + public function Translate__construct(&$res) { self::$currentEntity = array(null,null,null); //start with empty array } diff --git a/view/SSTemplateParser.php b/view/SSTemplateParser.php index f516aa6b0..f08bd945b 100644 --- a/view/SSTemplateParser.php +++ b/view/SSTemplateParser.php @@ -65,14 +65,20 @@ class SSTemplateParseException extends Exception { * Angle Bracket: angle brackets "<" and ">" are used to eat whitespace between template elements * N: eats white space including newlines (using in legacy _t support) */ -class SSTemplateParser extends Parser { +class SSTemplateParser extends Parser implements TemplateParser { /** * @var bool - Set true by SSTemplateParser::compileString if the template should include comments intended * for debugging (template source, included files, etc) */ protected $includeDebuggingComments = false; - + + /** + * Override the Parser constructor to change the requirement of setting a string + */ + function __construct() { + } + /** * Override the function that constructs the result arrays to also prepare a 'php' item in the array */ @@ -1757,7 +1763,7 @@ class SSTemplateParser extends Parser { /* CacheBlockArgument: !( "if " | "unless " ) ( - :DollarMarkedLookup | + :DollarMarkedLookup | :QuotedString | :Lookup ) */ @@ -4548,7 +4554,8 @@ class SSTemplateParser extends Parser { // non-dynamically calculated $text = preg_replace( '/href\s*\=\s*\"\#/', - 'href="\' . (Config::inst()->get(\'SSViewer\', \'rewrite_hash_links\') ? strip_tags( $_SERVER[\'REQUEST_URI\'] ) : "") . + 'href="\' . (Config::inst()->get(\'SSViewer\', \'rewrite_hash_links\') ?' . + ' strip_tags( $_SERVER[\'REQUEST_URI\'] ) : "") . \'#', $text ); @@ -4563,29 +4570,28 @@ class SSTemplateParser extends Parser { /** * Compiles some passed template source code into the php code that will execute as per the template source. * - * @static * @throws SSTemplateParseException * @param $string The source of the template * @param string $templateName The name of the template, normally the filename the template source was loaded from * @param bool $includeDebuggingComments True is debugging comments should be included in the output * @return mixed|string The php that, when executed (via include or exec) will behave as per the template source */ - static function compileString($string, $templateName = "", $includeDebuggingComments=false) { + public function compileString($string, $templateName = "", $includeDebuggingComments=false) { if (!trim($string)) { $code = ''; } else { - // Construct a parser instance - $parser = new SSTemplateParser($string); - $parser->includeDebuggingComments = $includeDebuggingComments; + parent::__construct($string); + + $this->includeDebuggingComments = $includeDebuggingComments; // Ignore UTF8 BOM at begining of string. TODO: Confirm this is needed, make sure SSViewer handles UTF // (and other encodings) properly - if(substr($string, 0,3) == pack("CCC", 0xef, 0xbb, 0xbf)) $parser->pos = 3; + if(substr($string, 0,3) == pack("CCC", 0xef, 0xbb, 0xbf)) $this->pos = 3; // Match the source against the parser - $result = $parser->match_TopTemplate(); - if(!$result) throw new SSTemplateParseException('Unexpected problem parsing template', $parser); + $result = $this->match_TopTemplate(); + if(!$result) throw new SSTemplateParseException('Unexpected problem parsing template', $this); // Get the result $code = $result['php']; @@ -4593,7 +4599,7 @@ class SSTemplateParser extends Parser { // Include top level debugging comments if desired if($includeDebuggingComments && $templateName && stripos($code, "includeDebuggingComments($code, $templateName); + $code = $this->includeDebuggingComments($code, $templateName); } return $code; @@ -4640,7 +4646,7 @@ class SSTemplateParser extends Parser { * @param $template - A file path that contains template source code * @return mixed|string - The php that, when executed (via include or exec) will behave as per the template source */ - static function compileFile($template) { - return self::compileString(file_get_contents($template), $template); + public function compileFile($template) { + return $this->compileString(file_get_contents($template), $template); } } diff --git a/view/SSTemplateParser.php.inc b/view/SSTemplateParser.php.inc index e90860953..4a6c2e30f 100644 --- a/view/SSTemplateParser.php.inc +++ b/view/SSTemplateParser.php.inc @@ -86,14 +86,20 @@ class SSTemplateParseException extends Exception { * Angle Bracket: angle brackets "<" and ">" are used to eat whitespace between template elements * N: eats white space including newlines (using in legacy _t support) */ -class SSTemplateParser extends Parser { +class SSTemplateParser extends Parser implements TemplateParser { /** * @var bool - Set true by SSTemplateParser::compileString if the template should include comments intended * for debugging (template source, included files, etc) */ protected $includeDebuggingComments = false; - + + /** + * Override the Parser constructor to change the requirement of setting a string + */ + function __construct() { + } + /** * Override the function that constructs the result arrays to also prepare a 'php' item in the array */ @@ -462,7 +468,7 @@ class SSTemplateParser extends Parser { CacheBlockArgument: !( "if " | "unless " ) ( - :DollarMarkedLookup | + :DollarMarkedLookup | :QuotedString | :Lookup ) @@ -1018,29 +1024,28 @@ class SSTemplateParser extends Parser { /** * Compiles some passed template source code into the php code that will execute as per the template source. * - * @static * @throws SSTemplateParseException * @param $string The source of the template * @param string $templateName The name of the template, normally the filename the template source was loaded from * @param bool $includeDebuggingComments True is debugging comments should be included in the output * @return mixed|string The php that, when executed (via include or exec) will behave as per the template source */ - static function compileString($string, $templateName = "", $includeDebuggingComments=false) { + public function compileString($string, $templateName = "", $includeDebuggingComments=false) { if (!trim($string)) { $code = ''; } else { - // Construct a parser instance - $parser = new SSTemplateParser($string); - $parser->includeDebuggingComments = $includeDebuggingComments; + parent::__construct($string); + + $this->includeDebuggingComments = $includeDebuggingComments; // Ignore UTF8 BOM at begining of string. TODO: Confirm this is needed, make sure SSViewer handles UTF // (and other encodings) properly - if(substr($string, 0,3) == pack("CCC", 0xef, 0xbb, 0xbf)) $parser->pos = 3; + if(substr($string, 0,3) == pack("CCC", 0xef, 0xbb, 0xbf)) $this->pos = 3; // Match the source against the parser - $result = $parser->match_TopTemplate(); - if(!$result) throw new SSTemplateParseException('Unexpected problem parsing template', $parser); + $result = $this->match_TopTemplate(); + if(!$result) throw new SSTemplateParseException('Unexpected problem parsing template', $this); // Get the result $code = $result['php']; @@ -1048,7 +1053,7 @@ class SSTemplateParser extends Parser { // Include top level debugging comments if desired if($includeDebuggingComments && $templateName && stripos($code, "includeDebuggingComments($code, $templateName); + $code = $this->includeDebuggingComments($code, $templateName); } return $code; @@ -1095,7 +1100,7 @@ class SSTemplateParser extends Parser { * @param $template - A file path that contains template source code * @return mixed|string - The php that, when executed (via include or exec) will behave as per the template source */ - static function compileFile($template) { - return self::compileString(file_get_contents($template), $template); + public function compileFile($template) { + return $this->compileString(file_get_contents($template), $template); } } diff --git a/view/SSViewer.php b/view/SSViewer.php index 9a21febfe..b94e86382 100644 --- a/view/SSViewer.php +++ b/view/SSViewer.php @@ -614,6 +614,11 @@ class SSViewer { */ protected $includeRequirements = true; + /** + * @var TemplateParser + */ + protected $parser; + /** * Create a template from a string instead of a .ss file * @@ -691,7 +696,9 @@ class SSViewer { * array('MySpecificPage', 'MyPage', 'Page') * */ - public function __construct($templateList) { + public function __construct($templateList, TemplateParser $parser = null) { + $this->setParser($parser ?: Injector::inst()->get('SSTemplateParser')); + // flush template manifest cache if requested if (isset($_GET['flush']) && $_GET['flush'] == 'all') { if(Director::isDev() || Director::is_cli() || Permission::check('ADMIN')) { @@ -728,7 +735,25 @@ class SSViewer { ); } } - + + /** + * Set the template parser that will be used in template generation + * @param \TemplateParser $parser + */ + public function setParser(TemplateParser $parser) + { + $this->parser = $parser; + } + + /** + * Returns the parser that is set for template generation + * @return \TemplateParser + */ + public function getParser() + { + return $this->parser; + } + /** * Returns true if at least one of the listed templates exists. * @@ -970,7 +995,7 @@ class SSViewer { if(!file_exists($cacheFile) || filemtime($cacheFile) < $lastEdited || isset($_GET['flush'])) { $content = file_get_contents($template); - $content = SSViewer::parseTemplateContent($content, $template); + $content = $this->parseTemplateContent($content, $template); $fh = fopen($cacheFile,'w'); fwrite($fh, $content); @@ -983,7 +1008,7 @@ class SSViewer { // through $Content and $Layout placeholders. foreach(array('Content', 'Layout') as $subtemplate) { if(isset($this->chosenTemplates[$subtemplate])) { - $subtemplateViewer = new SSViewer($this->chosenTemplates[$subtemplate]); + $subtemplateViewer = new SSViewer($this->chosenTemplates[$subtemplate], $this->parser); $subtemplateViewer->includeRequirements(false); $subtemplateViewer->setPartialCacheStore($this->getPartialCacheStore()); @@ -1028,10 +1053,10 @@ class SSViewer { return $v->process($data, $arguments, $scope); } - public static function parseTemplateContent($content, $template="") { - return SSTemplateParser::compileString( - $content, - $template, + public function parseTemplateContent($content, $template="") { + return $this->parser->compileString( + $content, + $template, Director::isDev() && Config::inst()->get('SSViewer', 'source_file_comments') ); } @@ -1079,7 +1104,8 @@ class SSViewer { class SSViewer_FromString extends SSViewer { protected $content; - public function __construct($content) { + public function __construct($content, TemplateParser $parser = null) { + $this->setParser($parser ?: Injector::inst()->get('SSTemplateParser')); $this->content = $content; } @@ -1091,7 +1117,7 @@ class SSViewer_FromString extends SSViewer { $arguments = null; } - $template = SSViewer::parseTemplateContent($this->content, "string sha1=".sha1($this->content)); + $template = $this->parseTemplateContent($this->content, "string sha1=".sha1($this->content)); $tmpFile = tempnam(TEMP_FOLDER,""); $fh = fopen($tmpFile, 'w'); diff --git a/view/TemplateParser.php b/view/TemplateParser.php new file mode 100644 index 000000000..a256ef007 --- /dev/null +++ b/view/TemplateParser.php @@ -0,0 +1,19 @@ +