243 lines
7.4 KiB
PHP
243 lines
7.4 KiB
PHP
<?php
|
|
|
|
namespace App\Twig;
|
|
|
|
use App\BusProNet\DataProvider\CountryDataProvider;
|
|
use App\BusProNet\DataProvider\PickupDataProvider;
|
|
use App\Entity\Teamer;
|
|
use App\Entity\Upload;
|
|
use App\Service\Teamer\PickupResolver;
|
|
use App\Service\Upload\UploadHandler;
|
|
use Carbon\CarbonImmutable;
|
|
use Symfony\Component\HttpFoundation\RequestStack;
|
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
|
use Twig\Environment;
|
|
use Twig\Extension\RuntimeExtensionInterface;
|
|
use Twig\Extra\Intl\IntlExtension;
|
|
|
|
class AppRuntime implements RuntimeExtensionInterface
|
|
{
|
|
public function __construct(
|
|
private readonly RequestStack $requestStack,
|
|
private readonly IntlExtension $intlExtension,
|
|
private readonly TranslatorInterface $translator,
|
|
private readonly CountryDataProvider $countries,
|
|
private readonly PickupDataProvider $pickups,
|
|
private readonly PickupResolver $pickupResolver,
|
|
private readonly string $environment,
|
|
) {
|
|
}
|
|
|
|
public function teamerStatusLabel(Teamer $teamer): string
|
|
{
|
|
$labelItems = [];
|
|
$user = $teamer->getUser();
|
|
|
|
if (null !== $user) {
|
|
if ($user->hasRole('ROLE_ADMIN')) {
|
|
$labelItems[] = 'Admin';
|
|
}
|
|
|
|
if ($user->hasRole('ROLE_MANAGER')) {
|
|
$labelItems[] = 'Reisemanagement';
|
|
}
|
|
|
|
if ($user->hasRole('ROLE_HOUSE_MANAGER')) {
|
|
$labelItems[] = 'Hausleitung';
|
|
}
|
|
}
|
|
|
|
if (0 < count($labelItems)) {
|
|
return implode(', ', $labelItems);
|
|
}
|
|
|
|
if (Teamer::STATUS_NEW === $teamer->getStatus()) {
|
|
return 'Neuteamer:in';
|
|
}
|
|
|
|
return 'Bestandsteamer:in';
|
|
}
|
|
|
|
public function licenseLabel(string $type): string
|
|
{
|
|
return sprintf('Offizielle %slehrer:innenlizenz', ucfirst(strtolower($type)));
|
|
}
|
|
|
|
public function bpnCountryLabel(?string $token, string $property = 'name'): string
|
|
{
|
|
$country = $this->countries->get($token);
|
|
|
|
if (null === $country) {
|
|
return 'unbekannt';
|
|
}
|
|
|
|
return 'nationality' === $property ? $country->getNationality() : $country->getName();
|
|
}
|
|
|
|
public function bpnPickupLabel($id): ?string
|
|
{
|
|
if (null === $id) {
|
|
return 'keine Busbegleitung';
|
|
}
|
|
|
|
$pickup = $this->pickups->get((int) $id);
|
|
|
|
if (null === $pickup) {
|
|
return null;
|
|
}
|
|
|
|
return 'ab '.$pickup->getCity();
|
|
}
|
|
|
|
public function hasPickup(?int $pickupId, Teamer $teamer): bool
|
|
{
|
|
return $this->pickupResolver->hasPickup($pickupId, $teamer);
|
|
}
|
|
|
|
public function fileIconFilter(Environment $environment, string $mimeType, ?string $classes = 'w-4 h-4'): string
|
|
{
|
|
$icon = match ($mimeType) {
|
|
'application/pdf' => 'pdf',
|
|
'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'excel',
|
|
'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'word',
|
|
default => 'download',
|
|
};
|
|
|
|
return $this->renderIcon($environment, $icon, $classes);
|
|
}
|
|
|
|
public function formatBytes(int $bytes, ?int $precision = 2): string
|
|
{
|
|
$size = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
|
$factor = floor((strlen($bytes) - 1) / 3);
|
|
|
|
return sprintf("%.{$precision}f", $bytes / (1024 ** $factor)).@$size[$factor];
|
|
}
|
|
|
|
public function formatMoney(int $amount): string
|
|
{
|
|
// Amounts are stored as integers so divide by 100 first
|
|
$amount = $amount / 100;
|
|
|
|
return $this->intlExtension->formatCurrency($amount, 'EUR');
|
|
}
|
|
|
|
public function formatRating(?int $rating): string
|
|
{
|
|
if (null === $rating) {
|
|
return '-';
|
|
}
|
|
|
|
// Ratings are stored as integers so divide by 100 first
|
|
$rating = $rating / 100;
|
|
|
|
return 'Ø '.$this->intlExtension->formatNumber($rating, ['fraction_digit' => 2]);
|
|
}
|
|
|
|
public function renderIcon(Environment $environment, string $icon, string $classes = 'w-5 h-5'): string
|
|
{
|
|
return $environment->render('_partials/_icon.html.twig', [
|
|
'icon' => $icon,
|
|
'class' => $classes,
|
|
]);
|
|
}
|
|
|
|
public function renderUploadStatusBadge(string $status): string
|
|
{
|
|
$label = $this->translator->trans('label.document.status.'.$status);
|
|
$class = 'upload-status-badge ';
|
|
$class .= match ($status) {
|
|
Upload::STATUS_NEW => 'upload-status-badge--new',
|
|
Upload::STATUS_REJECTED => 'upload-status-badge--error',
|
|
Upload::STATUS_PAID => 'upload-status-badge--paid',
|
|
Upload::STATUS_CHECKED => 'upload-status-badge--checked',
|
|
default => 'upload-status-badge--default',
|
|
};
|
|
|
|
return sprintf('<span class="%s">%s</span>', $class, $label);
|
|
}
|
|
|
|
public function nl2List(?string $content, string $class = 'list-disc pl-4'): string
|
|
{
|
|
if (null === $content) {
|
|
return '';
|
|
}
|
|
|
|
$items = explode(PHP_EOL, $content);
|
|
|
|
$list = '<ul class="'.$class.'">';
|
|
foreach ($items as $item) {
|
|
$list .= '<li>'.htmlspecialchars($item, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8').'</li>';
|
|
}
|
|
$list .= '</ul>';
|
|
|
|
return $list;
|
|
}
|
|
|
|
public function isCurrentRoute(string $route): bool
|
|
{
|
|
$requestedRoute = $this->requestStack->getMainRequest()->attributes->get('_route');
|
|
|
|
return $requestedRoute === $route;
|
|
}
|
|
|
|
public function getEncodedReturnUrl(): string
|
|
{
|
|
$masterRequest = $this->requestStack->getMainRequest();
|
|
|
|
if (null === $masterRequest) {
|
|
return '';
|
|
}
|
|
|
|
return rawurlencode($masterRequest->getRequestUri());
|
|
}
|
|
|
|
/**
|
|
* Passes the return url of the current page on to the next one.
|
|
*
|
|
* Used by links that lead deeper into a detail view or trigger an action on it:
|
|
* they have to keep pointing back at where the user originally came from instead
|
|
* of at the page they sit on. Null when there is nothing to pass on, so that the
|
|
* url generator drops the parameter rather than emitting an empty one.
|
|
*/
|
|
public function getForwardedReturnUrl(): ?string
|
|
{
|
|
$returnUrl = $this->requestStack->getMainRequest()?->query->get('r');
|
|
|
|
return is_string($returnUrl) && '' !== $returnUrl ? $returnUrl : null;
|
|
}
|
|
|
|
public function renderQaAttribute(string $label, ?string $value = null): string
|
|
{
|
|
if ('test' !== $this->environment) {
|
|
return '';
|
|
}
|
|
|
|
if (null === $value) {
|
|
return sprintf(' data-qa-%s', strtolower($label));
|
|
}
|
|
|
|
return sprintf(' data-qa-%s="%s"', strtolower($label), $value);
|
|
}
|
|
|
|
public function dateDiffForHumans(\DateTimeInterface $dateTime, ?\DateTimeInterface $other = null): string
|
|
{
|
|
$oldLocale = CarbonImmutable::getLocale();
|
|
$locale = $this->requestStack->getMainRequest()->getLocale();
|
|
CarbonImmutable::setLocale($locale);
|
|
|
|
$result = CarbonImmutable::instance($dateTime)->diffForHumans($other);
|
|
|
|
CarbonImmutable::setLocale($oldLocale);
|
|
|
|
return $result;
|
|
}
|
|
|
|
public function getFilenameWithFolder(Upload $upload): string
|
|
{
|
|
$folder = substr($upload->getFilename(), 0, 1);
|
|
|
|
return sprintf('%s/%s', $folder, $upload->getFilename());
|
|
}
|
|
}
|