diff --git a/tests/templates/SSViewerTestIncludeObjectArguments.ss b/tests/templates/SSViewerTestIncludeObjectArguments.ss new file mode 100644 index 000000000..269d0d145 --- /dev/null +++ b/tests/templates/SSViewerTestIncludeObjectArguments.ss @@ -0,0 +1 @@ +$A.Key $B.Key diff --git a/tests/view/SSViewerTest.php b/tests/view/SSViewerTest.php index 45319cb35..f816ba1dd 100644 --- a/tests/view/SSViewerTest.php +++ b/tests/view/SSViewerTest.php @@ -508,6 +508,17 @@ after') new ArrayData(array('Arg1' => 'Foo', 'Arg2' => 'Bar'))), '

A

Bar

' ); + + $data = new ArrayData(array( + 'Nested' => new ArrayData(array( + 'Object' => new ArrayData(array('Key' => 'A')) + )), + 'Object' => new ArrayData(array('Key' => 'B')) + )); + + $tmpl = SSViewer::fromString('<% include SSViewerTestIncludeObjectArguments A=$Nested.Object, B=$Object %>'); + $res = $tmpl->process($data); + $this->assertEqualIgnoringWhitespace('A B', $res, 'Objects can be passed as named arguments'); } diff --git a/view/SSTemplateParser.php b/view/SSTemplateParser.php index 5cd895538..08c319a08 100644 --- a/view/SSTemplateParser.php +++ b/view/SSTemplateParser.php @@ -646,7 +646,8 @@ class SSTemplateParser extends Parser { } - /* Translate: "<%t" < Entity < (Default:QuotedString)? < (!("is" "=") < "is" < Context:QuotedString)? < (InjectionVariables)? > "%>" */ + /* Translate: "<%t" < Entity < (Default:QuotedString)? < (!("is" "=") < "is" < Context:QuotedString)? < + (InjectionVariables)? > "%>" */ protected $match_Translate_typestack = array('Translate'); function match_Translate ($stack = array()) { $matchrule = "Translate"; $result = $this->construct($matchrule, $matchrule, null); @@ -1671,7 +1672,7 @@ class SSTemplateParser extends Parser { function Require_Call(&$res, $sub) { $res['php'] = "Requirements::".$sub['Method']['text'].'('.$sub['CallArguments']['php'].');'; } - + /* CacheBlockArgument: !( "if " | "unless " ) @@ -2914,7 +2915,7 @@ class SSTemplateParser extends Parser { function OldTTag_OldTPart(&$res, $sub) { $res['php'] = $sub['php']; } - + /* OldSprintfTag: "<%" < "sprintf" < "(" < OldTPart < "," < CallArguments > ")" > "%>" */ protected $match_OldSprintfTag_typestack = array('OldSprintfTag'); function match_OldSprintfTag ($stack = array()) { @@ -3052,8 +3053,19 @@ class SSTemplateParser extends Parser { } function NamedArgument_Value(&$res, $sub) { - $res['php'] .= ($sub['ArgumentMode'] == 'default') ? $sub['string_php'] - : str_replace('$$FINAL', 'XML_val', $sub['php']); + switch($sub['ArgumentMode']) { + case 'string': + $res['php'] .= $sub['php']; + break; + + case 'default': + $res['php'] .= $sub['string_php']; + break; + + default: + $res['php'] .= str_replace('$$FINAL', 'obj', $sub['php']) . '->self()'; + break; + } } /* Include: "<%" < "include" < Template:Word < (NamedArgument ( < "," < NamedArgument )*)? > "%>" */ @@ -3642,7 +3654,8 @@ class SSTemplateParser extends Parser { $method = 'OpenBlock_Handle_'.$blockname; if (method_exists($this, $method)) $res['php'] = $this->$method($res); else { - throw new SSTemplateParseException('Unknown open block "'.$blockname.'" encountered. Perhaps you missed the closing tag or have mis-spelled it?', $this); + throw new SSTemplateParseException('Unknown open block "'.$blockname.'" encountered. Perhaps you missed ' . + ' the closing tag or have mis-spelled it?', $this); } } @@ -3711,7 +3724,8 @@ class SSTemplateParser extends Parser { function MismatchedEndBlock__finalise(&$res) { $blockname = $res['Word']['text']; - throw new SSTemplateParseException('Unexpected close tag end_'.$blockname.' encountered. Perhaps you have mis-nested blocks, or have mis-spelled a tag?', $this); + throw new SSTemplateParseException('Unexpected close tag end_' . $blockname . + ' encountered. Perhaps you have mis-nested blocks, or have mis-spelled a tag?', $this); } /* MalformedOpenTag: '<%' < !NotBlockTag Tag:Word !( ( [ :BlockArguments ] )? > '%>' ) */ @@ -3796,7 +3810,8 @@ class SSTemplateParser extends Parser { function MalformedOpenTag__finalise(&$res) { $tag = $res['Tag']['text']; - throw new SSTemplateParseException("Malformed opening block tag $tag. Perhaps you have tried to use operators?", $this); + throw new SSTemplateParseException("Malformed opening block tag $tag. Perhaps you have tried to use operators?" + , $this); } /* MalformedCloseTag: '<%' < Tag:('end_' :Word ) !( > '%>' ) */ @@ -3860,7 +3875,8 @@ class SSTemplateParser extends Parser { function MalformedCloseTag__finalise(&$res) { $tag = $res['Tag']['text']; - throw new SSTemplateParseException("Malformed closing block tag $tag. Perhaps you have tried to pass an argument to one?", $this); + throw new SSTemplateParseException("Malformed closing block tag $tag. Perhaps you have tried to pass an " . + "argument to one?", $this); } /* MalformedBlock: MalformedOpenTag | MalformedCloseTag */ @@ -4448,10 +4464,12 @@ class SSTemplateParser extends Parser { $text = stripslashes($text); $text = addcslashes($text, '\'\\'); - // TODO: This is pretty ugly & gets applied on all files not just html. I wonder if we can make this non-dynamically calculated + // TODO: This is pretty ugly & gets applied on all files not just html. I wonder if we can make this + // non-dynamically calculated $text = preg_replace( '/href\s*\=\s*\"\#/', - 'href="\' . (SSViewer::$options[\'rewriteHashlinks\'] ? strip_tags( $_SERVER[\'REQUEST_URI\'] ) : "") . \'#', + 'href="\' . (SSViewer::$options[\'rewriteHashlinks\'] ? strip_tags( $_SERVER[\'REQUEST_URI\'] ) : "") . + \'#', $text ); @@ -4467,10 +4485,10 @@ class SSTemplateParser extends Parser { * * @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 + * @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) { if (!trim($string)) { @@ -4481,7 +4499,8 @@ class SSTemplateParser extends Parser { $parser = new SSTemplateParser($string); $parser->includeDebuggingComments = $includeDebuggingComments; - // Ignore UTF8 BOM at begining of string. TODO: Confirm this is needed, make sure SSViewer handles UTF (and other encodings) properly + // 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; // Match the source against the parser @@ -4494,12 +4513,14 @@ class SSTemplateParser extends Parser { // Include top level debugging comments if desired if($includeDebuggingComments && $templateName && stripos($code, "]*>)/i', "\\1", $code); $code = preg_replace('/(<\/html[^>]*>)/i', "\\1", $code); } else { - $code = str_replace('\';' . "\n", $code); + $code = str_replace('\';' . "\n", $code); $code .= "\n" . '$val .= \'\';'; } } diff --git a/view/SSTemplateParser.php.inc b/view/SSTemplateParser.php.inc index 7652ed105..45a4650b4 100644 --- a/view/SSTemplateParser.php.inc +++ b/view/SSTemplateParser.php.inc @@ -662,8 +662,19 @@ class SSTemplateParser extends Parser { } function NamedArgument_Value(&$res, $sub) { - $res['php'] .= ($sub['ArgumentMode'] == 'default') ? $sub['string_php'] - : str_replace('$$FINAL', 'XML_val', $sub['php']); + switch($sub['ArgumentMode']) { + case 'string': + $res['php'] .= $sub['php']; + break; + + case 'default': + $res['php'] .= $sub['string_php']; + break; + + default: + $res['php'] .= str_replace('$$FINAL', 'obj', $sub['php']) . '->self()'; + break; + } } /*!* diff --git a/view/SSViewer.php b/view/SSViewer.php index 5c1317d55..cac477c55 100644 --- a/view/SSViewer.php +++ b/view/SSViewer.php @@ -96,7 +96,19 @@ class SSViewer_Scope { $this->upIndex, $this->currentIndex); return $this; } - + + /** + * Gets the current object and resets the scope. + * + * @return object + */ + public function self() { + $result = $this->itemIterator ? $this->itemIterator->current() : $this->item; + $this->resetLocalScope(); + + return $result; + } + public function pushScope(){ $newLocalIndex = count($this->itemStack)-1;