phpmyadmin/src/Template.php
Maurício Meneghini Fauth 90ee00efd5
Create the 'pma' global variable for Twig templates
Creates the Twig\PmaGlobalVariable class to handle the 'pma' Twig global
variable.

The idea of this global variable is to automatically inject in all
templates some useful information.

For now it only includes `pma.version` to get the phpMyAdmin version
and `pma.text_dir` to get the text direction ('ltr' or 'rtl').

Adding new variables to the `pma` global variable should be done with
caution.

- https://twig.symfony.com/doc/3.x/advanced.html#globals

Signed-off-by: Maurício Meneghini Fauth <mauricio@fauth.dev>
2024-07-09 20:30:48 -03:00

132 lines
3.8 KiB
PHP

<?php
declare(strict_types=1);
namespace PhpMyAdmin;
use PhpMyAdmin\Container\ContainerBuilder;
use PhpMyAdmin\Twig\AssetExtension;
use PhpMyAdmin\Twig\CoreExtension;
use PhpMyAdmin\Twig\FlashMessengerExtension;
use PhpMyAdmin\Twig\I18nExtension;
use PhpMyAdmin\Twig\MessageExtension;
use PhpMyAdmin\Twig\PmaGlobalVariable;
use PhpMyAdmin\Twig\SanitizeExtension;
use PhpMyAdmin\Twig\TransformationsExtension;
use PhpMyAdmin\Twig\UrlExtension;
use PhpMyAdmin\Twig\UtilExtension;
use RuntimeException;
use Throwable;
use Twig\Environment;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Error\SyntaxError;
use Twig\Extension\DebugExtension;
use Twig\Loader\FilesystemLoader;
use Twig\RuntimeLoader\ContainerRuntimeLoader;
use Twig\TemplateWrapper;
/**
* Handle front end templating
*/
class Template
{
/**
* Twig environment
*/
protected static Environment|null $twig = null;
public const TEMPLATES_FOLDER = ROOT_PATH . 'resources/templates';
private Config $config;
public function __construct(Config|null $config = null)
{
$this->config = $config ?? Config::getInstance();
}
public static function getTwigEnvironment(string|null $cacheDir, bool $isDevEnv): Environment
{
/* Twig expects false when cache is not configured */
if ($cacheDir === null) {
$cacheDir = false;
}
$loader = new FilesystemLoader(self::TEMPLATES_FOLDER);
$twig = new Environment($loader, ['auto_reload' => true, 'cache' => $cacheDir]);
$twig->addRuntimeLoader(new ContainerRuntimeLoader(ContainerBuilder::getContainer()));
if ($isDevEnv) {
$twig->enableDebug();
$twig->enableStrictVariables();
$twig->addExtension(new DebugExtension());
} else {
$twig->disableDebug();
$twig->disableStrictVariables();
}
$twig->addGlobal('pma', new PmaGlobalVariable());
$twig->addExtension(new AssetExtension());
$twig->addExtension(new CoreExtension());
$twig->addExtension(new FlashMessengerExtension());
$twig->addExtension(new I18nExtension());
$twig->addExtension(new MessageExtension());
$twig->addExtension(new SanitizeExtension());
$twig->addExtension(new TransformationsExtension());
$twig->addExtension(new UrlExtension());
$twig->addExtension(new UtilExtension());
return $twig;
}
/**
* Loads a template.
*
* @param string $templateName Template path name
*
* @throws LoaderError
* @throws RuntimeError
* @throws SyntaxError
*/
private function load(string $templateName): TemplateWrapper
{
if (static::$twig === null) {
$isDevEnv = $this->config->config->environment === 'development';
static::$twig = self::getTwigEnvironment(CACHE_DIR . 'twig', $isDevEnv);
}
try {
return static::$twig->load($templateName . '.twig');
} catch (RuntimeException) { // @phpstan-ignore-line thrown by Twig\Cache\FilesystemCache
/* Retry with disabled cache */
static::$twig->setCache(false);
return static::$twig->load($templateName . '.twig');
}
}
/**
* @param string $template Template path name
* @param mixed[] $data Associative array of template variables
*
* @throws Throwable
* @throws LoaderError
* @throws RuntimeError
* @throws SyntaxError
*/
public function render(string $template, array $data = []): string
{
return $this->load($template)->render($data);
}
public function disableCache(): void
{
if (static::$twig === null) {
static::$twig = self::getTwigEnvironment(null, false);
}
static::$twig->setCache(false);
}
}