added export context (#2216)
This commit is contained in:
@@ -8,6 +8,10 @@ you can upgrade your Kimai installation to the latest stable release.
|
||||
Check below if there are more version specific steps required, which need to be executed after the normal update process.
|
||||
Perform EACH version specific task between your version and the new one, otherwise you risk data inconsistency or a broken installation.
|
||||
|
||||
## [1.13](https://github.com/kevinpapst/kimai2/releases/tag/1.13)
|
||||
|
||||
- Deprecated `now` variable in export templates: create it yourself with `{% set now = create_date('now', app.user) %}`
|
||||
|
||||
## [1.12](https://github.com/kevinpapst/kimai2/releases/tag/1.12)
|
||||
|
||||
- Export templates can now include items from plugins (eg. Expenses).
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
|
||||
namespace App\Export\Base;
|
||||
|
||||
use App\Export\ExportContext;
|
||||
use App\Export\ExportItemInterface;
|
||||
use App\Repository\ProjectRepository;
|
||||
use App\Repository\Query\TimesheetQuery;
|
||||
use App\Timesheet\UserDateTimeFactory;
|
||||
use App\Utils\HtmlToPdfConverter;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
|
||||
@@ -26,10 +26,6 @@ class PDFRenderer
|
||||
* @var Environment
|
||||
*/
|
||||
private $twig;
|
||||
/**
|
||||
* @var UserDateTimeFactory
|
||||
*/
|
||||
private $dateTime;
|
||||
/**
|
||||
* @var HtmlToPdfConverter
|
||||
*/
|
||||
@@ -46,11 +42,14 @@ class PDFRenderer
|
||||
* @var string
|
||||
*/
|
||||
private $template = 'default.pdf.twig';
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $pdfOptions = [];
|
||||
|
||||
public function __construct(Environment $twig, UserDateTimeFactory $dateTime, HtmlToPdfConverter $converter, ProjectRepository $projectRepository)
|
||||
public function __construct(Environment $twig, HtmlToPdfConverter $converter, ProjectRepository $projectRepository)
|
||||
{
|
||||
$this->twig = $twig;
|
||||
$this->dateTime = $dateTime;
|
||||
$this->converter = $converter;
|
||||
$this->projectRepository = $projectRepository;
|
||||
}
|
||||
@@ -72,6 +71,18 @@ class PDFRenderer
|
||||
return ['decimal' => $decimal];
|
||||
}
|
||||
|
||||
public function getPdfOptions(): array
|
||||
{
|
||||
return $this->pdfOptions;
|
||||
}
|
||||
|
||||
public function setPdfOption(string $key, string $value): PDFRenderer
|
||||
{
|
||||
$this->pdfOptions[$key] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ExportItemInterface[] $timesheets
|
||||
* @param TimesheetQuery $query
|
||||
@@ -82,21 +93,33 @@ class PDFRenderer
|
||||
*/
|
||||
public function render(array $timesheets, TimesheetQuery $query): Response
|
||||
{
|
||||
$context = new ExportContext();
|
||||
$context->setOption('filename', 'kimai-export.pdf');
|
||||
|
||||
$summary = $this->calculateSummary($timesheets);
|
||||
$content = $this->twig->render($this->getTemplate(), array_merge([
|
||||
'entries' => $timesheets,
|
||||
'query' => $query,
|
||||
'now' => $this->dateTime->createDateTime(),
|
||||
// @deprecated since 1.13
|
||||
'now' => new \DateTime('now', new \DateTimeZone(date_default_timezone_get())),
|
||||
'summaries' => $summary,
|
||||
'budgets' => $this->calculateProjectBudget($timesheets, $query, $this->projectRepository),
|
||||
'decimal' => false,
|
||||
'pdfContext' => $context
|
||||
], $this->getOptions($query)));
|
||||
|
||||
$content = $this->converter->convertToPdf($content);
|
||||
$pdfOptions = array_merge($context->getOptions(), $this->getPdfOptions());
|
||||
|
||||
$content = $this->converter->convertToPdf($content, $pdfOptions);
|
||||
|
||||
$response = new Response($content);
|
||||
|
||||
$disposition = $response->headers->makeDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, 'kimai-export.pdf');
|
||||
$filename = $context->getOption('filename');
|
||||
if (empty($filename)) {
|
||||
$filename = 'kimai-export.pdf';
|
||||
}
|
||||
|
||||
$disposition = $response->headers->makeDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $filename);
|
||||
|
||||
$response->headers->set('Content-Type', 'application/pdf');
|
||||
$response->headers->set('Content-Disposition', $disposition);
|
||||
|
||||
37
src/Export/ExportContext.php
Normal file
37
src/Export/ExportContext.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?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\Export;
|
||||
|
||||
/**
|
||||
* A simple class that is available in twig renderer context, which can be used to define global renderer options.
|
||||
*/
|
||||
final class ExportContext
|
||||
{
|
||||
private $options = [];
|
||||
|
||||
public function setOption(string $key, string $value): void
|
||||
{
|
||||
$this->options[$key] = $value;
|
||||
}
|
||||
|
||||
public function getOptions(): array
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
public function getOption(string $key): ?string
|
||||
{
|
||||
if (\array_key_exists($key, $this->options)) {
|
||||
return $this->options[$key];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,6 @@
|
||||
namespace App\Export\Renderer;
|
||||
|
||||
use App\Repository\ProjectRepository;
|
||||
use App\Timesheet\UserDateTimeFactory;
|
||||
use App\Utils\HtmlToPdfConverter;
|
||||
use Twig\Environment;
|
||||
|
||||
@@ -20,10 +19,6 @@ final class PdfRendererFactory
|
||||
* @var Environment
|
||||
*/
|
||||
private $twig;
|
||||
/**
|
||||
* @var UserDateTimeFactory
|
||||
*/
|
||||
private $dateTime;
|
||||
/**
|
||||
* @var HtmlToPdfConverter
|
||||
*/
|
||||
@@ -33,17 +28,16 @@ final class PdfRendererFactory
|
||||
*/
|
||||
private $projectRepository;
|
||||
|
||||
public function __construct(Environment $twig, UserDateTimeFactory $dateTime, HtmlToPdfConverter $converter, ProjectRepository $projectRepository)
|
||||
public function __construct(Environment $twig, HtmlToPdfConverter $converter, ProjectRepository $projectRepository)
|
||||
{
|
||||
$this->twig = $twig;
|
||||
$this->dateTime = $dateTime;
|
||||
$this->converter = $converter;
|
||||
$this->projectRepository = $projectRepository;
|
||||
}
|
||||
|
||||
public function create(string $id, string $template): PDFRenderer
|
||||
{
|
||||
$renderer = new PDFRenderer($this->twig, $this->dateTime, $this->converter, $this->projectRepository);
|
||||
$renderer = new PDFRenderer($this->twig, $this->converter, $this->projectRepository);
|
||||
$renderer->setId($id);
|
||||
$renderer->setTemplate($template);
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace App\Twig;
|
||||
|
||||
use App\Configuration\LanguageFormattings;
|
||||
use App\Constants;
|
||||
use App\Entity\User;
|
||||
use App\Utils\LocaleFormats;
|
||||
use App\Utils\LocaleFormatter;
|
||||
use DateTime;
|
||||
@@ -89,6 +90,7 @@ class DateExtensions extends AbstractExtension
|
||||
{
|
||||
return [
|
||||
new TwigFunction('get_format_duration', [$this, 'getDurationFormat']),
|
||||
new TwigFunction('create_date', [$this, 'createDate']),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -130,6 +132,13 @@ class DateExtensions extends AbstractExtension
|
||||
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
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
namespace App\Utils;
|
||||
|
||||
use App\Constants;
|
||||
use Mpdf\Config\ConfigVariables;
|
||||
use Mpdf\Config\FontVariables;
|
||||
use Mpdf\Mpdf;
|
||||
use Mpdf\Output\Destination;
|
||||
|
||||
@@ -25,6 +27,32 @@ class MPdfConverter implements HtmlToPdfConverter
|
||||
$this->cacheDirectory = $cacheDirectory;
|
||||
}
|
||||
|
||||
protected function sanitizeOptions(array $options): array
|
||||
{
|
||||
$configs = new ConfigVariables();
|
||||
$fonts = new FontVariables();
|
||||
$allowed = [
|
||||
'mode', 'format', 'default_font_size', 'default_font', 'margin_left', 'margin_right', 'margin_top',
|
||||
'margin_bottom', 'margin_header', 'margin_footer', 'orientation'
|
||||
];
|
||||
|
||||
$filtered = array_filter($options, function ($key) use ($allowed, $configs, $fonts) {
|
||||
if (!\in_array($key, $allowed)) {
|
||||
if (!\array_key_exists($key, $configs->getDefaults())) {
|
||||
return \array_key_exists($key, $fonts->getDefaults());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}, ARRAY_FILTER_USE_KEY);
|
||||
|
||||
if (\array_key_exists('tempDir', $filtered)) {
|
||||
unset($filtered['tempDir']);
|
||||
}
|
||||
|
||||
return $filtered;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $html
|
||||
* @param array $options
|
||||
@@ -33,7 +61,11 @@ class MPdfConverter implements HtmlToPdfConverter
|
||||
*/
|
||||
public function convertToPdf(string $html, array $options = [])
|
||||
{
|
||||
$options = array_merge($options, ['tempDir' => $this->cacheDirectory]);
|
||||
$options = array_merge(
|
||||
$this->sanitizeOptions($options),
|
||||
['tempDir' => $this->cacheDirectory, 'exposeVersion' => false]
|
||||
);
|
||||
|
||||
$mpdf = new Mpdf($options);
|
||||
$mpdf->creator = Constants::SOFTWARE;
|
||||
|
||||
|
||||
@@ -116,7 +116,11 @@
|
||||
<br>
|
||||
<small>{{ widgets.label_customer(entry.project.customer) }}</small>
|
||||
</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'activity') }}">{{ widgets.label_activity(entry.activity) }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'activity') }}">
|
||||
{% if entry.activity is not null %}
|
||||
{{ widgets.label_activity(entry.activity) }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'description') }}">
|
||||
{{ entry.description|desc2html }}
|
||||
</td>
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
{% set showRateColumn = showRateColumn ?? is_granted('view_rate_other_timesheet') %}
|
||||
{% set showRateBudget = showRateBudget ?? false %}
|
||||
{% set showTimeBudget = showTimeBudget ?? false %}
|
||||
{% set showTotalSummary = showTotalSummary ?? true %}
|
||||
{% set now = create_date('now', app.user) %}
|
||||
{% set decimal = decimal ?? false %}
|
||||
{# this is only triggered, if a user exports from his personal timesheet screen #}
|
||||
{% if query.user is not null %}
|
||||
@@ -12,7 +14,7 @@
|
||||
{% endif %}
|
||||
<html lang="{{ app.request.locale }}">
|
||||
<head>
|
||||
{% block styles %}
|
||||
{% block styles %}
|
||||
<style>
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
@@ -70,7 +72,7 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
{% block pdf_footer %}
|
||||
@@ -132,7 +134,17 @@ mpdf-->
|
||||
{% set customerInternalRate = 0 %}
|
||||
{% set customerCurrency = null %}
|
||||
{% set customerCount = 0 %}
|
||||
{% set multiCurrency = false %}
|
||||
{% set totalDuration = 0 %}
|
||||
{% set totalInternalRate = 0 %}
|
||||
{% set totalRate = 0 %}
|
||||
{% for id, summary in summaries %}
|
||||
{% set totalDuration = totalDuration + summary.duration %}
|
||||
{% set totalInternalRate = totalInternalRate + summary.rate_internal %}
|
||||
{% set totalRate = totalRate + summary.rate %}
|
||||
{% if customerCurrency is not null and customerCurrency is not same as(summary.currency) %}
|
||||
{% set multiCurrency = true %}
|
||||
{% endif %}
|
||||
{% if customer is same as(null) %}
|
||||
{% set customer = summary.customer %}
|
||||
{% set customerCurrency = summary.currency %}
|
||||
@@ -210,6 +222,26 @@ mpdf-->
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if showTotalSummary and not multiCurrency %}
|
||||
<tr class="summary-total">
|
||||
<td class="totals" colspan="2">
|
||||
{{ 'sum.total'|trans }}
|
||||
</td>
|
||||
{% if showTimeBudget %}
|
||||
<td></td>
|
||||
{% endif %}
|
||||
{% if showRateBudget %}
|
||||
<td></td>
|
||||
{% endif %}
|
||||
<td class="totals duration">{{ totalDuration|duration(decimal) }}</td>
|
||||
{% if showRateColumn %}
|
||||
{% if showInternalRate %}
|
||||
<td class="totals cost">{{ totalInternalRate|money(customerCurrency) }}</td>
|
||||
{% endif %}
|
||||
<td class="totals cost">{{ totalRate|money(customerCurrency) }}</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
@@ -92,14 +92,22 @@ class ExportControllerTest extends ControllerBaseTest
|
||||
$this->assertDataTableRowCount($client, 'datatable_export', 23);
|
||||
|
||||
// assert export type buttons are available
|
||||
$expected = ['csv', 'default.html.twig', 'default-budget.pdf.twig', 'default-internal.pdf.twig', 'default.pdf.twig', 'xlsx'];
|
||||
$expected = [
|
||||
'csv' => 'csv',
|
||||
'default.html.twig' => 'default.html.twig',
|
||||
'default-budget.pdf.twig' => 'default-budget.pdf.twig',
|
||||
'default-internal.pdf.twig' => 'default-internal.pdf.twig',
|
||||
'default.pdf.twig' => 'default.pdf.twig',
|
||||
'xlsx' => 'xlsx'
|
||||
];
|
||||
$node = $client->getCrawler()->filter('#export-buttons .startExportBtn');
|
||||
$this->assertEquals(\count($expected), $node->count());
|
||||
$this->assertGreaterThanOrEqual(\count($expected), $node->count());
|
||||
/** @var \DOMElement $button */
|
||||
foreach ($node->getIterator() as $button) {
|
||||
$type = $button->getAttribute('data-type');
|
||||
$this->assertContains($type, $expected);
|
||||
unset($expected[$type]);
|
||||
}
|
||||
$this->assertEmpty($expected);
|
||||
}
|
||||
|
||||
public function testIndexActionWithEntriesForTeamleadDoesNotShowUserWithoutTeam()
|
||||
@@ -144,14 +152,22 @@ class ExportControllerTest extends ControllerBaseTest
|
||||
$this->assertDataTableRowCount($client, 'datatable_export', 3);
|
||||
|
||||
// assert export type buttons are available
|
||||
$expected = ['csv', 'default.html.twig', 'default-budget.pdf.twig', 'default-internal.pdf.twig', 'default.pdf.twig', 'xlsx'];
|
||||
$expected = [
|
||||
'csv' => 'csv',
|
||||
'default.html.twig' => 'default.html.twig',
|
||||
'default-budget.pdf.twig' => 'default-budget.pdf.twig',
|
||||
'default-internal.pdf.twig' => 'default-internal.pdf.twig',
|
||||
'default.pdf.twig' => 'default.pdf.twig',
|
||||
'xlsx' => 'xlsx'
|
||||
];
|
||||
$node = $client->getCrawler()->filter('#export-buttons .startExportBtn');
|
||||
$this->assertEquals(\count($expected), $node->count());
|
||||
$this->assertGreaterThanOrEqual(\count($expected), $node->count());
|
||||
/** @var \DOMElement $button */
|
||||
foreach ($node->getIterator() as $button) {
|
||||
$type = $button->getAttribute('data-type');
|
||||
$this->assertContains($type, $expected);
|
||||
unset($expected[$type]);
|
||||
}
|
||||
$this->assertEmpty($expected);
|
||||
}
|
||||
|
||||
public function testExportActionWithMissingRenderer()
|
||||
|
||||
37
tests/Export/ExportContextTest.php
Normal file
37
tests/Export/ExportContextTest.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?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\Tests\Export;
|
||||
|
||||
use App\Export\ExportContext;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Export\ExportContext
|
||||
*/
|
||||
class ExportContextTest extends TestCase
|
||||
{
|
||||
public function testEmptyObject()
|
||||
{
|
||||
$sut = new ExportContext();
|
||||
|
||||
self::assertIsArray($sut->getOptions());
|
||||
self::assertEmpty($sut->getOptions());
|
||||
self::assertNull($sut->getOption('unknown'));
|
||||
}
|
||||
|
||||
public function testSetterAndGetter()
|
||||
{
|
||||
$sut = new ExportContext();
|
||||
|
||||
self::assertNull($sut->getOption('unknown'));
|
||||
$sut->setOption('unknown', 'foo');
|
||||
self::assertEquals('foo', $sut->getOption('unknown'));
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,6 @@ namespace App\Tests\Export\Renderer;
|
||||
use App\Export\Renderer\PDFRenderer;
|
||||
use App\Export\Renderer\PdfRendererFactory;
|
||||
use App\Repository\ProjectRepository;
|
||||
use App\Timesheet\UserDateTimeFactory;
|
||||
use App\Utils\HtmlToPdfConverter;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Twig\Environment;
|
||||
@@ -26,7 +25,6 @@ class PdfRendererFactoryTest extends TestCase
|
||||
{
|
||||
$sut = new PdfRendererFactory(
|
||||
$this->createMock(Environment::class),
|
||||
$this->createMock(UserDateTimeFactory::class),
|
||||
$this->createMock(HtmlToPdfConverter::class),
|
||||
$this->createMock(ProjectRepository::class)
|
||||
);
|
||||
|
||||
@@ -11,7 +11,6 @@ namespace App\Tests\Export\Renderer;
|
||||
|
||||
use App\Export\Renderer\PDFRenderer;
|
||||
use App\Repository\ProjectRepository;
|
||||
use App\Tests\Mocks\Security\UserDateTimeFactoryFactory;
|
||||
use App\Utils\HtmlToPdfConverter;
|
||||
use App\Utils\MPdfConverter;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@@ -25,16 +24,10 @@ use Twig\Environment;
|
||||
*/
|
||||
class PdfRendererTest extends AbstractRendererTest
|
||||
{
|
||||
protected function getDateTimeFactory()
|
||||
{
|
||||
return (new UserDateTimeFactoryFactory($this))->create();
|
||||
}
|
||||
|
||||
public function testConfiguration()
|
||||
{
|
||||
$sut = new PDFRenderer(
|
||||
$this->createMock(Environment::class),
|
||||
$this->getDateTimeFactory(),
|
||||
$this->createMock(HtmlToPdfConverter::class),
|
||||
$this->createMock(ProjectRepository::class)
|
||||
);
|
||||
@@ -42,6 +35,11 @@ class PdfRendererTest extends AbstractRendererTest
|
||||
$this->assertEquals('pdf', $sut->getId());
|
||||
$this->assertEquals('pdf', $sut->getTitle());
|
||||
$this->assertEquals('pdf', $sut->getIcon());
|
||||
$this->assertEquals([], $sut->getPdfOptions());
|
||||
|
||||
$sut->setPdfOption('foo', 'bar');
|
||||
$sut->setPdfOption('bar1', 'foo1');
|
||||
$this->assertEquals(['foo' => 'bar', 'bar1' => 'foo1'], $sut->getPdfOptions());
|
||||
}
|
||||
|
||||
public function testRender()
|
||||
@@ -56,7 +54,7 @@ class PdfRendererTest extends AbstractRendererTest
|
||||
$request->setLocale('en');
|
||||
$stack->push($request);
|
||||
|
||||
$sut = new PDFRenderer($twig, $this->getDateTimeFactory(), $converter, $this->createMock(ProjectRepository::class));
|
||||
$sut = new PDFRenderer($twig, $converter, $this->createMock(ProjectRepository::class));
|
||||
|
||||
$response = $this->render($sut);
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ namespace App\Tests\Export\Timesheet;
|
||||
|
||||
use App\Export\Timesheet\PDFRenderer;
|
||||
use App\Repository\ProjectRepository;
|
||||
use App\Tests\Mocks\Security\UserDateTimeFactoryFactory;
|
||||
use App\Utils\HtmlToPdfConverter;
|
||||
use App\Utils\MPdfConverter;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@@ -25,16 +24,10 @@ use Twig\Environment;
|
||||
*/
|
||||
class PdfRendererTest extends AbstractRendererTest
|
||||
{
|
||||
protected function getDateTimeFactory()
|
||||
{
|
||||
return (new UserDateTimeFactoryFactory($this))->create();
|
||||
}
|
||||
|
||||
public function testConfiguration()
|
||||
{
|
||||
$sut = new PDFRenderer(
|
||||
$this->createMock(Environment::class),
|
||||
$this->getDateTimeFactory(),
|
||||
$this->createMock(HtmlToPdfConverter::class),
|
||||
$this->createMock(ProjectRepository::class)
|
||||
);
|
||||
@@ -54,7 +47,7 @@ class PdfRendererTest extends AbstractRendererTest
|
||||
$request->setLocale('en');
|
||||
$stack->push($request);
|
||||
|
||||
$sut = new PDFRenderer($twig, $this->getDateTimeFactory(), $converter, $this->createMock(ProjectRepository::class));
|
||||
$sut = new PDFRenderer($twig, $converter, $this->createMock(ProjectRepository::class));
|
||||
|
||||
$response = $this->render($sut);
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
namespace App\Tests\Twig;
|
||||
|
||||
use App\Configuration\LanguageFormattings;
|
||||
use App\Entity\User;
|
||||
use App\Twig\DateExtensions;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@@ -54,7 +55,7 @@ class DateExtensionsTest extends TestCase
|
||||
|
||||
public function testGetFunctions()
|
||||
{
|
||||
$functions = ['get_format_duration'];
|
||||
$functions = ['get_format_duration', 'create_date'];
|
||||
$sut = $this->getSut('de', []);
|
||||
$twigFunctions = $sut->getFunctions();
|
||||
$this->assertCount(\count($functions), $twigFunctions);
|
||||
@@ -217,4 +218,21 @@ class DateExtensionsTest extends TestCase
|
||||
/* @phpstan-ignore-next-line */
|
||||
$this->assertEquals(189.45, $sut->dateTimeFull(189.45));
|
||||
}
|
||||
|
||||
public function testCreateDate()
|
||||
{
|
||||
$user = new User();
|
||||
$user->setTimezone('Europe/Berlin');
|
||||
$sut = $this->getSut('en', []);
|
||||
$date = $sut->createDate('now', $user);
|
||||
$this->assertEquals('Europe/Berlin', $date->getTimezone()->getName());
|
||||
|
||||
$user->setTimezone('Asia/Dubai');
|
||||
$date = $sut->createDate('2019-08-27 16:30:45', $user);
|
||||
$this->assertEquals('2019-08-27T16:30:45+0400', $date->format(DATE_ISO8601));
|
||||
$this->assertEquals('Asia/Dubai', $date->getTimezone()->getName());
|
||||
|
||||
$date = $sut->createDate('2019-08-27 16:30:45', null);
|
||||
$this->assertEquals(date_default_timezone_get(), $date->getTimezone()->getName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +80,10 @@
|
||||
<source>rates.title</source>
|
||||
<target>Gebühren</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sum.total">
|
||||
<source>sum.total</source>
|
||||
<target>Gesamt</target>
|
||||
</trans-unit>
|
||||
<!--
|
||||
Login / Security
|
||||
-->
|
||||
|
||||
@@ -80,7 +80,10 @@
|
||||
<source>rates.title</source>
|
||||
<target>Fees</target>
|
||||
</trans-unit>
|
||||
|
||||
<trans-unit id="sum.total">
|
||||
<source>sum.total</source>
|
||||
<target>Total</target>
|
||||
</trans-unit>
|
||||
<!--
|
||||
Login / Security
|
||||
-->
|
||||
|
||||
Reference in New Issue
Block a user