diff --git a/src/Export/Base/AbstractSpreadsheetRenderer.php b/src/Export/Base/AbstractSpreadsheetRenderer.php index 12f69234..d0726ee6 100644 --- a/src/Export/Base/AbstractSpreadsheetRenderer.php +++ b/src/Export/Base/AbstractSpreadsheetRenderer.php @@ -16,6 +16,7 @@ use App\Event\MetaDisplayEventInterface; use App\Event\ProjectMetaDisplayEvent; use App\Event\TimesheetMetaDisplayEvent; use App\Event\UserPreferenceDisplayEvent; +use App\Export\ExportFilename; use App\Export\ExportItemInterface; use App\Repository\Query\CustomerQuery; use App\Repository\Query\TimesheetQuery; @@ -753,9 +754,10 @@ abstract class AbstractSpreadsheetRenderer public function render(array $exportItems, TimesheetQuery $query): Response { $spreadsheet = $this->fromArrayToSpreadsheet($exportItems, $query); - $filename = $this->saveSpreadsheet($spreadsheet); + $file = $this->saveSpreadsheet($spreadsheet); + $filename = new ExportFilename($query); - return $this->getFileResponse($filename, 'kimai-export' . $this->getFileExtension()); + return $this->getFileResponse($file, $filename->getFilename() . $this->getFileExtension()); } /** diff --git a/src/Export/Base/PDFRenderer.php b/src/Export/Base/PDFRenderer.php index 4fe421a1..7f3680f3 100644 --- a/src/Export/Base/PDFRenderer.php +++ b/src/Export/Base/PDFRenderer.php @@ -10,6 +10,7 @@ namespace App\Export\Base; use App\Export\ExportContext; +use App\Export\ExportFilename; use App\Export\ExportItemInterface; use App\Project\ProjectStatisticService; use App\Repository\Query\TimesheetQuery; @@ -94,8 +95,9 @@ class PDFRenderer */ public function render(array $timesheets, TimesheetQuery $query): Response { + $filename = new ExportFilename($query); $context = new ExportContext(); - $context->setOption('filename', 'kimai-export'); + $context->setOption('filename', $filename->getFilename()); $summary = $this->calculateSummary($timesheets); $content = $this->twig->render($this->getTemplate(), array_merge([ @@ -117,7 +119,8 @@ class PDFRenderer $filename = $context->getOption('filename'); if (empty($filename)) { - $filename = 'kimai-export'; + $filename = new ExportFilename($query); + $filename = $filename->getFilename(); } $filename = FileHelper::convertToAsciiFilename($filename); diff --git a/src/Export/ExportFilename.php b/src/Export/ExportFilename.php new file mode 100644 index 00000000..da9c5a6d --- /dev/null +++ b/src/Export/ExportFilename.php @@ -0,0 +1,82 @@ +getCustomers(); + if (\count($customers) === 1) { + $filename .= '-' . $this->convert($this->getCustomerName($customers[0])); + $hasName = true; + } + + $projects = $query->getProjects(); + if (\count($projects) === 1) { + if (!$hasName) { + $filename .= '-' . $this->convert($this->getCustomerName($projects[0]->getCustomer())); + } + $filename .= '-' . $this->convert($projects[0]->getName()); + $hasName = true; + } + + $users = $query->getUsers(); + if (\count($users) === 1) { + $filename .= '-' . $this->convert($users[0]->getDisplayName()); + $hasName = true; + } + + if (!$hasName) { + $filename .= '-kimai-export'; + } + + $filename = str_replace(['/', '\\'], '-', $filename); + + $this->filename = $filename; + } + + private function getCustomerName(Customer $customer): string + { + $company = $customer->getCompany(); + if (empty($company)) { + $company = $customer->getName(); + } + + return $company; + } + + private function convert(string $filename): string + { + return FileHelper::convertToAsciiFilename($filename); + } + + public function getFilename() + { + return $this->filename; + } + + public function __toString() + { + return $this->getFilename(); + } +} diff --git a/tests/Export/ExportFilenameTest.php b/tests/Export/ExportFilenameTest.php new file mode 100644 index 00000000..32c730ad --- /dev/null +++ b/tests/Export/ExportFilenameTest.php @@ -0,0 +1,96 @@ +getFilename()); + self::assertEquals($datePrefix . '-kimai-export', (string) $sut); + + $customer = new Customer(); + $customer->setName('foo'); + $query = new TimesheetQuery(); + $query->addCustomer($customer); + $sut = new ExportFilename($query); + + self::assertEquals($datePrefix . '-foo', $sut->getFilename()); + self::assertEquals($datePrefix . '-foo', (string) $sut); + + $customer->setCompany('barß / laölala # ldksjf 123 MyAwesome GmbH'); + $sut = new ExportFilename($query); + + self::assertEquals($datePrefix . '-barss_laolala_ldksjf_123_MyAwesome_GmbH', $sut->getFilename()); + self::assertEquals($datePrefix . '-barss_laolala_ldksjf_123_MyAwesome_GmbH', (string) $sut); + + $customer->setCompany('까깨꺄꺠꺼께껴꼐꼬꽈sssss'); + $sut = new ExportFilename($query); + self::assertEquals($datePrefix . '-kkakkaekkyakkyaekkeokkekkyeokkyekkokkwasssss', $sut->getFilename()); + + $customer->setCompany('\"#+ß.!$%&/()=?\\n=/*-+´_<>@' . "\n"); + $sut = new ExportFilename($query); + self::assertEquals($datePrefix . '-ss_n_-', $sut->getFilename()); + + $project = new Project(); + $project->setName('Demo ProjecT1'); + $customer->setCompany('\"#+ß.!$%&/()=?\\n=/*-+´_<>@' . "\n"); + $query->addProject($project); + + $sut = new ExportFilename($query); + self::assertEquals($datePrefix . '-ss_n_--Demo_ProjecT1', $sut->getFilename()); + + $user = new User(); + $user->setUsername('thorsten'); + $query->addUser($user); + + $sut = new ExportFilename($query); + self::assertEquals($datePrefix . '-ss_n_--Demo_ProjecT1-thorsten', $sut->getFilename()); + $user->setAlias('Martin Müller-Lüdenscheidt'); + + $sut = new ExportFilename($query); + self::assertEquals($datePrefix . '-ss_n_--Demo_ProjecT1-Martin_Muller-Ludenscheidt', $sut->getFilename()); + + $user = $this->createMock(User::class); + $user->method('getId')->willReturn(1); + $query->addUser($user); + $sut = new ExportFilename($query); + self::assertEquals($datePrefix . '-ss_n_--Demo_ProjecT1', $sut->getFilename()); + + $project = new Project(); + $project->setName('Project2'); + $query->addProject($project); + $sut = new ExportFilename($query); + self::assertEquals($datePrefix . '-ss_n_-', $sut->getFilename()); + + $customer = new Customer(); + $customer->setName('Customer AAAA'); + $query->addCustomer($customer); + + $sut = new ExportFilename($query); + self::assertEquals($datePrefix . '-kimai-export', $sut->getFilename()); + } +} diff --git a/tests/Export/Renderer/CsvRendererTest.php b/tests/Export/Renderer/CsvRendererTest.php index 9991df6a..4a902da3 100644 --- a/tests/Export/Renderer/CsvRendererTest.php +++ b/tests/Export/Renderer/CsvRendererTest.php @@ -49,8 +49,9 @@ class CsvRendererTest extends AbstractRendererTest $response = $this->render($sut); $file = $response->getFile(); + $prefix = date('Ymd'); $this->assertEquals('text/csv', $response->headers->get('Content-Type')); - $this->assertEquals('attachment; filename=kimai-export.csv', $response->headers->get('Content-Disposition')); + $this->assertEquals('attachment; filename=' . $prefix . '-Customer_Name-project_name.csv', $response->headers->get('Content-Disposition')); $this->assertTrue(file_exists($file->getRealPath())); $content = file_get_contents($file->getRealPath()); diff --git a/tests/Export/Renderer/PdfRendererTest.php b/tests/Export/Renderer/PdfRendererTest.php index b4099794..d1a9b0f3 100644 --- a/tests/Export/Renderer/PdfRendererTest.php +++ b/tests/Export/Renderer/PdfRendererTest.php @@ -58,8 +58,9 @@ class PdfRendererTest extends AbstractRendererTest $response = $this->render($sut); + $prefix = date('Ymd'); $this->assertEquals('application/pdf', $response->headers->get('Content-Type')); - $this->assertEquals('attachment; filename=kimai-export.pdf', $response->headers->get('Content-Disposition')); + $this->assertEquals('attachment; filename=' . $prefix . '-Customer_Name-project_name.pdf', $response->headers->get('Content-Disposition')); $this->assertNotEmpty($response->getContent()); } diff --git a/tests/Export/Renderer/XlsxRendererTest.php b/tests/Export/Renderer/XlsxRendererTest.php index 956ff55c..e76b0a70 100644 --- a/tests/Export/Renderer/XlsxRendererTest.php +++ b/tests/Export/Renderer/XlsxRendererTest.php @@ -39,8 +39,9 @@ class XlsxRendererTest extends AbstractRendererTest $response = $this->render($sut); $file = $response->getFile(); + $prefix = date('Ymd'); $this->assertEquals('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', $response->headers->get('Content-Type')); - $this->assertEquals('attachment; filename=kimai-export.xlsx', $response->headers->get('Content-Disposition')); + $this->assertEquals('attachment; filename=' . $prefix . '-Customer_Name-project_name.xlsx', $response->headers->get('Content-Disposition')); $this->assertTrue(file_exists($file->getRealPath())); diff --git a/tests/Export/Timesheet/CsvRendererTest.php b/tests/Export/Timesheet/CsvRendererTest.php index 832d9c42..af70a2a6 100644 --- a/tests/Export/Timesheet/CsvRendererTest.php +++ b/tests/Export/Timesheet/CsvRendererTest.php @@ -46,8 +46,9 @@ class CsvRendererTest extends AbstractRendererTest $response = $this->render($sut); $file = $response->getFile(); + $prefix = date('Ymd'); $this->assertEquals('text/csv', $response->headers->get('Content-Type')); - $this->assertEquals('attachment; filename=kimai-export.csv', $response->headers->get('Content-Disposition')); + $this->assertEquals('attachment; filename=' . $prefix . '-Customer_Name-project_name.csv', $response->headers->get('Content-Disposition')); $this->assertTrue(file_exists($file->getRealPath())); $content = file_get_contents($file->getRealPath()); diff --git a/tests/Export/Timesheet/PdfRendererTest.php b/tests/Export/Timesheet/PdfRendererTest.php index 9c2b7f64..b4d1b880 100644 --- a/tests/Export/Timesheet/PdfRendererTest.php +++ b/tests/Export/Timesheet/PdfRendererTest.php @@ -51,8 +51,9 @@ class PdfRendererTest extends AbstractRendererTest $response = $this->render($sut); + $prefix = date('Ymd'); $this->assertEquals('application/pdf', $response->headers->get('Content-Type')); - $this->assertEquals('attachment; filename=kimai-export.pdf', $response->headers->get('Content-Disposition')); + $this->assertEquals('attachment; filename=' . $prefix . '-Customer_Name-project_name.pdf', $response->headers->get('Content-Disposition')); $this->assertNotEmpty($response->getContent()); } diff --git a/tests/Export/Timesheet/XlsxRendererTest.php b/tests/Export/Timesheet/XlsxRendererTest.php index 2bfc2994..16457924 100644 --- a/tests/Export/Timesheet/XlsxRendererTest.php +++ b/tests/Export/Timesheet/XlsxRendererTest.php @@ -36,8 +36,9 @@ class XlsxRendererTest extends AbstractRendererTest $response = $this->render($sut); $file = $response->getFile(); + $prefix = date('Ymd'); $this->assertEquals('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', $response->headers->get('Content-Type')); - $this->assertEquals('attachment; filename=kimai-export.xlsx', $response->headers->get('Content-Disposition')); + $this->assertEquals('attachment; filename=' . $prefix . '-Customer_Name-project_name.xlsx', $response->headers->get('Content-Disposition')); $this->assertTrue(file_exists($file->getRealPath()));