Files
wp-bootstrap/inc/Twig/TwigService.php

168 lines
5.7 KiB
PHP
Raw Normal View History

<?php
/**
* Twig Template Engine Service.
*
* @package WPBootstrap
* @since 0.0.1
*/
namespace WPBootstrap\Twig;
use Twig\Environment;
use Twig\Loader\FilesystemLoader;
use Twig\TwigFunction;
use Twig\TwigFilter;
class TwigService
{
private static ?TwigService $instance = null;
private Environment $twig;
private function __construct()
{
$viewsDir = get_template_directory() . '/views';
$cacheDir = WP_CONTENT_DIR . '/cache/twig';
$loader = new FilesystemLoader($viewsDir);
$this->twig = new Environment($loader, [
'cache' => WP_DEBUG ? false : $cacheDir,
'debug' => WP_DEBUG,
'auto_reload' => true,
]);
$this->registerWordPressFunctions();
$this->registerWordPressGlobals();
$this->registerFilters();
}
public static function getInstance(): self
{
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
public function render(string $template, array $context = []): string
{
return $this->twig->render($template, $context);
}
public function display(string $template, array $context = []): void
{
$this->twig->display($template, $context);
}
public function getEnvironment(): Environment
{
return $this->twig;
}
private function registerWordPressFunctions(): void
{
// Translation functions.
$this->twig->addFunction(new TwigFunction('__', function (string $text, string $domain = 'wp-bootstrap'): string {
return __($text, $domain);
}));
$this->twig->addFunction(new TwigFunction('_e', function (string $text, string $domain = 'wp-bootstrap'): void {
_e($text, $domain);
}));
$this->twig->addFunction(new TwigFunction('_n', function (string $single, string $plural, int $number, string $domain = 'wp-bootstrap'): string {
return _n($single, $plural, $number, $domain);
}));
// Escaping functions.
$this->twig->addFunction(new TwigFunction('esc_html', 'esc_html'));
$this->twig->addFunction(new TwigFunction('esc_attr', 'esc_attr'));
$this->twig->addFunction(new TwigFunction('esc_url', 'esc_url'));
// WordPress head/footer output (captured via output buffering).
$this->twig->addFunction(new TwigFunction('wp_head', function (): string {
ob_start();
wp_head();
return ob_get_clean();
}, ['is_safe' => ['html']]));
$this->twig->addFunction(new TwigFunction('wp_footer', function (): string {
ob_start();
wp_footer();
return ob_get_clean();
}, ['is_safe' => ['html']]));
$this->twig->addFunction(new TwigFunction('wp_body_open', function (): string {
ob_start();
wp_body_open();
return ob_get_clean();
}, ['is_safe' => ['html']]));
// HTML attribute helpers.
$this->twig->addFunction(new TwigFunction('language_attributes', function (): string {
ob_start();
language_attributes();
return ob_get_clean();
}, ['is_safe' => ['html']]));
$this->twig->addFunction(new TwigFunction('body_class', function (string $extra = ''): string {
ob_start();
body_class($extra);
return ob_get_clean();
}, ['is_safe' => ['html']]));
// URL and info helpers.
$this->twig->addFunction(new TwigFunction('home_url', function (string $path = '/'): string {
return home_url($path);
}));
$this->twig->addFunction(new TwigFunction('get_template_directory_uri', function (): string {
return get_template_directory_uri();
}));
$this->twig->addFunction(new TwigFunction('get_bloginfo', function (string $show): string {
return get_bloginfo($show);
}));
$this->twig->addFunction(new TwigFunction('get_search_query', function (): string {
return get_search_query();
}));
// Content filtering.
$this->twig->addFunction(new TwigFunction('wp_kses_post', function (string $content): string {
return wp_kses_post($content);
}, ['is_safe' => ['html']]));
$this->twig->addFunction(new TwigFunction('do_shortcode', function (string $content): string {
return do_shortcode($content);
}, ['is_safe' => ['html']]));
// Formatting.
$this->twig->addFunction(new TwigFunction('number_format_i18n', function (float $number, int $decimals = 0): string {
return number_format_i18n($number, $decimals);
}));
// Block template parts (allows FSE Template Editor changes to take effect).
$this->twig->addFunction(new TwigFunction('block_template_part', function (string $part): string {
ob_start();
block_template_part($part);
return ob_get_clean();
}, ['is_safe' => ['html']]));
}
private function registerWordPressGlobals(): void
{
$this->twig->addGlobal('site_name', get_bloginfo('name'));
$this->twig->addGlobal('site_description', get_bloginfo('description'));
$this->twig->addGlobal('site_url', home_url('/'));
$this->twig->addGlobal('theme_uri', get_template_directory_uri());
$this->twig->addGlobal('charset', get_bloginfo('charset'));
$this->twig->addGlobal('current_year', date('Y'));
}
private function registerFilters(): void
{
$this->twig->addFilter(new TwigFilter('wpautop', 'wpautop', ['is_safe' => ['html']]));
$this->twig->addFilter(new TwigFilter('wp_kses_post', 'wp_kses_post', ['is_safe' => ['html']]));
}
}