diff --git a/phpstan.neon b/phpstan.neon index 674b240d..de92cf96 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -987,11 +987,6 @@ parameters: count: 1 path: src/Controller/TimesheetAbstractController.php - - - message: "#^Parameter \\#1 \\$id of method App\\\\Export\\\\ServiceExport\\:\\:getTimesheetExporterById\\(\\) expects string, bool\\|float\\|int\\|string given\\.$#" - count: 1 - path: src/Controller/TimesheetAbstractController.php - - message: "#^PHPDoc tag @var for variable \\$teams contains generic class Doctrine\\\\Common\\\\Collections\\\\ArrayCollection but does not specify its types\\: TKey, T$#" count: 1 @@ -2782,61 +2777,6 @@ parameters: count: 2 path: src/Form/Toolbar/TeamToolbarForm.php - - - message: "#^Method App\\\\Form\\\\Toolbar\\\\TimesheetExportToolbarForm\\:\\:addActivityMultiChoice\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#" - count: 1 - path: src/Form/Toolbar/TimesheetExportToolbarForm.php - - - - message: "#^Method App\\\\Form\\\\Toolbar\\\\TimesheetExportToolbarForm\\:\\:addActivitySelect\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#" - count: 1 - path: src/Form/Toolbar/TimesheetExportToolbarForm.php - - - - message: "#^Method App\\\\Form\\\\Toolbar\\\\TimesheetExportToolbarForm\\:\\:addCustomerMultiChoice\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#" - count: 1 - path: src/Form/Toolbar/TimesheetExportToolbarForm.php - - - - message: "#^Method App\\\\Form\\\\Toolbar\\\\TimesheetExportToolbarForm\\:\\:addCustomerSelect\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#" - count: 1 - path: src/Form/Toolbar/TimesheetExportToolbarForm.php - - - - message: "#^Method App\\\\Form\\\\Toolbar\\\\TimesheetExportToolbarForm\\:\\:addDateRange\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#" - count: 1 - path: src/Form/Toolbar/TimesheetExportToolbarForm.php - - - - message: "#^Method App\\\\Form\\\\Toolbar\\\\TimesheetExportToolbarForm\\:\\:addOrderBy\\(\\) has parameter \\$allowedColumns with no value type specified in iterable type array\\.$#" - count: 1 - path: src/Form/Toolbar/TimesheetExportToolbarForm.php - - - - message: "#^Method App\\\\Form\\\\Toolbar\\\\TimesheetExportToolbarForm\\:\\:addProjectMultiChoice\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#" - count: 1 - path: src/Form/Toolbar/TimesheetExportToolbarForm.php - - - - message: "#^Method App\\\\Form\\\\Toolbar\\\\TimesheetExportToolbarForm\\:\\:addProjectSelect\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#" - count: 1 - path: src/Form/Toolbar/TimesheetExportToolbarForm.php - - - - message: "#^Method App\\\\Form\\\\Toolbar\\\\TimesheetExportToolbarForm\\:\\:addTeamsChoice\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#" - count: 1 - path: src/Form/Toolbar/TimesheetExportToolbarForm.php - - - - message: "#^Method App\\\\Form\\\\Toolbar\\\\TimesheetExportToolbarForm\\:\\:addUsersChoice\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#" - count: 1 - path: src/Form/Toolbar/TimesheetExportToolbarForm.php - - - - message: "#^Parameter \\#1 \\$user of method App\\\\Repository\\\\Query\\\\BaseFormTypeQuery\\:\\:setUser\\(\\) expects App\\\\Entity\\\\User, mixed given\\.$#" - count: 2 - path: src/Form/Toolbar/TimesheetExportToolbarForm.php - - message: "#^Method App\\\\Form\\\\Toolbar\\\\TimesheetToolbarForm\\:\\:addActivityMultiChoice\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#" count: 1 diff --git a/src/Controller/AbstractController.php b/src/Controller/AbstractController.php index 3fa0cd35..72f2b813 100644 --- a/src/Controller/AbstractController.php +++ b/src/Controller/AbstractController.php @@ -160,17 +160,13 @@ abstract class AbstractController extends BaseAbstractController implements Serv * * @param array $parameter */ - private function addFlashTranslated(string $type, string $message, array $parameter = []): void + private function addFlashTranslated(string $type, string $message, array $parameter = [], string $domain = 'flashmessages'): void { if (!empty($parameter)) { foreach ($parameter as $key => $value) { - $parameter[$key] = $this->getTranslator()->trans($value, [], 'flashmessages'); + $parameter[$key] = $this->getTranslator()->trans($value, [], $domain); } - $message = $this->getTranslator()->trans( - $message, - $parameter, - 'flashmessages' - ); + $message = $this->getTranslator()->trans($message, $parameter, $domain); } $this->addFlash($type, $message); diff --git a/src/Controller/TimesheetAbstractController.php b/src/Controller/TimesheetAbstractController.php index a311a75c..c5ef9e1e 100644 --- a/src/Controller/TimesheetAbstractController.php +++ b/src/Controller/TimesheetAbstractController.php @@ -23,7 +23,6 @@ use App\Form\MultiUpdate\TimesheetMultiUpdate; use App\Form\MultiUpdate\TimesheetMultiUpdateDTO; use App\Form\TimesheetEditForm; use App\Form\TimesheetPreCreateForm; -use App\Form\Toolbar\TimesheetExportToolbarForm; use App\Form\Toolbar\TimesheetToolbarForm; use App\Repository\Query\BaseQuery; use App\Repository\Query\TimesheetQuery; @@ -34,7 +33,6 @@ use App\Timesheet\TrackingMode\TrackingModeInterface; use App\Utils\DataTable; use App\Utils\PageSetup; use Psr\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormTypeInterface; use Symfony\Component\HttpFoundation\Request; @@ -237,19 +235,22 @@ abstract class TimesheetAbstractController extends AbstractController ]); } - protected function export(Request $request, ServiceExport $serviceExport): Response + protected function export(string $type, Request $request, ServiceExport $serviceExport): Response { + $exporter = $serviceExport->getTimesheetExporterById($type); + + if (null === $exporter) { + throw $this->createNotFoundException(); + } + $query = $this->createDefaultQuery(); $query->setOrder(BaseQuery::ORDER_ASC); - $form = $this->getExportForm($query); - - if ($request->isMethod(Request::METHOD_POST)) { - $request->query->set('performSearch', true); - } + $form = $this->getToolbarForm($query); + $request->query->set('performSearch', true); if ($this->handleSearch($form, $request)) { - return $this->redirectToRoute($this->getExportRoute()); + return $this->redirectToRoute($this->getTimesheetRoute()); } $this->prepareQuery($query); @@ -263,29 +264,8 @@ abstract class TimesheetAbstractController extends AbstractController } $entries = $this->repository->getTimesheetResult($query); - $stats = $entries->getStatistic(); - // perform the real export - if ($request->isMethod(Request::METHOD_POST)) { - $type = $request->request->get('exporter'); - if (null !== $type) { - $exporter = $serviceExport->getTimesheetExporterById($type); - - if (null === $exporter) { - $form->addError(new FormError('Invalid timesheet exporter given')); - } else { - return $exporter->render($entries->getResults(), $query); - } - } - } - - return $this->render('timesheet/layout-export.html.twig', [ - 'page_setup' => new PageSetup('export'), - 'form' => $form->createView(), - 'route_back' => $this->getTimesheetRoute(), - 'exporter' => $serviceExport->getTimesheetExporter(), - 'stats' => $stats, - ]); + return $exporter->render($entries->getResults(), $query); } protected function multiUpdate(Request $request): Response @@ -548,16 +528,6 @@ abstract class TimesheetAbstractController extends AbstractController ]); } - private function getExportForm(TimesheetQuery $query): FormInterface - { - return $this->createSearchForm(TimesheetExportToolbarForm::class, $query, [ - 'action' => $this->generateUrl($this->getExportRoute()), - 'timezone' => $this->getDateTimeFactory()->getTimezone()->getName(), - 'method' => Request::METHOD_POST, - 'include_user' => $this->includeUserInForms('toolbar'), - ]); - } - protected function getPermissionEditExport(): string { return 'edit_export_own_timesheet'; @@ -611,11 +581,6 @@ abstract class TimesheetAbstractController extends AbstractController return 'timesheet_multi_delete'; } - protected function getExportRoute(): string - { - return 'timesheet_export'; - } - protected function canSeeStartEndTime(): bool { return $this->getTrackingMode()->canSeeBeginAndEndTimes(); diff --git a/src/Controller/TimesheetController.php b/src/Controller/TimesheetController.php index 714ccee3..9b4c3222 100644 --- a/src/Controller/TimesheetController.php +++ b/src/Controller/TimesheetController.php @@ -41,11 +41,11 @@ final class TimesheetController extends TimesheetAbstractController return $this->index($query, $request, 'timesheet', 'timesheet_paginated', TimesheetMetaDisplayEvent::TIMESHEET); } - #[Route(path: '/export/', name: 'timesheet_export', methods: ['GET', 'POST'])] + #[Route(path: '/export/{exporter}', name: 'timesheet_export', methods: ['GET', 'POST'])] #[IsGranted('export_own_timesheet')] - public function exportAction(Request $request, ServiceExport $serviceExport): Response + public function exportAction(string $exporter, Request $request, ServiceExport $serviceExport): Response { - return $this->export($request, $serviceExport); + return $this->export($exporter, $request, $serviceExport); } #[Route(path: '/{id}/edit', name: 'timesheet_edit', methods: ['GET', 'POST'])] diff --git a/src/Controller/TimesheetTeamController.php b/src/Controller/TimesheetTeamController.php index 8705b90e..67a75835 100644 --- a/src/Controller/TimesheetTeamController.php +++ b/src/Controller/TimesheetTeamController.php @@ -50,11 +50,11 @@ final class TimesheetTeamController extends TimesheetAbstractController return $this->index($query, $request, 'admin_timesheet', 'admin_timesheet_paginated', TimesheetMetaDisplayEvent::TEAM_TIMESHEET); } - #[Route(path: '/export/', name: 'admin_timesheet_export', methods: ['GET', 'POST'])] + #[Route(path: '/export/{exporter}', name: 'admin_timesheet_export', methods: ['GET', 'POST'])] #[IsGranted('export_other_timesheet')] - public function exportAction(Request $request, ServiceExport $serviceExport): Response + public function exportAction(string $exporter, Request $request, ServiceExport $serviceExport): Response { - return $this->export($request, $serviceExport); + return $this->export($exporter, $request, $serviceExport); } #[Route(path: '/{id}/edit', name: 'admin_timesheet_edit', methods: ['GET', 'POST'])] @@ -233,11 +233,6 @@ final class TimesheetTeamController extends TimesheetAbstractController return 'admin_timesheet_edit'; } - protected function getExportRoute(): string - { - return 'admin_timesheet_export'; - } - protected function getMultiUpdateRoute(): string { return 'admin_timesheet_multi_update'; diff --git a/src/EventSubscriber/Actions/TimesheetsSubscriber.php b/src/EventSubscriber/Actions/TimesheetsSubscriber.php index 12d76a11..236eb245 100644 --- a/src/EventSubscriber/Actions/TimesheetsSubscriber.php +++ b/src/EventSubscriber/Actions/TimesheetsSubscriber.php @@ -10,9 +10,17 @@ namespace App\EventSubscriber\Actions; use App\Event\PageActionsEvent; +use App\Export\ServiceExport; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; final class TimesheetsSubscriber extends AbstractActionsSubscriber { + public function __construct(AuthorizationCheckerInterface $auth, UrlGeneratorInterface $urlGenerator, private readonly ServiceExport $serviceExport) + { + parent::__construct($auth, $urlGenerator); + } + public static function getActionName(): string { return 'timesheets'; @@ -25,7 +33,9 @@ final class TimesheetsSubscriber extends AbstractActionsSubscriber } if ($this->isGranted('export_own_timesheet')) { - $event->addAction('download', ['url' => $this->path('timesheet_export'), 'class' => 'modal-ajax-form', 'title' => 'export']); + foreach ($this->serviceExport->getTimesheetExporter() as $exporter) { + $event->addActionToSubmenu('export', $exporter->getId(), ['url' => $this->path('timesheet_export', ['exporter' => $exporter->getId()]), 'class' => 'toolbar-action', 'title' => 'button.' . $exporter->getId(), 'translation_domain' => 'messages']); + } } } } diff --git a/src/EventSubscriber/Actions/TimesheetsTeamSubscriber.php b/src/EventSubscriber/Actions/TimesheetsTeamSubscriber.php index 92be6a4f..6cea13c1 100644 --- a/src/EventSubscriber/Actions/TimesheetsTeamSubscriber.php +++ b/src/EventSubscriber/Actions/TimesheetsTeamSubscriber.php @@ -10,9 +10,17 @@ namespace App\EventSubscriber\Actions; use App\Event\PageActionsEvent; +use App\Export\ServiceExport; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; final class TimesheetsTeamSubscriber extends AbstractActionsSubscriber { + public function __construct(AuthorizationCheckerInterface $auth, UrlGeneratorInterface $urlGenerator, private readonly ServiceExport $serviceExport) + { + parent::__construct($auth, $urlGenerator); + } + public static function getActionName(): string { return 'timesheets_team'; @@ -26,7 +34,9 @@ final class TimesheetsTeamSubscriber extends AbstractActionsSubscriber } if ($this->isGranted('export_other_timesheet')) { - $event->addAction('download', ['url' => $this->path('admin_timesheet_export'), 'class' => 'modal-ajax-form', 'title' => 'export']); + foreach ($this->serviceExport->getTimesheetExporter() as $exporter) { + $event->addActionToSubmenu('export', $exporter->getId(), ['url' => $this->path('admin_timesheet_export', ['exporter' => $exporter->getId()]), 'class' => 'toolbar-action', 'title' => 'button.' . $exporter->getId(), 'translation_domain' => 'messages']); + } } } } diff --git a/src/Export/ExportRendererInterface.php b/src/Export/ExportRendererInterface.php index 02d74bc8..3033dedd 100644 --- a/src/Export/ExportRendererInterface.php +++ b/src/Export/ExportRendererInterface.php @@ -27,11 +27,6 @@ interface ExportRendererInterface */ public function getId(): string; - /** - * @return string - */ - public function getIcon(): string; - /** * @return string */ diff --git a/src/Export/Renderer/CsvRenderer.php b/src/Export/Renderer/CsvRenderer.php index bfb64087..eded5274 100644 --- a/src/Export/Renderer/CsvRenderer.php +++ b/src/Export/Renderer/CsvRenderer.php @@ -14,11 +14,6 @@ use App\Export\RendererInterface; final class CsvRenderer extends BaseCsvRenderer implements RendererInterface { - public function getIcon(): string - { - return 'csv'; - } - public function getTitle(): string { return 'csv'; diff --git a/src/Export/Renderer/HtmlRenderer.php b/src/Export/Renderer/HtmlRenderer.php index ae44702e..bc4d2983 100644 --- a/src/Export/Renderer/HtmlRenderer.php +++ b/src/Export/Renderer/HtmlRenderer.php @@ -14,11 +14,6 @@ use App\Export\ExportRendererInterface; final class HtmlRenderer extends BaseHtmlRenderer implements ExportRendererInterface { - public function getIcon(): string - { - return 'print'; - } - public function getTitle(): string { return 'print'; diff --git a/src/Export/Renderer/PDFRenderer.php b/src/Export/Renderer/PDFRenderer.php index 4dc6b5c5..321b2a81 100644 --- a/src/Export/Renderer/PDFRenderer.php +++ b/src/Export/Renderer/PDFRenderer.php @@ -14,11 +14,6 @@ use App\Export\ExportRendererInterface; final class PDFRenderer extends BasePDFRenderer implements ExportRendererInterface { - public function getIcon(): string - { - return 'pdf'; - } - public function getTitle(): string { return 'pdf'; diff --git a/src/Export/Renderer/XlsxRenderer.php b/src/Export/Renderer/XlsxRenderer.php index 3f6e4074..bbc2e256 100644 --- a/src/Export/Renderer/XlsxRenderer.php +++ b/src/Export/Renderer/XlsxRenderer.php @@ -14,11 +14,6 @@ use App\Export\RendererInterface; final class XlsxRenderer extends BaseXlsxRenderer implements RendererInterface { - public function getIcon(): string - { - return 'xlsx'; - } - public function getTitle(): string { return 'xlsx'; diff --git a/src/Export/Timesheet/CsvRenderer.php b/src/Export/Timesheet/CsvRenderer.php index ec99dd07..c6f9655d 100644 --- a/src/Export/Timesheet/CsvRenderer.php +++ b/src/Export/Timesheet/CsvRenderer.php @@ -14,4 +14,8 @@ use App\Export\TimesheetExportInterface; final class CsvRenderer extends BaseCsvRenderer implements TimesheetExportInterface { + public function getTitle(): string + { + return 'csv'; + } } diff --git a/src/Export/Timesheet/HtmlRenderer.php b/src/Export/Timesheet/HtmlRenderer.php index e0206af3..06059b41 100644 --- a/src/Export/Timesheet/HtmlRenderer.php +++ b/src/Export/Timesheet/HtmlRenderer.php @@ -19,11 +19,13 @@ final class HtmlRenderer extends BaseHtmlRenderer implements TimesheetExportInte return 'timesheet/export.html.twig'; } - /** - * @return string - */ public function getId(): string { return 'print'; } + + public function getTitle(): string + { + return 'print'; + } } diff --git a/src/Export/Timesheet/PDFRenderer.php b/src/Export/Timesheet/PDFRenderer.php index bf6e150e..9ad104d3 100644 --- a/src/Export/Timesheet/PDFRenderer.php +++ b/src/Export/Timesheet/PDFRenderer.php @@ -14,4 +14,8 @@ use App\Export\TimesheetExportInterface; final class PDFRenderer extends BasePDFRenderer implements TimesheetExportInterface { + public function getTitle(): string + { + return 'pdf'; + } } diff --git a/src/Export/Timesheet/XlsxRenderer.php b/src/Export/Timesheet/XlsxRenderer.php index c4d57e9f..adb70dc6 100644 --- a/src/Export/Timesheet/XlsxRenderer.php +++ b/src/Export/Timesheet/XlsxRenderer.php @@ -14,4 +14,8 @@ use App\Export\TimesheetExportInterface; final class XlsxRenderer extends BaseXlsxRenderer implements TimesheetExportInterface { + public function getTitle(): string + { + return 'xlsx'; + } } diff --git a/src/Export/TimesheetExportInterface.php b/src/Export/TimesheetExportInterface.php index 2ab6fdbf..c9c59dfc 100644 --- a/src/Export/TimesheetExportInterface.php +++ b/src/Export/TimesheetExportInterface.php @@ -19,13 +19,10 @@ interface TimesheetExportInterface { /** * @param Timesheet[] $timesheets - * @param TimesheetQuery $query - * @return Response */ public function render(array $timesheets, TimesheetQuery $query): Response; - /** - * @return string - */ public function getId(): string; + + public function getTitle(): string; } diff --git a/src/Form/Extension/ToolbarFormExtension.php b/src/Form/Extension/ToolbarFormExtension.php index d3abf8fe..c54c4514 100644 --- a/src/Form/Extension/ToolbarFormExtension.php +++ b/src/Form/Extension/ToolbarFormExtension.php @@ -12,7 +12,6 @@ namespace App\Form\Extension; use App\Form\Helper\ToolbarHelper; use App\Form\Toolbar\ExportToolbarForm; use App\Form\Toolbar\InvoiceToolbarForm; -use App\Form\Toolbar\TimesheetExportToolbarForm; use App\Form\Toolbar\TimesheetToolbarForm; use App\Form\Toolbar\UserToolbarForm; use App\Reporting\MonthlyUserList\MonthlyUserListForm; @@ -33,7 +32,6 @@ final class ToolbarFormExtension extends AbstractTypeExtension InvoiceToolbarForm::class, ExportToolbarForm::class, TimesheetToolbarForm::class, - TimesheetExportToolbarForm::class, UserToolbarForm::class, WeeklyUserListForm::class, MonthlyUserListForm::class, diff --git a/src/Form/Toolbar/TimesheetExportToolbarForm.php b/src/Form/Toolbar/TimesheetExportToolbarForm.php deleted file mode 100644 index 6c9ad363..00000000 --- a/src/Form/Toolbar/TimesheetExportToolbarForm.php +++ /dev/null @@ -1,58 +0,0 @@ - - */ -final class TimesheetExportToolbarForm extends AbstractType -{ - use ToolbarFormTrait; - - public function buildForm(FormBuilderInterface $builder, array $options): void - { - $newOptions = []; - if ($options['ignore_date'] === true) { - $newOptions['ignore_date'] = true; - } - - $this->addSearchTermInputField($builder); - $this->addDateRange($builder, ['timezone' => $options['timezone']]); - $this->addCustomerMultiChoice($builder, $newOptions, true); - $this->addProjectMultiChoice($builder, $newOptions, true, true); - $this->addActivityMultiChoice($builder, [], true); - $this->addTagInputField($builder); - if ($options['include_user']) { - $this->addUsersChoice($builder); - } - $this->addTimesheetStateChoice($builder); - $this->addBillableChoice($builder); - $this->addExportStateChoice($builder); - $this->addOrder($builder); - $this->addOrderBy($builder, TimesheetQuery::TIMESHEET_ORDER_ALLOWED); - } - - public function configureOptions(OptionsResolver $resolver): void - { - $resolver->setDefaults([ - 'data_class' => TimesheetQuery::class, - 'csrf_protection' => false, - 'include_user' => false, - 'ignore_date' => true, - 'timezone' => date_default_timezone_get(), - ]); - } -} diff --git a/templates/timesheet/layout-export.html.twig b/templates/timesheet/layout-export.html.twig deleted file mode 100644 index 8dc7b395..00000000 --- a/templates/timesheet/layout-export.html.twig +++ /dev/null @@ -1,43 +0,0 @@ -{% extends kimai_context.modalRequest ? 'form.html.twig' : 'base.html.twig' %} -{% import "macros/widgets.html.twig" as widgets %} - -{% block main %} - {% if stats.count > 1000 %} - {{ widgets.alert('warning', ('export.warn_result_amount'|trans({'%count%': stats.count})), null, 'warning') }} - {% endif %} - {% set formEditTemplate = kimai_context.modalRequest ? 'default/_form_modal.html.twig' : 'default/_form.html.twig' %} - {% set formOptions = { - 'title': 'export'|trans, - 'form': form, - 'back': path(route_back), - 'formStartOptions': {'attr': {'class': 'searchform', 'target': '_blank'}}, - } %} - {% embed formEditTemplate with formOptions %} - {% form_theme form 'form/search.html.twig' %} - {% block modal_size %}{% endblock %} - {% block form_body %} - {% set orderHasError = form.orderBy.vars.errors|length > 0 or form.order.vars.errors|length > 0 %} - {% set orderBy = form_widget(form.orderBy) %} - {% set order = form_widget(form.order) %} - {{ form_rest(form) }} -
- {{ form_label(form.orderBy) }} -
- {{ orderBy|raw }} - {{ form_errors(form.orderBy) }} -
-
- {{ order|raw }} - {{ form_errors(form.order) }} -
-
- {% endblock %} - {% block submit_button %} -
- {% for exp in exporter %} - - {% endfor %} -
- {% endblock %} - {% endembed %} -{% endblock %} diff --git a/tests/Controller/ControllerBaseTest.php b/tests/Controller/ControllerBaseTest.php index e54147a2..1804c0a2 100644 --- a/tests/Controller/ControllerBaseTest.php +++ b/tests/Controller/ControllerBaseTest.php @@ -245,14 +245,6 @@ abstract class ControllerBaseTest extends WebTestCase self::assertEquals(Response::HTTP_NOT_FOUND, $client->getResponse()->getStatusCode()); } - protected function assert404(Response $response, ?string $message = null): void - { - $message = 'Page not found'; - self::assertFalse($response->isSuccessful()); - self::assertEquals(Response::HTTP_NOT_FOUND, $response->getStatusCode()); - self::assertStringContainsString($message, $response->getContent()); - } - protected function assertMainContentClass(HttpKernelBrowser $client, string $classname): void { self::assertStringContainsString('
', $client->getResponse()->getContent()); diff --git a/tests/Controller/ExportControllerTest.php b/tests/Controller/ExportControllerTest.php index 1bb5445c..8db26f88 100644 --- a/tests/Controller/ExportControllerTest.php +++ b/tests/Controller/ExportControllerTest.php @@ -172,9 +172,7 @@ class ExportControllerTest extends ControllerBaseTest { $client = $this->getClientForAuthenticatedUser(User::ROLE_TEAMLEAD); $this->request($client, '/export/data', 'POST'); - - $response = $client->getResponse(); - $this->assert404($response, 'Missing export renderer'); + $this->assertRouteNotFound($client); } public function testExportActionWithInvalidRenderer(): void @@ -193,8 +191,7 @@ class ExportControllerTest extends ControllerBaseTest 'renderer' => 'default' ]); - $response = $client->getResponse(); - $this->assert404($response, 'Unknown export renderer'); + $this->assertRouteNotFound($client); } public function testExportAction(): void diff --git a/tests/Controller/TimesheetControllerTest.php b/tests/Controller/TimesheetControllerTest.php index 93061897..f957a7f3 100644 --- a/tests/Controller/TimesheetControllerTest.php +++ b/tests/Controller/TimesheetControllerTest.php @@ -41,8 +41,11 @@ class TimesheetControllerTest extends ControllerBaseTest // there are no records by default in the test database $this->assertHasNoEntriesWithFilter($client); $this->assertPageActions($client, [ - 'download modal-ajax-form' => $this->createUrl('/timesheet/export/'), 'create modal-ajax-form' => $this->createUrl('/timesheet/create'), + 'dropdown-item action-csv toolbar-action' => $this->createUrl('/timesheet/export/csv'), + 'dropdown-item action-print toolbar-action' => $this->createUrl('/timesheet/export/print'), + 'dropdown-item action-pdf toolbar-action' => $this->createUrl('/timesheet/export/pdf'), + 'dropdown-item action-xlsx toolbar-action' => $this->createUrl('/timesheet/export/xlsx'), ]); } @@ -155,12 +158,14 @@ class TimesheetControllerTest extends ControllerBaseTest $fixture->setStartDate(new \DateTime('-10 days')); $this->importFixture($fixture); - $this->request($client, '/timesheet/export/'); + $this->request($client, '/timesheet/'); $this->assertTrue($client->getResponse()->isSuccessful()); $dateRange = $this->formatDateRange(new \DateTime('-10 days'), new \DateTime()); - $client->submitForm('export-btn-print', [ + $form = $client->getCrawler()->filter('form.searchform')->form(); + $form->getNode()->setAttribute('action', $this->createUrl('/timesheet/export/print')); + $client->submit($form, [ 'state' => 1, 'daterange' => $dateRange, 'customers' => [], @@ -177,6 +182,13 @@ class TimesheetControllerTest extends ControllerBaseTest $this->assertEquals(5, \count($result)); } + public function testExporterNotFoundAction(): void + { + $client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN); + $this->request($client, '/timesheet/export/notfound'); + $this->assertRouteNotFound($client); + } + public function testCreateAction(): void { $client = $this->getClientForAuthenticatedUser(); diff --git a/tests/Controller/TimesheetTeamControllerTest.php b/tests/Controller/TimesheetTeamControllerTest.php index 5d0bba1e..00be7741 100644 --- a/tests/Controller/TimesheetTeamControllerTest.php +++ b/tests/Controller/TimesheetTeamControllerTest.php @@ -43,9 +43,12 @@ class TimesheetTeamControllerTest extends ControllerBaseTest $this->assertHasNoEntriesWithFilter($client); $this->assertPageActions($client, [ - 'download modal-ajax-form' => $this->createUrl('/team/timesheet/export/'), 'create create-ts modal-ajax-form' => $this->createUrl('/team/timesheet/create'), 'multi-user create-ts-mu modal-ajax-form' => $this->createUrl('/team/timesheet/create_mu'), + 'dropdown-item action-csv toolbar-action' => $this->createUrl('/team/timesheet/export/csv'), + 'dropdown-item action-print toolbar-action' => $this->createUrl('/team/timesheet/export/print'), + 'dropdown-item action-pdf toolbar-action' => $this->createUrl('/team/timesheet/export/pdf'), + 'dropdown-item action-xlsx toolbar-action' => $this->createUrl('/team/timesheet/export/xlsx'), ]); } @@ -136,12 +139,14 @@ class TimesheetTeamControllerTest extends ControllerBaseTest $fixture->setStartDate(new \DateTime('-10 days')); $this->importFixture($fixture); - $this->request($client, '/team/timesheet/export/'); + $this->request($client, '/team/timesheet/'); $this->assertTrue($client->getResponse()->isSuccessful()); $dateRange = $this->formatDateRange(new \DateTime('-10 days'), new \DateTime()); - $client->submitForm('export-btn-print', [ + $form = $client->getCrawler()->filter('form.searchform')->form(); + $form->getNode()->setAttribute('action', $this->createUrl('/team/timesheet/export/print')); + $client->submit($form, [ 'state' => 1, 'daterange' => $dateRange, 'customers' => [], @@ -158,6 +163,13 @@ class TimesheetTeamControllerTest extends ControllerBaseTest $this->assertEquals(10, \count($result)); } + public function testExporterNotFoundAction(): void + { + $client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN); + $this->request($client, '/team/timesheet/export/notfound'); + $this->assertRouteNotFound($client); + } + public function testCreateAction(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN); diff --git a/tests/Export/Renderer/CsvRendererTest.php b/tests/Export/Renderer/CsvRendererTest.php index a6691507..635ce252 100644 --- a/tests/Export/Renderer/CsvRendererTest.php +++ b/tests/Export/Renderer/CsvRendererTest.php @@ -27,7 +27,6 @@ class CsvRendererTest extends AbstractRendererTest $this->assertEquals('csv', $sut->getId()); $this->assertEquals('csv', $sut->getTitle()); - $this->assertEquals('csv', $sut->getIcon()); } public function getTestModel() diff --git a/tests/Export/Renderer/HtmlRendererTest.php b/tests/Export/Renderer/HtmlRendererTest.php index 0628e5bd..228b7979 100644 --- a/tests/Export/Renderer/HtmlRendererTest.php +++ b/tests/Export/Renderer/HtmlRendererTest.php @@ -40,7 +40,6 @@ class HtmlRendererTest extends AbstractRendererTest $this->assertEquals('html', $sut->getId()); $this->assertEquals('print', $sut->getTitle()); - $this->assertEquals('print', $sut->getIcon()); } public function testRender(): void diff --git a/tests/Export/Renderer/PdfRendererTest.php b/tests/Export/Renderer/PdfRendererTest.php index d08acb40..f5fc7104 100644 --- a/tests/Export/Renderer/PdfRendererTest.php +++ b/tests/Export/Renderer/PdfRendererTest.php @@ -36,7 +36,6 @@ 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'); diff --git a/tests/Export/Renderer/XlsxRendererTest.php b/tests/Export/Renderer/XlsxRendererTest.php index e411ad6a..e595365c 100644 --- a/tests/Export/Renderer/XlsxRendererTest.php +++ b/tests/Export/Renderer/XlsxRendererTest.php @@ -27,7 +27,6 @@ class XlsxRendererTest extends AbstractRendererTest $this->assertEquals('xlsx', $sut->getId()); $this->assertEquals('xlsx', $sut->getTitle()); - $this->assertEquals('xlsx', $sut->getIcon()); } public function testRender(): void diff --git a/tests/Export/Timesheet/CsvRendererTest.php b/tests/Export/Timesheet/CsvRendererTest.php index d71a6be1..1a779a45 100644 --- a/tests/Export/Timesheet/CsvRendererTest.php +++ b/tests/Export/Timesheet/CsvRendererTest.php @@ -26,6 +26,7 @@ class CsvRendererTest extends AbstractRendererTest $sut = $this->getAbstractRenderer(CsvRenderer::class); $this->assertEquals('csv', $sut->getId()); + $this->assertEquals('csv', $sut->getTitle()); } public function getTestModel() diff --git a/tests/Export/Timesheet/HtmlRendererTest.php b/tests/Export/Timesheet/HtmlRendererTest.php index 5bf0d4b7..977d9d5c 100644 --- a/tests/Export/Timesheet/HtmlRendererTest.php +++ b/tests/Export/Timesheet/HtmlRendererTest.php @@ -33,6 +33,7 @@ class HtmlRendererTest extends AbstractRendererTest ); $this->assertEquals('print', $sut->getId()); + $this->assertEquals('print', $sut->getTitle()); } public function testRender(): void diff --git a/tests/Export/Timesheet/PdfRendererTest.php b/tests/Export/Timesheet/PdfRendererTest.php index e8ab60a8..5704f423 100644 --- a/tests/Export/Timesheet/PdfRendererTest.php +++ b/tests/Export/Timesheet/PdfRendererTest.php @@ -35,6 +35,7 @@ class PdfRendererTest extends AbstractRendererTest ); $this->assertEquals('pdf', $sut->getId()); + $this->assertEquals('pdf', $sut->getTitle()); } public function testRender(): void diff --git a/tests/Export/Timesheet/XlsxRendererTest.php b/tests/Export/Timesheet/XlsxRendererTest.php index 786bac75..881f470e 100644 --- a/tests/Export/Timesheet/XlsxRendererTest.php +++ b/tests/Export/Timesheet/XlsxRendererTest.php @@ -26,6 +26,7 @@ class XlsxRendererTest extends AbstractRendererTest $sut = $this->getAbstractRenderer(XlsxRenderer::class); $this->assertEquals('xlsx', $sut->getId()); + $this->assertEquals('xlsx', $sut->getTitle()); } public function testRender(): void diff --git a/tests/phpstan.neon b/tests/phpstan.neon index f268e0ea..54feaec3 100644 --- a/tests/phpstan.neon +++ b/tests/phpstan.neon @@ -676,7 +676,7 @@ parameters: - message: "#^Parameter \\#2 \\$haystack of static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertStringContainsString\\(\\) expects string, string\\|false given\\.$#" - count: 10 + count: 9 path: Controller/ControllerBaseTest.php - @@ -1434,16 +1434,6 @@ parameters: count: 1 path: Export/Renderer/AbstractRendererTest.php - - - message: "#^Call to an undefined method App\\\\Export\\\\ExportRendererInterface\\|App\\\\Export\\\\TimesheetExportInterface\\:\\:getIcon\\(\\)\\.$#" - count: 1 - path: Export/Renderer/CsvRendererTest.php - - - - message: "#^Call to an undefined method App\\\\Export\\\\ExportRendererInterface\\|App\\\\Export\\\\TimesheetExportInterface\\:\\:getTitle\\(\\)\\.$#" - count: 1 - path: Export/Renderer/CsvRendererTest.php - - message: "#^Method App\\\\Tests\\\\Export\\\\Renderer\\\\CsvRendererTest\\:\\:getTestModel\\(\\) has no return type specified\\.$#" count: 1 @@ -1524,16 +1514,6 @@ parameters: count: 7 path: Export/Renderer/HtmlRendererTest.php - - - message: "#^Call to an undefined method App\\\\Export\\\\ExportRendererInterface\\|App\\\\Export\\\\TimesheetExportInterface\\:\\:getIcon\\(\\)\\.$#" - count: 1 - path: Export/Renderer/XlsxRendererTest.php - - - - message: "#^Call to an undefined method App\\\\Export\\\\ExportRendererInterface\\|App\\\\Export\\\\TimesheetExportInterface\\:\\:getTitle\\(\\)\\.$#" - count: 1 - path: Export/Renderer/XlsxRendererTest.php - - message: "#^Parameter \\#1 \\$renderer of method App\\\\Tests\\\\Export\\\\Renderer\\\\AbstractRendererTest\\:\\:render\\(\\) expects App\\\\Export\\\\ExportRendererInterface, App\\\\Export\\\\ExportRendererInterface\\|App\\\\Export\\\\TimesheetExportInterface given\\.$#" count: 1