* @copyright Copyright (c) 2022, Robert Strutts. * @license https://mit-license.org/ */ namespace tts; final class view { public $white_space_control = false; private $vars = array(); private $project_dir; private $files = array(); private $template = false; private $use_template_engine = false; private $template_type = 'tpl'; protected $tempalte_engine = null; public function __construct() { $this->project_dir = \bs_tts\site_helper::get_project(); } private function get_file(string $view_file, string $default, string $render_path = 'project'): string { $file_ext = \bs_tts\common::get_string_right($view_file, 4); if (! \bs_tts\common::is_string_found($file_ext, '.')) { $view_file .= '.php'; } if ($render_path === 'tts') { $file = (empty($default)) ? "views/{$view_file}" : "views/{$default}/{$view_file}"; $path = \main_tts\TTS_FRAMEWORK; } else { $file = (empty($default)) ? "{$this->project_dir}/views/{$view_file}" : "{$this->project_dir}/views/{$default}/{$view_file}"; $path = \bs_tts\site_helper::get_root(); } $vf = $path . $file; if ( \bs_tts\requires::safer_file_exists($vf) !== false) { return $file; } return ''; } /** * Alias to set_view */ public function include(string $file, string $render_path = 'project'): void { $this->set_view($file, $render_path); } /** * Alias to set_view */ public function add_view(string $file, string $render_path = 'project'): void { $this->set_view($file, $render_path); } private function find_view_path(string $view_file, string $render_path) { $found = false; $default_paths = \main_tts\configure::get('view_mode', 'default_paths'); $get = \tts\misc::request_var('render'); if (in_array($get, $default_paths)) { if (($key = array_search($get, $default_paths)) !== false) { unset($default_paths[$key]); // Remove as we'll make it first later... } array_unshift($default_paths, $get); // Make First in Array! } foreach ($default_paths as $default) { $file = $this->get_file($view_file, $default, $render_path); if ( ! empty($file) ) { $found = true; break; } } return ($found) ? $file : false; } private function find_template_path($tpl_file, $render_path) { $file = "{$this->project_dir}/views/includes/{$tpl_file}"; $path = ($render_path === 'project') ? \bs_tts\site_helper::get_root() : \main_tts\TTS_FRAMEWORK; $vf = $path . $file; return \bs_tts\requires::safer_file_exists($vf); } /** * Use View File * @param string $view_file * @param string $render_path * @throws Exception */ public function set_view(string $view_file = null, string $render_path = 'project'): void { if ($view_file === null) { return; } $file_ext = \bs_tts\common::get_string_right($view_file, 4); if (! \bs_tts\common::is_string_found($file_ext, '.')) { $file_ext = '.php'; } else if ($file_ext !== '.php') { $this->use_template_engine = true; $this->template_type = str_replace('.', '', $file_ext); } if ($file_ext === '.php') { $file = $this->find_view_path($view_file, $render_path); } else { $file = $this->find_template_path($view_file, $render_path); } if ($file === false) { echo "No view file exists for: {$view_file}!"; throw new \Exception("View File does not exist: " . $view_file); } else { $this->files[] = array('file'=>$file, 'path'=>$render_path, 'file_type'=>$file_ext); } } public function clear_template(): void { $this->template = false; } /** * Use Template with view * @param string $render_page * @return bool was found */ public function set_template(string $render_page): bool { if (! empty($render_page)) { $render_page = str_replace('.php', '', $render_page); $templ = "{$this->project_dir}/templates/{$render_page}"; if (\bs_tts\requires::safer_file_exists(\bs_tts\site_helper::get_root() . $templ. '.php') !== false) { $this->template = $templ; // echo $this->template; return true; } } $this->template = false; return false; } private function clear_ob(int $saved_ob_level): void { while (ob_get_level() > $saved_ob_level) { ob_end_flush(); } } /** * Sets a variable in this view with the given name and value * * @param mixed $name Name of the variable to set in the view, or an array of key/value pairs where each key is the variable and each value is the value to set. * @param mixed $value Value of the variable to set in the view. */ public function set($name, $value = null): void { if (is_array($name)) { foreach ($name as $var_name => $value) { $this->vars[$var_name] = $value; } } else { $this->vars[$name] = $value; } } /** * Alias to fetch with Built-in echo * @param type $local * @param string $file */ public function render($local, string $file = null) { echo $this->fetch($local, $file); } /** * Outputs view * @param type $local = $this * @param $file (optional view file) */ public function fetch($local, string $file = null): string { $page_output = ob_get_clean(); // Get echos before View \main_tts\views::ob_start(); $saved_ob_level = ob_get_level(); $this->set_view($file); unset($file); if (!is_object($local)) { $local = $this; // FALL Back, please use fetch($this); } if ($this->use_template_engine) { $this->tempalte_engine = \main_tts\registry::get('di')->get_service('templates', [$this->template_type]); if ($this->white_space_control) { $this->tempalte_engine->whitespace_control(); } } if (count($this->files) > 0) { foreach ($this->files as $view_file) { if ($view_file['file_type'] == '.php') { \bs_tts\requires::secure_include($view_file['file'], $view_file['path'], $local, $this->vars); // Include the file } else { $template_file = str_replace('.tpl', '', $view_file['file']); $this->tempalte_engine->parse_file($template_file); $assigns = $this->vars['template_assigns'] ?? []; $filters = $this->vars['template_filters'] ?? null; $registers = $this->vars['template_registers'] ?? []; $assigns['production'] =(\main_tts\configure::get('tts', 'live') === true) ? true : false; echo $this->tempalte_engine->render($assigns, $filters, $registers); } } } $this->clear_ob($saved_ob_level); $page_output .= ob_get_clean(); try { if (\bs_tts\common::get_bool(\main_tts\configure::get('tts', 'check_HTML_tags')) === true) { $tags = \tts\tag_matches::check_tags($page_output); if (! empty($tags['output'])) { $page_output .= $tags['output']; $page_output .= ''; foreach($this->files as $bad) { $page_output .= ""; } } } } catch (\tts\exceptions\Bool_Exception $e) { if (\main_tts\configure::get('tts', 'live') === false) { $page_output .= \tts\assets::alert('SET Config for tts: check_HTML_tags'); } } if ($this->template !== false && \bs_tts\requires::safer_file_exists(\bs_tts\site_helper::get_root() . $this->template . ".php") !== false) { \main_tts\views::ob_start(); $saved_ob_level = ob_get_level(); $local->page_output = $page_output; \bs_tts\requires::secure_include($this->template, 'project', $local, $this->vars); $this->clear_ob($saved_ob_level); $page_output = ob_get_clean(); } // Reset Files to zero, as they were outputed.... unset($this->files); $this->files = []; return $page_output; } }