main
Robert 5 months ago
parent 32567ea58e
commit bd1c35d830
  1. 2
      docs/TODO.md
  2. 1
      src/bootstrap/requires.php
  3. 4
      src/classes/enums/view_type.php
  4. 35
      src/classes/php_file_cache.php
  5. 78
      src/classes/services/liquid_templates.php
  6. 23
      src/classes/services/twig.php
  7. 102
      src/classes/view.php

@ -21,7 +21,7 @@
[.] → Models [.] → Models
[ ] → Views (Twig/Liquid/PHP) [x] → Views (Twig/Liquid/PHP)
[x] → JavaScript/CSS Asset loading [x] → JavaScript/CSS Asset loading

@ -117,6 +117,7 @@ final class requires {
$file_name = common::get_string_left($file, $pos); $file_name = common::get_string_left($file, $pos);
$file_kind = common::get_string_right($file, common::string_length($file) - $pos); $file_kind = common::get_string_right($file, common::string_length($file) - $pos);
$file_type = match ($file_kind) { $file_type = match ($file_kind) {
".twig" => ".twig",
".tpl" => ".tpl", ".tpl" => ".tpl",
default => ".php", default => ".php",
}; };

@ -13,4 +13,8 @@ enum view_type: string {
case LIQUID = ".tpl"; case LIQUID = ".tpl";
case TWIG = ".twig"; case TWIG = ".twig";
case PHP = ".php"; case PHP = ".php";
public static function get_file_extension_for(view_type $type): string {
return $type->value;
}
} }

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace CodeHydrater;
/**
* @author Robert Strutts <Bob_586@Yahoo.com>
* @copyright (c) 2025, Robert Strutts
* @license MIT
*/
class php_file_cache {
protected $cache_path;
public function __construct($path) {
$this->cache_path = rtrim($path, '/') . '/';
if (!is_dir($this->cache_path)) {
mkdir($this->cache_path, 0775, true);
}
}
public function get($key) {
$file = $this->cache_path . md5($key) . '.cache.php';
if (file_exists($file)) {
return unserialize(file_get_contents($file));
}
return null;
}
public function set($key, $value) {
$file = $this->cache_path . md5($key) . '.cache.php';
file_put_contents($file, serialize($value));
}
}

@ -0,0 +1,78 @@
<?php
declare(strict_types=1);
/**
* @author Robert Strutts <Bob_586@Yahoo.com>
* @copyright (c) 2025, Robert Strutts
* @license MIT
*/
namespace CodeHydrater\services;
use CodeHydrater\bootstrap\registry as Reg;
use CodeHydrater\php_file_cache as FileCache;
use Liquid\{Liquid, Template, Context};
use Liquid\Cache\Local;
final class liquid_templates {
private $use_local_cache = false;
private $liquid;
private $dir;
private $extension = 'tpl';
public function __construct(string $template_extension = 'tpl') {
$this->extension = $template_extension;
if (! Reg::get('loader')->is_loaded('Liquid')) {
Reg::get('loader')->add_namespace('Liquid', CodeHydrater_PROJECT . 'vendor/liquid/liquid/src/Liquid');
}
Liquid::set('INCLUDE_SUFFIX', $template_extension);
Liquid::set('INCLUDE_PREFIX', '');
$this->dir = CodeHydrater_PROJECT . 'views/liquid';
$this->liquid = new Template($this->dir);
}
public function whitespace_control() {
/* Force whitespace control to be used by switching tags from {%- to {%
* Also, will error out if you try {%-
* Need to figure out how to turn back on whitespaces with {%@ errors! not important...
*/
Liquid::set('TAG_START', '(?:{%@)|\s*{%');
Liquid::set('TAG_END', '(?:@%}|%}\s*)');
}
public function parse(string $source) {
return $this->liquid->parse($source);
}
public function parse_file(string $file) {
$safe_file = \CodeHydrater\security::filter_uri($file);
if ($this->use_local_cache) {
$cache = new FileCache(BaseDir . "/protected/runtime/liquid_cache");
$templateName = $safe_file . "." . $this->extension;
$templatePath = $this->dir . "/". $safe_file . "." . $this->extension;
$templateSource = file_get_contents($templatePath);
$cached = $cache->get($templateName);
if (!$cached) {
$this->liquid->parseFile($safe_file);
$cache->set($templateName, $this->liquid);
} else {
$this->liquid = $cached;
}
} else {
$this->liquid->parseFile($safe_file);
}
}
public function render(array $assigns = array(), $filters = null, array $registers = array()): string {
return $this->liquid->render($assigns, $filters, $registers);
}
public function get_engine() {
return $this->liquid;
}
}

@ -0,0 +1,23 @@
<?php
declare(strict_types = 1);
/**
* @author Robert Strutts <Bob_586@Yahoo.com>
* @copyright (c) 2025, Robert Strutts
* @license MIT
*/
namespace CodeHydrater\services;
class twig {
public static function init() {
\CodeHydrater\bootstrap\registry::get('loader')->add_namespace("Twig", CodeHydrater_PROJECT. "/vendor/twig/twig/src");
\CodeHydrater\bootstrap\registry::get('loader')->add_namespace("Symfony\Polyfill\Mbstring", CodeHydrater_PROJECT. "/vendor/symfony/polyfill-mbstring");
\CodeHydrater\bootstrap\registry::get('loader')->add_namespace("Symfony\Polyfill\Ctype", CodeHydrater_PROJECT. "/vendor/symfony/polyfill-ctype");
$loader = new \Twig\Loader\FilesystemLoader(CodeHydrater_PROJECT. "views/twig");
$twig = new \Twig\Environment($loader, [
'cache' => BaseDir . "/protected/runtime/compilation_cache",
]);
return $twig;
}
}

@ -10,23 +10,23 @@ declare(strict_types=1);
namespace CodeHydrater; namespace CodeHydrater;
use \CodeHydrater\enums\view_type as ViewType;
final class view { final class view {
public $white_space_control = false; public $white_space_control = false;
public $page_output; public $page_output;
private $vars = []; private $vars = [];
private $project_dir = ""; // Not used anymore
private $files = []; private $files = [];
private $template = false; private $template = false;
private $use_template_engine = false; private $use_template_engine = false;
private $use_template_engine_twig = false;
private $use_template_engine_liquid = false;
private $template_type = 'tpl'; private $template_type = 'tpl';
protected $tempalte_engine = null; protected $tempalte_engine_twig = null;
protected $tempalte_engine_liquid = null;
private function get_file(string $view_file, string $default): string { private function get_file(string $view_file, string $default): string {
$file_ext = bootstrap\common::get_string_right($view_file, 4); $file = (empty($default)) ? "views/{$view_file}" : "views/{$default}/{$view_file}";
if (! bootstrap\common::is_string_found($file_ext, '.')) {
$view_file .= '.php';
}
$file = (empty($default)) ? "{$this->project_dir}/views/{$view_file}" : "{$this->project_dir}/views/{$default}/{$view_file}";
$path = bootstrap\site_helper::get_root(); $path = bootstrap\site_helper::get_root();
$vf = $path . $file; $vf = $path . $file;
if ( bootstrap\requires::safer_file_exists($vf) !== false) { if ( bootstrap\requires::safer_file_exists($vf) !== false) {
@ -38,18 +38,23 @@ final class view {
/** /**
* Alias to set_view * Alias to set_view
*/ */
public function include(string $file): void { public function include(string $file, ViewType $type = ViewType::PHP): void {
$this->set_view($file); $this->set_view($file);
} }
/** /**
* Alias to set_view * Alias to set_view
*/ */
public function add_view(string $file): void { public function add_view(string $file, ViewType $type = ViewType::PHP): void {
$this->set_view($file); $this->set_view($file);
} }
private function find_view_path(string $view_file) { /**
* Check the $_GET['render'] for which folder to use to render the view
* @param string $view_file
* @return file | false
*/
private function find_view_path(string $view_file): string|false {
$found = false; $found = false;
$default_paths = bootstrap\configure::get('view_mode', 'default_paths'); $default_paths = bootstrap\configure::get('view_mode', 'default_paths');
@ -71,43 +76,40 @@ final class view {
return ($found) ? $file : false; return ($found) ? $file : false;
} }
private function find_template_path($tpl_file) {
$file = "{$this->project_dir}/views/includes/{$tpl_file}";
$path = bootstrap\site_helper::get_root();
$vf = $path . $file;
return bootstrap\requires::safer_file_exists($vf);
}
/** /**
* Use View File * Use View File
* @param string $view_file * @param string $view_file
* @param string $render_path * @param string $render_path
* @throws Exception * @throws Exception
*/ */
public function set_view(string $view_file = null): void { public function set_view(string $view_file = null, ViewType $type = ViewType::PHP): void {
if ($view_file === null) { if ($view_file === null) {
return; return;
} }
$file_ext = bootstrap\common::get_string_right($view_file, 4); $file_ext = ViewType::get_file_extension_for($type);
if (! bootstrap\common::is_string_found($file_ext, '.')) { $file = $this->find_view_path($view_file . $file_ext);
$file_ext = '.php'; if ($type == ViewType::TWIG) {
} else if ($file_ext !== '.php') { $this->use_template_engine_twig = true;
$this->use_template_engine = true;
$this->template_type = str_replace('.', '', $file_ext); $this->template_type = str_replace('.', '', $file_ext);
$path = bootstrap\site_helper::get_root();
if ($file !== false) {
$file = str_replace("views/twig", "", $file); // Remove Path, as it is defined in the service file
}
}
if ($type == ViewType::LIQUID) {
$this->use_template_engine_liquid = true;
$this->template_type = str_replace('.', '', $file_ext);
if ($file !== false) {
$file = ltrim(str_replace("views/liquid", "", $file), "/"); // Remove Path, as it is defined in the service file
} }
if ($file_ext === '.php') {
$file = $this->find_view_path($view_file);
} else {
$file = $this->find_template_path($view_file);
} }
if ($file === false) { if ($file === false) {
echo "No view file exists for: {$view_file}!"; echo "No view file exists for: {$view_file}!";
throw new \Exception("View File does not exist: " . $view_file); throw new \Exception("View File does not exist: " . $view_file);
} else { } else {
$this->files[] = array('file'=>$file, 'path'=>"project", 'file_type'=>$file_ext); $this->files[] = array('file'=>$file, 'path'=> bootstrap\UseDir::PROJECT, 'file_type'=>$file_ext);
} }
} }
@ -116,17 +118,16 @@ final class view {
} }
/** /**
* Use Template with view * Use PHP Template with view
* @param string $render_page * @param string $render_page
* @return bool was found * @return bool was found
*/ */
public function set_template(string $render_page): bool { public function set_template(string $render_page): bool {
if (! empty($render_page)) { if (! empty($render_page)) {
$render_page = str_replace('.php', '', $render_page); $render_page = str_replace('.php', '', $render_page);
$templ = "{$this->project_dir}/templates/{$render_page}"; $templ = "/templates/{$render_page}";
if (bootstrap\requires::safer_file_exists(bootstrap\site_helper::get_root() . $templ. '.php') !== false) { if (bootstrap\requires::safer_file_exists(bootstrap\site_helper::get_root() . $templ. '.php') !== false) {
$this->template = $templ; $this->template = $templ;
// echo $this->template;
return true; return true;
} }
} }
@ -161,8 +162,8 @@ final class view {
* @param type $local * @param type $local
* @param string $file * @param string $file
*/ */
public function render($local, string $file = null) { public function render($local, string $file = null, ViewType $type = ViewType::PHP) {
echo $this->fetch($local, $file); echo $this->fetch($local, $file, $type);
} }
/** /**
@ -170,11 +171,11 @@ final class view {
* @param type $local = $this * @param type $local = $this
* @param $file (optional view file) * @param $file (optional view file)
*/ */
public function fetch($local, string $file = null): string { public function fetch($local, string $file = null, ViewType $type = ViewType::PHP): string {
$page_output = ob_get_clean(); // Get echos before View $page_output = ob_get_clean(); // Get echos before View
bootstrap\views::ob_start(); bootstrap\views::ob_start();
$saved_ob_level = ob_get_level(); $saved_ob_level = ob_get_level();
$this->set_view($file); $this->set_view($file, $type);
unset($file); unset($file);
@ -182,25 +183,38 @@ final class view {
$local = $this; // FALL Back, please use fetch($this); $local = $this; // FALL Back, please use fetch($this);
} }
if ($this->use_template_engine) { if ($this->use_template_engine_liquid) {
$this->tempalte_engine = bootstrap\registry::get('di')->get_service('templates', [$this->template_type]); $this->tempalte_engine_liquid = bootstrap\registry::get('di')->get_service('liquid', [$this->template_type]);
if ($this->white_space_control) { if ($this->white_space_control) {
$this->tempalte_engine->whitespace_control(); $this->tempalte_engine->whitespace_control();
} }
} }
if ($this->use_template_engine_twig) {
$this->tempalte_engine_twig = bootstrap\registry::get('di')->get_service('twig', [$this->template_type]);
}
if (count($this->files) > 0) { if (count($this->files) > 0) {
foreach ($this->files as $view_file) { foreach ($this->files as $view_file) {
if ($view_file['file_type'] == '.php') { if ($view_file['file_type'] == '.php') {
bootstrap\requires::secure_include($view_file['file'], bootstrap\UseDir::PROJECT, $local, $this->vars); // Include the file bootstrap\requires::secure_include($view_file['file'], bootstrap\UseDir::PROJECT, $local, $this->vars); // Include the PHP file
} else {
} else if ($view_file['file_type'] == '.tpl') {
// Liquid uses .tpl by default, so remove that File Ext
$template_file = str_replace('.tpl', '', $view_file['file']); $template_file = str_replace('.tpl', '', $view_file['file']);
$this->tempalte_engine->parse_file($template_file); $this->tempalte_engine_liquid->parse_file($template_file);
$assigns = $this->vars['template_assigns'] ?? []; $assigns = $this->vars['template_assigns'] ?? [];
$filters = $this->vars['template_filters'] ?? null; $filters = $this->vars['template_filters'] ?? null;
$registers = $this->vars['template_registers'] ?? []; $registers = $this->vars['template_registers'] ?? [];
$assigns['production'] =(\main_tts\is_live()); $assigns['production'] =(bootstrap\is_live());
echo $this->tempalte_engine->render($assigns, $filters, $registers); echo $this->tempalte_engine_liquid->render($assigns, $filters, $registers);
} else if ($view_file['file_type'] == '.twig') {
$twig_data = $this->vars['twig_data'] ?? [];
echo $this->tempalte_engine_twig->render($view_file['file'], $twig_data);
} else {
throw new \Exception("Unable View File Type");
} }
} }
} }
@ -220,7 +234,7 @@ final class view {
} }
} catch (exceptions\Bool_Exception $e) { } catch (exceptions\Bool_Exception $e) {
if (bootstrap\configure::get('CodeHydrater', 'live') === false) { if (bootstrap\configure::get('CodeHydrater', 'live') === false) {
$page_output .= assets::alert('SET Config for tts: check_HTML_tags'); $page_output .= assets::alert('SET Config for: check_HTML_tags');
} }
} }

Loading…
Cancel
Save