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 explicitly 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)
Properties
protected | bool | $includeDebuggingComments | ||
protected | array | $closedBlocks | Stores the user-supplied closed block extension rules in the form: [ 'name' => function (&$res) {} ] See SSTemplateParser::ClosedBlock_Handle_Loop for an example of what the callable should look like |
|
protected | array | $openBlocks | Stores the user-supplied open block extension rules in the form: [ 'name' => function (&$res) {} ] See SSTemplateParser::OpenBlock_Handle_Base_tag for an example of what the callable should look like |
|
protected | $match_Template_typestack | |||
protected | $match_Word_typestack | |||
protected | $match_NamespacedWord_typestack | |||
protected | $match_Number_typestack | |||
protected | $match_Value_typestack | |||
protected | $match_CallArguments_typestack | |||
protected | $match_Call_typestack | |||
protected | $match_LookupStep_typestack | |||
protected | $match_LastLookupStep_typestack | |||
protected | $match_Lookup_typestack | |||
protected | $match_Translate_typestack | |||
protected | $match_InjectionVariables_typestack | |||
protected | $match_Entity_typestack | |||
protected | $match_MalformedBracketInjection_typestack | |||
protected | $match_SimpleInjection_typestack | |||
protected | $match_BracketInjection_typestack | |||
protected | $match_Injection_typestack | |||
protected | $match_DollarMarkedLookup_typestack | |||
protected | $match_QuotedString_typestack | |||
protected | $match_FreeString_typestack | |||
protected | $match_Argument_typestack | |||
protected | $match_ComparisonOperator_typestack | |||
protected | $match_Comparison_typestack | |||
protected | $match_PresenceCheck_typestack | |||
protected | $match_IfArgumentPortion_typestack | |||
protected | $match_BooleanOperator_typestack | |||
protected | $match_IfArgument_typestack | |||
protected | $match_IfPart_typestack | |||
protected | $match_ElseIfPart_typestack | |||
protected | $match_ElsePart_typestack | |||
protected | $match_If_typestack | |||
protected | $match_Require_typestack | |||
protected | $match_CacheBlockArgument_typestack | |||
protected | $match_CacheBlockArguments_typestack | |||
protected | $match_CacheBlockTemplate_typestack | |||
protected | $match_UncachedBlock_typestack | |||
protected | $match_CacheRestrictedTemplate_typestack | |||
protected | $match_CacheBlock_typestack | |||
protected | $match_OldTPart_typestack | |||
protected | $match_N_typestack | |||
protected | $match_OldTTag_typestack | |||
protected | $match_OldSprintfTag_typestack | |||
protected | $match_OldI18NTag_typestack | |||
protected | $match_NamedArgument_typestack | |||
protected | $match_Include_typestack | |||
protected | $match_BlockArguments_typestack | |||
protected | $match_NotBlockTag_typestack | |||
protected | $match_ClosedBlock_typestack | |||
protected | $match_OpenBlock_typestack | |||
protected | $match_MismatchedEndBlock_typestack | |||
protected | $match_MalformedOpenTag_typestack | |||
protected | $match_MalformedCloseTag_typestack | |||
protected | $match_MalformedBlock_typestack | |||
protected | $match_CommentWithContent_typestack | |||
protected | $match_EmptyComment_typestack | |||
protected | $match_Comment_typestack | |||
protected | $match_TopTemplate_typestack | |||
protected | $match_Text_typestack |
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
Add a closed block callable to allow <% name %><% end_name %> syntax
Add a closed block callable to allow <% name %> syntax
Ensures that the arguments to addOpenBlock and addClosedBlock are valid
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.
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.
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.
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
This is an example of a block handler function. This one handles the loop tag.
This is an open block handler, for the <% current_page %> tag
The TopTemplate also includes the opening stanza to start off the template
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 $openBlocks = [])
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
protected
validateExtensionBlock($name, $callable, $type)
Ensures that the arguments to addOpenBlock and addClosedBlock are valid
match_Template($stack = array())
No description
Template_STR($res, $sub)
No description
match_Word($stack = array())
No description
match_NamespacedWord($stack = array())
No description
match_Number($stack = array())
No description
match_Value($stack = array())
No description
match_CallArguments($stack = array())
No description
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())
No description
match_LookupStep($stack = array())
No description
match_LastLookupStep($stack = array())
No description
match_Lookup($stack = array())
No description
Lookup__construct($res)
No description
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)
No description
Lookup_LastLookupStep($res, $sub)
No description
match_Translate($stack = array())
No description
match_InjectionVariables($stack = array())
No description
match_Entity($stack = array())
No description
Translate__construct($res)
No description
Translate_Entity($res, $sub)
No description
Translate_Default($res, $sub)
No description
Translate_Context($res, $sub)
No description
Translate_InjectionVariables($res, $sub)
No description
Translate__finalise($res)
No description
InjectionVariables__construct($res)
No description
InjectionVariables_InjectionName($res, $sub)
No description
InjectionVariables_Argument($res, $sub)
No description
InjectionVariables__finalise($res)
No description
match_MalformedBracketInjection($stack = array())
No description
MalformedBracketInjection__finalise($res)
No description
match_SimpleInjection($stack = array())
No description
match_BracketInjection($stack = array())
No description
match_Injection($stack = array())
No description
Injection_STR($res, $sub)
No description
match_DollarMarkedLookup($stack = array())
No description
DollarMarkedLookup_STR($res, $sub)
No description
match_QuotedString($stack = array())
No description
match_FreeString($stack = array())
No description
match_Argument($stack = array())
No description
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)
No description
Argument_Lookup($res, $sub)
No description
Argument_FreeString($res, $sub)
No description
match_ComparisonOperator($stack = array())
No description
match_Comparison($stack = array())
No description
Comparison_Argument($res, $sub)
No description
Comparison_ComparisonOperator($res, $sub)
No description
match_PresenceCheck($stack = array())
No description
PresenceCheck_Not($res, $sub)
No description
PresenceCheck_Argument($res, $sub)
No description
match_IfArgumentPortion($stack = array())
No description
IfArgumentPortion_STR($res, $sub)
No description
match_BooleanOperator($stack = array())
No description
match_IfArgument($stack = array())
No description
IfArgument_IfArgumentPortion($res, $sub)
No description
IfArgument_BooleanOperator($res, $sub)
No description
match_IfPart($stack = array())
No description
match_ElseIfPart($stack = array())
No description
match_ElsePart($stack = array())
No description
match_If($stack = array())
No description
If_IfPart($res, $sub)
No description
If_ElseIfPart($res, $sub)
No description
If_ElsePart($res, $sub)
No description
match_Require($stack = array())
No description
Require_Call($res, $sub)
No description
match_CacheBlockArgument($stack = array())
No description
CacheBlockArgument_DollarMarkedLookup($res, $sub)
No description
CacheBlockArgument_QuotedString($res, $sub)
No description
CacheBlockArgument_Lookup($res, $sub)
No description
match_CacheBlockArguments($stack = array())
No description
CacheBlockArguments_CacheBlockArgument($res, $sub)
No description
match_CacheBlockTemplate($stack = array())
No description
match_UncachedBlock($stack = array())
No description
UncachedBlock_Template($res, $sub)
No description
match_CacheRestrictedTemplate($stack = array())
No description
CacheRestrictedTemplate_CacheBlock($res, $sub)
No description
CacheRestrictedTemplate_UncachedBlock($res, $sub)
No description
match_CacheBlock($stack = array())
No description
CacheBlock__construct($res)
No description
CacheBlock_CacheBlockArguments($res, $sub)
No description
CacheBlock_Condition($res, $sub)
No description
CacheBlock_CacheBlock($res, $sub)
No description
CacheBlock_UncachedBlock($res, $sub)
No description
CacheBlock_CacheBlockTemplate($res, $sub)
No description
match_OldTPart($stack = array())
No description
match_N($stack = array())
No description
OldTPart__construct($res)
No description
OldTPart_QuotedString($res, $sub)
No description
OldTPart_CallArguments($res, $sub)
No description
OldTPart__finalise($res)
No description
match_OldTTag($stack = array())
No description
OldTTag_OldTPart($res, $sub)
No description
match_OldSprintfTag($stack = array())
No description
OldSprintfTag__construct($res)
No description
OldSprintfTag_OldTPart($res, $sub)
No description
OldSprintfTag_CallArguments($res, $sub)
No description
match_OldI18NTag($stack = array())
No description
OldI18NTag_STR($res, $sub)
No description
match_NamedArgument($stack = array())
No description
NamedArgument_Name($res, $sub)
No description
NamedArgument_Value($res, $sub)
No description
match_Include($stack = array())
No description
Include__construct($res)
No description
Include_Template($res, $sub)
No description
Include_NamedArgument($res, $sub)
No description
Include__finalise($res)
No description
match_BlockArguments($stack = array())
No description
match_NotBlockTag($stack = array())
No description
match_ClosedBlock($stack = array())
No description
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)
No description
ClosedBlock__finalise($res)
No description
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())
No description
OpenBlock__construct($res)
No description
OpenBlock_BlockArguments($res, $sub)
No description
OpenBlock__finalise($res)
No description
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())
No description
MismatchedEndBlock__finalise($res)
No description
match_MalformedOpenTag($stack = array())
No description
MalformedOpenTag__finalise($res)
No description
match_MalformedCloseTag($stack = array())
No description
MalformedCloseTag__finalise($res)
No description
match_MalformedBlock($stack = array())
No description
match_CommentWithContent($stack = array())
No description
match_EmptyComment($stack = array())
No description
match_Comment($stack = array())
No description
Comment__construct($res)
No description
match_TopTemplate($stack = array())
No description
TopTemplate__construct($res)
The TopTemplate also includes the opening stanza to start off the template
match_Text($stack = array())
No description
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.
protected string
includeDebuggingComments(string $code, string $templateName)
No description
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