partial}} * - Simple string-based rendering (no external dependencies) */ class SimpleTemplate { private $data; /** * Render template with data * * @param string $template Template content with placeholders * @param array $data Data to populate template * @return string Rendered template */ public static function render($template, $data) { $instance = new self(); $instance->data = $data; return $instance->renderTemplate($template); } /** * Process template and replace placeholders * * @param string $template Template content * @return string Processed template */ private function renderTemplate($template) { // Handle partial includes first ({{>partial}}) $template = preg_replace_callback('/{{>([^}]+)}}/', [$this, 'replacePartial'], $template); // Handle equal conditionals first $template = preg_replace_callback('/{{#equal\s+(\w+)\s+["\']([^"\']+)["\']}}(.*?){{\/equal}}/s', function($matches) { $key = $matches[1]; $expectedValue = $matches[2]; $content = $matches[3]; $actualValue = $this->data[$key] ?? ''; return ($actualValue === $expectedValue) ? $content : ''; }, $template); // Handle conditional blocks foreach ($this->data as $key => $value) { if (is_array($value)) { // Handle {{#key}}...{{/key}} blocks for arrays (iteration) $pattern = '/{{#' . preg_quote($key, '/') . '}}(.*?){{\/' . preg_quote($key, '/') . '}}/s'; if (preg_match($pattern, $template, $matches)) { $blockTemplate = $matches[1]; $replacement = ''; foreach ($value as $item) { if (is_array($item)) { // Create a temporary template instance for nested data $tempTemplate = new self(); $tempTemplate->data = $item; $replacement .= $tempTemplate->renderTemplate($blockTemplate); } else { // Simple array, replace {{.}} with the item value $itemBlock = str_replace('{{.}}', htmlspecialchars($item, ENT_QUOTES, 'UTF-8'), $blockTemplate); $replacement .= $itemBlock; } } $template = preg_replace($pattern, $replacement, $template); } // Handle {{^key}}...{{/key}} blocks (negative condition for empty arrays) $pattern = '/{{\^' . preg_quote($key, '/') . '}}(.*?){{\/' . preg_quote($key, '/') . '}}/s'; if (empty($value)) { // Show the content if array is empty if (preg_match($pattern, $template, $matches)) { $template = preg_replace($pattern, $matches[1], $template); } } else { // Remove the content if array is not empty $template = preg_replace($pattern, '', $template); } } elseif ((is_string($value) && !empty($value)) || (is_bool($value) && $value === true)) { // Handle {{#key}}...{{/key}} blocks for truthy values $pattern = '/{{#' . preg_quote($key, '/') . '}}(.*?){{\/' . preg_quote($key, '/') . '}}/s'; if (preg_match($pattern, $template, $matches)) { $replacement = $matches[1]; $template = preg_replace($pattern, $replacement, $template); } // Handle {{^key}}...{{/key}} blocks (negative condition) $pattern = '/{{\^' . preg_quote($key, '/') . '}}(.*?){{\/' . preg_quote($key, '/') . '}}/s'; $template = preg_replace($pattern, '', $template); } else { // Handle empty blocks $pattern = '/{{#' . preg_quote($key, '/') . '}}.*?{{\/' . preg_quote($key, '/') . '}}/s'; $template = preg_replace($pattern, '', $template); // Handle {{^key}}...{{/key}} blocks (show when empty) $pattern = '/{{\^' . preg_quote($key, '/') . '}}(.*?){{\/' . preg_quote($key, '/') . '}}/s'; if (preg_match_all($pattern, $template, $matches)) { foreach ($matches[1] as $match) { $template = preg_replace('/{{\^' . preg_quote($key, '/') . '}}.*?{{\/' . preg_quote($key, '/') . '}}/s', $match, $template, 1); } } } } // Handle variable replacements foreach ($this->data as $key => $value) { // Handle triple braces for unescaped HTML content if (strpos($template, '{{{' . $key . '}}}') !== false) { $template = str_replace('{{{' . $key . '}}}', is_string($value) ? $value : print_r($value, true), $template); } // Handle double braces for escaped content elseif (strpos($template, '{{' . $key . '}}') !== false) { if (is_string($value)) { $template = str_replace('{{' . $key . '}}', htmlspecialchars($value, ENT_QUOTES, 'UTF-8'), $template); } elseif (is_array($value)) { // For arrays, convert to JSON string for display $template = str_replace('{{' . $key . '}}', htmlspecialchars(json_encode($value), ENT_QUOTES, 'UTF-8'), $template); } else { // Convert other types to string $template = str_replace('{{' . $key . '}}', htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'), $template); } } } return $template; } /** * Replace partial includes with data values * * @param array $matches Regex matches from preg_replace_callback * @return string Replacement content */ private function replacePartial($matches) { $partialName = $matches[1]; return isset($this->data[$partialName]) ? $this->data[$partialName] : $matches[0]; } }