You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
259 lines
6.1 KiB
259 lines
6.1 KiB
1 year ago
|
<?php declare(strict_types = 0);
|
||
|
/*
|
||
|
** Zabbix
|
||
|
** Copyright (C) 2001-2023 Zabbix SIA
|
||
|
**
|
||
|
** This program is free software; you can redistribute it and/or modify
|
||
|
** it under the terms of the GNU General Public License as published by
|
||
|
** the Free Software Foundation; either version 2 of the License, or
|
||
|
** (at your option) any later version.
|
||
|
**
|
||
|
** This program is distributed in the hope that it will be useful,
|
||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
** GNU General Public License for more details.
|
||
|
**
|
||
|
** You should have received a copy of the GNU General Public License
|
||
|
** along with this program; if not, write to the Free Software
|
||
|
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
|
**/
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Class for rendering views.
|
||
|
*/
|
||
|
class CView {
|
||
|
|
||
|
/**
|
||
|
* Directory list of MVC views ordered by search priority.
|
||
|
*/
|
||
|
private static array $directories = ['local/app/views', 'app/views', 'include/views'];
|
||
|
|
||
|
/**
|
||
|
* Indicates support of web layout modes.
|
||
|
*/
|
||
|
private bool $layout_modes_enabled = false;
|
||
|
|
||
|
/**
|
||
|
* Explicitly set layout mode.
|
||
|
*/
|
||
|
private ?int $layout_mode = null;
|
||
|
|
||
|
/**
|
||
|
* Directory where the view file was found.
|
||
|
*/
|
||
|
private ?string $directory = null;
|
||
|
|
||
|
private string $assets_path = 'assets';
|
||
|
|
||
|
/**
|
||
|
* View name.
|
||
|
*/
|
||
|
private string $name;
|
||
|
|
||
|
/**
|
||
|
* List of JavaScript files for inclusion into HTML page using <script src="...">.
|
||
|
*/
|
||
|
private array $js_files = [];
|
||
|
|
||
|
/**
|
||
|
* List of CSS files for inclusion into HTML page using <link rel="stylesheet" type="text/css" src="...">.
|
||
|
*/
|
||
|
private array $css_files = [];
|
||
|
|
||
|
/**
|
||
|
* Data provided for view.
|
||
|
*/
|
||
|
private array $data;
|
||
|
|
||
|
/**
|
||
|
* Create a view based on view name and data.
|
||
|
*
|
||
|
* @param string $name View name to search for.
|
||
|
* @param array $data Accessible data within the view.
|
||
|
*
|
||
|
* @throws InvalidArgumentException if view name not valid.
|
||
|
* @throws RuntimeException if view not found or not readable.
|
||
|
*/
|
||
|
public function __construct(string $name, array $data = []) {
|
||
|
if (!preg_match('/^[a-z]+(\/[a-z]+)*(\.[a-z]+)*$/', $name)) {
|
||
|
throw new InvalidArgumentException(sprintf('Invalid view name: "%s".', $name));
|
||
|
}
|
||
|
|
||
|
$file_path = null;
|
||
|
|
||
|
foreach (self::$directories as $directory) {
|
||
|
$file_path = $directory.'/'.$name.'.php';
|
||
|
|
||
|
if (is_file($file_path)) {
|
||
|
$this->directory = $directory;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($this->directory === null) {
|
||
|
throw new RuntimeException(sprintf('View not found: "%s".', $name));
|
||
|
}
|
||
|
|
||
|
if (!is_readable($file_path)) {
|
||
|
throw new RuntimeException(sprintf('View not readable: "%s".', $file_path));
|
||
|
}
|
||
|
|
||
|
$this->name = $name;
|
||
|
$this->data = $data;
|
||
|
}
|
||
|
|
||
|
public function getDirectory(): string {
|
||
|
return $this->directory;
|
||
|
}
|
||
|
|
||
|
public function setAssetsPath(string $asset_path): self {
|
||
|
$this->assets_path = $asset_path;
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
public function getAssetsPath(): string {
|
||
|
RETURN $this->assets_path;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Render view and return the output.
|
||
|
* Note: view should only output textual content like HTML, JSON, scripts or similar.
|
||
|
*
|
||
|
* @throws RuntimeException if view not found, not readable or returned false.
|
||
|
*/
|
||
|
public function getOutput(): string {
|
||
|
$data = $this->data;
|
||
|
|
||
|
$file_path = $this->directory.'/'.$this->name.'.php';
|
||
|
|
||
|
ob_start();
|
||
|
|
||
|
if ((include $file_path) === false) {
|
||
|
ob_end_clean();
|
||
|
|
||
|
throw new RuntimeException(sprintf('Cannot render view: "%s".', $file_path));
|
||
|
}
|
||
|
|
||
|
return ob_get_clean();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the contents of a PHP-preprocessed JavaScript file.
|
||
|
* Notes:
|
||
|
* - JavaScript file will be searched in the "js" subdirectory of the view file.
|
||
|
* - A copy of $data variable will be available for using within the file.
|
||
|
*
|
||
|
* @param string $file_name
|
||
|
* @param array|null $data
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function readJsFile(string $file_name, array $data = null, $relative_dir = '/js'): string {
|
||
|
$data = $data ?? $this->data;
|
||
|
|
||
|
$file_path = $this->directory.$relative_dir.'/'.$file_name;
|
||
|
|
||
|
ob_start();
|
||
|
|
||
|
if ((include $file_path) === false) {
|
||
|
ob_end_clean();
|
||
|
|
||
|
throw new RuntimeException(sprintf('Cannot read file: "%s".', $file_path));
|
||
|
}
|
||
|
|
||
|
return ob_get_clean();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Include a PHP-preprocessed JavaScript file inline.
|
||
|
* Notes:
|
||
|
* - JavaScript file will be searched in the "js" subdirectory of the view file.
|
||
|
* - A copy of $data variable will be available for using within the file.
|
||
|
*
|
||
|
* @throws RuntimeException if the file not found, not readable or returned false.
|
||
|
*/
|
||
|
public function includeJsFile(string $file_name, array $data = null): self {
|
||
|
echo $this->readJsFile($file_name, $data);
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Add a native JavaScript file to this view.
|
||
|
*/
|
||
|
public function addJsFile(string $js): self {
|
||
|
$this->js_files[] = $js;
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get list of native JavaScript files added to this view.
|
||
|
*/
|
||
|
public function getJsFiles(): array {
|
||
|
return $this->js_files;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Add a CSS file to this view.
|
||
|
*/
|
||
|
public function addCssFile($css): self {
|
||
|
$this->css_files[] = $css;
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get list of CSS files added to this view.
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
public function getCssFiles(): array {
|
||
|
return $this->css_files;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Enable support of web layout modes.
|
||
|
*/
|
||
|
public function enableLayoutModes(): self {
|
||
|
$this->layout_modes_enabled = true;
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set layout mode explicitly.
|
||
|
*
|
||
|
* @param int $layout_mode ZBX_LAYOUT_NORMAL | ZBX_LAYOUT_KIOSKMODE
|
||
|
*/
|
||
|
public function setLayoutMode(int $layout_mode): self {
|
||
|
$this->layout_mode = $layout_mode;
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get current layout mode.
|
||
|
*
|
||
|
* @return int ZBX_LAYOUT_NORMAL | ZBX_LAYOUT_KIOSKMODE
|
||
|
*/
|
||
|
public function getLayoutMode(): int {
|
||
|
if ($this->layout_modes_enabled) {
|
||
|
return $this->layout_mode ?? CViewHelper::loadLayoutMode();
|
||
|
}
|
||
|
|
||
|
return ZBX_LAYOUT_NORMAL;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Register custom directory of MVC views. The last registered will have the first priority.
|
||
|
*/
|
||
|
public static function registerDirectory(string $directory): void {
|
||
|
if (!in_array($directory, self::$directories, true)) {
|
||
|
array_unshift(self::$directories, $directory);
|
||
|
}
|
||
|
}
|
||
|
}
|