1f3281ad6SGreg Roach<?php 2f3281ad6SGreg Roach/** 3f3281ad6SGreg Roach * webtrees: online genealogy 41062a142SGreg Roach * Copyright (C) 2018 webtrees development team 5f3281ad6SGreg Roach * This program is free software: you can redistribute it and/or modify 6f3281ad6SGreg Roach * it under the terms of the GNU General Public License as published by 7f3281ad6SGreg Roach * the Free Software Foundation, either version 3 of the License, or 8f3281ad6SGreg Roach * (at your option) any later version. 9f3281ad6SGreg Roach * This program is distributed in the hope that it will be useful, 10f3281ad6SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 11f3281ad6SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12f3281ad6SGreg Roach * GNU General Public License for more details. 13f3281ad6SGreg Roach * You should have received a copy of the GNU General Public License 14f3281ad6SGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>. 15f3281ad6SGreg Roach */ 16e7f56f2aSGreg Roachdeclare(strict_types=1); 17e7f56f2aSGreg Roach 18f3281ad6SGreg Roachnamespace Fisharebest\Webtrees; 19f3281ad6SGreg Roach 2050c68a25SGreg Roachuse Exception; 2150c68a25SGreg Roach 22f3281ad6SGreg Roach/** 23f3281ad6SGreg Roach * Simple view/template class. 24f3281ad6SGreg Roach */ 25c1010edaSGreg Roachclass View 26c1010edaSGreg Roach{ 27*dd6b2bfcSGreg Roach // Where do our templates live 28*dd6b2bfcSGreg Roach const TEMPLATE_PATH = 'resources/views/'; 29*dd6b2bfcSGreg Roach 30*dd6b2bfcSGreg Roach // File extension for our template files. 31*dd6b2bfcSGreg Roach const TEMPLATE_EXTENSION = '.phtml'; 32*dd6b2bfcSGreg Roach 33f3281ad6SGreg Roach /** 34f3281ad6SGreg Roach * @var string The (file) name of the view. 35f3281ad6SGreg Roach */ 36f3281ad6SGreg Roach private $name; 37f3281ad6SGreg Roach 38f3281ad6SGreg Roach /** 39f3281ad6SGreg Roach * @var mixed[] Data to be inserted into the view. 40f3281ad6SGreg Roach */ 41f3281ad6SGreg Roach private $data; 42f3281ad6SGreg Roach 43f3281ad6SGreg Roach /** 4408d24c7aSGreg Roach * @var mixed[] Data to be inserted into all views. 4508d24c7aSGreg Roach */ 4608d24c7aSGreg Roach private static $shared_data = []; 4708d24c7aSGreg Roach 4808d24c7aSGreg Roach /** 49ecf66805SGreg Roach * @var string Implementation of Blade "stacks". 50ecf66805SGreg Roach */ 51ecf66805SGreg Roach private static $stack; 52ecf66805SGreg Roach 53ecf66805SGreg Roach /** 54ecf66805SGreg Roach * @var array[] Implementation of Blade "stacks". 55ecf66805SGreg Roach */ 56ecf66805SGreg Roach private static $stacks = []; 57ecf66805SGreg Roach 58ecf66805SGreg Roach /** 59f3281ad6SGreg Roach * Createa view from a template name and optional data. 60f3281ad6SGreg Roach * 61fa4036e8SGreg Roach * @param string $name 62f3281ad6SGreg Roach * @param array $data 63f3281ad6SGreg Roach */ 64fa4036e8SGreg Roach public function __construct(string $name, $data = []) 65c1010edaSGreg Roach { 66f3281ad6SGreg Roach $this->name = $name; 67f3281ad6SGreg Roach $this->data = $data; 68f3281ad6SGreg Roach } 69f3281ad6SGreg Roach 70f3281ad6SGreg Roach /** 7108d24c7aSGreg Roach * Shared data that is available to all views. 72962e29c9SGreg Roach * 73962e29c9SGreg Roach * @param string $key 74962e29c9SGreg Roach * @param mixed $value 75fa4036e8SGreg Roach * 76fa4036e8SGreg Roach * @return void 7708d24c7aSGreg Roach */ 78c1010edaSGreg Roach public static function share(string $key, $value) 79c1010edaSGreg Roach { 8008d24c7aSGreg Roach self::$shared_data[$key] = $value; 8108d24c7aSGreg Roach } 8208d24c7aSGreg Roach 8308d24c7aSGreg Roach /** 84ecf66805SGreg Roach * Implementation of Blade "stacks". 85ecf66805SGreg Roach * 86ecf66805SGreg Roach * @see https://laravel.com/docs/5.5/blade#stacks 87962e29c9SGreg Roach * 88962e29c9SGreg Roach * @param string $stack 89fa4036e8SGreg Roach * 90fa4036e8SGreg Roach * @return void 91ecf66805SGreg Roach */ 92c1010edaSGreg Roach public static function push(string $stack) 93c1010edaSGreg Roach { 94ecf66805SGreg Roach self::$stack = $stack; 95ecf66805SGreg Roach ob_start(); 96ecf66805SGreg Roach } 97ecf66805SGreg Roach 98ecf66805SGreg Roach /** 99ecf66805SGreg Roach * Implementation of Blade "stacks". 100fa4036e8SGreg Roach * 101fa4036e8SGreg Roach * @return void 102ecf66805SGreg Roach */ 103c1010edaSGreg Roach public static function endpush() 104c1010edaSGreg Roach { 105ecf66805SGreg Roach self::$stacks[self::$stack][] = ob_get_clean(); 106ecf66805SGreg Roach } 107ecf66805SGreg Roach 108ecf66805SGreg Roach /** 109ecf66805SGreg Roach * Implementation of Blade "stacks". 110ecf66805SGreg Roach * 111962e29c9SGreg Roach * @param string $stack 112962e29c9SGreg Roach * 113ecf66805SGreg Roach * @return string 114ecf66805SGreg Roach */ 115c1010edaSGreg Roach public static function stack(string $stack): string 116c1010edaSGreg Roach { 117ecf66805SGreg Roach $content = implode('', self::$stacks[$stack] ?? []); 118ecf66805SGreg Roach 119ecf66805SGreg Roach self::$stacks[$stack] = []; 120ecf66805SGreg Roach 121ecf66805SGreg Roach return $content; 122ecf66805SGreg Roach } 123ecf66805SGreg Roach 124ecf66805SGreg Roach /** 125f3281ad6SGreg Roach * Render a view. 126f3281ad6SGreg Roach * 127f3281ad6SGreg Roach * @return string 128f3281ad6SGreg Roach */ 1298f53f488SRico Sonntag public function render(): string 130c1010edaSGreg Roach { 1314a86d714SGreg Roach $variables_for_view = $this->data + self::$shared_data; 1324a86d714SGreg Roach extract($variables_for_view); 133f3281ad6SGreg Roach 134f3281ad6SGreg Roach ob_start(); 135bc241c54SGreg Roach // Do not use require, so we can catch errors for missing files 136bc241c54SGreg Roach include $this->getFilenameForView($this->name); 13775d70144SGreg Roach 138f3281ad6SGreg Roach return ob_get_clean(); 139f3281ad6SGreg Roach } 140f3281ad6SGreg Roach 141f3281ad6SGreg Roach /** 14275d70144SGreg Roach * Allow a theme to override the default views. 143f3281ad6SGreg Roach * 144f3281ad6SGreg Roach * @param string $view_name 145f3281ad6SGreg Roach * 14675d70144SGreg Roach * @return string 14750c68a25SGreg Roach * @throws Exception 148f3281ad6SGreg Roach */ 1498f53f488SRico Sonntag public function getFilenameForView($view_name): string 150c1010edaSGreg Roach { 15150c68a25SGreg Roach foreach ($this->paths() as $path) { 152*dd6b2bfcSGreg Roach $view_file = $path . $view_name . self::TEMPLATE_EXTENSION; 15375d70144SGreg Roach 15450c68a25SGreg Roach if (is_file($view_file)) { 15550c68a25SGreg Roach return $view_file; 156f21917b2SGreg Roach } 157f3281ad6SGreg Roach } 158f3281ad6SGreg Roach 15950c68a25SGreg Roach throw new Exception('View not found: ' . e($view_name)); 16050c68a25SGreg Roach } 16150c68a25SGreg Roach 162f3281ad6SGreg Roach /** 163f3281ad6SGreg Roach * Cerate and render a view in a single operation. 164f3281ad6SGreg Roach * 165f3281ad6SGreg Roach * @param string $name 166f3281ad6SGreg Roach * @param mixed[] $data 167f3281ad6SGreg Roach * 168f3281ad6SGreg Roach * @return string 169f3281ad6SGreg Roach */ 1708f53f488SRico Sonntag public static function make($name, $data = []): string 171c1010edaSGreg Roach { 172f3281ad6SGreg Roach $view = new static($name, $data); 173f3281ad6SGreg Roach 17444116e73SGreg Roach DebugBar::addView($name, $data); 17544116e73SGreg Roach 176f3281ad6SGreg Roach return $view->render(); 177f3281ad6SGreg Roach } 17850c68a25SGreg Roach 17950c68a25SGreg Roach /** 18050c68a25SGreg Roach * @return string[] 18150c68a25SGreg Roach */ 18250c68a25SGreg Roach private function paths(): array 18350c68a25SGreg Roach { 18450c68a25SGreg Roach static $paths = []; 18550c68a25SGreg Roach 18650c68a25SGreg Roach if (empty($paths)) { 18750c68a25SGreg Roach // Module views 18850c68a25SGreg Roach // @TODO - this includes disabled modules. 189*dd6b2bfcSGreg Roach $paths = glob(WT_ROOT . WT_MODULES_DIR . '*/' . self::TEMPLATE_PATH); 19050c68a25SGreg Roach // Theme views 191*dd6b2bfcSGreg Roach $paths[] = WT_ROOT . WT_THEMES_DIR . Theme::theme()->themeId() . self::TEMPLATE_PATH; 19250c68a25SGreg Roach // Core views 193*dd6b2bfcSGreg Roach $paths[] = WT_ROOT . self::TEMPLATE_PATH; 19450c68a25SGreg Roach 195bdb3725aSGreg Roach $paths = array_filter($paths, function (string $path): bool { 196bdb3725aSGreg Roach return is_dir($path); 197bdb3725aSGreg Roach }); 19850c68a25SGreg Roach } 19950c68a25SGreg Roach 20050c68a25SGreg Roach return $paths; 20150c68a25SGreg Roach } 202f3281ad6SGreg Roach} 203