performance improvements (#2329)

* remove work from constructor
* refactor twig extensions
* upgrade theme
* replace sub-request with direct template rendering
This commit is contained in:
Kevin Papst
2021-02-20 23:52:01 +01:00
committed by GitHub
parent 9eb25c412e
commit 607d09aefb
40 changed files with 992 additions and 1092 deletions

View File

@@ -9,18 +9,18 @@
namespace App\Twig;
use App\Configuration\ThemeConfiguration;
use App\Configuration\SystemConfiguration;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
class ConfigExtension extends AbstractExtension
final class ConfigExtension extends AbstractExtension
{
/**
* @var ThemeConfiguration
* @var SystemConfiguration
*/
protected $configuration;
private $configuration;
public function __construct(ThemeConfiguration $configuration)
public function __construct(SystemConfiguration $configuration)
{
$this->configuration = $configuration;
}
@@ -41,6 +41,15 @@ class ConfigExtension extends AbstractExtension
*/
public function getThemeConfig(string $name)
{
switch ($name) {
case 'soft_limit':
return $this->configuration->getTimesheetActiveEntriesSoftLimit();
default:
$name = 'theme.' . $name;
break;
}
return $this->configuration->find($name);
}
}

View File

@@ -1,189 +0,0 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Twig;
use App\Configuration\LanguageFormattings;
use App\Constants;
use App\Entity\User;
use App\Utils\LocaleFormats;
use App\Utils\LocaleFormatter;
use DateTime;
use Symfony\Component\HttpFoundation\RequestStack;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
use Twig\TwigFunction;
use Twig\TwigTest;
/**
* Date specific twig extensions
*/
class DateExtensions extends AbstractExtension
{
/**
* @var LocaleFormats|null
*/
protected $localeFormats = null;
/**
* @var LocaleFormatter
*/
private $formatter;
/**
* @var LanguageFormattings
*/
private $formats;
public function __construct(RequestStack $requestStack, LanguageFormattings $formats)
{
$locale = Constants::DEFAULT_LOCALE;
// request is null in a console command
if (null !== $requestStack->getMasterRequest()) {
$locale = $requestStack->getMasterRequest()->getLocale();
}
$this->formats = $formats;
$this->setLocale($locale);
}
/**
* {@inheritdoc}
*/
public function getFilters()
{
return [
new TwigFilter('month_name', [$this, 'monthName']),
new TwigFilter('day_name', [$this, 'dayName']),
new TwigFilter('date_short', [$this, 'dateShort']),
new TwigFilter('date_time', [$this, 'dateTime']),
new TwigFilter('date_full', [$this, 'dateTimeFull']),
new TwigFilter('date_format', [$this, 'dateFormat']),
new TwigFilter('time', [$this, 'time']),
new TwigFilter('hour24', [$this, 'hour24']),
];
}
public function getTests()
{
return [
new TwigTest('weekend', function ($dateTime) {
if (!$dateTime instanceof \DateTime) {
return false;
}
$day = (int) $dateTime->format('w');
return ($day === 0 || $day === 6);
}),
];
}
/**
* {@inheritdoc}
*/
public function getFunctions()
{
return [
new TwigFunction('get_format_duration', [$this, 'getDurationFormat']),
new TwigFunction('create_date', [$this, 'createDate']),
];
}
/**
* Allows to switch the locale used for all twig filter and functions.
*
* @param string $locale
*/
public function setLocale(string $locale)
{
$this->formatter = new LocaleFormatter($this->formats, $locale);
$this->localeFormats = new LocaleFormats($this->formats, $locale);
}
/**
* @param DateTime|string $date
* @return string
*/
public function dateShort($date)
{
return $this->formatter->dateShort($date);
}
/**
* @param DateTime|string $date
* @return string
*/
public function dateTime($date)
{
return $this->formatter->dateTime($date);
}
/**
* @param DateTime|string $date
* @return bool|false|string
*/
public function dateTimeFull($date)
{
return $this->formatter->dateTimeFull($date);
}
public function createDate(string $date, ?User $user = null): \DateTime
{
$timezone = $user !== null ? $user->getTimezone() : date_default_timezone_get();
return new DateTime($date, new \DateTimeZone($timezone));
}
/**
* @param DateTime|string $date
* @param string $format
* @return false|string
* @throws \Exception
*/
public function dateFormat($date, string $format)
{
return $this->formatter->dateFormat($date, $format);
}
/**
* @param DateTime|string $date
* @return string
*/
public function time($date)
{
return $this->formatter->time($date);
}
public function monthName(\DateTime $dateTime, bool $withYear = false): string
{
return $this->formatter->monthName($dateTime, $withYear);
}
public function dayName(\DateTime $dateTime, bool $short = false): string
{
return $this->formatter->dayName($dateTime, $short);
}
/**
* @param mixed $twentyFour
* @param mixed $twelveHour
* @return mixed
*/
public function hour24($twentyFour, $twelveHour)
{
return $this->formatter->hour24($twentyFour, $twelveHour);
}
/**
* @return string
*/
public function getDurationFormat()
{
return $this->localeFormats->getDurationFormat();
}
}

View File

@@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Twig;
use App\Twig\Runtime\ThemeEventExtension;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
class EventExtensions extends AbstractExtension
{
/**
* {@inheritdoc}
*/
public function getFunctions()
{
return [
new TwigFunction('trigger', [ThemeEventExtension::class, 'trigger']),
new TwigFunction('javascript_translations', [ThemeEventExtension::class, 'getJavascriptTranslations']),
];
}
}

View File

@@ -1,169 +0,0 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Twig;
use App\Configuration\LanguageFormattings;
use App\Constants;
use App\Entity\Timesheet;
use App\Utils\Duration;
use App\Utils\LocaleFormatter;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Intl\Locales;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
use Twig\TwigFunction;
/**
* Locale specific Twig extensions
*/
final class LocaleExtensions extends AbstractExtension
{
/**
* @var LocaleFormatter
*/
private $formatter;
/**
* @var LanguageFormattings
*/
private $formats;
public function __construct(RequestStack $requestStack, LanguageFormattings $formats)
{
$locale = Constants::DEFAULT_LOCALE;
// request is null in a console command
if (null !== $requestStack->getMasterRequest()) {
$locale = $requestStack->getMasterRequest()->getLocale();
}
$this->formats = $formats;
$this->setLocale($locale);
}
/**
* {@inheritdoc}
*/
public function getFilters()
{
return [
new TwigFilter('duration', [$this, 'duration']),
new TwigFilter('duration_decimal', [$this, 'durationDecimal']),
new TwigFilter('money', [$this, 'money']),
new TwigFilter('currency', [$this, 'currency']),
new TwigFilter('country', [$this, 'country']),
new TwigFilter('language', [$this, 'language']),
new TwigFilter('amount', [$this, 'amount']),
];
}
/**
* {@inheritdoc}
*/
public function getFunctions()
{
return [
new TwigFunction('locales', [$this, 'getLocales']),
];
}
/**
* Allows to switch the locale used for all twig filter and functions.
*
* @param string $locale
*/
public function setLocale(string $locale)
{
$this->formatter = new LocaleFormatter($this->formats, $locale);
}
/**
* Transforms seconds into a duration string.
*
* @param int|Timesheet|null $duration
* @param bool $decimal
* @return string
*/
public function duration($duration, $decimal = false)
{
return $this->formatter->duration($duration, $decimal);
}
/**
* Transforms seconds into a decimal formatted duration string.
*
* @param int|Timesheet|null $duration
* @return string
*/
public function durationDecimal($duration)
{
return $this->formatter->durationDecimal($duration);
}
/**
* @param string|float $amount
* @return bool|false|string
*/
public function amount($amount)
{
return $this->formatter->amount($amount);
}
/**
* Returns the currency symbol.
*
* @param string $currency
* @return string
*/
public function currency($currency)
{
return $this->formatter->currency($currency);
}
/**
* @param string $language
* @return string
*/
public function language($language)
{
return $this->formatter->language($language);
}
/**
* @param string $country
* @return string
*/
public function country($country)
{
return $this->formatter->country($country);
}
/**
* @param float $amount
* @param string|null $currency
* @param bool $withCurrency
* @return string
*/
public function money($amount, ?string $currency = null, bool $withCurrency = true)
{
return $this->formatter->money($amount, $currency, $withCurrency);
}
/**
* Takes the list of codes of the locales (languages) enabled in the
* application and returns an array with the name of each locale written
* in its own language (e.g. English, Français, Español, etc.)
*
* @return array
*/
public function getLocales()
{
return $this->formatter->getLocales();
}
}

View File

@@ -0,0 +1,298 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Twig;
use App\Configuration\LanguageFormattings;
use App\Entity\Timesheet;
use App\Entity\User;
use App\Utils\LocaleFormats;
use App\Utils\LocaleFormatter;
use DateTime;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
use Twig\TwigFunction;
use Twig\TwigTest;
final class LocaleFormatExtensions extends AbstractExtension
{
/**
* @var LanguageFormattings|null
*/
private $formats;
/**
* @var LocaleFormats|null
*/
private $localeFormats;
/**
* @var LocaleFormatter|null
*/
private $formatter;
/**
* @var string
*/
private $locale;
public function __construct(LanguageFormattings $formats)
{
$this->formats = $formats;
}
/**
* {@inheritdoc}
*/
public function getFilters()
{
return [
new TwigFilter('month_name', [$this, 'monthName']),
new TwigFilter('day_name', [$this, 'dayName']),
new TwigFilter('date_short', [$this, 'dateShort']),
new TwigFilter('date_time', [$this, 'dateTime']),
new TwigFilter('date_full', [$this, 'dateTimeFull']),
new TwigFilter('date_format', [$this, 'dateFormat']),
new TwigFilter('time', [$this, 'time']),
new TwigFilter('hour24', [$this, 'hour24']),
new TwigFilter('duration', [$this, 'duration']),
new TwigFilter('duration_decimal', [$this, 'durationDecimal']),
new TwigFilter('money', [$this, 'money']),
new TwigFilter('currency', [$this, 'currency']),
new TwigFilter('country', [$this, 'country']),
new TwigFilter('language', [$this, 'language']),
new TwigFilter('amount', [$this, 'amount']),
];
}
public function getTests()
{
return [
new TwigTest('weekend', function ($dateTime) {
if (!$dateTime instanceof \DateTime) {
return false;
}
$day = (int) $dateTime->format('w');
return ($day === 0 || $day === 6);
}),
];
}
/**
* {@inheritdoc}
*/
public function getFunctions()
{
return [
new TwigFunction('get_format_duration', [$this, 'getDurationFormat']),
new TwigFunction('create_date', [$this, 'createDate']),
new TwigFunction('locales', [$this, 'getLocales']),
];
}
/**
* Allows to switch the locale used for all twig filter and functions.
*
* @param string $locale
*/
public function setLocale(string $locale)
{
$this->locale = $locale;
$this->formatter = null;
$this->localeFormats = null;
}
private function getLocaleFormats(): LocaleFormats
{
if (null === $this->localeFormats) {
$this->localeFormats = new LocaleFormats($this->formats, $this->getLocale());
}
return $this->localeFormats;
}
private function getFormatter(): LocaleFormatter
{
if (null === $this->formatter) {
$this->formatter = new LocaleFormatter($this->formats, $this->getLocale());
}
return $this->formatter;
}
private function getLocale()
{
if (null === $this->locale) {
$this->locale = \Locale::getDefault();
}
return $this->locale;
}
/**
* @param DateTime|string $date
* @return string
*/
public function dateShort($date)
{
return $this->getFormatter()->dateShort($date);
}
/**
* @param DateTime|string $date
* @return string
*/
public function dateTime($date)
{
return $this->getFormatter()->dateTime($date);
}
/**
* @param DateTime|string $date
* @return bool|false|string
*/
public function dateTimeFull($date)
{
return $this->getFormatter()->dateTimeFull($date);
}
public function createDate(string $date, ?User $user = null): \DateTime
{
$timezone = $user !== null ? $user->getTimezone() : date_default_timezone_get();
return new DateTime($date, new \DateTimeZone($timezone));
}
/**
* @param DateTime|string $date
* @param string $format
* @return false|string
* @throws \Exception
*/
public function dateFormat($date, string $format)
{
return $this->getFormatter()->dateFormat($date, $format);
}
/**
* @param DateTime|string $date
* @return string
*/
public function time($date)
{
return $this->getFormatter()->time($date);
}
public function monthName(\DateTime $dateTime, bool $withYear = false): string
{
return $this->getFormatter()->monthName($dateTime, $withYear);
}
public function dayName(\DateTime $dateTime, bool $short = false): string
{
return $this->getFormatter()->dayName($dateTime, $short);
}
/**
* @param mixed $twentyFour
* @param mixed $twelveHour
* @return mixed
*/
public function hour24($twentyFour, $twelveHour)
{
return $this->getFormatter()->hour24($twentyFour, $twelveHour);
}
public function getDurationFormat(): string
{
return $this->getLocaleFormats()->getDurationFormat();
}
/**
* Transforms seconds into a duration string.
*
* @param int|Timesheet|null $duration
* @param bool $decimal
* @return string
*/
public function duration($duration, $decimal = false)
{
return $this->getFormatter()->duration($duration, $decimal);
}
/**
* Transforms seconds into a decimal formatted duration string.
*
* @param int|Timesheet|null $duration
* @return string
*/
public function durationDecimal($duration)
{
return $this->getFormatter()->durationDecimal($duration);
}
/**
* @param string|float $amount
* @return bool|false|string
*/
public function amount($amount)
{
return $this->getFormatter()->amount($amount);
}
/**
* Returns the currency symbol.
*
* @param string $currency
* @return string
*/
public function currency($currency)
{
return $this->getFormatter()->currency($currency);
}
/**
* @param string $language
* @return string
*/
public function language($language)
{
return $this->getFormatter()->language($language);
}
/**
* @param string $country
* @return string
*/
public function country($country)
{
return $this->getFormatter()->country($country);
}
/**
* @param float $amount
* @param string|null $currency
* @param bool $withCurrency
* @return string
*/
public function money($amount, ?string $currency = null, bool $withCurrency = true)
{
return $this->getFormatter()->money($amount, $currency, $withCurrency);
}
/**
* Takes the list of codes of the locales (languages) enabled in the
* application and returns an array with the name of each locale written
* in its own language (e.g. English, Français, Español, etc.)
*
* @return array
*/
public function getLocales()
{
return $this->getFormatter()->getLocales();
}
}

View File

@@ -31,7 +31,6 @@ class PaginationExtension extends AbstractExtension
public function __construct(UrlGeneratorInterface $router)
{
$this->view = new TwitterBootstrap3View();
$this->router = $router;
}
@@ -46,6 +45,15 @@ class PaginationExtension extends AbstractExtension
];
}
private function getView(): ViewInterface
{
if (null === $this->view) {
$this->view = new TwitterBootstrap3View();
}
return $this->view;
}
/**
* @deprecated since 1.8
*/
@@ -70,7 +78,7 @@ class PaginationExtension extends AbstractExtension
$options['prev_message'] = '<i class="fas fa-chevron-left"></i>';
$options['next_message'] = '<i class="fas fa-chevron-right"></i>';
return $this->view->render($pagerfanta, $routeGenerator, $options);
return $this->getView()->render($pagerfanta, $routeGenerator, $options);
}
private function createRouteGenerator(array $options = [])

View File

@@ -7,15 +7,14 @@
* file that was distributed with this source code.
*/
namespace App\Twig;
namespace App\Twig\Runtime;
use Psr\Container\ContainerInterface;
use Symfony\Contracts\Service\ServiceSubscriberInterface;
use Symfony\WebpackEncoreBundle\Asset\EntrypointLookupInterface;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
use Twig\Extension\RuntimeExtensionInterface;
class EncoreExtension extends AbstractExtension implements ServiceSubscriberInterface
final class EncoreExtension implements RuntimeExtensionInterface, ServiceSubscriberInterface
{
/**
* @var string
@@ -39,16 +38,6 @@ class EncoreExtension extends AbstractExtension implements ServiceSubscriberInte
];
}
/**
* {@inheritdoc}
*/
public function getFunctions()
{
return [
new TwigFunction('encore_entry_css_source', [$this, 'getEncoreEntryCssSource']),
];
}
public function getEncoreEntryCssSource(string $packageName): string
{
$lookup = $this->container->get(EntrypointLookupInterface::class);

View File

@@ -7,13 +7,12 @@
* file that was distributed with this source code.
*/
namespace App\Twig;
namespace App\Twig\Runtime;
use App\Export\ServiceExport;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
use Twig\Extension\RuntimeExtensionInterface;
class TimesheetExtension extends AbstractExtension
final class ExporterExtension implements RuntimeExtensionInterface
{
/**
* @var ServiceExport
@@ -25,16 +24,6 @@ class TimesheetExtension extends AbstractExtension
$this->service = $service;
}
/**
* {@inheritdoc}
*/
public function getFunctions()
{
return [
new TwigFunction('timesheet_exporter', [$this, 'getTimesheetExporter'], []),
];
}
public function getTimesheetExporter(): array
{
$ids = [];

View File

@@ -7,17 +7,13 @@
* file that was distributed with this source code.
*/
namespace App\Twig;
namespace App\Twig\Runtime;
use App\Configuration\SystemConfiguration;
use App\Utils\Markdown;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
use Twig\Extension\RuntimeExtensionInterface;
/**
* A twig extension to handle markdown content.
*/
final class MarkdownExtension extends AbstractExtension
final class MarkdownExtension implements RuntimeExtensionInterface
{
/**
* @var Markdown
@@ -27,26 +23,24 @@ final class MarkdownExtension extends AbstractExtension
* @var SystemConfiguration
*/
private $configuration;
/**
* @param Markdown $parser
* @var bool|null
*/
private $markdownEnabled;
public function __construct(Markdown $parser, SystemConfiguration $configuration)
{
$this->markdown = $parser;
$this->configuration = $configuration;
}
/**
* @return TwigFilter[]
*/
public function getFilters()
private function isMarkdownEnabled(): bool
{
return [
new TwigFilter('md2html', [$this, 'markdownToHtml'], ['pre_escape' => 'html', 'is_safe' => ['html']]),
new TwigFilter('desc2html', [$this, 'timesheetContent'], ['pre_escape' => 'html', 'is_safe' => ['html']]),
new TwigFilter('comment2html', [$this, 'commentContent'], ['pre_escape' => 'html', 'is_safe' => ['html']]),
];
if (null === $this->markdownEnabled) {
$this->markdownEnabled = $this->configuration->isTimesheetMarkdownEnabled();
}
return $this->markdownEnabled;
}
/**
@@ -66,7 +60,7 @@ final class MarkdownExtension extends AbstractExtension
$content = trim(substr($content, 0, 100)) . ' &hellip;';
}
if ($this->configuration->isTimesheetMarkdownEnabled()) {
if ($this->isMarkdownEnabled()) {
$content = $this->markdown->toHtml($content, false);
} elseif ($fullLength) {
$content = '<p>' . nl2br($content) . '</p>';
@@ -87,7 +81,7 @@ final class MarkdownExtension extends AbstractExtension
return '';
}
if ($this->configuration->isTimesheetMarkdownEnabled()) {
if ($this->isMarkdownEnabled()) {
return $this->markdown->toHtml($content, false);
}

View File

@@ -9,37 +9,40 @@
namespace App\Twig\Runtime;
use App\Entity\User;
use App\Event\ThemeEvent;
use App\Event\ThemeJavascriptTranslationsEvent;
use App\Security\CurrentUser;
use Symfony\Bridge\Twig\AppVariable;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Twig\Environment;
use Twig\Extension\RuntimeExtensionInterface;
final class ThemeEventExtension implements RuntimeExtensionInterface
final class ThemeExtension implements RuntimeExtensionInterface
{
/**
* @var EventDispatcherInterface
*/
private $eventDispatcher;
/**
* @var CurrentUser
*/
private $user;
public function __construct(EventDispatcherInterface $dispatcher, CurrentUser $user)
public function __construct(EventDispatcherInterface $dispatcher)
{
$this->eventDispatcher = $dispatcher;
$this->user = $user;
}
/**
* @param Environment $environment
* @param string $eventName
* @param mixed|null $payload
* @return ThemeEvent
*/
public function trigger(string $eventName, $payload = null): ThemeEvent
public function trigger(Environment $environment, string $eventName, $payload = null): ThemeEvent
{
$themeEvent = new ThemeEvent($this->user->getUser(), $payload);
/** @var AppVariable $app */
$app = $environment->getGlobals()['app'];
/** @var User $user */
$user = $app->getUser();
$themeEvent = new ThemeEvent($user, $payload);
if ($this->eventDispatcher->hasListeners($eventName)) {
$this->eventDispatcher->dispatch($themeEvent, $eventName);

View File

@@ -0,0 +1,32 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Twig\Runtime;
use App\Entity\User;
use App\Repository\TimesheetRepository;
use Twig\Extension\RuntimeExtensionInterface;
final class TimesheetExtension implements RuntimeExtensionInterface
{
/**
* @var TimesheetRepository
*/
private $repository;
public function __construct(TimesheetRepository $repository)
{
$this->repository = $repository;
}
public function activeEntries(User $user): array
{
return $this->repository->getActiveEntries($user);
}
}

View File

@@ -7,37 +7,25 @@
* file that was distributed with this source code.
*/
namespace App\Twig;
namespace App\Twig\Runtime;
use App\Widget\WidgetException;
use App\Widget\WidgetInterface;
use App\Widget\WidgetService;
use InvalidArgumentException;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
use Twig\Extension\RuntimeExtensionInterface;
class WidgetExtension extends AbstractExtension
final class WidgetExtension implements RuntimeExtensionInterface
{
/**
* @var WidgetService
*/
protected $service;
private $service;
public function __construct(WidgetService $service)
{
$this->service = $service;
}
/**
* {@inheritdoc}
*/
public function getFunctions()
{
return [
new TwigFunction('render_widget', [$this, 'renderWidget'], ['is_safe' => ['html']]),
];
}
/**
* @param WidgetInterface|string $widget
* @param array $options
@@ -47,12 +35,12 @@ class WidgetExtension extends AbstractExtension
public function renderWidget($widget, array $options = [])
{
if (!($widget instanceof WidgetInterface) && !\is_string($widget)) {
throw new InvalidArgumentException('Widget must either implement WidgetInterface or be a string');
throw new \InvalidArgumentException('Widget must either implement WidgetInterface or be a string');
}
if (\is_string($widget)) {
if (!$this->service->hasWidget($widget)) {
throw new InvalidArgumentException(sprintf('Unknown widget "%s" requested', $widget));
throw new \InvalidArgumentException(sprintf('Unknown widget "%s" requested', $widget));
}
$widget = $this->service->getWidget($widget);

View File

@@ -0,0 +1,50 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Twig;
use App\Twig\Runtime\EncoreExtension;
use App\Twig\Runtime\ExporterExtension;
use App\Twig\Runtime\MarkdownExtension;
use App\Twig\Runtime\ThemeExtension;
use App\Twig\Runtime\TimesheetExtension;
use App\Twig\Runtime\WidgetExtension;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
use Twig\TwigFunction;
class RuntimeExtensions extends AbstractExtension
{
/**
* {@inheritdoc}
*/
public function getFunctions()
{
return [
new TwigFunction('trigger', [ThemeExtension::class, 'trigger'], ['needs_environment' => true]),
new TwigFunction('javascript_translations', [ThemeExtension::class, 'getJavascriptTranslations']),
new TwigFunction('timesheet_exporter', [ExporterExtension::class, 'getTimesheetExporter']),
new TwigFunction('active_timesheets', [TimesheetExtension::class, 'activeEntries']),
new TwigFunction('encore_entry_css_source', [EncoreExtension::class, 'getEncoreEntryCssSource']),
new TwigFunction('render_widget', [WidgetExtension::class, 'renderWidget'], ['is_safe' => ['html']]),
];
}
/**
* {@inheritdoc}
*/
public function getFilters()
{
return [
new TwigFilter('md2html', [MarkdownExtension::class, 'markdownToHtml'], ['pre_escape' => 'html', 'is_safe' => ['html']]),
new TwigFilter('desc2html', [MarkdownExtension::class, 'timesheetContent'], ['pre_escape' => 'html', 'is_safe' => ['html']]),
new TwigFilter('comment2html', [MarkdownExtension::class, 'commentContent'], ['pre_escape' => 'html', 'is_safe' => ['html']]),
];
}
}