mirror of
https://github.com/scummvm/scummvm-web.git
synced 2026-05-21 05:40:47 +00:00
710b95a5f4
When PHP functions fail they often return false instead of the expected object type. CHeck for this value and fail properly.
250 lines
8.2 KiB
PHP
250 lines
8.2 KiB
PHP
<?php
|
|
namespace ScummVM;
|
|
|
|
use Smarty\Smarty;
|
|
use Smarty\Template;
|
|
use ScummVM\Models\SimpleYamlModel;
|
|
use ScummVM\SiteUtils;
|
|
|
|
/**
|
|
* The Controller class will create an instance of the Smarty object configured
|
|
* as specified in config.inc. Should be subclassed by all webpages so they can
|
|
* take advantage of Smarty.
|
|
*/
|
|
class Controller
|
|
{
|
|
protected string $template;
|
|
private Smarty $smarty;
|
|
/** @var string[] */
|
|
private array $css_files;
|
|
/** @var string[] */
|
|
private array $js_files;
|
|
private SimpleYamlModel $menuModel;
|
|
|
|
/**
|
|
* Constructor that will create a Smarty object and configure it according
|
|
* to what's been specified in config.inc.
|
|
*/
|
|
public function __construct()
|
|
{
|
|
/* Create a Smarty object. */
|
|
$this->smarty = new Smarty();
|
|
|
|
global $lang;
|
|
global $available_languages;
|
|
|
|
/* Configure smarty. */
|
|
$this->smarty->setCompileDir(SMARTY_DIR_COMPILE);
|
|
$this->smarty->setCacheDir(SMARTY_DIR_CACHE);
|
|
$this->smarty->setTemplateDir(SMARTY_DIR_TEMPLATE);
|
|
$this->smarty->compile_id = $lang;
|
|
|
|
// First we read English, so all defaults are there
|
|
$this->smarty->configLoad(join(DIRECTORY_SEPARATOR, [DIR_DATA, DEFAULT_LOCALE, "strings.ini"]));
|
|
|
|
// Now we try to read translations
|
|
if (is_file(($fname = join(DIRECTORY_SEPARATOR, [DIR_DATA, $lang, "strings.ini"])))
|
|
&& is_readable($fname)
|
|
) {
|
|
$this->smarty->configLoad($fname);
|
|
}
|
|
|
|
/**
|
|
* Add a output-filter to make sure ampersands are properly encoded to
|
|
* HTML-entities.
|
|
*/
|
|
$this->smarty->registerFilter('output', array($this, 'outputFilter'));
|
|
|
|
/* Give Smarty-template access to date(). */
|
|
$this->smarty->registerPlugin('modifier', 'date_localized', array(&$this, 'dateLocalizedSmartyModifier'));
|
|
$this->smarty->registerPlugin('modifier', 'lang', array(SiteUtils::class, 'localizePath'));
|
|
$this->smarty->registerPlugin('modifier', 'download', array(&$this, 'downloadsSmartyModifier'));
|
|
$this->smarty->registerPlugin('modifier', 'release', array(&$this, 'releaseSmartyModifier'));
|
|
|
|
/* Register PHP functions used by pages */
|
|
$this->smarty->registerPlugin('modifier', 'htmlspecialchars', '\htmlspecialchars');
|
|
$this->smarty->registerPlugin('modifier', 'locale_get_display_language', '\locale_get_display_language');
|
|
$this->smarty->registerPlugin('modifier', 'preg_replace', '\preg_replace');
|
|
$this->smarty->registerPlugin('modifier', 'rand', '\rand');
|
|
$this->smarty->registerPlugin('modifier', 'str_contains', '\str_contains');
|
|
$this->smarty->registerPlugin('modifier', 'strpos', '\strpos');
|
|
|
|
$this->css_files = array();
|
|
$this->js_files = array();
|
|
|
|
$this->menuModel = new SimpleYamlModel("MenuItem", "menus.yaml");
|
|
$menus = [];
|
|
/* The menus have caused an exception, need to skip them. */
|
|
if (!ExceptionHandler::skipMenus()) {
|
|
$menus = $this->menuModel->getAllData();
|
|
}
|
|
|
|
// Construct lang URL
|
|
$langs = join("|", array_keys($available_languages));
|
|
$pageurl = preg_replace("/\/\b($langs)\b\/?/i", '/', $_SERVER['REQUEST_URI']);
|
|
// Remove leading /
|
|
$pageurl = substr($pageurl, 1);
|
|
/* Check RTL */
|
|
$rtl = $this->isRtl($available_languages[$lang]);
|
|
|
|
/* Set up the common variables before displaying. */
|
|
$vars = array(
|
|
'release' => RELEASE,
|
|
'baseurl' => URL_BASE,
|
|
'heroes_num' => HEROES_NUM,
|
|
'menus' => $menus,
|
|
'pageurl' => $pageurl,
|
|
'themes' => THEMES,
|
|
'available_languages' => $available_languages,
|
|
'lang' => $lang,
|
|
'rtl' => $rtl,
|
|
);
|
|
$this->smarty->assign($vars);
|
|
}
|
|
|
|
/**
|
|
* Checks whether a locale string is RTL or LTR
|
|
*/
|
|
private function isRtl(string $localeName): bool
|
|
{
|
|
$rtl_chars_pattern = '/[\x{0590}-\x{05ff}\x{0600}-\x{06ff}]/u';
|
|
return preg_match($rtl_chars_pattern, $localeName) === 1;
|
|
}
|
|
|
|
/**
|
|
* Smarty outputfilter, run just before displaying.
|
|
*/
|
|
public function outputFilter(string $string, Template $smarty): string
|
|
{
|
|
/* Properly encode all ampersands as "&". */
|
|
$string = preg_replace('/&(?!([a-z]+|(#\d+));)/i', '&', $string);
|
|
/* Replace weird characters that appears in some of the data. */
|
|
return $string;
|
|
}
|
|
|
|
/**
|
|
* Formating of dateAs, registered as a modifier for Smarty templates.
|
|
*/
|
|
public function dateLocalizedSmartyModifier(int $timestamp): string
|
|
{
|
|
global $lang;
|
|
$formatter = new \IntlDateFormatter($lang, \IntlDateFormatter::MEDIUM, \IntlDateFormatter::NONE);
|
|
$ret = $formatter->format($timestamp);
|
|
if ($ret === false) {
|
|
$ret = '';
|
|
}
|
|
return $ret;
|
|
}
|
|
|
|
/**
|
|
* Formating of download URLs, registered as a modifier for Smarty templates.
|
|
*/
|
|
public function downloadsSmartyModifier(string $path): string
|
|
{
|
|
if (\strpos($path, "http") === 0) {
|
|
return $path;
|
|
} elseif (\strpos($path, "/frs") === 0) {
|
|
return DOWNLOADS_BASE . $path;
|
|
} elseif (\strpos($path, "frs") === 0) {
|
|
return DOWNLOADS_BASE . "/$path";
|
|
}
|
|
|
|
return $path;
|
|
}
|
|
|
|
/**
|
|
* Formating of version, registered as a modifier for Smarty templates.
|
|
*/
|
|
public function releaseSmartyModifier(string $string): string
|
|
{
|
|
$string = preg_replace("/\{[$]?release\}/", RELEASE, $string);
|
|
$string = preg_replace("/\{[$]?release_tools\}/", RELEASE_TOOLS, $string);
|
|
return $string;
|
|
}
|
|
|
|
/* Render the HTML using the template and any set variables and displays it. */
|
|
public function display(string $content): void
|
|
{
|
|
$vars = array(
|
|
'css_files' => $this->css_files,
|
|
'js_files' => $this->js_files,
|
|
'content' => $content,
|
|
);
|
|
$this->smarty->assign($vars);
|
|
$this->smarty->display('pages/index.tpl');
|
|
}
|
|
|
|
/* Render the HTML using the template and any set variables and returns it. */
|
|
/**
|
|
* @param ?array<string, mixed> $vars
|
|
*/
|
|
public function fetch(string $template, ?array $vars = null): string
|
|
{
|
|
if (!is_null($vars)) {
|
|
$this->smarty->assign($vars);
|
|
}
|
|
return $this->smarty->fetch($template);
|
|
}
|
|
|
|
/* Set up the variables used by the template and render the page. */
|
|
/**
|
|
* @param ?array<string, mixed> $vars
|
|
*/
|
|
public function renderPage(?array $vars): void
|
|
{
|
|
$this->display($this->fetch($this->template, $vars));
|
|
}
|
|
|
|
/* Assign extra CSS files needed by the different pages/templates. */
|
|
/**
|
|
* @param string|string[] $extra_css
|
|
*/
|
|
public function addCSSFiles(string|array $extra_css): void
|
|
{
|
|
if (is_array($extra_css)) {
|
|
$this->css_files = array_merge(
|
|
$this->css_files,
|
|
$extra_css
|
|
);
|
|
} elseif (strlen($extra_css) > 0) {
|
|
$this->css_files[] = $extra_css;
|
|
}
|
|
}
|
|
|
|
/* Assign javascripts files needed by the different pages/templates. */
|
|
/**
|
|
* @param string|string[] $extra_js
|
|
*/
|
|
public function addJSFiles(string|array $extra_js): void
|
|
{
|
|
if (is_array($extra_js)) {
|
|
$this->js_files = array_merge(
|
|
$this->js_files,
|
|
$extra_js
|
|
);
|
|
} elseif (strlen($extra_js) > 0) {
|
|
$this->js_files[] = $extra_js;
|
|
}
|
|
}
|
|
|
|
protected function getConfigVars(string $title): ?string
|
|
{
|
|
return $this->smarty->getConfigVars($title);
|
|
}
|
|
|
|
protected function getHeadline(string $body): string
|
|
{
|
|
$headline = '';
|
|
for ($line = \strtok($body, PHP_EOL); $line !== false; $line = \strtok(PHP_EOL)) {
|
|
$line = \strip_tags($line);
|
|
$headline .= $line . ' ';
|
|
if (\strlen($headline) > 250) {
|
|
$headline = substr($headline, 0, 249);
|
|
$headline .= "\u{2026}";
|
|
break;
|
|
}
|
|
}
|
|
return $headline;
|
|
}
|
|
}
|