SSTemplateParser
class SSTemplateParser extends Parser implements TemplateParser (View source)
This is the parser for the SilverStripe template language. It gets called on a string and uses a php-peg parser to match that string against the language structure, building up the PHP code to execute that structure as it parses
The $result array that is built up as part of the parsing (see thirdparty/php-peg/README.md for more on how parsers build results) has one special member, 'php', which contains the php equivalent of that part of the template tree.
Some match rules generate alternate php, or other variations, so check the per-match documentation too.
Terms used:
Marked: A string or lookup in the template that has been explictly marked as such - lookups by prepending with "$" (like $Foo.Bar), strings by wrapping with single or double quotes ('Foo' or "Foo")
Bare: The opposite of marked. An argument that has to has it's type inferred by usage and 2.4 defaults.
Example of using a bare argument for a loop block: <% loop Foo %>
Block: One of two SS template structures. The special characters "<%" and "%>" are used to wrap the opening and (required or forbidden depending on which block exactly) closing block marks.
Open Block: An SS template block that doesn't wrap any content or have a closing end tag (in fact, a closing end tag is forbidden)
Closed Block: An SS template block that wraps content, and requires a counterpart <% end_blockname %> tag
Angle Bracket: angle brackets "<" and ">" are used to eat whitespace between template elements N: eats white space including newlines (using in legacy _t support)
Methods
Allow the injection of new closed & open block callables
Override the function that constructs the result arrays to also prepare a 'php' item in the array
Set the closed blocks that the template parser should use
Set the open blocks that the template parser should use
Add a closed block callable to allow <% name %><% end_name %> syntax
Add a closed block callable to allow <% name %> syntax
No description
No description
No description
No description
No description
No description
No description
Values are bare words in templates, but strings in PHP. We rely on PHP's type conversion to back-convert strings to numbers when needed.
No description
No description
No description
No description
No description
The basic generated PHP of LookupStep and LastLookupStep is the same, except that LookupStep calls 'obj' to get the next ViewableData in the sequence, and LastLookupStep calls different methods (XML_val, hasValue, obj) depending on the context the lookup is used in.
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
If we get a bare value, we don't know enough to determine exactly what php would be the translation, because we don't know if the position of use indicates a lookup or a string argument.
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
As mentioned in the parser comment, block handling is kept fairly generic for extensibility. The match rule builds up two important elements in the match result array: 'ArgumentCount' - how many arguments were passed in the opening tag 'Arguments' an array of the Argument match rule result arrays
No description
No description
This is an example of a block handler function. This one handles the loop tag.
The closed block handler for with blocks
No description
No description
No description
No description
This is an open block handler, for the <% debug %> utility tag
This is an open block handler, for the <% base_tag %> tag
This is an open block handler, for the <% current_page %> tag
No description
No description
No description
No description
No description
No description
No description
No description
No description
No description
The TopTemplate also includes the opening stanza to start off the template
No description
We convert text
Compiles some passed template source code into the php code that will execute as per the template source.
Compiles some file that contains template source code, and returns the php code that will execute as per that source
Details
__construct(array $closedBlocks = array(), array $openBlocks = array())
Allow the injection of new closed & open block callables
construct($matchrule, $name, $arguments = null)
Override the function that constructs the result arrays to also prepare a 'php' item in the array
setClosedBlocks(array $closedBlocks)
Set the closed blocks that the template parser should use
This method will delete any existing closed blocks, please use addClosedBlock if you don't want to overwrite
setOpenBlocks(array $openBlocks)
Set the open blocks that the template parser should use
This method will delete any existing open blocks, please use addOpenBlock if you don't want to overwrite
addClosedBlock(string $name, callable $callable)
Add a closed block callable to allow <% name %><% end_name %> syntax
addOpenBlock(string $name, callable $callable)
Add a closed block callable to allow <% name %> syntax
match_Template($stack = array())
Template_STR($res, $sub)
match_Word($stack = array())
match_NamespacedWord($stack = array())
match_Number($stack = array())
match_Value($stack = array())
match_CallArguments($stack = array())
CallArguments_Argument($res, $sub)
Values are bare words in templates, but strings in PHP. We rely on PHP's type conversion to back-convert strings to numbers when needed.
match_Call($stack = array())
match_LookupStep($stack = array())
match_LastLookupStep($stack = array())
match_Lookup($stack = array())
Lookup__construct($res)
Lookup_AddLookupStep($res, $sub, $method)
The basic generated PHP of LookupStep and LastLookupStep is the same, except that LookupStep calls 'obj' to get the next ViewableData in the sequence, and LastLookupStep calls different methods (XML_val, hasValue, obj) depending on the context the lookup is used in.
Lookup_LookupStep($res, $sub)
Lookup_LastLookupStep($res, $sub)
match_Translate($stack = array())
match_InjectionVariables($stack = array())
match_Entity($stack = array())
Translate__construct($res)
Translate_Entity($res, $sub)
Translate_Default($res, $sub)
Translate_Context($res, $sub)
Translate_InjectionVariables($res, $sub)
Translate__finalise($res)
InjectionVariables__construct($res)
InjectionVariables_InjectionName($res, $sub)
InjectionVariables_Argument($res, $sub)
InjectionVariables__finalise($res)
match_SimpleInjection($stack = array())
match_BracketInjection($stack = array())
match_Injection($stack = array())
Injection_STR($res, $sub)
match_DollarMarkedLookup($stack = array())
DollarMarkedLookup_STR($res, $sub)
match_QuotedString($stack = array())
match_Null($stack = array())
match_Boolean($stack = array())
match_Sign($stack = array())
match_Float($stack = array())
match_Hexadecimal($stack = array())
match_Octal($stack = array())
match_Binary($stack = array())
match_Decimal($stack = array())
match_IntegerOrFloat($stack = array())
match_FreeString($stack = array())
match_Argument($stack = array())
Argument_DollarMarkedLookup($res, $sub)
If we get a bare value, we don't know enough to determine exactly what php would be the translation, because we don't know if the position of use indicates a lookup or a string argument.
Instead, we record 'ArgumentMode' as a member of this matches results node, which can be:
- lookup if this argument was unambiguously a lookup (marked as such)
- string is this argument was unambiguously a string (marked as such, or impossible to parse as lookup)
- default if this argument needs to be handled as per 2.4
In the case of 'default', there is no php member of the results node, but instead 'lookup_php', which should be used by the parent if the context indicates a lookup, and 'string_php' which should be used if the context indicates a string
Argument_QuotedString($res, $sub)
Argument_Null($res, $sub)
Argument_Boolean($res, $sub)
Argument_IntegerOrFloat($res, $sub)
Argument_Lookup($res, $sub)
Argument_FreeString($res, $sub)
match_ComparisonOperator($stack = array())
match_Comparison($stack = array())
Comparison_Argument($res, $sub)
Comparison_ComparisonOperator($res, $sub)
match_PresenceCheck($stack = array())
PresenceCheck_Not($res, $sub)
PresenceCheck_Argument($res, $sub)
match_IfArgumentPortion($stack = array())
IfArgumentPortion_STR($res, $sub)
match_BooleanOperator($stack = array())
match_IfArgument($stack = array())
IfArgument_IfArgumentPortion($res, $sub)
IfArgument_BooleanOperator($res, $sub)
match_IfPart($stack = array())
match_ElseIfPart($stack = array())
match_ElsePart($stack = array())
match_If($stack = array())
If_IfPart($res, $sub)
If_ElseIfPart($res, $sub)
If_ElsePart($res, $sub)
match_Require($stack = array())
Require_Call($res, $sub)
match_CacheBlockArgument($stack = array())
CacheBlockArgument_DollarMarkedLookup($res, $sub)
CacheBlockArgument_QuotedString($res, $sub)
CacheBlockArgument_Lookup($res, $sub)
match_CacheBlockArguments($stack = array())
CacheBlockArguments_CacheBlockArgument($res, $sub)
match_CacheBlockTemplate($stack = array())
match_UncachedBlock($stack = array())
UncachedBlock_Template($res, $sub)
match_CacheRestrictedTemplate($stack = array())
CacheRestrictedTemplate_CacheBlock($res, $sub)
CacheRestrictedTemplate_UncachedBlock($res, $sub)
match_CacheBlock($stack = array())
CacheBlock__construct($res)
CacheBlock_CacheBlockArguments($res, $sub)
CacheBlock_Condition($res, $sub)
CacheBlock_CacheBlock($res, $sub)
CacheBlock_UncachedBlock($res, $sub)
CacheBlock_CacheBlockTemplate($res, $sub)
match_OldTPart($stack = array())
match_N($stack = array())
OldTPart__construct($res)
OldTPart_QuotedString($res, $sub)
OldTPart_CallArguments($res, $sub)
OldTPart__finalise($res)
match_OldTTag($stack = array())
OldTTag_OldTPart($res, $sub)
match_OldSprintfTag($stack = array())
OldSprintfTag__construct($res)
OldSprintfTag_OldTPart($res, $sub)
OldSprintfTag_CallArguments($res, $sub)
match_OldI18NTag($stack = array())
OldI18NTag_STR($res, $sub)
match_NamedArgument($stack = array())
NamedArgument_Name($res, $sub)
NamedArgument_Value($res, $sub)
match_Include($stack = array())
Include__construct($res)
Include_Template($res, $sub)
Include_NamedArgument($res, $sub)
Include__finalise($res)
match_BlockArguments($stack = array())
match_NotBlockTag($stack = array())
match_ClosedBlock($stack = array())
ClosedBlock__construct($res)
As mentioned in the parser comment, block handling is kept fairly generic for extensibility. The match rule builds up two important elements in the match result array: 'ArgumentCount' - how many arguments were passed in the opening tag 'Arguments' an array of the Argument match rule result arrays
Once a block has successfully been matched against, it will then look for the actual handler, which should be on this class (either defined or extended on) as ClosedBlock_Handler_Name(&$res), where Name is the tag name, first letter captialized (i.e Control, Loop, With, etc).
This function will be called with the match rule result array as it's first argument. It should return the php result of this block as it's return value, or throw an error if incorrect arguments were passed.
ClosedBlock_BlockArguments($res, $sub)
ClosedBlock__finalise($res)
ClosedBlock_Handle_Loop($res)
This is an example of a block handler function. This one handles the loop tag.
ClosedBlock_Handle_With($res)
The closed block handler for with blocks
match_OpenBlock($stack = array())
OpenBlock__construct($res)
OpenBlock_BlockArguments($res, $sub)
OpenBlock__finalise($res)
OpenBlock_Handle_Debug($res)
This is an open block handler, for the <% debug %> utility tag
OpenBlock_Handle_Base_tag($res)
This is an open block handler, for the <% base_tag %> tag
OpenBlock_Handle_Current_page($res)
This is an open block handler, for the <% current_page %> tag
match_MismatchedEndBlock($stack = array())
MismatchedEndBlock__finalise($res)
match_MalformedOpenTag($stack = array())
MalformedOpenTag__finalise($res)
match_MalformedCloseTag($stack = array())
MalformedCloseTag__finalise($res)
match_MalformedBlock($stack = array())
match_Comment($stack = array())
Comment__construct($res)
match_TopTemplate($stack = array())
TopTemplate__construct($res)
The TopTemplate also includes the opening stanza to start off the template
match_Text($stack = array())
Text__finalise($res)
We convert text
string
compileString(string $string, string $templateName = "", bool $includeDebuggingComments = false, bool $topTemplate = true)
Compiles some passed template source code into the php code that will execute as per the template source.
static mixed|string
compileFile($template)
Compiles some file that contains template source code, and returns the php code that will execute as per that source