CHtmlRender
in package
A powerful and robust template parser for rendering HTML from templates with custom tag syntax.
This implementation uses a DOM-based approach, ensuring compatibility with JavaScript components. It pre-processes complex tags ([switch], [else], etc.) into simpler [if] statements before parsing the main structure, combining syntactic convenience with robust DOM-based rendering.
IMPORTANT: This version implements AUTOMATIC TRANSLATION as per the manual specification:
- All literal strings {{ 'text' }} are automatically translated with _T()
- All variables {{ user::name }} are automatically translated with _T()
- Special attributes {{locals::component_id}} are NOT translated (unless | T modifier)
- Use | raw modifier to disable both translation and escaping
Table of Contents
Constants
- RAW_TOKEN_PREFIX = 'DAPI_RAW_'
- REGEX_PLACEHOLDER = '/\{\{(.*?)\}\}/s'
- TAG_PREFIX = 'dressapi'
Properties
- $data_context : array<string|int, mixed>
- $debugger : Closure|null
- $include_resolver : Closure|null
- $logger : ILogger|null
- $modifiers : array<string, callable>
- $raw_counter : int
- $raw_placeholders : array<string, string>
- $translator : Closure|null
Methods
- __construct() : mixed
- CHtmlRender constructor.
- RegisterModifier() : void
- Registers a new variable modifier (filter) usable in placeholders.
- Render() : string
- The main method to render a template component.
- SetIncludeResolver() : void
- Sets the function that the parser will use to resolve file paths specified in [include] tags.
- Test() : array<string, string>
- Runs tests for all features described in the user manual.
- ConvertBracketsToTags() : string
- Converts bracket-based custom tags (e.g., [if], [foreach]) into XML-style tags.
- EvaluateCondition() : bool
- Evaluates a condition string from an [if] or [case] tag.
- GetVariableValue() : mixed
- Retrieves a value from the context using a '::' separated path.
- HandleElement() : string
- Handles the processing of a single DOMElement.
- HandleElementInPlace() : void
- Handles the processing of a single DOMElement by mutating the DOM in-place.
- HandleEmptyNode() : string
- Handles a custom <dressapi-empty> node.
- HandleEmptyNodeInPlace() : void
- Handles a custom <dressapi-empty> node by mutating the DOM in-place.
- HandleForeachNode() : string
- Handles a custom <dressapi-foreach> node.
- HandleForeachNodeInPlace() : void
- Handles a custom <dressapi-foreach> node by mutating the DOM in-place.
- HandleIfexistsNode() : string
- Handles a custom <dressapi-if-exists> node.
- HandleIfexistsNodeInPlace() : void
- Handles a custom <dressapi-if-exists> node by mutating the DOM in-place.
- HandleIfNode() : string
- Handles a custom <dressapi-if> node.
- HandleIfNodeInPlace() : void
- Handles a custom <dressapi-if> node by mutating the DOM in-place.
- HandleIfnotexistsNode() : string
- Handles a custom <dressapi-if-not-exists> node.
- HandleIfnotexistsNodeInPlace() : void
- Handles a custom <dressapi-if-not-exists> node by mutating the DOM in-place.
- HandleMultipleNode() : string
- Handles a custom <dressapi-multiple> node.
- HandleMultipleNodeInPlace() : void
- Handles a custom <dressapi-multiple> node by mutating the DOM in-place.
- HandlePermissionNode() : string
- Handles a custom <dressapi-permission> node.
- HandlePermissionNodeInPlace() : void
- Handles a custom <dressapi-permission> node by mutating the DOM in-place.
- HandleSingleNode() : string
- Handles a custom <dressapi-single> node.
- HandleSingleNodeInPlace() : void
- Handles a custom <dressapi-single> node by mutating the DOM in-place.
- Log() : void
- Logs a message if a logger is available.
- ParseAttributes() : array<string|int, mixed>
- Parses a string of attributes (e.g., 'key="value" foo="bar"') into an associative array.
- ProcessCardinalityTags() : string
- Pre-processes cardinality tags ([single], [multiple], [empty]) to convert to [if-exists] or [if].
- ProcessDressapiAttributes() : void
- Processes the special data-dressapi-* attributes on an HTML element, modifying the element's attributes accordingly.
- ProcessElse() : string
- Pre-processes [if]...[else]...[/if] blocks, converting them into two separate [if] blocks.
- ProcessIncludes() : string
- Pre-processes [include] tags recursively.
- ProcessInlineConditionals() : string
- Pre-processes inline conditionals with shorthand syntax [if-exists(var)] and [if-not-exists(var)].
- ProcessNode() : string
- Recursively processes a DOM node and its children.
- ProcessNodeInPlace() : void
- Recursively processes a DOM node and its children by mutating the DOM in-place.
- ProcessPlaceholders() : string
- Finds and processes all placeholders {{...}} within a string.
- ProcessSwitches() : string
- Pre-processes [switch] blocks, converting them into a series of [if] blocks.
- RegisterDefaultModifiers() : void
- Registers default modifiers for common transformations.
- ReplaceNodeWithHTML() : void
- Replaces a DOM node with HTML content.
- ResolveExpression() : mixed
- Resolves the value of an expression, including variables, defaults, and modifiers.
Constants
RAW_TOKEN_PREFIX
private
mixed
RAW_TOKEN_PREFIX
= 'DAPI_RAW_'
REGEX_PLACEHOLDER
private
mixed
REGEX_PLACEHOLDER
= '/\{\{(.*?)\}\}/s'
TAG_PREFIX
private
mixed
TAG_PREFIX
= 'dressapi'
Properties
$data_context
private
array<string|int, mixed>
$data_context
= []
The main data context for the current rendering process.
$debugger
private
Closure|null
$debugger
An optional function for advanced data printing (debugging).
$include_resolver
private
Closure|null
$include_resolver
A resolver function to find the full path of included files.
$logger
private
ILogger|null
$logger
An optional logger object, e.g., a Monolog implementation.
$modifiers
private
array<string, callable>
$modifiers
= []
A registry for variable modifiers (filters).
$raw_counter
private
int
$raw_counter
= 0
Counter for generating unique raw placeholder tokens.
$raw_placeholders
private
array<string, string>
$raw_placeholders
= []
Storage for raw HTML values that bypass DOM escaping.
When a {{ var | raw }} placeholder is resolved, the HTML value is stored here and replaced with a unique token. After DOM serialization (saveHTML), the tokens are replaced with the actual HTML values.
$translator
private
Closure|null
$translator
An optional function for string translation.
Methods
__construct()
CHtmlRender constructor.
public
__construct([callable|null $translator = null ][, ILogger|null $logger = null ][, callable|null $debugger = null ]) : mixed
Parameters
- $translator : callable|null = null
-
An optional function for string translation.
- $logger : ILogger|null = null
-
An optional logger object like Monolog.
- $debugger : callable|null = null
-
An optional function for debug printing, like the framework's printr().
RegisterModifier()
Registers a new variable modifier (filter) usable in placeholders.
public
RegisterModifier(string $name, callable $callback) : void
Parameters
- $name : string
-
The name of the modifier (e.g., 'upper').
- $callback : callable
-
The function to execute.
Render()
The main method to render a template component.
public
Render(array<string|int, mixed> $data, string $template_string) : string
Parameters
- $data : array<string|int, mixed>
-
The main data context.
- $template_string : string
-
The template string to process.
Return values
string —The final HTML string after rendering.
SetIncludeResolver()
Sets the function that the parser will use to resolve file paths specified in [include] tags.
public
SetIncludeResolver(callable $resolver) : void
Parameters
- $resolver : callable
-
The resolver function.
Test()
Runs tests for all features described in the user manual.
public
Test() : array<string, string>
This method demonstrates at least one example for each functionality, including the AUTOMATIC TRANSLATION behavior as specified in the manual.
Return values
array<string, string> —An array of test results.
ConvertBracketsToTags()
Converts bracket-based custom tags (e.g., [if], [foreach]) into XML-style tags.
private
ConvertBracketsToTags(string $template) : string
Parameters
- $template : string
-
The template string with bracket tags.
Return values
string —The template string with XML-style tags.
EvaluateCondition()
Evaluates a condition string from an [if] or [case] tag.
private
EvaluateCondition(string $condition_string, array<string|int, mixed> $context) : bool
Parameters
- $condition_string : string
-
The condition string (e.g., "user::age > 18").
- $context : array<string|int, mixed>
-
The current data context.
Return values
bool —The result of the evaluation.
GetVariableValue()
Retrieves a value from the context using a '::' separated path.
private
GetVariableValue(string $path, array<string|int, mixed> $context) : mixed
Parameters
- $path : string
-
The variable path (e.g., "user::details::email" or "$attribute").
- $context : array<string|int, mixed>
-
The data context.
Return values
mixed —The found value or null if not found.
HandleElement()
Handles the processing of a single DOMElement.
private
HandleElement(DOMElement $node, array<string|int, mixed> $context) : string
LEGACY METHOD: Kept for backward compatibility with Test() method.
Parameters
- $node : DOMElement
-
The DOM element to handle.
- $context : array<string|int, mixed>
-
The current data context.
Return values
string —The rendered HTML of the element.
HandleElementInPlace()
Handles the processing of a single DOMElement by mutating the DOM in-place.
private
HandleElementInPlace(DOMElement $node, array<string|int, mixed> $context) : void
Parameters
- $node : DOMElement
-
The DOM element to handle.
- $context : array<string|int, mixed>
-
The current data context.
HandleEmptyNode()
Handles a custom <dressapi-empty> node.
private
HandleEmptyNode(DOMElement $node, array<string|int, mixed> $context) : string
Parameters
- $node : DOMElement
-
The node to process.
- $context : array<string|int, mixed>
-
The current data context.
Return values
string —The rendered content if the array is empty.
HandleEmptyNodeInPlace()
Handles a custom <dressapi-empty> node by mutating the DOM in-place.
private
HandleEmptyNodeInPlace(DOMElement $node, array<string|int, mixed> $context) : void
Parameters
- $node : DOMElement
-
The node to process.
- $context : array<string|int, mixed>
-
The current data context.
HandleForeachNode()
Handles a custom <dressapi-foreach> node.
private
HandleForeachNode(DOMElement $node, array<string|int, mixed> $context) : string
Parameters
- $node : DOMElement
-
The node to process.
- $context : array<string|int, mixed>
-
The current data context.
Return values
string —The rendered content for each iteration.
HandleForeachNodeInPlace()
Handles a custom <dressapi-foreach> node by mutating the DOM in-place.
private
HandleForeachNodeInPlace(DOMElement $node, array<string|int, mixed> $context) : void
Parameters
- $node : DOMElement
-
The node to process.
- $context : array<string|int, mixed>
-
The current data context.
HandleIfexistsNode()
Handles a custom <dressapi-if-exists> node.
private
HandleIfexistsNode(DOMElement $node, array<string|int, mixed> $context) : string
Parameters
- $node : DOMElement
-
The node to process.
- $context : array<string|int, mixed>
-
The current data context.
Return values
string —The rendered content if the variable exists.
HandleIfexistsNodeInPlace()
Handles a custom <dressapi-if-exists> node by mutating the DOM in-place.
private
HandleIfexistsNodeInPlace(DOMElement $node, array<string|int, mixed> $context) : void
Supports [else] blocks inside [if-exists]: [if-exists var="x"] content when x exists [else] content when x doesn't exist [/if-exists]
Note: The DOM parser puts content after [else] INSIDE the
Parameters
- $node : DOMElement
-
The node to process.
- $context : array<string|int, mixed>
-
The current data context.
HandleIfNode()
Handles a custom <dressapi-if> node.
private
HandleIfNode(DOMElement $node, array<string|int, mixed> $context) : string
Parameters
- $node : DOMElement
-
The node to process.
- $context : array<string|int, mixed>
-
The current data context.
Return values
string —The rendered content if the condition is true, otherwise empty.
HandleIfNodeInPlace()
Handles a custom <dressapi-if> node by mutating the DOM in-place.
private
HandleIfNodeInPlace(DOMElement $node, array<string|int, mixed> $context) : void
Parameters
- $node : DOMElement
-
The node to process.
- $context : array<string|int, mixed>
-
The current data context.
HandleIfnotexistsNode()
Handles a custom <dressapi-if-not-exists> node.
private
HandleIfnotexistsNode(DOMElement $node, array<string|int, mixed> $context) : string
Parameters
- $node : DOMElement
-
The node to process.
- $context : array<string|int, mixed>
-
The current data context.
Return values
string —The rendered content if the variable does not exist.
HandleIfnotexistsNodeInPlace()
Handles a custom <dressapi-if-not-exists> node by mutating the DOM in-place.
private
HandleIfnotexistsNodeInPlace(DOMElement $node, array<string|int, mixed> $context) : void
Parameters
- $node : DOMElement
-
The node to process.
- $context : array<string|int, mixed>
-
The current data context.
HandleMultipleNode()
Handles a custom <dressapi-multiple> node.
private
HandleMultipleNode(DOMElement $node, array<string|int, mixed> $context) : string
Parameters
- $node : DOMElement
-
The node to process.
- $context : array<string|int, mixed>
-
The current data context.
Return values
string —The rendered content if the array has more than one element.
HandleMultipleNodeInPlace()
Handles a custom <dressapi-multiple> node by mutating the DOM in-place.
private
HandleMultipleNodeInPlace(DOMElement $node, array<string|int, mixed> $context) : void
Parameters
- $node : DOMElement
-
The node to process.
- $context : array<string|int, mixed>
-
The current data context.
HandlePermissionNode()
Handles a custom <dressapi-permission> node.
private
HandlePermissionNode(DOMElement $node, array<string|int, mixed> $context) : string
Checks if the user has the specified permission and renders content accordingly.
Syntax: [permission can_insert]content[/permission]
Converted to:
Parameters
- $node : DOMElement
-
The node to process.
- $context : array<string|int, mixed>
-
The current data context.
Return values
string —The rendered content if permission exists, empty otherwise.
HandlePermissionNodeInPlace()
Handles a custom <dressapi-permission> node by mutating the DOM in-place.
private
HandlePermissionNodeInPlace(DOMElement $node, array<string|int, mixed> $context) : void
Parameters
- $node : DOMElement
-
The node to process.
- $context : array<string|int, mixed>
-
The current data context.
HandleSingleNode()
Handles a custom <dressapi-single> node.
private
HandleSingleNode(DOMElement $node, array<string|int, mixed> $context) : string
Parameters
- $node : DOMElement
-
The node to process.
- $context : array<string|int, mixed>
-
The current data context.
Return values
string —The rendered content if the array has exactly one element.
HandleSingleNodeInPlace()
Handles a custom <dressapi-single> node by mutating the DOM in-place.
private
HandleSingleNodeInPlace(DOMElement $node, array<string|int, mixed> $context) : void
Parameters
- $node : DOMElement
-
The node to process.
- $context : array<string|int, mixed>
-
The current data context.
Log()
Logs a message if a logger is available.
private
Log(string $message, string $level) : void
Parameters
- $message : string
-
The message to log.
- $level : string
-
The log level (DEBUG, WARNING, ERROR).
ParseAttributes()
Parses a string of attributes (e.g., 'key="value" foo="bar"') into an associative array.
private
ParseAttributes(string $attribute_string) : array<string|int, mixed>
Parameters
- $attribute_string : string
-
The string containing attributes.
Return values
array<string|int, mixed> —The parsed attributes.
ProcessCardinalityTags()
Pre-processes cardinality tags ([single], [multiple], [empty]) to convert to [if-exists] or [if].
private
ProcessCardinalityTags(string $template) : string
Parameters
- $template : string
-
The template string.
Return values
string —The template with cardinality tags converted to simpler forms.
ProcessDressapiAttributes()
Processes the special data-dressapi-* attributes on an HTML element, modifying the element's attributes accordingly.
private
ProcessDressapiAttributes(DOMElement $node, array<string|int, mixed> $context) : void
Parameters
- $node : DOMElement
-
The element to process.
- $context : array<string|int, mixed>
-
The current data context.
ProcessElse()
Pre-processes [if]...[else]...[/if] blocks, converting them into two separate [if] blocks.
private
ProcessElse(string $template) : string
Supports both syntaxes: [if condition="..."] and [if(...)]
Parameters
- $template : string
-
The template string.
Return values
string —The template with [else] blocks converted to [if] blocks.
ProcessIncludes()
Pre-processes [include] tags recursively.
private
ProcessIncludes(string $template, array<string|int, mixed> $context) : string
Parameters
- $template : string
-
The template string.
- $context : array<string|int, mixed>
-
The current data context.
Return values
string —The template with includes resolved.
ProcessInlineConditionals()
Pre-processes inline conditionals with shorthand syntax [if-exists(var)] and [if-not-exists(var)].
private
ProcessInlineConditionals(string $template, array<string|int, mixed> $context) : string
These are evaluated as string replacements BEFORE DOM parsing, allowing them to be used inside HTML attribute values where DOM tags would not be valid.
Syntax:
- [if-exists(varname)]content[/if-exists] - shows content if varname exists
- [if-not-exists(varname)]content[/if-not-exists] - shows content if varname doesn't exist
Parameters
- $template : string
-
The template string.
- $context : array<string|int, mixed>
-
The data context for variable lookup.
Return values
string —The template with inline conditionals evaluated.
ProcessNode()
Recursively processes a DOM node and its children.
private
ProcessNode(DOMNode $node, array<string|int, mixed> $context) : string
LEGACY METHOD: Kept for backward compatibility with Test() method.
Parameters
- $node : DOMNode
-
The DOM node to process.
- $context : array<string|int, mixed>
-
The current data context.
Return values
string —The rendered HTML of the node.
ProcessNodeInPlace()
Recursively processes a DOM node and its children by mutating the DOM in-place.
private
ProcessNodeInPlace(DOMNode $node, array<string|int, mixed> $context) : void
This approach preserves all existing content (CSS, JS, comments, etc.).
Parameters
- $node : DOMNode
-
The DOM node to process.
- $context : array<string|int, mixed>
-
The current data context.
ProcessPlaceholders()
Finds and processes all placeholders {{...}} within a string.
private
ProcessPlaceholders(string $text, array<string|int, mixed> $context) : string
Parameters
- $text : string
-
The text containing placeholders.
- $context : array<string|int, mixed>
-
The current data context.
Return values
string —The text with placeholders replaced by their evaluated values.
ProcessSwitches()
Pre-processes [switch] blocks, converting them into a series of [if] blocks.
private
ProcessSwitches(string $template) : string
Parameters
- $template : string
-
The template string.
Return values
string —The template with [switch] blocks converted to [if] blocks.
RegisterDefaultModifiers()
Registers default modifiers for common transformations.
private
RegisterDefaultModifiers() : void
ReplaceNodeWithHTML()
Replaces a DOM node with HTML content.
private
ReplaceNodeWithHTML(DOMElement $node, string $html_content) : void
This helper method is used to replace custom tags with their processed content.
Parameters
- $node : DOMElement
-
The node to replace.
- $html_content : string
-
The HTML content to insert in place of the node.
ResolveExpression()
Resolves the value of an expression, including variables, defaults, and modifiers.
private
ResolveExpression(string $expression, array<string|int, mixed> $context[, bool $escape_output = true ]) : mixed
AUTOMATIC TRANSLATION BEHAVIOR (as per manual):
- Literal strings {{ 'text' }} → _T('text') → htmlentities()
- Variables {{ user::name }} → _T($value) → htmlentities()
- Special attributes {{locals::id}} → $value → htmlentities() (NO translation)
- Default values {{ x ?? 'default' }} → _T('default') → htmlentities()
- Raw modifier {{ x | raw }} → NO translation, NO escaping
- T modifier {{ $id | T }} → force translation
Parameters
- $expression : string
-
The full expression string.
- $context : array<string|int, mixed>
-
The data context to use for resolving variables.
- $escape_output : bool = true
-
Whether to HTML-escape the final output.
Return values
mixed —The resolved value.