diff --git a/UPGRADING.md b/UPGRADING.md index e9b1bded..54e74319 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -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.10](https://github.com/kevinpapst/kimai2/releases/tag/1.10) + +- Invoice renderer `CSV` was removed + ## [1.9](https://github.com/kevinpapst/kimai2/releases/tag/1.9) **New database tables and fields were created, don't forget to [run the updater](https://www.kimai.org/documentation/updates.html).** diff --git a/src/Invoice/Renderer/CsvRenderer.php b/src/Invoice/Renderer/CsvRenderer.php deleted file mode 100644 index 0e703d17..00000000 --- a/src/Invoice/Renderer/CsvRenderer.php +++ /dev/null @@ -1,51 +0,0 @@ -save($filename); - - return $filename; - } -} diff --git a/src/Twig/Extensions.php b/src/Twig/Extensions.php index 46bf2028..4313e05c 100644 --- a/src/Twig/Extensions.php +++ b/src/Twig/Extensions.php @@ -105,16 +105,19 @@ class Extensions extends AbstractExtension return ''; } - $parts = explode("\r\n", $string); - if (\count($parts) === 1) { - $parts = explode("\n", $string); + $parts = []; + + foreach (explode("\r\n", $string) as $part) { + foreach (explode("\n", $part) as $tmp) { + $parts[] = $tmp; + } } $parts = array_map(function ($part) use ($indent) { return $indent . $part; }, $parts); - return implode("\n", $parts); + return implode(PHP_EOL, $parts); } /** diff --git a/tests/Invoice/Renderer/CsvRendererTest.php b/tests/Invoice/Renderer/CsvRendererTest.php deleted file mode 100644 index a53b38c8..00000000 --- a/tests/Invoice/Renderer/CsvRendererTest.php +++ /dev/null @@ -1,82 +0,0 @@ -getAbstractRenderer(CsvRenderer::class); - - $this->assertFalse($sut->supports($this->getInvoiceDocument('default.html.twig'))); - $this->assertFalse($sut->supports($this->getInvoiceDocument('freelancer.html.twig'))); - $this->assertFalse($sut->supports($this->getInvoiceDocument('timesheet.html.twig'))); - $this->assertFalse($sut->supports($this->getInvoiceDocument('foo.html.twig'))); - $this->assertFalse($sut->supports($this->getInvoiceDocument('company.docx'))); - $this->assertTrue($sut->supports($this->getInvoiceDocument('export.csv', true))); - $this->assertFalse($sut->supports($this->getInvoiceDocument('spreadsheet.xlsx'))); - $this->assertFalse($sut->supports($this->getInvoiceDocument('open-spreadsheet.ods'))); - } - - public function getTestModel() - { - yield [$this->getInvoiceModel(), '€1,947.99', 6, 4, 1, 2, 2]; - yield [$this->getInvoiceModelOneEntry(), '$293.27', 2, 1, 0, 1, 0]; - } - - /** - * @dataProvider getTestModel - */ - public function testRender(InvoiceModel $model, $expectedRate, $expectedRows, $expectedDescriptions, $expectedUser1, $expectedUser2, $expectedUser3) - { - /** @var CsvRenderer $sut */ - $sut = $this->getAbstractRenderer(CsvRenderer::class); - $document = $this->getInvoiceDocument('export.csv', true); - /** @var BinaryFileResponse $response */ - $response = $sut->render($document, $model); - - $file = $response->getFile(); - $this->assertEquals('text/csv', $response->headers->get('Content-Type')); - $filename = $model->getInvoiceNumber() . '-customer_with_special_name.csv'; - $this->assertEquals('attachment; filename=' . $filename, $response->headers->get('Content-Disposition')); - - $this->assertTrue(file_exists($file->getRealPath())); - $content = file_get_contents($file->getRealPath()); - - $this->assertStringNotContainsString('${', $content); - $this->assertStringContainsString(',"' . $expectedRate . '"', $content); - $this->assertEquals($expectedRows, substr_count($content, PHP_EOL)); - $this->assertEquals($expectedDescriptions, substr_count($content, 'activity description')); - $this->assertEquals($expectedUser1, substr_count($content, ',"kevin",')); - $this->assertEquals($expectedUser3, substr_count($content, ',"hello-world",')); - $this->assertEquals($expectedUser2, substr_count($content, ',"foo-bar",')); - - ob_start(); - $response->sendContent(); - $content2 = ob_get_clean(); - - $this->assertEquals($content, $content2); - $this->assertFalse(file_exists($file->getRealPath())); - } -} diff --git a/tests/Invoice/Renderer/RendererTestTrait.php b/tests/Invoice/Renderer/RendererTestTrait.php index 928a416c..45c52d79 100644 --- a/tests/Invoice/Renderer/RendererTestTrait.php +++ b/tests/Invoice/Renderer/RendererTestTrait.php @@ -113,7 +113,7 @@ trait RendererTestTrait $customer->setMetaField((new CustomerMeta())->setName('foo-customer')->setValue('bar-customer')->setIsVisible(true)); $template = new InvoiceTemplate(); - $template->setTitle('a very *long* test invoice / template title with [special] character'); + $template->setTitle('a very *long* test invoice / template title with [ßpecial] chäracter'); $template->setVat(19); $template->setLanguage('en'); @@ -192,6 +192,14 @@ trait RendererTestTrait ->setProject($project) ->setBegin(new \DateTime()) ->setEnd(new \DateTime()) + ->setDescription( + "foo\n" . + "foo\r\n" . + 'foo' . PHP_EOL . + "bar\n" . + "bar\r\n" . + 'Hello' + ) ->setMetaField((new TimesheetMeta())->setName('foo-timesheet3')->setValue('bluuuub')->setIsVisible(true)) ; @@ -204,6 +212,14 @@ trait RendererTestTrait ->setProject($project) ->setBegin(new \DateTime()) ->setEnd(new \DateTime()) + ->setDescription( + "foo\n" . + "foo\r\n" . + 'foo' . PHP_EOL . + "bar\n" . + "bar\r\n" . + 'Hello' + ) ; $entries = [$timesheet, $timesheet2, $timesheet3, $timesheet4, $timesheet5]; diff --git a/tests/Invoice/Renderer/TextRendererTest.php b/tests/Invoice/Renderer/TextRendererTest.php index e22c703a..602eab14 100644 --- a/tests/Invoice/Renderer/TextRendererTest.php +++ b/tests/Invoice/Renderer/TextRendererTest.php @@ -85,5 +85,15 @@ class TextRendererTest extends KernelTestCase } } self::assertEquals(\count($model->getCalculator()->getEntries()), substr_count($content, PHP_EOL . '---' . PHP_EOL)); + $this->assertStringContainsString( + 'entry.description' . PHP_EOL . + ' foo' . PHP_EOL . + ' foo' . PHP_EOL . + ' foo' . PHP_EOL . + ' bar' . PHP_EOL . + ' bar' . PHP_EOL . + ' Hello', + $content + ); } } diff --git a/tests/Invoice/Renderer/TwigRendererTest.php b/tests/Invoice/Renderer/TwigRendererTest.php index 317382e3..f696af94 100644 --- a/tests/Invoice/Renderer/TwigRendererTest.php +++ b/tests/Invoice/Renderer/TwigRendererTest.php @@ -65,8 +65,14 @@ class TwigRendererTest extends KernelTestCase $filename = $model->getInvoiceNumber() . '-customer_with_special_name'; $this->assertStringContainsString('' . $filename . '', $content); $this->assertStringContainsString('', $content); - $this->assertEquals(4, substr_count($content, 'activity description')); + $this->assertEquals(2, substr_count($content, 'activity description')); + $this->assertStringContainsString(nl2br("foo\n" . + "foo\r\n" . + 'foo' . PHP_EOL . + "bar\n" . + "bar\r\n" . + 'Hello'), $content); } } diff --git a/tests/Invoice/templates/export.csv b/tests/Invoice/templates/export.csv deleted file mode 100644 index 47cb5ccd..00000000 --- a/tests/Invoice/templates/export.csv +++ /dev/null @@ -1,2 +0,0 @@ -start_date,start_timestamp,end_date,end_timestamp,duration,username,description,rate,amount,total -${entry.begin},${entry.begin_timestamp},${entry.end},${entry.end_timestamp},${entry.duration},${entry.user_name},${entry.description},${entry.rate},${entry.amount},${entry.total} diff --git a/tests/Twig/ExtensionsTest.php b/tests/Twig/ExtensionsTest.php index aeea4f81..4b96f58f 100644 --- a/tests/Twig/ExtensionsTest.php +++ b/tests/Twig/ExtensionsTest.php @@ -312,26 +312,25 @@ class ExtensionsTest extends TestCase [' ', null, ['']], [' ', '', ['']], [' ', 0, [' 0']], - [' ', 'sdfsdf -sdfsdf - - aksljdfh laksjd hflka sjhdf lakjhsdflak jsdfh -dfsdfsdfsdfsdf', - [' sdfsdf', ' sdfsdf', ' ', ' aksljdfh laksjd hflka sjhdf lakjhsdflak jsdfh', ' dfsdfsdfsdfsdf'] + [' ', '1dfsdf +sdfsdf' . PHP_EOL . "\n" . +' aksljdfh laksjd hflka sjhdf lakjhsdflak jsdfh' . "\n" . +'dfsdfsdfsdfsdf', + [' 1dfsdf', ' sdfsdf', ' ', ' aksljdfh laksjd hflka sjhdf lakjhsdflak jsdfh', ' dfsdfsdfsdfsdf'] ], - ['###', 'sdfsdf' . PHP_EOL . + ['###', '2dfsdf' . PHP_EOL . 'sdfsdf' . PHP_EOL . -'' . PHP_EOL . +'' . "\r\n" . ' aksljdfh laksjd hflka sjhdf lakjhsdflak jsdfh' . PHP_EOL . 'dfsdfsdfsdfsdf', - ['###sdfsdf', '###sdfsdf', '###', '### aksljdfh laksjd hflka sjhdf lakjhsdflak jsdfh', '###dfsdfsdfsdfsdf'] + ['###2dfsdf', '###sdfsdf', '###', '### aksljdfh laksjd hflka sjhdf lakjhsdflak jsdfh', '###dfsdfsdfsdfsdf'] ], - [' ', 'sdfsdf' . "\r\n" . + [' ', '3dfsdf' . "\n" . 'sdfsdf' . "\r\n" . -'' . "\r\n" . +'' . "\n" . ' aksljdfh laksjd hflka sjhdf lakjhsdflak jsdfh' . "\r\n" . 'dfsdfsdfsdfsdf', - [' sdfsdf', ' sdfsdf', ' ', ' aksljdfh laksjd hflka sjhdf lakjhsdflak jsdfh', ' dfsdfsdfsdfsdf'] + [' 3dfsdf', ' sdfsdf', ' ', ' aksljdfh laksjd hflka sjhdf lakjhsdflak jsdfh', ' dfsdfsdfsdfsdf'] ], ]; }