Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- /**
- * Gestor de Templates
- * @version 2.0
- */
- class Template {
- /**
- * Diretório base dos templates
- */
- private string $dir;
- /**
- * Extensão dos arquivos de template
- */
- private string $ext;
- /**
- * Cache em memória: ['nome' => 'conteúdo raw']
- */
- private array $cache = [];
- // -------------------------------------------------------------------------
- /**
- * @param string $dir Diretório dos templates (padrão: 'template/')
- * @param string $ext Extensão dos arquivos (padrão: '.tpl')
- *
- * @throws RuntimeException se o diretório não existir
- */
- public function __construct(string $dir = 'template', string $ext = '.tpl') {
- if (!is_dir($dir)) {
- throw new RuntimeException(
- "Template: diretório não encontrado — \"{$dir}\""
- );
- }
- $this->dir = rtrim($dir, '/\\');
- $this->ext = '.' . ltrim($ext, '.');
- }
- // -------------------------------------------------------------------------
- /**
- * Renderiza um template e retorna o HTML como string
- *
- * @param string $name Nome do template (sem extensão)
- * @param array $data Variáveis para substituir no template
- * @param bool $minify Minifica o resultado
- *
- * @throws RuntimeException se o arquivo não existir
- * @throws InvalidArgumentException se $data não for array
- *
- * @example
- * $tpl = new Template();
- * echo $tpl->render('home', ['titulo' => 'Olá Mundo']);
- */
- public function render(string $name, array $data = [], bool $minify = false): string {
- $raw = $this->load($name);
- $output = $this->replace($raw, $data);
- if ($minify) {
- $output = $this->minify($output);
- }
- return $output;
- }
- /**
- * Renderiza e envia direto para o output com o Content-Type correto
- *
- * @param string $name
- * @param array $data
- * @param bool $minify
- * @param string $contentType Ex: 'text/html; charset=UTF-8'
- *
- * @example
- * $tpl->output('home', ['titulo' => 'Olá'], minify: true);
- * $tpl->output('style', [], contentType: 'text/css');
- */
- public function output(
- string $name,
- array $data = [],
- bool $minify = false,
- string $contentType = 'text/html; charset=UTF-8'
- ): void {
- if (headers_sent($file, $line)) {
- throw new RuntimeException(
- "Template: headers já enviados em {$file}:{$line}"
- );
- }
- header('Content-Type: ' . $contentType);
- echo $this->render($name, $data, $minify);
- }
- // -------------------------------------------------------------------------
- // CACHE
- // -------------------------------------------------------------------------
- /**
- * Pré-carrega um ou mais templates na memória
- *
- * @example
- * $tpl->preload(['header', 'footer', 'home']);
- */
- public function preload(array $names): void {
- foreach ($names as $name) {
- $this->load($name);
- }
- }
- /**
- * Limpa o cache em memória
- */
- public function clearCache(?string $name = null): void {
- if ($name === null) {
- $this->cache = [];
- } else {
- unset($this->cache[$name]);
- }
- }
- // -------------------------------------------------------------------------
- // PRIVADOS
- // -------------------------------------------------------------------------
- /**
- * Carrega o template do disco ou do cache em memória
- *
- * @throws RuntimeException se o arquivo não existir
- */
- private function load(string $name): string {
- if (isset($this->cache[$name])) {
- return $this->cache[$name];
- }
- $path = $this->dir . DIRECTORY_SEPARATOR . $name . $this->ext;
- if (!file_exists($path)) {
- throw new RuntimeException(
- "Template: arquivo não encontrado — \"{$name}{$this->ext}\""
- );
- }
- $this->cache[$name] = file_get_contents($path);
- return $this->cache[$name];
- }
- /**
- * Substitui os placeholders {chave} pelos valores de $data
- * Placeholders sem correspondência são mantidos no output
- */
- private function replace(string $template, array $data): string {
- foreach ($data as $key => $value) {
- $template = str_replace('{' . $key . '}', (string) $value, $template);
- }
- return $template;
- }
- /**
- * Minifica HTML, CSS ou JS de forma segura
- *
- * - Remove comentários HTML <!-- ... -->
- * - Remove comentários CSS /* ... */
- * - Colapsa espaços e quebras de linha entre tags HTML
- * - NÃO toca em conteúdo dentro de <pre>, <script> ou <style>
- * para evitar quebrar código
- */
- private function minify(string $content): string {
- // Remove comentários HTML (não remove condicionais <!--[if ...]>)
- $content = preg_replace('/<!--(?!\[if).*?-->/s', '', $content);
- // Remove comentários CSS/JS /* ... */
- $content = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $content);
- // Colapsa múltiplas quebras de linha e tabs em um único espaço
- $content = preg_replace('/\s{2,}/u', ' ', $content);
- // Remove espaços entre tags HTML
- $content = preg_replace('/>\s+</u', '><', $content);
- return trim($content);
- }
- }
- USO
- $tpl = new Template('template', '.tpl');
- // Retorna string
- $html = $tpl->render('home', ['titulo' => 'Olá Mundo']);
- // Envia direto com header
- $tpl->output('home', ['titulo' => 'Olá'], minify: true);
- // CSS com Content-Type correto
- $tpl->output('style', [], contentType: 'text/css');
Advertisement
Add Comment
Please, Sign In to add comment