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 */ 16*e7f56f2aSGreg Roachdeclare(strict_types=1); 17*e7f56f2aSGreg 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{ 27f3281ad6SGreg Roach /** 28f3281ad6SGreg Roach * @var string The (file) name of the view. 29f3281ad6SGreg Roach */ 30f3281ad6SGreg Roach private $name; 31f3281ad6SGreg Roach 32f3281ad6SGreg Roach /** 33f3281ad6SGreg Roach * @var mixed[] Data to be inserted into the view. 34f3281ad6SGreg Roach */ 35f3281ad6SGreg Roach private $data; 36f3281ad6SGreg Roach 37f3281ad6SGreg Roach /** 3808d24c7aSGreg Roach * @var mixed[] Data to be inserted into all views. 3908d24c7aSGreg Roach */ 4008d24c7aSGreg Roach private static $shared_data = []; 4108d24c7aSGreg Roach 4208d24c7aSGreg Roach /** 43ecf66805SGreg Roach * @var string Implementation of Blade "stacks". 44ecf66805SGreg Roach */ 45ecf66805SGreg Roach private static $stack; 46ecf66805SGreg Roach 47ecf66805SGreg Roach /** 48ecf66805SGreg Roach * @var array[] Implementation of Blade "stacks". 49ecf66805SGreg Roach */ 50ecf66805SGreg Roach private static $stacks = []; 51ecf66805SGreg Roach 52ecf66805SGreg Roach /** 53f3281ad6SGreg Roach * Createa view from a template name and optional data. 54f3281ad6SGreg Roach * 55fa4036e8SGreg Roach * @param string $name 56f3281ad6SGreg Roach * @param array $data 57f3281ad6SGreg Roach */ 58fa4036e8SGreg Roach public function __construct(string $name, $data = []) 59c1010edaSGreg Roach { 60f3281ad6SGreg Roach $this->name = $name; 61f3281ad6SGreg Roach $this->data = $data; 62f3281ad6SGreg Roach } 63f3281ad6SGreg Roach 64f3281ad6SGreg Roach /** 6508d24c7aSGreg Roach * Shared data that is available to all views. 66962e29c9SGreg Roach * 67962e29c9SGreg Roach * @param string $key 68962e29c9SGreg Roach * @param mixed $value 69fa4036e8SGreg Roach * 70fa4036e8SGreg Roach * @return void 7108d24c7aSGreg Roach */ 72c1010edaSGreg Roach public static function share(string $key, $value) 73c1010edaSGreg Roach { 7408d24c7aSGreg Roach self::$shared_data[$key] = $value; 7508d24c7aSGreg Roach } 7608d24c7aSGreg Roach 7708d24c7aSGreg Roach /** 78ecf66805SGreg Roach * Implementation of Blade "stacks". 79ecf66805SGreg Roach * 80ecf66805SGreg Roach * @see https://laravel.com/docs/5.5/blade#stacks 81962e29c9SGreg Roach * 82962e29c9SGreg Roach * @param string $stack 83fa4036e8SGreg Roach * 84fa4036e8SGreg Roach * @return void 85ecf66805SGreg Roach */ 86c1010edaSGreg Roach public static function push(string $stack) 87c1010edaSGreg Roach { 88ecf66805SGreg Roach self::$stack = $stack; 89ecf66805SGreg Roach ob_start(); 90ecf66805SGreg Roach } 91ecf66805SGreg Roach 92ecf66805SGreg Roach /** 93ecf66805SGreg Roach * Implementation of Blade "stacks". 94fa4036e8SGreg Roach * 95fa4036e8SGreg Roach * @return void 96ecf66805SGreg Roach */ 97c1010edaSGreg Roach public static function endpush() 98c1010edaSGreg Roach { 99ecf66805SGreg Roach self::$stacks[self::$stack][] = ob_get_clean(); 100ecf66805SGreg Roach } 101ecf66805SGreg Roach 102ecf66805SGreg Roach /** 103ecf66805SGreg Roach * Implementation of Blade "stacks". 104ecf66805SGreg Roach * 105962e29c9SGreg Roach * @param string $stack 106962e29c9SGreg Roach * 107ecf66805SGreg Roach * @return string 108ecf66805SGreg Roach */ 109c1010edaSGreg Roach public static function stack(string $stack): string 110c1010edaSGreg Roach { 111ecf66805SGreg Roach $content = implode('', self::$stacks[$stack] ?? []); 112ecf66805SGreg Roach 113ecf66805SGreg Roach self::$stacks[$stack] = []; 114ecf66805SGreg Roach 115ecf66805SGreg Roach return $content; 116ecf66805SGreg Roach } 117ecf66805SGreg Roach 118ecf66805SGreg Roach /** 119f3281ad6SGreg Roach * Render a view. 120f3281ad6SGreg Roach * 121f3281ad6SGreg Roach * @return string 122f3281ad6SGreg Roach */ 1238f53f488SRico Sonntag public function render(): string 124c1010edaSGreg Roach { 1254a86d714SGreg Roach $variables_for_view = $this->data + self::$shared_data; 1264a86d714SGreg Roach extract($variables_for_view); 127f3281ad6SGreg Roach 128f3281ad6SGreg Roach ob_start(); 129bc241c54SGreg Roach // Do not use require, so we can catch errors for missing files 130bc241c54SGreg Roach include $this->getFilenameForView($this->name); 13175d70144SGreg Roach 132f3281ad6SGreg Roach return ob_get_clean(); 133f3281ad6SGreg Roach } 134f3281ad6SGreg Roach 135f3281ad6SGreg Roach /** 13675d70144SGreg Roach * Allow a theme to override the default views. 137f3281ad6SGreg Roach * 138f3281ad6SGreg Roach * @param string $view_name 139f3281ad6SGreg Roach * 14075d70144SGreg Roach * @return string 14150c68a25SGreg Roach * @throws Exception 142f3281ad6SGreg Roach */ 1438f53f488SRico Sonntag public function getFilenameForView($view_name): string 144c1010edaSGreg Roach { 14550c68a25SGreg Roach foreach ($this->paths() as $path) { 14650c68a25SGreg Roach $view_file = $path . '/' . $view_name . '.php'; 14775d70144SGreg Roach 14850c68a25SGreg Roach if (is_file($view_file)) { 14950c68a25SGreg Roach return $view_file; 150f21917b2SGreg Roach } 151f3281ad6SGreg Roach } 152f3281ad6SGreg Roach 15350c68a25SGreg Roach throw new Exception('View not found: ' . e($view_name)); 15450c68a25SGreg Roach } 15550c68a25SGreg Roach 156f3281ad6SGreg Roach /** 157f3281ad6SGreg Roach * Cerate and render a view in a single operation. 158f3281ad6SGreg Roach * 159f3281ad6SGreg Roach * @param string $name 160f3281ad6SGreg Roach * @param mixed[] $data 161f3281ad6SGreg Roach * 162f3281ad6SGreg Roach * @return string 163f3281ad6SGreg Roach */ 1648f53f488SRico Sonntag public static function make($name, $data = []): string 165c1010edaSGreg Roach { 166f3281ad6SGreg Roach $view = new static($name, $data); 167f3281ad6SGreg Roach 16844116e73SGreg Roach DebugBar::addView($name, $data); 16944116e73SGreg Roach 170f3281ad6SGreg Roach return $view->render(); 171f3281ad6SGreg Roach } 17250c68a25SGreg Roach 17350c68a25SGreg Roach /** 17450c68a25SGreg Roach * @return string[] 17550c68a25SGreg Roach */ 17650c68a25SGreg Roach private function paths(): array 17750c68a25SGreg Roach { 17850c68a25SGreg Roach static $paths = []; 17950c68a25SGreg Roach 18050c68a25SGreg Roach if (empty($paths)) { 18150c68a25SGreg Roach // Module views 18250c68a25SGreg Roach // @TODO - this includes disabled modules. 18350c68a25SGreg Roach $paths = glob(WT_ROOT . WT_MODULES_DIR . '*/resources/views'); 18450c68a25SGreg Roach // Theme views 18550c68a25SGreg Roach $paths[] = WT_ROOT . WT_THEMES_DIR . Theme::theme()->themeId() . '/resources/views'; 18650c68a25SGreg Roach // Core views 18750c68a25SGreg Roach $paths[] = WT_ROOT . 'resources/views'; 18850c68a25SGreg Roach 189bdb3725aSGreg Roach $paths = array_filter($paths, function (string $path): bool { 190bdb3725aSGreg Roach return is_dir($path); 191bdb3725aSGreg Roach }); 19250c68a25SGreg Roach } 19350c68a25SGreg Roach 19450c68a25SGreg Roach return $paths; 19550c68a25SGreg Roach } 196f3281ad6SGreg Roach} 197